Skip to main content

ADR-0001: Split the sprint reconciliation log from the sprint plan

  • Status: accepted (2026-07-14)
  • Deciders: TPM (CDP), with the change applied repo-wide to the sprint-layer doctrine
  • Scope: repo-wide sprint-doc shape (doctrine lives in .claude/reference/sprint-layer.md / sprint-resync.md); CDP Sprint 1 is the reference migration.

Context

sprint-resync was specified to append a dated ## Jira reconciliation — recheck (<date>) section to the sprint doc on every pass, with each pass re-narrating every prior finding (STILL OPEN prose). At the observed cadence this destroyed the sprint doc as a dev-facing source of truth: by 2026-07-14, cdp/delivery/sprints/2026-07-07-sprint-01.md was 855 lines, ~590 of them (69%) six appended reconciliation passes written over 7 days — the actual plan (envelope, initiative index, per-engineer queues, deviations, blockers) was the first ~255 lines. Growth was superlinear (every pass restates all prior open findings), and at the intended daily-ish cadence a sprint would close carrying ~12 passes with the plan under 15% of its own file. The bloat had also leaked into the sprint_goal frontmatter (a 6-line amendment narrative), violating the doctrine's own "sprint_goal stays fixed" rule.

The append-forever shape also contradicted the layer's first principle — "a sprint is a render + an envelope, never a fourth source of truth" — by making the sprint file the de facto system of record for drift history.

Decision

Split state from log (the snapshot + event-stream pattern):

  1. One immutable dated file per reconciliation pass at <team>/delivery/reconciliations/<sprint-basename>/<YYYY-MM-DD>-pass-NN.md (frontmatter title + status + type: Sprint Reconciliation; latest pass status: active, prior passes flipped to archived — the same latest-=-truth convention as delivery/status/<date>.md). Full narrative, engine output, and the per-pass downstream propagation worklist live there.
  2. The sprint doc keeps a single ## Jira reconciliation — findings ledger (<date>) section, rewritten in place each pass: a numbered list of currently-open findings with stable F-<n> ids (never reused), each row carrying type, STILL OPEN (<n>th pass) / ⛔ ESCALATED marker, owner, routed home, and its origin pass link — plus a bounded bulleted "Resolved" list linking each closing pass. No re-narration; resolution detail lives in the pass files.
  3. sprint_goal stays fixed. Mid-window absorptions are recorded in ## Deviations from roadmap priority (or the Expedite render), never appended to the goal.

Compatibility with the pinned linter (why no upstream change is required)

lint-delivery.mjs CHECK GROUP K (pinned SYSTEM_REF 8837118) scans the last ## Jira reconciliation…-headed section of an active sprint doc and counts numbered-list items marked STILL OPEN/STILL PRESENT or . The ledger deliberately keeps that contract — heading prefix ## Jira reconciliation — findings ledger (<date>), numbered-list rows, the same markers — so JIRA_RECONCILE_OPEN / JIRA_RECONCILE_ESCALATED keep firing unchanged. The pass files live outside sprints/ (in delivery/reconciliations/) because the delivery model's sprint collection (teamSprintswalkMarkdown) is recursive — anything under sprints/ is parsed as a Sprint Plan (verified: it fired SPRINT_GOAL_MISSING on a trial in-sprints/ layout). In reconciliations/ they lint as plain delivery docs (title + status).

Consequences

  • Dev-facing sprint doc stays bounded (~plan size + ~1 ledger line per open finding) regardless of reconciliation cadence; auditors read exactly the pass they care about.
  • sprint-layer.md, sprint-resync.md §1/§5, the sprint-resync skill, and templates/delivery-sprint-template.md updated to the ledger + pass-file shape (this repo is the authority for all four — repo-local extension, to be upstreamed to AI-SDLC with the rest of the sprint layer).
  • Migration: CDP Sprint 1 migrated 2026-07-14 (six passes → reconciliations/, ledger F-1…F-9 seeded from the pass-6 carry-forward; historical pass files keep their per-pass finding numbering, cited as p<pass>#<n>). Bifrost 2026-07-06-sprint-01.md and chatbot 2026-07-13-sprint-01.md migrated the same day, same method. Any future legacy sprint doc migrates on its next sprint-resync pass (the skill instructs this).
  • Optional future upstream improvement (not required): CHECK GROUP K could learn the reconciliations/ directory explicitly; if that lands, bump SYSTEM_REF and append to .claude/reference/system-ref-history.md per the usual provenance rule.

References (pattern precedent)

  • Martin Fowler, Event Sourcing — append-only event log kept separate from a compact current-state projection/snapshot.
  • Michael Nygard, Documenting Architecture Decisions (ADR / MADR) — immutable dated records + a lightweight current index; already this repo's delivery/decisions/ convention.
  • Atlassian Atlas / Jira Align status updates — stable project brief, separate dated update stream; already this repo's delivery/status/<date>.md convention. Sprints were the one delivery artifact not following it.
  • Kubernetes KEPs — the proposal document is the spec; per-release status tracking lives outside it.