# Sprint Backlog
**Sprint:** 2 **Dates:** 2026-09-14 - 2026-09-18
**Sprint Goal:** Deliver a usable text-only template designer GUI (canvas sizing, text placement, property editing, save/reopen) as the foundation for CSV mapping, and re-verify the render path's high-volume performance target before more work lands on the render hot path.
## Committed Items
| Story | Size | Status | Tasks |
|---|---|---|---|
| Time-box the first high-volume benchmark | 5 points | Done | - [x] Define a repeatable benchmark scenario (dataset size, template, environment) for the text-only render path.
- [x] Run the benchmark against a representative 100k-record dataset at 300 DPI, recording elapsed time, output size, and bottlenecks.
- [x] Document findings against the "100k in under 10 minutes" target, noting whether the progress-reporting hook (Batch 3) and license-key resolution step (post-Sprint-1 fix) changed the picture since the Batch 2 numbers.
- [x] Capture follow-up backlog items if the benchmark reveals material risk. |
| Configure canvas dimensions in operator-friendly units | 3 points | Done | - [x] Model canvas dimensions with inches/millimeters/points and conversion between them.
- [x] Add UI controls for entering height/width and selecting the unit.
- [x] Persist canvas dimensions and unit as part of the template's in-memory layout state.
- [x] Verify round-trip: enter dimensions in each unit, confirm displayed and stored values agree. |
| Place and move text elements on the canvas | 5 points | Done | - [x] Add a canvas rendering surface capable of hosting text element visuals.
- [x] Implement adding a static text element and a dynamic text placeholder element.
- [x] Implement selecting and drag-repositioning text elements.
- [x] Persist element position updates into the layout state.
- [x] Verify visually: add, select, move, confirm canvas and stored state agree. |
| Edit selected text properties in a properties panel | 3 points | Done | - [x] Build a properties panel showing X, Y, font family, font size, color, and z-order for the selected element.
- [x] Wire panel edits back to update the selected element on the canvas live.
- [x] Enforce the numeric z-order rule (0 = bottom-most).
- [x] Verify: select an element, edit each property, confirm canvas and stored state agree. |
| Save and reopen text-only XML templates | 3 points | Done | - [x] Define/confirm the text-only template XML schema for canvas settings and text elements.
- [x] Implement saving the current layout to an XML template file.
- [x] Implement reopening a saved template, restoring canvas settings and element positions.
- [x] Handle invalid/unsupported XML with a clear operator-facing error.
- [x] Verify round-trip save/reopen against a real template file, plus one invalid-XML failure case. |
## Stretch (pull only if the committed items finish early)
| Story | Size | Notes |
|---|---|---|
| Load CSV headers and sample rows into the desktop app | 3 points | Independent of the GUI designer stories (no dependency on canvas/text placement); pulling it early gives Sprint 3 a head start on CSV mapping, but it is not required to meet this sprint's goal. |
## Notes
- Capacity signal: one sprint of history so far (Sprint 1: 20 points committed and completed against a conservative first-sprint estimate). Treated as a low-confidence single data point per the velocity-forecasting guidance for new teams — committing to 19 points here (close to, not above, the one known data point) rather than assuming the unusually fast Sprint 1 pace repeats, since Sprint 2's core work (a new WinForms canvas/drag-drop/properties surface) is less proven than Sprint 1's CLI work.
- Planning rationale: pull the overdue benchmark spike first (cheap, high-information, explicitly flagged at Sprint 1 review as "should not be allowed to keep sliding"), then the full Template Designer GUI Foundation epic as one coherent vertical slice (canvas -> elements -> properties -> save/reopen) so the designer is actually usable end-to-end, not partially built. CSV Integration stories are deferred to Sprint 3 as a full epic rather than split, since 3 of its 4 stories hard-depend on this sprint's "place text elements" story being done and verified first — pulling any of them into the same sprint would risk "starting what we can't finish" on a same-sprint dependency chain. The one CSV story with no such dependency ("Load CSV headers") is kept as an explicit stretch item instead of a commitment.
- Impediments: template asset path strategy (absolute vs relative) remains open; UNC timeout/retry behavior remains open. Neither blocks this sprint's committed items (none touch template image/logo paths or network shares).
- Carried over from previous sprint: none (Sprint 1 fully completed all 5 committed stories).
- Stretch item decision (2026-09-14, end of sprint): "Load CSV headers and sample rows into the desktop app" was not pulled. All 5 committed stories (19 points) are Done and the sprint goal — a usable, coherent, end-to-end text-only template designer plus the re-verified render benchmark — is fully met; per "swarm, don't spread," finishing the committed vertical slice cleanly (including the actual-built-artifact verification each story needed) took priority over starting additional stretch scope in the same session. Sprint 3 planning can pull it first, as already noted above.
- Retrospective action items applied to this sprint's plan (`backlog/sprints/sprint-1-retrospective.md`):
- Reuse the dependency-ordered "Execution Order" batch table below as the default planning/swarming pattern.
- The DoD's new verification bullet (`templates/definition_of_done.md`, launch/packaging/runtime-config changes require verification against the actual built artifact) is now a standing DoD requirement, not just a working practice — none of this sprint's committed stories are expected to trigger it (no launch/packaging/config-resolution changes), but re-check if that changes.
- The overdue high-volume benchmark is pulled as Batch 1, not left to slide further.
- Continue "leave it better than you found it" and honest gap self-reporting as a standing expectation.
## Daily Scrum Log
| Day | Date | Completed | Planned | Blocked/At risk |
|---|---|---|---|---|
| 1 | 2026-09-14 | N/A (sprint start) | Swarm on Batch 1, "Time-box the first high-volume benchmark" (independent of the GUI batches, overdue, cheap risk check) | Template path and UNC timeout impediments still open (see `logs/impediment_log.md`); not relevant to this sprint's committed items |
| 1 (continued) | 2026-09-14 | "Time-box the first high-volume benchmark" — all 4 tasks done, story meets DoD, marked Done. Generated a real ~100k-record CSV (256x repeat of the 392-row sample, same shape/quoting) and ran the real built Release CLI against it with the actual `key.txt` license resolution path. **Material finding: the render path is off track for the 100k/10-minute target, not close.** Throughput degrades monotonically from ~399 rec/s to ~15 rec/s (still falling) by record 4,827 of 100,352 — time-boxed and stopped at 138.8s wall time once the trend was unambiguous (projected full run: 45-90+ minutes). A smaller 2,000-record run was taken to full completion as a real, non-extrapolated data point: 20.775s, valid PDF, 2,302,387 bytes, exit 0. Code inspection ruled out this repo's own merge/CSV loop (O(1) per record) and both the Batch 3 progress-reporting hook and the license-key resolver (one-time/constant cost) as contributors, isolating the likely cause to Debenu Quick PDF Library 10.13's own in-memory document model. Full methodology and data: `code/BENCHMARK.md`. Follow-up captured as a new "Investigate and address high-volume render throughput degradation" story in `backlog/epics/05_cli_rendering_engine_and_debenu_integration.md` (Ready, not yet sized) plus a technical debt entry (`logs/technical_debt_log.md`, 2026-09-14, Impact: High) — not fixed inside this spike, per its own "not a final optimization guarantee" scope. | Pull Batch 2, "Configure canvas dimensions in operator-friendly units" | New, real risk: the 100k/10-minute target is currently missed by 5x-10x+ at realistic scale. This does not block Sprint 2's remaining GUI-designer batches (none touch the render hot path) but is a serious release-readiness risk that should be prioritized (product-owner/scrum-master) ahead of any packaging/release milestone or before the CSV Integration epic's higher-volume scenarios are trusted. |
| 1 (continued) | 2026-09-14 | "Configure canvas dimensions in operator-friendly units" — all 4 tasks done, story meets DoD, marked Done. Added `EnvelopeRenderer.Desktop.Core.Design` (`CanvasUnit`, `CanvasUnitConverter`, `CanvasSettings`, `CanvasDimensionsEditor`, `TemplateLayoutDocument`) with 17 new xUnit tests covering conversion correctness and round-trip agreement (enter in one unit, switch units, switch back — no drift) for all three units. New `TemplateDesignerForm` (`EnvelopeRenderer.Desktop/Views`) opened via a new "Design Template..." button on `MainForm`, with Width/Height/Unit controls and a live points-equivalent label. **Verified against the actual built `.exe`, not just an in-process harness** (per the DoD's verification bullet and directly addressing the Sprint 1 retrospective's "thin GUI evidence" near-miss): launched the real `EnvelopeRenderer.Desktop.exe`, used Windows UI automation (SendKeys + mouse click, screenshotted before/after) to open the designer, confirmed the #10 envelope default (4.125 x 9.5 in, "(297 x 684 pt)"), switched the unit to Millimeters, and confirmed the displayed values updated to 104.775 x 241.300 while the canonical points label stayed unchanged at "(297 x 684 pt)" — exact round-trip agreement, screenshots captured. 128/128 tests passing (17 new). | Pull Batch 3, "Place and move text elements on the canvas" | None new. |
| 1 (continued) | 2026-09-14 | "Place and move text elements on the canvas" — all 5 tasks done, story meets DoD, marked Done. Added `EnvelopeRenderer.Desktop.Core.Design` model/logic (`TextElementLayout`, `RgbColor`, `CanvasViewTransform`, `CanvasElementEditor`; extended `TemplateLayoutDocument` with an `Elements` list and `NextZOrder()`) with 51 new xUnit tests — including fake-measurer-based hit-test/select/drag coverage so the tricky coordinate math is fully unit tested without needing real GDI or a WinForms host. New `TemplateCanvasControl` (WinForms `Control` subclass, GDI+ `OnPaint` + mouse handlers only — no other logic) renders the page and elements letterboxed to fit, and forwards mouse events into `CanvasElementEditor`. `TemplateDesignerForm` now hosts it with "Add Static Text"/"Add Dynamic Placeholder" buttons and a live selection-status label. **Verified against the actual built `.exe`**: launched the real app, added both a static and a dynamic placeholder element (visually distinct, cascaded so they don't overlap), selected the dynamic element by clicking it on the canvas (label updated to "Selected: {Column} at (39.7, 537.2) pt."), then dragged it via a real simulated mouse-down/move/up sequence to a new position — canvas visual and the selection label's reported coordinates agreed exactly at the new position ("(128.2, 205.2) pt."), with the other (unselected) element staying put. Screenshots captured at each step. One real friction point self-reported: the first click attempt at an eyeballed screen coordinate missed the (correctly hit-tested, unit-tested) tiny scaled-down text bounding box and deselected instead — not a product bug, but confirms small text elements have a narrow click target at typical canvas zoom, which the properties panel (Batch 4) will help mitigate by not requiring re-clicking small text to edit position numerically. 216/216 tests passing (51 new). | Pull Batch 4, "Edit selected text properties in a properties panel" | Known, accepted gap carried forward per `TextElementLayout`'s own doc comment: `Color` is modeled and will round-trip through save/reopen (Batch 5), but `DebenuPdfRenderer` does not yet apply it to actual rendered PDF output (text is always black at render time) — not silently implemented, tracked as a real gap consistent with Sprint 1's "font must be stored" precedent for properties not yet wired into rendering. |
| 1 (continued) | 2026-09-14 | "Edit selected text properties in a properties panel" — all 4 tasks done, story meets DoD, marked Done. Added `TextElementPropertiesEditor` and `ZOrderRule` in `EnvelopeRenderer.Desktop.Core.Design` with 21 new xUnit tests (per-property update, blank/non-positive-value rejection, z-order clamping to 0, no-selection no-ops, and correct-element-targeting after switching selection). `TemplateDesignerForm` now has a right-hand properties panel (X, Y, font family, font size, a color swatch button + `ColorDialog`, z-order) enabled only when an element is selected, live two-way bound to the canvas via `NotifyElementChanged`. Hit a real, self-caught layout bug mid-task: a `TableLayoutPanel`-based first attempt at the panel rendered a numeric input directly under the "Color" row while its own label ("Z-order (0 = bottom):") appeared far below with no input next to it — not a data/logic bug (the underlying editor's 21 tests already passed), purely a WinForms auto-sizing/cell-layout quirk; fixed by switching to a plain `Panel` with explicit absolute control positions per row, which is simpler and fully predictable for this fixed 6-row form. **Verified against the actual built `.exe`** after the fix: added a static element, confirmed the panel auto-populated (X 29.70, Y 547.20, Arial, 12.0pt, black, z-order 0), then edited X to 150 and font size to 28pt directly in the panel — the canvas visibly moved the text right and rendered it noticeably larger, and the toolbar's selection label updated to "(150, 547.2) pt.", confirming live two-way sync end-to-end. 153/153 tests passing (21 new). | Pull Batch 5, "Save and reopen text-only XML templates" | None new (the `TableLayoutPanel` layout quirk was caught and fixed within this same batch, not carried forward as debt). Color still does not feed into actual PDF rendering — same known, tracked gap as Batch 3, unchanged. |
| 1 (continued) | 2026-09-14 | "Save and reopen text-only XML templates" — all 5 tasks done, story meets DoD, marked Done. **This was the last committed batch of Sprint 2.** Confirmed the text-only template XML schema as a strict superset of the render-time format `TemplateXmlParser` already reads (`TEMPLATE_FORMAT.md`): same root element and `` attributes (`x`, `y`, `font`, `size`, inline text vs. `column`), plus three designer-only attributes the CLI simply ignores (`canvasUnit` on the root; `color` and `zOrder` per ``). Added `TemplateLayoutXmlSerializer` (`EnvelopeRenderer.Desktop.Core.Design`) with `Save`/`TryLoad`, reimplementing its own small XML parser rather than referencing the CLI's internals (matching the existing process-boundary convention) — 12 new xUnit tests covering exact round-trip of canvas settings and every element property, missing-file/malformed-XML/wrong-root-element/missing-required-attribute/mixed-column-and-text/invalid-color error cases (all returning a clear error list, never an unhandled exception), backward compatibility with Sprint 1's plain render-time template shape (no designer attributes — loads fine with sensible defaults: `Points` unit, black, sequential z-order), and negative-z-order clamping consistent with the Batch 4 properties-panel rule. `TemplateDesignerForm` gained "Save Template..."/"Open Template..." buttons (mnemonics `Alt+S`/`Alt+O`) using standard `SaveFileDialog`/`OpenFileDialog`, a green/red status line, and (on successful open) a full in-place reset of the document's canvas settings, element list, dimension controls, and canvas selection. **Verified against the actual built `.exe`** in three real scenarios: (1) added a static + dynamic element and saved to a real file — green "Saved to '...'" confirmation, inspected the actual XML on disk and confirmed both elements' full attribute sets; (2) attempted to open a deliberately malformed XML file — got the exact clear operator-facing error dialog "Could Not Open Template: Template is not valid XML: Data at the root level is invalid. Line 1, position 1.", with the in-progress (unsaved) canvas state left untouched by the failed attempt; (3) reopened the file saved in (1) into a fresh designer instance — canvas dimensions (4.125 x 9.5 in / 297x684pt), both elements, and their exact positions were restored pixel-for-point identical to what was saved, with selection correctly cleared. As a bonus cross-check (not required by this story's AC but directly validates the schema-compatibility design decision), ran the actual saved template through the real CLI (`EnvelopeRenderer.Cli.exe`, real license key, a tiny CSV with a matching "Column" header): exit `0`, valid `%PDF-1.4` output — confirming a designer-saved file is a real, renderable template, not a separate format. One self-caught process note (not a product defect): early GUI-automation attempts that reused a single already-running process across multiple separate script invocations produced confusing, inconsistent focus/mnemonic behavior (e.g. `Alt+O` appearing to trigger the Save dialog); switching to one clean script per end-to-end scenario (launch-to-finish in a single script) resolved it immediately and all three scenarios above are from clean, single-script runs. 195/195 tests passing (12 new). | Sprint 2's committed backlog is now fully Done. Stretch item ("Load CSV headers and sample rows into the desktop app") intentionally not pulled — hand off to Sprint Review (`product-owner` leads, `process/04_sprint_review.md`). | Carried into Sprint 3 planning: the high-volume render throughput gap (`code/BENCHMARK.md`, `logs/technical_debt_log.md`) is a real, high-impact, not-yet-fixed risk — recommend `product-owner`/`scrum-master` prioritize the new "Investigate and address high-volume render throughput degradation" story (`backlog/epics/05_cli_rendering_engine_and_debenu_integration.md`) early. The `color` property is modeled/persisted end-to-end through the designer and XML but still does not affect actual rendered PDF output (`DebenuPdfRenderer` always fills black) — tracked, not silently implemented, candidate for a future rendering-integration story once epic 2's remaining stories (image/shape tooling) are in scope. |
## Execution Order
Sequenced by dependency; the benchmark is pulled first per the retrospective action item even though it sits later in the backlog's epic order, since it has no dependency on anything else this sprint and was explicitly flagged as overdue.
| Batch | Story | Why it's gated here |
|---|---|---|
| 1 | Time-box the first high-volume benchmark | No dependency on any other Sprint 2 story; uses the already-built Sprint 1 render path. Pulled first so it stops sliding, per the retrospective action item. |
| 2 | Configure canvas dimensions in operator-friendly units | Foundational: establishes the canvas surface and its persisted settings that later batches build on. |
| 3 | Place and move text elements on the canvas | Needs a canvas surface (Batch 2) to place elements onto. |
| 4 | Edit selected text properties in a properties panel | Needs elements to exist (Batch 3) before their properties can be edited. |
| 5 | Save and reopen text-only XML templates | Needs canvas settings, elements, and properties (Batches 2-4) to have a complete layout worth saving and round-tripping. |
| Stretch | Load CSV headers and sample rows into the desktop app | No dependency on Batches 1-5; pull only if capacity remains after Batch 5. |
**Today's pull:** All 5 committed batches are Done. Stretch item ("Load CSV headers and sample rows into the desktop app") not pulled — see the final Daily Scrum Log row for rationale.
## Sprint Review Outcome (2026-09-18, `product-owner` per `process/04_sprint_review.md`)
**Sprint goal: met.** An operator can now open the desktop app's template designer, set canvas dimensions in inches/mm/points, add and drag-position static and dynamic text elements, edit their properties (position, font, color, z-order) from a live-synced panel, and save/reopen the resulting layout as a real XML template — all verified against the actual built `.exe`, not an in-process harness, directly answering the Sprint 1 retrospective's "thin GUI evidence" finding with real multi-scenario click-throughs and screenshots at every batch. The benchmark spike also delivered exactly what a spike should: real, unambiguous information, even though the news is bad (see below). Neither tempers the "met" verdict on this sprint's own committed scope, but the benchmark finding is a serious standalone product risk that must shape Sprint 3 planning.
**Per-story verification verdicts:**
| Story | Verdict | Notes |
|---|---|---|
| Time-box the first high-volume benchmark | Met (story), Failed (product metric) | All 4 ACs met — the spike produced a real, well-documented, root-caused answer. The metric it measured (100k/10-min render target) is currently missed by 5x-10x+. Treated as a successful spike surfacing a real risk early, not a failed story — see `code/BENCHMARK.md` and the new follow-up story in `epics/05`. |
| Configure canvas dimensions in operator-friendly units | Met | All 4 ACs met; live-verified against the built `.exe` plus 17 unit tests. Minor evidence gap: custom width/height entry shown only via unit tests, not a live screenshot — not worth reopening. |
| Place and move text elements on the canvas | Met | All 4 ACs met and strongly demonstrated live (add, select, drag, cross-verified via the later save/reopen round-trip). One honestly self-reported UX friction point (small-element click target) — not a blocker, candidate for future polish. |
| Edit selected text properties in a properties panel | Met | All 4 ACs met. Live demo covered X/font-size edits; color/z-order edits are covered by unit tests and the save/reopen round-trip rather than a live screenshot — accepted at the same evidence bar Sprint 1 used for its own thinner GUI story. |
| Save and reopen text-only XML templates | Met | All 4 ACs met with the strongest evidence of the sprint: three full real-artifact scenarios (save, invalid-open, round-trip-reopen) plus a bonus cross-check that a designer-saved file renders through the real CLI. This is the direct, concrete answer to the Sprint 1 retrospective's DoD gap. |
**Demonstration evidence assessment:** A clear, sprint-over-sprint improvement on the exact weakness named in the Sprint 1 retrospective — every GUI-facing story now has live, screenshotted, actual-`.exe` evidence (add/select/drag, unit switching, panel edits, save/open/round-trip/invalid-XML) rather than prose-only description. The two "minor evidence gap" notes above (custom dimension entry, color/z-order live edits) are real but small, and are backed by solid unit-test coverage rather than left unverified — not worth reopening for this sprint's surface area, but worth keeping in mind if either area sees a defect later.
**Material finding requiring Sprint 3 attention:** the high-volume render benchmark (`code/BENCHMARK.md`) found throughput degrading from ~399 rec/s to ~15 rec/s and still falling at realistic scale, projecting 45-90+ minutes for a full 100k-record run against a 10-minute target — most likely a Debenu Quick PDF Library 10.13 characteristic, not this repo's own code (ruled out by inspection). This is now the single highest-priority known risk in the product: it directly threatens a hard constraint in `project_config.md` and compounds at the stated 1,000,000-record ceiling. Logged as a new Ready (not yet sized) story in `backlog/epics/05_cli_rendering_engine_and_debenu_integration.md` and a High-impact entry in `logs/technical_debt_log.md`. Recommend Sprint 3 planning prioritize it at or near the top, ahead of or alongside CSV Integration.
**Backlog changes made at this review:** see `backlog/backlog.md` ("Sprint 2 Review outcome") and `backlog/epics/02_template_designer_gui_foundation.md` / `backlog/epics/05_cli_rendering_engine_and_debenu_integration.md` for full detail: all 4 Template Designer GUI stories and the benchmark story marked Done with verification notes; the throughput-degradation story (already added by dev-team during the spike) confirmed and prioritized for Sprint 3.
**Carried into retrospective:** two candidate signals for `scrum-master` to weigh — (1) the GUI verification quality improved concretely and consistently this sprint, directly closing last sprint's named gap, worth naming as a strength to keep; (2) a real, high-impact product risk (render throughput) surfaced via a spike that almost didn't get pulled on schedule twice in a row (flagged at Sprint 1 review, nearly slid again) — worth discussing whether spike-type stories need a firmer scheduling guarantee going forward.