Files
atomic-design-poc/docs/project/refactor-backlog-setup/refactor-backlog/00-baseline.md
T
ehoandClaude Opus 5 664a43bf2d docs: refactoring-backlog workspace — baseline + 3 Phase 1 agents
Runs the multi-agent refactoring-backlog pipeline in docs/project/
refactor-backlog-setup/ up to and including three of the seven Phase 1
agents.

00-baseline.md establishes the metrics every later agent must cite, using
only tooling already in the repo (vitest lcov, coverlet cobertura, ESLint's
core `complexity` rule at threshold 0 for a full distribution, depcruise
--metrics). Duplication and C# complexity had no tooling, so
tools/baseline-scan.mjs adds a deterministic ~200-line text scan rather
than a new dependency; the approximations are labelled as such.

Headline: FE 75.1% line coverage but only over the 98 of 220 source files a
spec loads; BE 97.6% line / 79.6% branch; 0 layering violations; 7.1%
duplication; 25 of 2085 TS functions over CC 10.

Then 02-testability, 04-cqrs-light and 06-adr-conformance (27 findings).
01/03/05 were skipped deliberately — the baseline shows little for them to
find; 07 (BIO2) and 08 (consolidation) are still open.

Each agent corrected a baseline observation of mine, and in every case the
error was in something derived rather than measured:

- BL-007 counted ~13 adapter "mutations" from the `runSubmit` helper name;
  5 of those call sites are reads. It also missed 3 real mutations that
  reach the raw ApiClient and never return a Result.
- BL-002 diagnosed the 100%-duplicated auth folders as ADR-0002's
  divergence prediction failing. It never had a chance to fail: §3's
  `Principal` union was never built.
- BL-004 named libs/shared/domain and libs/beheer/contracts as coverage
  gaps; both are pure type declarations where 0% is unimprovable.

All three corrections are recorded inline in 00-baseline.md §10, so agent
08 does not inherit the bad numbers.

.prettierignore excludes the agent prompt directories — reflowing their
markdown would edit the prompt text itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 16:44:32 +02:00

47 KiB
Raw Blame History

Scope: apps/ssp (6 contexts), apps/behandelportal (3 contexts), libs/shared (11 layers), libs/beheer (5 layers), backend/src/BigRegister.Api (6 folders), backend/tests

Status: complete

Last updated: 2026-08-26

Depends on: none

---

00 — Metrics Baseline

Fixed input to every Phase 1 agent (01–07). No agent may propose a change without citing a BL-### observation or a metric row from this file.


1. Method, and what to trust

Everything was measured with tooling already in the repo. No dependency was added, no config file edited.

Metric Command Trust
FE coverage npm run test:coverage → coverage/{ssp,behandelportal,shared,beheer}/lcov.info exact
FE spec reach derived: source files present in any lcov vs. files on disk exact
BE coverage cd backend && dotnet test BigRegister.slnx --filter "Category!=Integration" --collect:"XPlat Code Coverage" exact
TS complexity + fn length npx eslint apps libs --rule '{"complexity":["warn",0],"max-lines-per-function":["warn",{"max":0,"skipBlankLines":true,"skipComments":true}]}' -f json — threshold 0 makes ESLint report every function with its score, giving a full distribution rather than only violations exact (ESLint core rule, no plugin)
C# complexity node docs/project/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs --complexity file CC exact-ish; per-method CC approximate
Duplication node …/tools/baseline-scan.mjs --dup approximate
Layering violations npm run dep:check exact
Coupling / instability npx depcruise apps/<app>/src libs --config .dependency-cruiser.<app>.js --metrics --output-type metrics exact

tools/baseline-scan.mjs is new and lives in this workspace so the numbers reproduce. It is a crude text scan: line-window hashing for duplication (not token-based like jscpd), regex method detection for C# (does not understand expression-bodied members or nested lambdas). Deterministic, zero-install, good enough to answer "did this move". Upgrade path if a ticket ever needs more precision: jscpd, and a Roslyn analyzer.

Excluded as generated (counted once, then excluded everywhere): libs/shared/src/infrastructure/api-client.ts (2372 lines, NSwag) and backend/.../Data/Migrations/** (17 files, 2690 lines, EF Core).

LCOV aggregation rule. The four FE project runs overlap — libs/shared files appear in ssp's lcov as well as shared's. Each file is attributed to its owning module and the best result across the four runs is taken; a shared file exercised by an app's specs is genuinely covered.

Protocol deviation, stated for the record. The measurement runs are repo-global (one coverage run, one depcruise run) and cannot be executed module-by-module; only the write-up is per module. The resume contract still holds — the file is the recovery state.


2. Size inventory

Unit src .ts/.cs src lines spec files spec lines stories
apps/ssp 92 10 415 39 3 564 21
apps/behandelportal 29 1 309 7 396 4
libs/shared (excl. generated) 86 5 194 21 1 226 40
libs/beheer 13 1 146 4 269 1
Frontend total 220 18 064 71 5 455 66
backend/src (excl. Migrations) 54 4 989 — — —
backend/tests 39 — 39 4 253 —
e2e 5 332 — — —

Backend source by folder: Program.cs 940 · Data (excl. Migrations) 1 697 · Domain 991 · Zgw 710 · Contracts 329 · Stamdata 322. Zero .html template files exist anywhere in apps//libs/ — every Angular template is inline.


3. Coverage

3a. Frontend — line/branch coverage of files a spec actually reaches

Module Files Lines Line % Branches Branch %
ssp/auth 4 35 42.9% 26 46.2%
bhp/auth 4 35 42.9% 26 46.2%
libs/shared/upload 2 125 52.0% 118 50.0%
libs/beheer/application 1 70 65.7% 37 40.5%
libs/beheer/infrastructure 1 37 67.6% 43 60.5%
ssp/herregistratie 5 302 70.9% 286 67.8%
libs/shared/layout 2 80 72.5% 36 55.6%
libs/shared/ui 13 279 72.8% 230 75.2%
ssp/brief 11 486 75.3% 461 68.8%
ssp/registratie 21 430 80.0% 471 77.3%
libs/shared/application 8 76 80.3% 50 70.0%
bhp/behandeling 5 107 91.6% 146 81.5%
libs/shared/infrastructure 9 75 94.7% 84 81.0%
libs/shared/kernel 5 28 96.4% 20 90.0%
libs/beheer/domain 2 54 98.1% 64 75.0%
ssp/showcase 1 11 100.0% 4 100.0%
libs/shared/testing 3 9 100.0% 2 50.0%
TOTAL 98 2 240 75.1% 2 104 70.6%

3b. Frontend — spec reach (the number that matters)

75.1% is coverage of the 98 files a spec imports. It is not coverage of the codebase. 122 of 220 source files are never loaded by any Vitest run at all.

Module Source files Reached Never reached % reached
ssp/root, ssp/shell, bhp/root, bhp/shell 12 0 12 0%
libs/shared/domain 3 0 3 0%
libs/beheer/ui 4 0 4 0%
libs/beheer/contracts 1 0 1 0%
libs/shared/layout 11 2 9 18%
bhp/behandeling 16 5 11 31%
ssp/showcase 3 1 2 33%
libs/shared/ui 34 13 21 38%
ssp/brief 26 11 15 42%
bhp/auth 8 4 4 50%
libs/shared/upload 4 2 2 50%
ssp/registratie 41 21 20 51%
ssp/herregistratie 9 5 4 56%
ssp/auth 6 4 2 67%
libs/beheer/domain 3 2 1 67%
libs/shared/application 11 8 3 73%
libs/shared/infrastructure 11 9 2 82%
libs/shared/kernel 5 5 0 100%
TOTAL 220 98 122 45%

Most of the 122 are ui/ components, which CLAUDE.md §5 deliberately exercises through Storybook + the a11y addon (66 stories), not Vitest. That is a house decision, not a gap — see BL-004 before filing anything against it.

3c. Backend

Module Files Lines Line % Branches Branch %
backend/Domain 17 730 94.2% 356 82.0%
backend/Stamdata 10 252 96.8% 120 71.7%
backend/Program.cs 1 1 160 97.4% 316 84.8%
backend/Contracts 2 334 97.6% 40 65.0%
backend/Zgw 8 624 98.1% 124 85.5%
backend/Data 13 1 852 99.0% 400 75.5%
TOTAL 51 4 952 97.6% 1 356 79.6%

241 tests, all green. Every backend source file is reached. Branch coverage is the weak axis, not line coverage — Contracts 65.0%, Stamdata 71.7%, Data 75.5%.


4. Complexity

4a. TypeScript (exact — ESLint core complexity)

Distribution over 2 085 source functions (specs/stories excluded): p50 1 · p75 2 · p90 3 · p95 5 · p99 12 · max 27. 25 functions exceed CC 10 (1.2%).

Function length over 1 149 functions: p50 3 · p75 7 · p90 13 · p95 20 · p99 34 · max 143. Only 2 functions exceed 75 lines.

Module Fns max CC p90 CC CC>10 max fn lines fn>75
libs/shared/upload 90 27 4 1 109 1
ssp/registratie 361 23 4 7 143 1
ssp/herregistratie 144 19 3 4 31 0
libs/shared/infrastructure 32 19 6 1 33 0
ssp/brief 608 17 3 6 73 0
bhp/behandeling 85 16 5 3 28 0
libs/beheer/domain 22 11 7 1 24 0
libs/beheer/infrastructure 13 11 7 1 25 0
libs/shared/ui 285 11 3 1 37 0
libs/beheer/ui 100 10 1 0 8 0
libs/shared/application 61 7 3 0 30 0
bhp/auth · ssp/auth · ssp/shell 63 5 3 0 13 0
libs/beheer/application 42 4 3 0 15 0
libs/shared/kernel 18 4 4 0 13 0
libs/shared/layout 75 4 2 0 29 0
ssp/showcase · ssp/root · bhp/root · libs/shared/testing 86 3 1 0 15 0

Read BL-001 before filing any complexity ticket. 23 of the 25 CC>10 functions are reducers (9), parse* trust boundaries (10), or validate* (4) — all three are mandated house idioms.

The 25, in full:

CC Function Location Kind
27 reduceUpload libs/shared/src/upload/upload.machine.ts:131 reducer
23 validateStep apps/ssp/src/app/registratie/domain/registratie-wizard.machine.ts:117 validate
20 reduce apps/ssp/src/app/registratie/domain/registratie-wizard.machine.ts:321 reducer
19 validateStep apps/ssp/src/app/herregistratie/domain/intake.machine.ts:97 validate
19 parseAanvraagStatus apps/ssp/src/app/registratie/infrastructure/applications.adapter.ts:72 parse
19 fetch libs/shared/src/infrastructure/api-client.provider.ts:49 other
17 parseOrgTemplate apps/ssp/src/app/brief/infrastructure/brief.adapter.ts:331 parse
17 parseDuoLookup apps/ssp/src/app/registratie/infrastructure/duo.adapter.ts:46 parse
16 parseBeoordelingStatus apps/behandelportal/src/app/behandeling/infrastructure/beoordeling.adapter.ts:31 parse
16 parseStatus apps/ssp/src/app/brief/infrastructure/brief.adapter.ts:202 parse
16 validateAll apps/ssp/src/app/registratie/domain/registratie-wizard.machine.ts:166 validate
15 parseBeoordelingView apps/behandelportal/src/app/behandeling/infrastructure/beoordeling.adapter.ts:68 parse
15 validateAll apps/ssp/src/app/herregistratie/domain/intake.machine.ts:135 validate
14 reduce apps/behandelportal/src/app/behandeling/domain/besluit.machine.ts:70 reducer
14 reduce apps/ssp/src/app/brief/domain/org-template.machine.ts:57 reducer
14 reduce apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts:161 reducer
14 reduce apps/ssp/src/app/herregistratie/domain/intake.machine.ts:222 reducer
14 reduce apps/ssp/src/app/registratie/domain/change-request.machine.ts:57 reducer
13 reduce apps/ssp/src/app/brief/domain/brief.machine.ts:188 reducer
12 parsePassage apps/ssp/src/app/brief/infrastructure/brief.adapter.ts:235 parse
12 parseBrief apps/ssp/src/app/brief/infrastructure/brief.adapter.ts:277 parse
12 parseDashboardView apps/ssp/src/app/registratie/infrastructure/dashboard-view.adapter.ts:50 parse
11 reduce libs/beheer/src/domain/stamdata-editor.machine.ts:31 reducer
11 parseAuditEntries libs/beheer/src/infrastructure/audit.adapter.ts:21 parse
11 collect libs/shared/src/ui/rich-text-editor/rich-text-dom.ts:130 other

Functions over 75 lines — the entire population: createDraftSync 143 lines (apps/ssp/src/app/registratie/application/draft-sync.ts:50), reduceUpload 109 lines (libs/shared/src/upload/upload.machine.ts:131).

4b. C# (approximate)

Module Files Σ file CC max file CC Methods max method CC p90 CC>10
backend/Program.cs 1 78 78 13 12 7 1
backend/Data 23 101 27 77 16 4 1
backend/tests 39 121 26 230 20 2 1
backend/Domain 18 71 21 36 8 6 0
backend/Stamdata 10 34 21 11 10 6 0
backend/Zgw 8 39 11 20 8 4 0
backend/Contracts 2 4 3 6 3 3 0

Method-length distribution (n=393): p50 9 · p90 22 · p99 90 · max 293.

Highest-CC files: Program.cs 78 · Data/ApplicationStore.cs 27 · tests/OpenZaakZaakSourceTests.cs 26 · Domain/Letters/LetterHtml.cs 21 · Stamdata/StamdataTable.cs 21 · Data/BriefStore.cs 17.

Methods over CC 10: ToDto (Data/BriefStore.cs:34, CC 16), LogBrief (Program.cs:889, CC 12), and one 293-line test method (CreateZaak_posts_zaak_status_and_rol_and_maps_the_result_back, CC 20).


5. Duplication (approximate — 6-line normalized window)

Repo-wide: 1 755 of 24 701 significant lines duplicated = 7.1%.

Module Sig. lines Duplicated %
ssp/auth 211 211 100.0%
bhp/auth 243 211 86.8%
bhp/root 90 68 75.6%
ssp/root 122 68 55.7%
bhp/shell 21 8 38.1%
ssp/herregistratie 1 536 121 7.9%
ssp/brief 5 015 393 7.8%
backend/tests 2 538 197 7.8%
backend/Data 1 068 82 7.7%
libs/shared/infrastructure 510 36 7.1%
libs/beheer/domain 250 17 6.8%
libs/beheer/ui 509 34 6.7%
libs/beheer/application 185 12 6.5%
bhp/behandeling 954 55 5.8%
ssp/shell 194 8 4.1%
ssp/registratie 3 798 144 3.8%
libs/shared/ui 2 604 58 2.2%
backend/Zgw 327 6 1.8%
ssp/showcase 487 8 1.6%
backend/Program.cs 510 6 1.2%
libs/shared/application 566 6 1.1%
libs/shared/layout 869 6 0.7%
backend/Contracts, backend/Domain, backend/Stamdata, libs/shared/{domain,kernel,upload,testing,environments}, libs/beheer/{contracts,infrastructure}, e2e 1 894 0 0.0%

Top clone pairs:

Windows Pair
39 bhp/auth/application/session.store.ts ↔ ssp/auth/application/session.store.ts
36 bhp/auth/auth.guard.spec.ts ↔ ssp/auth/auth.guard.spec.ts
35 bhp/auth/ui/login-form/… ↔ ssp/auth/ui/login-form/…
25 bhp/app.config.ts ↔ ssp/app.config.ts
23 bhp/auth/ui/login.page.ts ↔ ssp/auth/ui/login.page.ts
21 bhp/auth/auth.guard.ts ↔ ssp/auth/auth.guard.ts
13 libs/shared/…/role.interceptor.spec.ts ↔ …/subject.interceptor.spec.ts
11 brief/ui/letter-canvas.stories.ts ↔ brief/ui/letter-composer.stories.ts
9 ssp/brief/ui/org-template.page.ts ↔ libs/beheer/src/ui/stamdata.page.ts
8 bhp/behandeling/domain/besluit.machine.ts ↔ ssp/registratie/domain/change-request.machine.ts
8 tests/OpenZaakZaakSourceTests.cs ↔ tests/ZgwDivergenceTests.cs
7 bhp/…/besluit-form.component.ts ↔ ssp/…/change-request-form.component.ts
7 ssp/…/intake-wizard.component.ts ↔ ssp/…/registratie-wizard.component.ts

The auth duplication is a deliberate decision, not an accident — see BL-002 before proposing to merge it.


6. Layering and coupling

npm run dep:check: 0 violations (223 modules, 584 dependencies cruised) across 11 severity: error rules — shared-no-features, beheer-no-features, shared-no-beheer, <app>-no-other-app, per-context <app>-<context>-scope, domain-is-pure, contracts-import-nothing, ui-not-infrastructure, apiclient-infrastructure-only, no-testing-in-production, no-circular.

Instability I = Ce/(Ca+Ce). Low I = stable base, high I = volatile leaf. Measured in the ssp cruise (behandelportal's figures for libs/* differ only in Ca, same shape):

Folder N Ca Ce I
apps/ssp/src/app/brief 46 2 143 99%
apps/ssp/src/app/herregistratie 18 4 80 95%
apps/ssp/src/app/showcase 4 1 17 94%
apps/ssp/src/app/registratie 67 19 181 91%
apps/behandelportal/src/app/behandeling 24 2 62 97%
apps/behandelportal/src/app/auth 11 4 25 86%
apps/ssp/src/app/auth 9 5 24 83%
libs/beheer/src/ui 5 3 27 90%
libs/beheer/src/application 3 2 16 89%
libs/beheer/src/infrastructure 3 3 11 79%
libs/shared/src/layout 19 22 52 70%
libs/shared/src/ui 68 128 111 46%
libs/shared/src/infrastructure 19 43 25 37%
libs/shared/src/application 18 55 30 35%
libs/shared/src/upload 5 30 13 30%
libs/beheer/src/domain 5 8 3 27%
libs/shared/src/testing 4 17 2 11%
libs/shared/src/kernel 9 71 4 5%
libs/shared/src/domain 3 11 0 0%
libs/beheer/src/contracts 1 0 0 0%

This is textbook: kernel/domain are the stable base (I ≤ 5%), feature contexts are volatile leaves (I ≥ 83%), nothing depends on them. The frontend dependency structure is not a problem area — do not spend tickets here.

The backend has no equivalent enforcement at all. Domain/ purity (verified: zero Microsoft.EntityFrameworkCore / Microsoft.AspNetCore imports) holds by convention and code review only. See BL-006.


7. Pattern inventory — what already exists

Agents 03 (DDD/hexagonal) and 04 (CQRS-light) may only extend what is listed here. They may not introduce either pattern into a module where it is absent.

Backend

Pattern State
Ports with 2+ implementations IZaakSource (Data/LocalZaakSource.cs ↔ Zgw/OpenZaakZaakSource.cs), IDocumentSource (Data/LocalDocumentSource.cs ↔ Zgw/OpenZaakDocumentSource.cs) — config-switched on Zgw:Enabled at Program.cs:57-84, ADR-0005
Single-impl interface IIdentityProvider → StubIdentityProvider
Not behind any port 7 static, non-DI stores: ApplicationStore, DocumentStore, BriefStore, OrgTemplateStore, FeatureFlagStore, AuthzAuditStore, IdempotencyStore. No AddDbContext; each opens a short-lived context via Db.Create() under its own lock. Deliberate, documented in Data/Db.cs and Program.cs:40-45
Domain purity Domain/ is EF-free and ASP-free (verified). Rules are static classes of pure functions with co-located tests in tests/Domain/: SubmissionRules, DocumentRules, IntakePolicy, BeoordelingRules, DiplomaRules, HerregistratieRule, LetterHtml, OrgTemplateRules, Authz, FeatureFlags. Domain/Applications/Aanvraag.cs is a C# tagged union (Concept/Submitted/Decided)
CQRS-light Partial. Contracts/Dtos.cs holds 65 records split by direction (*Request in, *Dto/*Response out). Read/write split exists as comment banners inside a single 940-line Program.cs carrying all 48 endpoint mappings. No handler types, no mediator, no Features/ folders. Cross-cutting behaviour is factored into local helpers (Submit, StamdataAdmin, CasesAdmin, Beoordelen, OrgAdmin, FlagsAdmin) — authorization/idempotency wrappers, not handlers
Mapping Contracts/Mappers.cs (.ToDto(), .ToDetailDto()), Data/AanvraagMapper.cs
ZGW anti-corruption layer Fully built: Zgw/{OpenZaakZaakSource,OpenZaakDocumentSource,ZgwHttpClient,ZgwTokenProvider,ZgwZaakMapper,ZgwOptions,ZgwDiagnosticHandler}.cs, 5 test files. ADR-0005

Frontend

Pattern Count Notes
Command factories (write side) 3 registratie/application/submit-change-request.ts, behandeling/application/submit-besluit.ts, registratie/application/draft-sync.ts
Mutations living inline in adapters ~13 brief.adapter.ts (save/submit/approve/reject/send/reset), org-template.adapter.ts (save/publish/rollback), stamdata.adapter.ts — they call runSubmit directly instead of going through a command factory
Infrastructure adapters (read side) 20 +1 outside an infrastructure/ folder: libs/shared/src/upload/upload.adapter.ts
parse* trust boundaries 30 24 in adapters, 6 in value objects / kernel
Application stores 15 all providedIn: 'root'
Elm-style machines 9 8 under a domain/ folder; outlier libs/shared/src/upload/upload.machine.ts
Explicit port 1 SessionPort + SESSION_PORT token (libs/shared/src/application/session.port.ts)
Config-seam tokens 3 DEBUG_PANEL, HEADER_NAV_ITEMS, HEADER_ADMIN_LINKS
contracts/ DTO files 4 most adapters consume NSwag-generated types directly instead

Shared application kit (libs/shared/src/application/): remote-data.ts, store.ts, submit.ts, action-state.ts, debounced-save.ts, history.ts, machine-remote-data.ts, pending-saves.ts.

ADRs on record

0001 BFF-lite + decision DTOs (Accepted) · 0002 user groups as actors, not bounded contexts (was Proposed when measured; promoted to Accepted 2026-08-26 by ADR-C-005, with §3's Principal omission recorded in the ADR as known debt) · 0003 CIBG Huisstijl (Accepted) · 0004 stamdata as code (Accepted) · 0005 OpenZaak behind the BFF — the explicit ports-and-adapters ADR (Accepted) · 0006 test data through the production door (Accepted).


8. Rankings, worst to best

Spec reach (FE): ssp/root · ssp/shell · bhp/root · bhp/shell · libs/shared/domain · libs/beheer/ui · libs/beheer/contracts (all 0%) → libs/shared/layout 18% → bhp/behandeling 31% → libs/shared/ui 38% → ssp/brief 42% → … → libs/shared/kernel 100%.

Line coverage (FE, of reached files): ssp/auth · bhp/auth 42.9% → libs/shared/upload 52.0% → libs/beheer/application 65.7% → … → ssp/showcase 100%.

Branch coverage (BE): Contracts 65.0% → Stamdata 71.7% → Data 75.5% → Domain 82.0% → Program.cs 84.8% → Zgw 85.5%.

Duplication: ssp/auth 100% → bhp/auth 86.8% → bhp/root 75.6% → ssp/root 55.7% → bhp/shell 38.1% → ssp/herregistratie 7.9% → … → 12 modules at 0%.

Complexity (TS, CC>10 count): ssp/registratie 7 → ssp/brief 6 → ssp/herregistratie 4 → bhp/behandeling 3 → 5 modules with 1 → the rest 0.

Complexity (C#, file CC): Program.cs 78 → Data 101 across 23 files (max 27) → Domain 71 (max 21) → Zgw 39 → Stamdata 34 → Contracts 4.

Coupling: nothing to rank — 0 violations, healthy instability gradient (§6).


9. Thresholds Phase 1 must use

Derived from the measured distributions above, not invented.

Threshold Value Basis
Cyclomatic complexity > 10 fixed by the agent prompt; TS p99 is 12, so this catches the top ~1%
Agent 01's [N] lines — TS function > 40 TS fn-length p99 is 34; only 4 functions exceed 50
Agent 01's [N] lines — C# method > 60 C# method p99 is 90, p90 is 22
Agent 01's [N] lines — component/file > 400 6 TS files and 1 C# file exceed it
Nesting depth > 3 fixed by the agent prompt
Duplication worth a ticket > 10% of a module's significant lines repo mean is 7.1%

Largest files (the >400 population): backend/Program.cs 940 · registratie/ui/registratie-wizard.component.ts 645 · showcase/concepts.page.ts 496 · brief/ui/letter-canvas.component.ts 463 · brief/infrastructure/brief.adapter.ts 437 · herregistratie/ui/intake-wizard.component.ts 406.


10. Baseline observations (cite these)

Stable IDs. A Phase 1 finding must reference one of these or a metric row above.

BL-001 — 23 of 25 TS functions over CC 10 are mandated house idioms. Reducers (9), parse* trust boundaries (10) and validate* (4) are switch/guard-dense by construction: CLAUDE.md §3 requires a tagged-union reducer over booleans, and ADR-0001 requires a hand-written parse* at every wire boundary. High CC there is the design working, not decaying. Only two CC>10 functions are outside the idiom: api-client.provider.ts:49 fetch (CC 19) and rich-text-dom.ts:130 collect (CC 11). Any complexity ticket against a reduce*/parse*/validate* must argue why this case differs — a bare CC number is not sufficient grounds.

BL-002 — ssp/auth is 100% duplicated against bhp/auth, deliberately. 211 of 211 significant lines; session.store.ts, login-form.component.ts, login.page.ts and auth.guard.ts are near-identical. CLAUDE.md §1 and ADR-0002 state auth is not shared because Zorgverlener and Medewerker are different Principal variants expected to diverge. The divergence has not happened yet. This is legitimately in scope for agent 06 (ADR conformance) as either an ADR-fix — the prediction has not held over two phases of work — or a "still waiting" note. It is not a straightforward extract-to-shared refactor; that would contradict an accepted ADR.

Sharpened 2026-08-26 by agent 06 (ADR-C-004/005) — verified. "The prediction has not held" is the wrong diagnosis. ADR-0002 §3's concrete deliverable, Session → Principal, was never built: grep -rn "Principal" apps libs returns exactly one hit, a comment in libs/shared/src/infrastructure/role.ts:8, and no type. diff -rq over the two auth folders shows zero content differences — 9 of 11 files identical, the only delta being two extra files in behandelportal. behandelportal's Behandelaar still carries a bsn and login.page.ts:31 logs a backoffice user in through DigiD. The rule was not falsified, it was untested; the divergence that did occur went through an orthogonal side door (medewerker.interceptor.ts) that never touches Session. Amending ADR-0002 would ratify the omission. Use agent 06's sequencing instead.

BL-003 — Program.cs is the single largest complexity concentration in the repo. 940 lines, 48 endpoint mappings, file CC 78 (next-highest file: 27), read/write separated only by comment banner. 97.4% line / 84.8% branch covered, so it is well-tested, not fragile — this is a structure finding, not a correctness one. It is the one place where agent 04's CQRS-light and agent 03's vertical-slice thinking both have real purchase, and the one place where "extend the existing pattern, don't introduce one" is hardest to honour: there is no Features/ folder to extend.

BL-004 — 122 of 220 FE source files (55%) are never loaded by any Vitest run. Overwhelmingly ui/ components, which CLAUDE.md §5 covers via 66 Storybook stories with the a11y addon instead. Agent 02 must distinguish "untested" from "tested through Storybook" before filing; the genuine gaps are non-ui/ files with no spec — libs/shared/domain (3 files, 0%), libs/beheer/contracts, and the app root/shell files.

Corrected 2026-08-26 by agent 02 — verified. The two named "genuine gaps" are false positives. libs/shared/src/domain is 30 lines across 3 files — interfaces and type aliases plus a single string const — and libs/beheer/src/contracts/stamdata.dto.ts is 30 lines of DTO shapes. Neither contains an executable statement, so 0% is correct and unimprovable. Close both rows rather than ticketing them. Only the app root/shell files remain as candidates from this observation.

BL-005 — backend branch coverage lags line coverage by 18 points (97.6% vs 79.6%). Weakest: Contracts 65.0%, Stamdata 71.7%, Data 75.5%. Line coverage is near-total, so the missing tests are edge-case branches, not whole units.

BL-006 — the backend has zero automated architecture enforcement. The frontend has 11 dependency-cruiser rules at severity: error, 0 violations, running in CI. The backend has none: one assembly, no Domain.csproj boundary, no NetArchTest/ArchUnitNET. Domain/ purity currently holds by convention. Any agent-03 proposal that depends on the backend's layering staying clean should note that nothing enforces it.

BL-007 — the FE write side is inconsistently placed. 3 command factories vs ~13 call sites invoking runSubmit directly inside adapters (brief.adapter.ts, org-template.adapter.ts, stamdata.adapter.ts). CLAUDE.md §3 makes the command factory the idiom. This is agent 04's clearest extend-an-existing-pattern target — the pattern exists, it is just not applied uniformly.

Corrected 2026-08-26 by agent 04 (CQ-003/CQ-005) — verified. The "~13 mutations" count was derived from the runSubmit helper name and is wrong: 5 of those call sites are reads, not writes. libs/beheer/src/infrastructure/stamdata.adapter.ts exposes only list() and load() and its own docstring says "Both endpoints are reads … There is no write method", yet both call runSubmit. Same at brief.adapter.ts:56 and org-template.adapter.ts:39,51. runSubmit is the write fold — it mints the Idempotency-Key — so the name, not the code, produced the miscount. Conversely agent 04 found 3 mutations this baseline missed entirely: ApplicationsStore.cancel, AdminCasesStore.delete, FeatureFlagStore.set reach the raw ApiClient and never return a Result. Use agent 04's inventory, not this count.

BL-008 — coverageExclude does not exclude the generated API client. libs/shared/src/infrastructure/api-client.ts is listed in coverageExclude in all four angular.json test targets, yet appears in all four lcov.info files (987 lines at ~7%), dragging the reported libs/shared/infrastructure figure from 94.7% down to 6.9%. This file excludes it manually. Small, real, and cheap to fix.

BL-009 — no coverage threshold is enforced anywhere. Neither angular.json nor CI sets a minimum; npm run test:coverage runs in CI and the output is discarded. There is no ratchet, so no ticket can be verified as "improved coverage" by CI alone — verify against the numbers in this file.

BL-010 — libs/shared/src/upload/ sits outside the layer convention. upload.machine.ts (CC 27, 109 lines — the highest in the repo) lives in its own top-level folder rather than under domain/, and upload.adapter.ts outside infrastructure/. It is carved out by name in the apiclient-infrastructure-only dependency-cruiser rule, i.e. the exception is already encoded rather than resolved.

BL-011 — the FE test suite is flaky under parallel load. npm run test:coverage failed on the first run with two [vitest-pool] Timeout waiting for worker to respond errors in libs/shared, then passed 21/21 when re-run serially. Not a code defect; relevant to any ticket whose acceptance is "CI green".


11. Reproducing this file

npm run test:coverage            # if flaky, re-run the failing project alone
cd backend && dotnet test BigRegister.slnx --filter "Category!=Integration" \
  --collect:"XPlat Code Coverage"
npx eslint apps libs --rule '{"complexity":["warn",0],"max-lines-per-function":["warn",{"max":0,"skipBlankLines":true,"skipComments":true}]}' -f json
node docs/project/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs
npm run dep:check
npx depcruise apps/ssp/src libs --config .dependency-cruiser.ssp.js --metrics --output-type metrics
npx depcruise apps/behandelportal/src libs --config .dependency-cruiser.behandelportal.js --metrics --output-type metrics

The baseline-scan.mjs figures are deterministic and must reproduce exactly. Coverage figures move with the tests.