Files
atomic-design-poc/docs/project/refactor-backlog-setup/refactor-backlog/_status.md
T
ehoandClaude Opus 5 25a5d415a5 docs(adr): land ADR-C-001, ADR-C-003, ADR-C-007 and ADR-C-009
The architect approved the four ADR-fix tickets. All four change what the
architecture documents claim. No code changes.

ADR-0001, ADR-C-001: the worked example claimed the POC has no real backend.
It rewrites against `backend/src/BigRegister.Api`. Every path it named is
repointed. The out-of-scope list drops two discharged bullets: 33 `parse*`
boundaries exist, and `npm run gen:api` is real.

ADR-0001, ADR-C-003: a new section states that the generated client is the wire
contract. A hand-written `contracts/*.dto.ts` is the exception for two cases
only. The four survivors stay, because NSwag emits every property as optional
and flattens `RegistrationStatusDto` into five optional strings. The `parse*`
trust boundary stays mandatory, because a generated type is a compile-time
claim about the wire and not a runtime guarantee.

ADR-0003, ADR-C-007: four paths moved in WP-67 and are repointed. Point 4 kept
the principle and changed its example to `skeleton` and `spinner`. Two of its
claims were false and the amendment says so: `app-alert` wraps the vendored
`.feedback` classes, and `site-header` composes the vendored `.titlebar`.

ADR-0004, ADR-C-009: the exception section states a four-part test instead of
one named exception. `OrgTemplateStore` and `FeatureFlagStore` both pass it. RB-07
gated this ticket, because clause 4 needs an audited allow path. RB-07 landed
that, so the ADR does not ratify a control that the code lacks.

Three tickets need a matching CLAUDE.md correction in the same diff. CLAUDE.md
section 2 loses the false `alert` example. Section 4 gets the generated-client
rule and the four-part test.

Two findings were wrong. ADR-C-001 asked to keep an out-of-scope bullet that
reads "SessionStore is in-memory". The session persists to `localStorage` now,
so the bullet covers multi-tab sync only. ADR-C-007 flagged one half of point 4
and missed that the other half is equally false.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 18:29:05 +02:00

28 KiB

Agent run status

Agent Status Last module processed Last updated Notes
baseline complete all (18 FE + 7 BE modules) 2026-08-26 0 layering violations. 11 observations BL-001..BL-011. Thresholds for Phase 1 in §9 — agent 01's [N] lines = 40 (TS fn) / 60 (C# method) / 400 (file). Read BL-001, BL-002 and BL-004 before filing complexity, duplication or coverage findings.
readability skipped n/a 2026-08-27 skipped — deliberate. BL-001: 23 of the 25 TS functions over CC 10 are reducers / parse* boundaries / validate*, all mandated house idioms; TS fn-length p99 is 34 with only 2 functions over 75 lines. Little left for this agent to find that is not a false positive. Revisit if the CC>10 population grows outside those three shapes.
testability complete all 24 modules 2026-08-26 9 findings TE-001..TE-009; 15 modules explicit "no findings". Corrected BL-004 — libs/shared/domain and libs/beheer/contracts are pure type declarations, 0% is unimprovable (amendment note in 00-baseline.md §10). TE-009 is also a latent correctness bug (dead ActiveOn branches). Acquitted createDraftSync, httpClientFetch, Contracts/Mappers.cs in writing.
ddd-hexagonal skipped n/a 2026-08-27 skipped — deliberate. FE layering is clean (baseline §6: 0 violations, healthy instability gradient, kernel I=5% vs contexts I>=83%); backend Domain/ is verified EF/ASP-free. The agent may only extend existing hexagonal structure, and the one real target (Program.cs) has no Features/ folder to extend — agent 04 already filed that as out-of-mandate OOM-A.
cqrs-light complete all (16 FE + 6 BE modules) 2026-08-26 7 findings CQ-001..CQ-007; 12 modules clean. Corrected BL-007 (see the amendment note in 00-baseline.md §10) and found 3 mutations the baseline missed. Program.csFeatures/+handlers filed as out-of-mandate OOM-A, not a ticket; CQ-006 is its prerequisite. bhp/behandeling named the reference implementation — do not "clean it up".
bdd skipped n/a 2026-08-27 skipped — deliberate. No BDD tooling present, and the prompt forbids proposing any; it self-reduces to a single structural note. gen:behaviour-spec already extracts behaviours from spec names into libs/shared/docs/behaviour-spec.mdx, which covers the intent.
adr-conformance complete all 6 ADRs 2026-08-26 11 findings: 6 code, 5 ADR-fix (architect approval required). Sharpened BL-002 — Principal was never built, so ADR-0002 was untested not falsified (amendment note in 00-baseline.md §10). ADR-0005 fully conformed. Gates: ADR-C-005→ADR-C-004; ADR-C-003 gates contracts/ cleanup. 3 ADR-fixes need a matching CLAUDE.md correction in the same diff.
bio2-compliance complete all modules + 7 control areas 2026-08-27 20 findings BIO-001..BIO-020 (12 defect now, 8 production gate). High: BIO-008 BSN concatenated into the authz audit Resource (Program.cs:674, verified); BIO-004 GET /uploads/{documentId}/content has no authz at all (verified). Answered agent 06's handoff as BIO-002 — a production behandelportal build resolves to the seeded zorgverlener, failing closed on backoffice caps but open on citizen-scoped ones incl. CanRevealBigNummer. Carries the mandatory "compliance review required" list: 16 rows over agents 02/04/06. Also a pre-production checklist (~25 boxes).
consolidation complete (approved) all inputs 2026-08-27 HALTED for human approval (per spec) — 99-backlog.md written, nothing implemented. 33 open tickets RB-01..RB-33 + 5 ADR-fixes + 5 already-shipped, from 47 findings. RB-01 (no authz on upload content) and RB-02 (BSN in the audit Resource) sort above all structural work. Gate relaxed to the 4 agents that ran; a "Coverage of this backlog" note records what the 3 skips leave unowned. Caught two orchestrator errors: CQ-002 is NOT fixed (verified — ApplicationsStore.cancel/AdminCasesStore.delete still swallow errors → RB-20), and CQ-004 shipped with half its compliance criterion unmet (no audit row on PUT /admin/flags/{key}, verified → RB-07, which blocks signing ADR-C-009). OOM-D: re-run the baseline before using it to verify any ticket — ADR-C-006 and BL-008 moved it. Approved 2026-08-27; HALT lifted.

Phase 3 — implementation

CD batch Tickets Status Notes
1 RB-01, RB-02, RB-03, RB-04, RB-05, RB-06 complete Six commits on refactor/adr-c-006-shared-route-guards, one per ticket, each with implementation/rb-0N.md. npm run ci green. Every ticket left a test that was verified red without its fix. Carryover: RB-01's residual belongs to RB-09 (the content endpoint is reached by a plain browser navigation with no identity header — BIO-002); Pii.MaskTail now lives in Domain/People/Pii.cs, use it in RB-11 rather than hand-rolling a second masker; RB-06 additionally deleted SubmissionRules.RejectRegistratie (judgement call, recorded).
2 RB-07, RB-08, RB-09, RB-10, RB-11 complete All five merged; npm run ci green on the fixed gate (see below). RB-07 unblocks signing ADR-C-009 and closes CQ-004's outstanding half. RB-09 makes Production throw at startup when no real IIdentityProvider exists — note an environment that is neither Development nor Production (e.g. Staging) still fails fast, but at GetRequiredService, with a worse message. RB-10 landed parseStoredSession twice, once per app, deliberately — TE-001/BL-002 say extract-to-shared contradicts ADR-0002; RB-13 differentiates them. RB-11 corrected a factual error in BIO-012 (the proefbrief error mapping was inlined, not already a separate function) and left the step-up as a literal moved one layer up to its only caller — BIO-006(c) stays a production gate. RB-01's residual is still open and is not solved by RB-09: the upload-content link is a plain browser navigation with no credential.
3 RB-12, RB-13, RB-14, RB-15, RB-16, RB-17 complete All six merged; npm run ci green (14 steps — RB-14 added one — backend 260/260). RB-12 rejected the ticket's binary framing: of 47 routes only 16 use one of the five admin wrappers; of the remaining 31 only 10 are genuinely public, the other 21 are ownership-scoped inline (ctx.Zorgverlener()/ctx.Caller()) or use another mechanism. The allow-list therefore carries a reason per route, not a blanket "public" label. Known limitation: detection is .Gate("XAdmin") metadata declared at mapping time — a declaration, not a derivation, so it cannot catch a route that declares a gate it does not have. This is RB-19's safety net; read rb-12.md before starting RB-19. RB-13 measured ssp/authbhp/auth duplication at 32 lines each side, down from 168 (backlog expected <40); each app holds only its own Principal variant, which is ADR-C-004's own proposed resolution, and ADR-0002's "Known debt" section became an amendment. RB-14 could not be built as written — dotnet list package --vulnerable exits 0 on a High advisory (verified), so a bare - run: would have been a gate that enforces nothing; scripts/dotnet-audit.sh matches the output instead and is shared by ci.yml and ci-local.sh. RB-15 used a third environment name (Staging) in its test, since RB-09 makes Production fail to boot at all.
4 RB-18..RB-23 in progress Split into three waves to keep the merge order honest, because three of the six tickets touch Program.cs. Wave A (dispatched, parallel): RB-18, RB-20, RB-21, RB-22 — no file overlap between them. Wave B: RB-23, which must merge after RB-22 (expand/contract pair: the FE must tolerate the 404 before the BE returns it). Wave C: RB-19 alone and last — it is the only High-risk ticket, it reorders all 48 endpoints in Program.cs, and landing it last means it reorders the final content instead of conflicting with RB-18's and RB-23's edits to the same file. RB-19 also needs RB-12's route-table test as its safety net; read rb-12.md first, including its stated limitation that detection is a declaration, not a derivation.
5 RB-24..RB-30 not started RB-25/26/27 all depend on RB-24.
6 RB-31, RB-32, RB-33 not started
ADR-fix ADR-C-001, ADR-C-003, ADR-C-007, ADR-C-009 complete All four signed and landed by the architect on 2026-08-27, in one commit; doc-only, no code touched. Three carried the mandatory matching CLAUDE.md edit in the same diff (§4 twice, §2 once). ADR-C-009's RB-07 gate was satisfied first — all four clauses of its new test were verified against both OrgTemplateStore and FeatureFlagStore before signing, so the ADR does not ratify a control the code lacks. Two findings were wrong and are corrected in the notes: ADR-C-001 told us to keep an out-of-scope bullet reading "SessionStore is in-memory", which RB-10/RB-13 made false (the session now persists to localStorage; only multi-tab sync is still open), and ADR-C-007 flagged only the .alert half of ADR-0003's point 4 — its "header/side-nav use .nav + a local blue bar" clause is equally false (site-header composes the vendored .titlebar/.logo__*). ADR-C-007 also over-listed one path: public/cibg-huisstijl/ never moved. ADR-C-003's open question was decided explicitly — the 4 hand-written contracts/*.dto.ts stay, because NSwag emits every property optional and flattens RegistrationStatusDto into five optional strings, which would make an illegal state representable (CLAUDE.md §3). Gates released: ADR-C-003 (contracts cleanup) and ADR-C-009 (a third runtime-editable surface). Still pending, untouched: ADR-C-008 → RB-32 — 9 CIBG-GAP markers vs 8 register rows, missing row is language-switcher.

Standing caveat for every batch: dotnet test reports one failure, OpenZaakIntegrationTests.Admin_cases_returns_the_seeded_zaak_mapped_through_real_HTTP_and_JWT, which needs a live OpenZaak container. It fails identically on a stashed tree — it is not caused by any of these tickets. npm run ci does not run it.

Gate integrity — read before trusting any "ci green" in this file

scripts/ci-local.sh chained six of its steps as cmd1 && cmd2 under set -e. Bash exempts every command of an AND-OR list except the last from errexit, so a crash in cmd1 was swallowed: the paired check never ran and the script still printed "local CI passed". Verified directly — bash -c 'set -e; false && true; echo hi' prints hi and exits 0.

This hid a real gen:api crash introduced by RB-09 (dotnet swagger's design-time host defaults to Production, which RB-09 made throw). .github/workflows/ci.yml runs each step as its own - run: and would have caught it, so the local gate was strictly weaker than the remote one — the opposite of its purpose. The worst instance was ng build ssp --localize && ng build behandelportal --localize: a missing English translation in ssp could not fail the run.

Fixed in build: stop ci-local.sh swallowing the first half of every paired step. Every "ci green" recorded for batch 1 and for RB-07/RB-10/RB-11 predates that fix and is therefore weaker than it reads; the batch-2 completion run above is the first one made on the honest gate (13/13 steps, exit 0). Nothing has since been found wrong with batch 1, but it has not been re-verified under the fixed gate either.

Dispatching implementation agents — what actually goes wrong

Batches 2 and 3 ran tickets as parallel agents in git worktrees. Six of seven agent-runs hit at least one of these. Put all of it in the prompt.

  1. The worktree base is not reliable. Four of the six agents were handed a worktree branched from a stale ancestor — batch 3 was three for three, all landing on ae7781e, an unrelated lineage missing every RB ticket and this backlog directory. Make step zero: git log --oneline -8, confirm a named expected commit, git merge the target branch if absent, and report which it was. The one agent that was not told to do this found out by luck.
  2. Agents park on background tasks. Two agents in batch 2 ran npm run ci in the background, then ended their turn waiting for a notification that never usefully arrived; one finished its work twice and never committed it. Ban run_in_background and Monitor, and say explicitly to pass the Bash tool's own timeout: 600000 — a batch-3 agent still auto-backgrounded because "run it in the foreground" alone does not defeat the 120s default.
  3. git checkout <file> destroys the work. Agents verify a test is red by undoing the fix; restoring it with git checkout reverts the whole file. Tell them to undo and redo with edits.
  4. behaviour-spec.mdx conflicts on nearly every merge. It is generated and every agent regenerates it. Resolve centrally with npm run gen:behaviour-spec && git add; tell agents to expect it and never hand-edit.
  5. Concurrent dotnet test runs flake — a burst of SQLite Error 1: 'no such table: Documents'. Partly host pressure, but RB-12 found a real cause: a bare new WebApplicationFactory<Program>() races on the static Db.ConnectionString. Use the house TestWebApplicationFactory + IClassFixture idiom. Do not trust a backend green while another agent is testing.
  6. Agent worktrees live inside the repo, so prettier --check . walks into them — fixed by ignoring .claude/worktrees/ in both .prettierignore and .gitignore.

Telling agents to report a ticket as wrong pays off. Three did: BIO-012 was factually wrong about the proefbrief error mapping (RB-11), RB-12's wrapper/public binary did not fit the code, and RB-14 as worded would have shipped a non-gate. None of the three would have been caught by a review of the diff alone.