RD-22 and RD-23 brought the wizard containers under the 250-line budget, so `max-lines` reports nothing. The files still read badly. Line count was never the problem. Fix three things in all three containers: 1. The member order was scrambled, and it differed per file. `registratie` declared `draftSync` in the middle of a run of `computed`s; `herregistratie` read `this.stepLabels.length` seven lines before `stepLabels` existed; the three files put the copy arrays in three different places. All three now use one nine-section order, so they compare side by side. 2. Pure logic sat in the container. Extract `digitalDocumentIds` into `upload.machine.ts` — the "digital and finished uploading" filter was written out four times, and it removes a `documentId!` assertion from both containers. Extract `diplomaMsg` into a sibling of the step files. 3. Comments carried archaeology. Drop the three RD-05 references and keep the rule. Drop "replaces sessionStorage" and the note about focus management that moved to the shell. Fix `intake`'s class comment, which claimed answers persist to sessionStorage and was contradicted 30 lines below. `phase` deliberately stays in all three: it cannot live in `domain/`, and three siblings plus three specs is a worse trade than 17 readable lines. The store ⇄ `draftSync` cycle also stays — both callbacks are deferred, so it is safe, and one comment now names it. No behaviour change. Member lists and every `private`/`protected`/`readonly` modifier are unchanged, which the showcase depends on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.8 KiB
RD-38 — One member order for the three wizard containers
Status: done Source: user report — "the registratie-wizard component still doesn't look readable"
Why
RD-22 and RD-23 split the intake and registratie wizards into step components. That brought
every container under the 250-line budget, so max-lines reports nothing. The user read the
result and still called it unreadable. Line count was never the problem.
Three problems remained, and the user named all three:
- The member order is scrambled, and it differs per file. You bounce up and down to follow one thread, and the three containers cannot be compared side by side.
- Pure logic sits in the container, where it has no test.
- Comments carry archaeology — ticket numbers, history, and one comment that describes code which is no longer in the file.
RD-02 measures a file. This ticket is about what a file reads like at a fixed size.
Evidence, before the change
registratiedeclaredstepLabels/stepTitlesbetween theseedinput andstate/dispatch;intakedeclared them near the bottom;herregistratiedeclared them afterdraftSync. Three files, three orders for the same three roles.registratiedeclareddraftSyncin the middle of a run ofcomputeds.herregistratie'ssnapshotreadthis.stepLabels.lengthseven lines beforestepLabelswas declared.intake's class comment claimed answers persist tosessionStorage. Thirty lines below, another comment said draft-sync replaced it. The class comment was false.- All three cited "RD-05's tag-transition rule" in an identical sentence.
Decisions (pre-made, don't relitigate)
-
One nine-section member order, identical in all three files. Injected stores → inputs → the store (
createStore,state,dispatch) → static copy → state projections → controllers → shell wiring → event handlers → constructor andrestart. Each section carries a// --- <name> ---header. Section 7's header already existed in all three files, so it is reused byte for byte. -
The store ⇄
draftSynccycle stays. The store's effect map callsthis.draftSync, anddraftSync'ssnapshotcallsthis.state(). Both are arrow functions that run after construction, so there is no temporal-dead-zone hazard; the cycle cannot be removed by reordering. One comment at the effect map names it. -
Extract
digitalDocumentIdsintolibs/shared/src/domain/upload.machine.ts. The "digital and finished uploading" filter was written out four times, in two shapes: mapped to ids in the two container snapshots, and as.some(...)inside two machines'hasProgress. One function serves all four, and it removes ther.documentId!non-null assertion from both containers. It joins an existing file besidedeliveryRefs, and its spec joins the existingdeliveryRefsblock. -
Extract
diplomaMsginto a new sibling of the step files.onDiplomaKeuzewas the fattest member in the three containers and had no test. It is pure: aDuoLookupDtoand a selected id in, a machine message ornullout.HANDMATIGdoes not move — the new file is its sibling and imports it exactly as the container did. -
phasestays in all three containers. It maps this machine's tags onto the shell'sWizardPhasevocabulary and composes a$localizefailure message. That is a container's job. It cannot move todomain/:WizardPhasecomes from an Angular component, anddomain/points inward only. Moving it to a per-wizard sibling would add three files and three specs to relocate 17 readable lines each. Decision 1 already fixes what was wrong with it — it belongs in the shell-wiring section, and only two of three files had it there. -
The four
err*computeds inherregistratiestay. They are one-line projections feeding four template bindings. Folding them into oneerrors()would edit the template, which is behaviour-shaped work this ticket does not do. -
Comment policy, four rules. Delete ticket references and keep the sentence (RD-18 decision 1 stripped
WP-/RB-for the same reason;RD-is the same debt). Delete history — a comment says what the code does now. Delete a comment that describes code which is not in the file. Keep a comment that states a current why: theuntrackedloop-avoidance notes, theIntakePolicy.RejectIncompleteScholingseam pointer, and thedemo-*preview note all stay.
Traps
messages.en.xlf. Every$localizeid in these files is translated. The reorder moves the copy arrays; it must not touch an id or its source text.enabled: () => this.seed() === initialis a reference-identity check against the exportedinitialsingleton. Never clone or rebuild it — breaking the identity turns draft-sync on inside Storybook and the tests.- Public members are load-bearing.
showcase/vragenlijst.section.tsreadsIntakeWizardComponent.steps;showcase/form-machine.section.tsreadsHerregistratieWizardComponent.state. Noprivate/protected/readonlymodifier changes. intake.machine.tscarries#region showcase:stepsmarkers that feedgen:snippets. This ticket does not touch them.- New specs change a generated document.
scripts/ci-local.shregenerateslibs/shared/docs/behaviour-spec.mdxand diffs it. Four newit()titles land there, so the regenerated file belongs in the same commit.
Acceptance
npm run cipasses.- Each container's member list and every modifier are unchanged:
diff <(git show HEAD:$f | grep -oE '^ (private|protected|readonly)? ?[a-zA-Z]+ *[=(]' | sort) <(...)reports no difference for all three files. git grep -nE "\bRD-[0-9]+" -- 'apps/ssp/src/app/*/ui/*wizard*'returns nothing.git grep -n "sessionStorage" -- 'apps/ssp/src/app/herregistratie/ui'returns nothing.