portfolixir

ADR-0042: one planning structure — the requirement registry and the work breakdown stop competing

Context

Portfolixir carries two structures that both claim to organise the work, and has done since June:

The tension has been recorded as a finding at every reconciliation since 2026-07-25, most recently as F2 (2026-08-12) and F7 (2026-08-17), each time noting that the structural decision is the owner’s and still open. Recording it five times has not resolved it, and the drift is no longer theoretical.

What is measurably true as of 2026-08-17

The drift is therefore not a tidiness problem. A planning document that answers “what should I build next” with a gated story, and a tracking file that fails its own validator, are load-bearing artifacts giving wrong answers — and this project’s gates are load-bearing precisely because the owner does not read code.

Who reads what — the correction this ADR was rewritten around

The first version of this decision argued that the tracker set should own the work breakdown because the work is already there. The owner’s response (2026-08-17) disposed of that argument in one sentence: “I don’t look in there.”

That is not a preference to be accommodated, it is a fact that changes what the evidence above means. Parentage being live in the API says where an agent files things. It says nothing about authority, and the first version treated the two as the same claim.

The consequence is a process defect, not a labelling problem. ADR-0038’s feedback loop ends with “thin issues after owner confirmation” — issues being the terminal artifact of a loop whose point is to inform the owner, delivered into a channel the owner does not read. Four triage rounds have now run through it. Filing an issue is an act of agent bookkeeping and must stop being counted as an act of owner communication.

So the readership, stated plainly, because the rest of this decision follows from it:

Reader Reads
the owner ADRs (decisions needing sign-off); the sprint lane plan (what a batch will do); the reviewer briefing on the PR (what a batch did)
the agent everything, and the tracker set as its work ledger
third parties the public issue tracker — the only channel that can catch them

Why now

Sprint 7 cannot be planned cleanly on top of it. Every one of the thirteen candidate issues is a GitHub issue with no epics.md story row, so generating tracking would add nothing and leave the same wrong recommendation standing. The choice was going to be forced by the next batch regardless.

Options considered

A — Dissolve epics.md E1–E19 into the tracker set. Delete the Epic List and Epic Detail; the trackers become the only structure. Rejected: it throws away the Requirements Inventory and FR Coverage Map, which are the parts that demonstrably work — the FR map is what every reconciliation actually reads, and it is where the two-way coverage rule and the scope ladder are enforced. Deleting the epic sections is right; deleting the document is not.

A2 — Abolish issues for internal work; keep them only for external reports. Raised by the owner on the strength of not reading them. Rejected, but it supplies §2’s reasoning: the owner is right that issues are not an owner artifact, and wrong that this makes them disposable. Removing them costs the closing-keyword mechanism and the cross-reference surface while saving the owner nothing, since the saving would be in a channel they already ignore. The half of the proposal that survives — issues are the external intake channel — is adopted as one of the three reasons to keep them.

B — Dissolve the trackers into epics.md. Give all 40 open issues story rows. Rejected: it is large mechanical work whose output would immediately re-drift, because issues are filed on GitHub and would have to be mirrored by hand forever. It also inverts the issue convention: AGENTS.md says issues are thin pointers and the ADR/epics document is authoritative for specs — not that the document must restate the backlog.

C — Split the two jobs, and name the execution artifact. epics.md keeps the requirement registry; the tracker set owns the work breakdown; the sprint lane plan becomes a named, described artifact. Recommended — see below.

D — Keep both and keep recording the finding. Rejected: this is the status quo, and five recordings across seven weeks are sufficient evidence that it does not converge.

Decision

1. epics.md is the requirement registry, and stops being a work breakdown

It keeps — and remains authoritative for — the Requirements Inventory (FR/NFR/UX-DR), the FR Coverage Map, the scope ladder boundaries, and the dated Implementation Status reconciliations. These are the sections every review actually reads.

It loses the Epic Detail sections and the ##### Story rows. What is worth keeping from them — each epic’s intent paragraph — is condensed into a short tracker index that stays in epics.md, one line per epic: its name, its tracker issue where one exists, and its intent in a sentence.

The first draft moved those paragraphs into the tracker issue bodies instead. The agentic review of 2026-08-17 killed that, on two counts:

A tracker index inside the registry keeps the intent authoritative, gives the trackerless epics a home, and is still not a work breakdown — which is the thing this decision set out to remove.

2. The GitHub tracker set is the work ledger — an agent artifact, kept on its merits

A unit of work is an issue; its parent is a tracker. That is already true in the data and merely stops being contradicted. The issue convention is unchanged: thin pointers, with the spec in the ADR or in epics.md.

It is kept deliberately, and not because the owner reads it. Three things make it worth more than the in-repo alternative, none of which is owner-facing:

What it is not: a way to inform the owner. Issue numbers are agent addresses. Where the owner needs to know a thing, it goes in an ADR, the lane plan, the triage document or the briefing — never cited as an issue number and left there.

External reports get a route, or the channel terminates nowhere. Keeping the tracker as the public intake channel while the owner does not read it would reproduce exactly the defect diagnosed above. So: a third-party report is triaged by the agent into the next triage document or the next lane plan’s candidates — artifacts the owner does read. Without that step, “external intake” is a reason to keep a mailbox nobody opens.

Requirement-to-work traceability lives in one place — the FR Coverage Map’s issue column, which already carries it.

2a. The owner-facing artifacts are named, so they stop being inferred

Four, and the list is closed. The fourth was missing from this ADR’s second version, which closed the list at three while its own Consequences section described eight rounds of the owner using the fourth — the agentic review caught it:

The still-unanswered Round 7 proposal (a gate-closure rule for ADR-0026) is the lever on the first of these, and is deliberately left to the owner.

3. The sprint lane plan is the execution artifact

sprint-plan-<date>-sprint<N>.md gains recorded status: lanes, the issues in each, sequencing constraints, risk-tier markings, and the open questions the batch must answer. It is what Sprints 3–6 already used; this only makes it describable and reviewable.

4. sprint-status.yaml is retired as a story tracker

This is the honest cost of the decision and is stated rather than buried: bmad-sprint-planning’s generate path stops being applicable to this project, because it derives story rows from epics.md sections that will no longer exist.

What replaces each thing it provided:

Provided by the tracking file Replacement
story status GitHub issue state, verified against merge commits on main
epic status tracker issue state
the close-out / reconciliation log kept — this is the part with real value
next-action recommendation the sprint lane plan
retrospective-completion ledger kept in place — see below

The file is therefore not deleted, and — corrected by the agentic review of 2026-08-17 — its development_status block is not deleted either. The first draft of this ADR said it went, along with the five invalid keys. That would have broken three things this decision has no intention of breaking:

What actually goes: the ##### Story-derived rows — the five schema-invalid 6-dx-* / 6-c-1 keys and the story keys for E17/E18/E19. What stays: the epic-N and epic-N-retrospective keys, both recognized by the script’s own classify_key, both surviving validate. Neither is a story breakdown, which is what this decision set out to remove.

5. #321 closes

Its “working agreement” section is preserved first — the 2026-08-04 reconciliation requires only that it survive “somewhere”, and the origin note of 2026-07-31 offered AGENTS.md or the epics document as alternatives. Since this decision deletes the epic sections, AGENTS.md is the surviving destination; that is a consequence of this ADR, not a pre-existing condition, and the first draft overstated it as one. #321 is then closed by hand with the reason, not by a keyword — it is invalidated rather than implemented.

Consequences

What this does not decide