ADR Status Index — Full Annotations
The war-room front door (CLAUDE.md) carries the ADR roll as subject lines only, per that section's own stated contract. The full status annotations — adoption waves, consumer rollouts, amendments, live-enforcement notes and the reasoning trail for each decision — live here.
Canonical ADR text remains at presentation/decisions/{slug}.md and renders to adrs.script.nl. This file is the status layer: what has shipped, what is in flight, what each amendment changed.
Relocated from CLAUDE.md on 2026-07-26. Backfilled for 0001–0036 on 2026-07-27 — see below.
Coverage. Every ADR 0001–0050 carries a status annotation (0050 added the day it was proposed, 2026-09-14) (0048 + 0049 added /muster 2026-09-10 — accepted 09-02 and 08-31 respectively, absent here for 8 and 10 days while the front door pointed readers at this index; 0047 added /muster 2026-08-20 — it was accepted 2026-08-19 and this file did not mention it, while the front door instructs readers to consult this index before acting on any ADR's state). Until 2026-07-27 this file held payload for 0037–0046 only and bare subject lines for 0001–0036, while the front door instructed readers to "read it before acting on any ADR's current state" — so it answered for 10 of 46. The 0001–0036 annotations below are derived from each canonical page's own ## Implementation table and amendment blocks (/muster 2026-07-27), not re-litigated from territory state.
War-room-internal ADRs — 0005, 0007, 0010, 0030, 0046, 0047, 0049 — are not published (no page at adrs.script.nl); they live in CLAUDE.md's roll and here. Full doctrine for everything else is at adrs.script.nl; this file is the status layer only.
An ADR's Implementation table is a hand-maintained record, and it decays
A row saying "PR #N open" is a claim, not live state. Five were spot-checked against gh on 2026-07-27 and all five were stale — every cited PR had merged, the oldest 82 days earlier (0022 emmie#195, 0023 emmie#218, 0028 emmie#637 / entreezuil#288 / ublgenie#467, 0032 kendo#1440). All five were corrected on their canonical pages 2026-08-18 (flipped to Complete with merge dates) and are marked ✅ RESOLVED below. The lesson stands and is the reason this banner remains: the drift was detected 2026-07-27 and sat unapplied for 22 days, so detection is not correction. Treat any un-flagged "open / in flight / In Review" row the same way: verify at HEAD before acting on it.
Second sweep, /muster 2026-08-20 — and it went 7 for 7. The 2026-07-27 pass corrected the five rows it named and left the general instruction above to the reader, so the reader never did it. Every remaining un-flagged open-state PR claim in this file was checked against gh, and all seven were stale: 0012 ublgenie#17 (merged 2026-04-01, 141 days), 0019 ublgenie#89 (2026-04-17), 0024 kendo#1028 (2026-05-22), 0029 isms#7 (2026-05-28), 0032 fs-packages#114 (2026-06-09), 0043 fs-packages#186 (2026-07-24 — the row read "OPEN / UNMERGED"), 0043 kendo#1823 (2026-07-28). The rot was in the canonical pages, not just this index; all six pages were corrected the same day, each with its territory state re-derived from HEAD rather than assumed from the merge. A merged PR is not a completed adoption — 0012 and 0019 went to Evergreen only because an arch test was found enforcing them, not because a PR closed.
- 0001 — Audit Logging System (badge corrected Kendo → Cross-Project 2026-08-02, resolving the badge/table scope mismatch. Last revised 2026-05-01. Compliance ISO 27001 A.8.15/A.5.33/A.8.5. kendo=Partial (Tier 1 done — Issue CRUD + User/AppSetting/GithubConnection/TimeLog, PRs #321/#357-360/#373; Tier 2 = 10 entities scoped-not-started, next target 2FA); entreezuil=Complete (4 audit tables, PRs #17–#19); emmie=Partial (Phase 1+1.5+1.6 deployed PR #184/EMMIE-0239; Phase 2/3/δ + owen-it retirement outstanding, ~21 Engineer-days in the Surveyor envelope). Carries a Snapshot-on-Retry Safety doctrine block with arch-test enforcement (shapes a/b/c +
@audit-snapshot-retry-safetyopt-out), flagged a promotion candidate for phpstan-warroom-rules Phase 2; entreezuil's 2026-05-01 port introduced shape (c) — promote fleet-wide on the next port wave. emmie row also queues a Phase-1.6assertWithinTransactionconnection-coupling port to kendo/ublgenie/entreezuil, latent-risk-only.) - 0002 — Cascade Deletion & Selective Soft Deletes (Cross-Project, 2026-02-11. kendo / brick-inventory / ublgenie all Partial and all blocked at the same place: Phase 3 soft deletes gate on an information-classification scheme that does not exist yet. kendo Phase 1 PR #260, Phase 2 PRs #261/#263; BIO Phase 1 #76, Phase 2 #77; ublgenie Phase 1 #25 — FKs already RESTRICT, no cascades, DeleteUser FK bug fixed. The classification scheme is the single unblocker for three territories at once.)
- 0003 — AI Interaction Logging (Multi-territory, last revised 2026-06-19. Compliance ISO 27001 A.8.15/A.15.1/A.8.6. Channel model is the load-bearing part: Ch1 outbound is the portable core and mandatory for any territory calling an external AI provider — content is never stored, which IS the data-minimization control on PHI territories; Ch2 is MCP-hosting-only, Ch3 AI-run-webhook-only; adopt only the channels your AI surface exposes. kendo=Complete (all three channels, PRs #423–425); emmie=In Progress, Channel 1 only (2 outbound paths —
ClientController::summarizeReports→OpenAI o4-mini viaCreateAiPromptAction, and Juvoly viaMapEvaluationTranscriptAction; tenant-scopedai_outbound_logson nativeApp\Audit\*; Ch2–3 N/A. Graduated 2026-06-19. DPA gate CLEARED — Art. 28 processor documents confirmed in hand 2026-06-19, so the open finding does not lift to Critical; build pends only a Medic Ch1 dispatch. Residual to confirm at dispatch:OPENAI_ORGANIZATIONresolves to a zero-retention/no-training tier — an account-dashboard fact, not a document).) - 0004 — Import Atomicity (Brick Inventory-specific, 2026-02-11. brick-inventory=Complete — per-page transactions, completion indicator, idempotent retry all shipped. No open legs; the quietest ADR in the roll.)
- 0005 — Autonomous Learning Spy System (internal — not published. Accepted. The two-phase mission/debrief lifecycle, human-gated graduation, and the 2-confirming-missions rule. Amendment 2 (Accepted 2026-07-29) RETIRED the 30-day-unconfirmed expiry and the one-extension mechanic — candidates are never dropped for elapsed time alone; states are
ACTIVE/PARKED(unexercised, no clock, must name a— Wake:condition), a drop requires disproof / low-value / inexercisability, and every terminal disposition is archived in the spy's own file. Evidence: the clock drifted unenforced (78% of the live pool past the line) then mass-fired at the 2026-05-19 cliff, dropping 35 of 48 (73%) dominantly for going unexercised, not disproved. The complementary 2026-05-19 proposal-intake gate still stands. First internal ADR to receive an actual document —.claude/decisions/adr-0005-autonomous-learning-spy-system.md; before 2026-07-29,See ADR-0005resolved to nothing./muster1.5a scanner migrated 2026-08-01 to the Amd-2 State/Wake schema (Implementation step 3 done); first fully-clean run 2026-08-02 — 56 candidates, snapshot-reconciled, zero schema violations.) - 0006 — Two-Tier Authorization Model (Kendo-specific, implemented 2026-02-16. kendo=Complete — Phase 1 PR #251, Phase 2 PR #656; 17 model Policies + 1 interaction permission
AssignRolePermission; 8 arch tests enforce the interaction boundary;CheckPermissionresolution engine inapp/Policies/. Phase 2 replaced the staticUserRoleEnumwith a granular RBAC matrix (16 resources × 4 actions, multi-role union, 6-step algorithm, admin + project-owner bypasses, frontendusePermission()mirror) — note it changed how Tier 1 permissions resolve, never where they are enforced; Phase 1's two-tier structure is explicitly preserved.) - 0007 — Specialized Soldiers and Territory Briefings (internal — not published. Accepted. Single-phase execution, no self-learning, General-curated prompts, briefing+pulse read at Pre-Deployment. Verified structurally intact across all three soldiers at
/muster2026-07-27.) - 0008 — Multi-Tenancy (Kendo-specific, last revised 2026-03-09. Compliance ISO 27001. kendo=Partial — DIY database-per-tenant live for 3 fixed tenants. The planned request-scoped-tenancy evolution is explicitly NOT started (the page carries its own
::: info Statussaying so): a 5-phase ladder splittingTenantManagerintoTenantContext(request-scoped) +TenantSwitcher(stateless) → full Octane readiness; 13 files referenceTenantManager. Impact table: ADR-0001 benefits (per-tenant hash chains, no cross-tenant contention, schema unchanged), 0002 unaffected, 0003 tenant-scoped, 0006 unaffected.) - 0009 — Unified ResourceData Pattern (Cross-Project, 2026-02-23, amended 2026-07-03 — Loud-Failure Hydration & the Hydrator supply side. The only page in the roll with two Implementation tables. Amendment adoption: self-heal
loadMissing()removed fromfrom()/collection(), the gate goes loud, and a new Hydrator class family owns the supply side — canonicalized off kendo PR #1474 (KD-0647). Per-territory: kendo LIVE on the Issue family, 14 factories still self-heal (KD-0906), flip queued KD-0905 + arch test KD-0907; codebook mostly live, WR-0313 executed 2026-07-03 (supply #453 + stacked flip #454, 9 gaps,ResourceLoudGateTest); entreezuil LIVE 3/3; ublgenie + brick-inventory dead (self-heal-then-validate) → supply-first migration then flip; town-crier live onReviewRequestResourceDatawithReviewRequestSummaryDatadocumenting a load-bearingcollection()self-heal reliance; emmie dead 11/11, sequenced LAST on a NEN 7510 500-risk asymmetry. Binding migration ordering: supply first, flip last — and on NEN 7510 / ISO territories the flip PR must be pure removal so a revert is trivial. Original-pattern adoption: kendo/BIO/ublgenie/entreezuil=Complete, emmie=Partial→full-migration ruled 2026-06-12 (95DTOResourcesubclasses + 25 rawJsonResource; the earlier "178" count was wrong; relation-safety is a latent CI regression-guard, not an active bleed). Enforcement: L1 arch test banningloadMissing(/->load(/loadCount(/loadSum(insideapp/Http/Resources/**, L1 Hydrator structure test, L2 deptrac Hydrators layer. Canonical base pinned with provenance — kendobackend/app/Hydrators/Hydrator.php@4aad21d45; promotion to a shared Composer package deliberately deferred until a base-class defect ships in two territories. BIO's dual-baseComputedResourceDatacarve-out is sanctioned by BIO's own sovereign ADR-0010 and does not cascade.) - 0010 — Squad System & Supply Corps (internal — not published. Accepted. Standing-SOP maintenance units, no bespoke orders, single-phase. Carries the anti-laundering seed: the 2026-06-30 entreezuil dispatch whose orders wrongly said "push + open PR" and which laundered the gated push through a spawned sub-agent.)
- 0011 — Action Class Architecture (Cross-Project, 2026-03-08, amended 2026-04-24: Actions are the sole owners of
->transaction(calls in application code, withAuditLogWriterthe documented infrastructure-layer exception. Scope boundary is narrow and deliberate —app/Http/*ONLY;app/Jobs/*andapp/Services/*keep transaction-opening privileges, tightening deferred to its own deliberation. Driver: a 2026-04-24 recon found 7 HTTP-layer transactions across ublgenie + entreezuil writing to hash-chained audit tables without SQLSTATE 40001 retry. kendo=Evergreen (clean by convention, zero HTTP-layer txns); emmie=Evergreen (all 316 Actions migrated__invoke()→execute(), PR #181;EnforceActionTransactionsRulewalksexecute()); BIO + the-laboratory=Evergreen but HTTP-layer txn audit not yet performed; ublgenie=Partial (13 Actions extracted PRs #7–9; stillDatabaseManagernotConnectionInterface, static model calls, facades; 3 HTTP-layer txns inAuthControllerawaiting Phase 2); entreezuil=Partial (4 HTTP-layer txns —AuthenticatedSessionController×3 +EnsureUserIsAdmin×1 — awaiting Phase 2); daymate-api=Not Assessed, audit deferred until the L12 upgrade lands.) - 0012 — FormRequest → DTO Flow (Cross-Project, 2026-03-08. kendo + brick-inventory=Evergreen, arch-test-enforced; ublgenie=In Progress (corrected 2026-08-20: now Evergreen — #17 MERGED 2026-04-01; 15/15 mutation FormRequests carry
toDto(), arch-enforced attests/Arch/FormRequestsTest.php:30. Was: PR #17 — 7 DTOs, 6 FormRequests withtoDto(), 8 Actions converted;ProcessInboundInvoicedeferred because it takes anUploadedFile). Note the table names only three territories — several territories on the pipeline are simply not tracked here.) - 0013 — Adapter-Store Pattern over Pinia (Kendo-badged, single-row table — this is NOT a cross-project ADR despite being widely cited as one. kendo=Evergreen, 15+ domain stores on the adapter-store factory. No other territory is listed; town-crier and wijs deliberately do not adopt it. Do not read absence elsewhere as non-compliance.)
- 0014 — Domain-Driven Frontend Structure (Cross-Project, 2026-03-08. kendo=Evergreen (vertical domain slices enforced by
domain-structure.spec.ts+import-boundaries.spec.ts); brick-inventory=Evergreen. Only two rows — wijs is described elsewhere as the cleanest ADR-0014-shaped Back-to-code territory but is not in this table; town-crier's flat/RPC console is a ratified deviation.) - 0015 — ADR Governance — Single Source of Truth (Cross-Project, 2026-03-09, amended 2026-03-27. This page defines the
### Statesvocabulary every other ADR table uses — Not Started / In Progress / Partial / Complete / Evergreen — so it is the schema, not just an entry. kendo=Complete (7 projected ADRs, PR #694); brick-inventory=Complete under the laboratory exemption (full ADR content in.claude/docs/adr/with sovereign numbering, 0001–0029 consolidated post-Brickworks Phase 5, PR #67); the-laboratory=Complete (5 ADRs); entreezuil=Complete (6 ADRs, PRs #19/#21); ublgenie=Partial (5 ADRs, PR #23; ADR-0014 frontend deferred); fs-packages=Partial (2 ADRs; backend-centric ones marked N/A); emmie=Not Started (CLAUDE.md exists, no projections section); daymate=Not Started (orchestrator has only a README; vassal CLAUDE.mds lack projections). Resolved 2026-03-27: BIO keeps full content even for graduated ADRs, and projections are both pushed-on-amend and audited-for-drift.) - 0016 — Config Attribute Injection (Cross-Project, 2026-03-13. the-laboratory=Complete (23 usages, 0
config()); brick-inventory=Complete (3 usages); kendo=Complete (all 10 migrated PR #475,ConfigTest.phpenforcing); entreezuil=Complete (4 migrated PR #16,ConfigTest.phpenforcing); ublgenie=Partial — 2 of 6 migrated (PR #24), and the remaining 4 are BLOCKED, not pending:LogicTokenService,LogicAPIServiceand a manually-new'd (not container-resolved)Invoicemodel need a DI refactor first. Arch-test gap: the-laboratory, brick-inventory and ublgenie are Complete/Partial without an enforcing arch test — the-laboratory's is deferred until "test infrastructure matures".) - 0017 — Page Integration Tests (Cross-Project + Universal, 2026-03-30. brick-inventory=Complete — BIO sovereign ADR-0024; 18 domain pages / 17 integration tests; the mock-server pattern (in-memory HTTP service replaces the transport layer while stores/translation/router/auth run real),
fileParallelism: false, Vite alias for icon stubs, arch test enforcing coverage. entreezuil=In Progress — but the state contradicts its own note, which records 12/12 pages tested, 65 tests, PR #43 merged 2026-04-15 (one router-mock residual onResetPassword.spec.ts); this looks like a Complete row nobody flipped. kendo=Not Started (43 domain pages — 32 tenant + 11 central;asyncShallowMounthelper exists with 21 usages; phased by shared-component usage count, targeting one dedicated sprint). The phasing is explicitly prioritization, not scoping — the goal is full coverage.) - 0018 — ISMS Information System (isms; badges conflict — the page carries both Cross-Project and Territory-Specific; the body scopes to the isms repo. Date 2026-03-24, last revised 2026-05-26, ally-approved 2026-04-16. Compliance ISO 27001 + AVG + NEN 7510. Row REWRITTEN 2026-07-29 (previously the "Not Started — Repo to be created" fiction, the stalest row in the roll): now
isms=In Progress, first-hand-verified at HEADc05555d— 265 commits, monorepo, Laravel ^13.18 / PHP ^8.4, live war-room coverage. First-policy/first-control sub-claims not re-verified in that pass — re-read before citing. Reader caution: a second## Implementationheading at ~line 129 sits inside a fenced example of the control-file format — only the later one is the status table.) Amendment 1 (2026-09-03): framework as a first-class dimension — ISO 27001 and NEN 7510 are separate control sets with separate SoAs; ownership by role (owner_role_id);review_cycle_daysrestored. Implementation: isms ISMS-0036 (framework), ISMS-0035 (roles register), ISMS-0016 (seeder). - 0019 — Explicit Model Hydration (Cross-Project + Universal, 2026-04-13. kendo=Evergreen (41 models, 0
$fillable, 0 mass-assignment); brick-inventory=Evergreen (11 models); the-laboratory=Evergreen (all 5 experiments clean); entreezuil=Evergreen and the only one with teeth — PR #36 stripped$fillable, banned mass-assignment methods, 3 arch tests enforcing; ublgenie=In Progress (corrected 2026-08-20: now Evergreen — #89 MERGED 2026-04-17; 0 of 17 models declare$fillableandtests/Arch/ModelsTest.phpenforces it. Was: PR #89, 6 of 9 models remaining, noModelsTest.phpyet). Same arch-test gap as 0016/0011: four territories are Evergreen on inspection alone, with "arch test needed" recorded on the page and routed nowhere.) - 0020 — Input/Result DTO Split by Usage Direction (Cross-Project + Universal, 2026-04-21. kendo=Complete (PRs #901/#903; deptrac InputDTOs/ResultDTOs layers; 3 arch tests); brick-inventory=Complete (PR #160, 19 moves + double-loop fix,
App\Data\retired, BIO sovereign ADR-0010 amended); ublgenie=Complete (Phase 1 #130, Phase 2 #158, Surveyor-verified 2026-05-22 — rootDataTransferObjectdeptrac layer retired); entreezuil=Complete (PR #111, 10 moves); the-laboratory=Partial — Crucible Complete (PR #11), Gatekeeper / War Table / Parlour / Smokestacks deferred under the sovereign-experiment clause; War Table is the next candidate, Parlour + Gatekeeper "likely deferred permanently". Housekeeping: the page's## Propagation Checkliststill has all 7 boxes unticked.) Amd 1 (2026-09-07) — Semantic Boundary Types: DTO fields carry the domain type (Money, calendar-day vs instant,PeriodBound,Cursor, enums), and the same one-decode boundary binds the read side (row → Action through complete casts) and the frontend (decoder, LK-0318); a failed decode is an integrity fault, never a silent normalisation. Seed: 112 of 354 crit findings in one week, DTO fields ≈75% primitive on lokalekeuze / ≈90% on emmie. Enforcement queued #221 (casts completeness arch test), #222 (date-parsing PHPStan rule + skeleton VOs), #223 (FE decoder spec after LK-0318). Adoption: lokalekeuze first, skeleton, emmie before epic 26 F3. - 0021 — Canonical PHPStan Rules Package (Cross-Project + Universal, 2026-04-29. Compliance ISO 27001 A.8.15/A.5.33, AVG, NEN 7510. emmie=Complete (origin/donor, merged 2026-04-29); kendo=Complete (merged 2026-04-29; 1 suppression on
ProvisionTenantDatabaseAction, 2 kendo-only inline rules retained); ublgenie + entreezuil recorded as "Phase 1 PR open" — non-canonical status text and stale-prone; daymate-api=Blocked (PHP 8.2 / Laravel 9 vs the package's PHP 8.3+ floor); lego-storage=Not Started (Building Permit required); the-laboratory experiments=Not Started (six Laravel 12 apps, each adopts independently). Live trigger on the page: 3+ territories sharing the same suppression class fires a third ADR-0011 amendment. Note v0.1.0 failed on Laravel 13 → v0.1.1 widened the constraint to^11||^12||^13. Fleet reality has moved far past this table — every consumer is at^0.7as of 2026-07-27.) - 0022 — Schedule End Date Inclusive Semantics (Emmie, Territory-Specific, 2026-04-30. emmie=Complete (corrected 2026-08-18). ✅ RESOLVED — was STALE, verified 2026-07-27, applied to the page 2026-08-18: the row calls backend PR #195 a "draft, awaiting Commander local PHPStan + ally review";
emmie-app/emmie#195MERGED 2026-05-06, and ADR-0023's own table has recorded it as merged (e47dae1c) for 82 days. Two ADR pages have disagreed about the same PR for nearly three months. Frontend leg (clientAvailability>→>=) landed in PR #191.ScheduleReport::updated()lines 56/60/64 are preserved by intent; General-review commit 7 caughtScheduleReport.php:80missing from the Surveyor M9 inventory.) - 0023 — Schedule Mutation Chokepoint (Emmie, Territory-Specific, 2026-04-30, five amendments — 2026-05-06 snap-down underflow (EMMIE-0248), 2026-05-08 AmbulatorySchedule extension, 2026-05-13 F-L2 flipped convention-only→repair-migration-shipped, 2026-05-18 Phase 2 (EMMIE-0277 PR #245, asymmetric snap rule), 2026-05-18 PM post-customer-4-beta scope narrowing. emmie Schedule=Complete (PR #195 merged 2026-05-06
e47dae1c; two pre-merge regressions closed — EMMIE-0248 underflow + an overlap-validator stale-input P1). emmie AmbulatorySchedule=Complete (corrected 2026-08-18). ✅ RESOLVED — was STALE, verified 2026-07-27, applied 2026-08-18: recorded as "PR #218 open and ready-for-review";emmie-app/emmie#218MERGED 2026-05-08, 80 days ago. Flip to Complete. Other territories=Not Applicable — and the transferability gate is worth quoting: the PHPStan rule waits for a second TERRITORY, explicitly not a second model. Two cross-territory-general amendments live here despite the emmie badge: forward-only chokepoint over editable historical data (2026-05-13) and snap design over adjacency invariants (2026-05-18).) - 0024 — Automated External Provisioning (Cross-Project + Universal, 2026-05-01, amended 2026-09-03 — kendo burn-in COMPLETE: 11 production signups since 2026-05-27, 0 rollbacks, flag removable at the ally's discretion; WR-1148; amended 2026-05-20 — retain-on-failure FLIPPED to rollback-on-failure to match kendo's pre-existing
SignupAction; §4 failure handling, §6 authorization, Options, Enforcement and Resolved Questions all rewritten. kendo=Complete (corrected 2026-08-20) — #1028 MERGED 2026-05-22;ProvisionDomainAction+RollbackProvisioningAction+DomainAuditLogger+DomainPolicyall live at HEAD. Every other territory remains Not Started. Was: "Every territory is Not Started — kendo is the intended first adopter with PR #1028 (KD-0580) being re-planned against the ADR", gated behindDomainAuditLogger, aDomainPolicy+RoutesAuthorizationTestcentral-route extension, and KD-0596. ublgenie needs a Cartographer pass before scoping; emmie'sCreateAwsBucket.phppredates the ADR; daymate-api speculative. An accepted ADR with zero adoption after ~3 months.) - 0025 — GitHub Integration Split (Kendo-specific, 2026-05-07. kendo="ADR adopted, refactor not started" — non-canonical state string; scoped from
docs/plans/KD-0611-github-integration-split/SEED.md, with the follow-up kendo issue to be created when Jasper begins execution (ally-clocked, not ours). Out-of-scope fortification — cachinggetInstallationTokenper-installation with a 5-minute pre-expiry skew — tracked separately as KD-0622.) - 0026 — Decrement Action Symmetry Discipline (Cross-Project + Universal, 2026-05-15, amended the same day: the atomic-conditional shape (Option E) supersedes the initially-accepted caller-side discipline (Option A) after a PR #240 reviewer surfaced a TOCTOU race in caller-side SELECT-then-decrement. No Implementation table exists — the
## Implementationsection is a three-phase plan, not per-territory states: Phase 1 retrofit on PR #240 (revert the caller-side guard inUpdateVacationAction:91-109from8ffae54f44, apply the atomic conditional, add a behavior test, authortests/Architecture/DecrementActionSymmetryTest.php, verify EMMIE-0273 closes in the same patch); Phase 2 Quartermaster sweep (F-2 backfill + F-5 Level-1 arch test); Phase 3 cross-territory propagation when a second territory introduces a counter-mutation Action. Current sites are emmie-only.) - 0027 — Canonical Territory Skeleton (Cross-Project + Universal, 2026-05-27; amended 2026-07-13 (frontend test layout & canonical Vitest config) and 2026-07-14 (canonical arch-test skeleton). Main table: entreezuil=Complete (full adoption campaign, merged 2026-06-30 — R1 #249, R2 #270, R3 #263, R4 #264; 2 ratified exemptions incl. non-final
CMSmsUser, tracked WR-0229); isms=In Progress (greenfield first adopter); brick-inventory=Partial (13 of 14 baseline dirs, missingAudit/); kendo=Partial (tests atArch/is a deviation, rename on next arch-test mission); ublgenie=Partial (baseline +ValueObjects/); emmie / codebook / daymate-api=Not Started. ✅ The "ublgenie listed TWICE with contradicting states" warning was re-verified at HEAD 2026-08-18 and does NOT reproduce — the## Implementationtable carries exactly one ublgenie row (Partial,canonical-territory-skeleton.md:174); the second match (:249) is a different table (the 2026-07-14 arch-test amendment scope), also Partial, so there is no contradiction and nothing to dedup. Warning withdrawn. Amendment 2026-07-13 has its own scope table: fleet Vitest baseline Established (4.x,.spec.tsundertests/, no globals), happy-dom/v8 Partial (wijs istanbul is a documented deliberate override),templates/vitest.config.tsComplete — explicitly Level 4 + template, NOT Level 1, no CI teeth; the path to teeth is a/canon-checkdrift axis, noted as a follow-up. Amendment 2026-07-14 IS Level 1 (runs viacomposer test:arch→ci-passed):templates/tests-architecture/Complete (6 test files +Support/ArchTestHelper.php+Pest.php.fragment), town-crier Complete as the extraction source, entreezuil Complete, ublgenie/codebook/wijs/kendo Partial, emmie/isms Opportunistic. Residual Level-6 gap: nothing gates a territory that never adopts at all.) - 0028 — Canonical Git Hooks (Cross-Project + Universal, 2026-05-27. ⚠ TWO NUMBERING AXES — settled 2026-08-31. The ADR's roadmap numbers the mechanism, and its stages were renamed Stage 2 (Lefthook) / Stage 3 (package distribution); neither is built, and the mechanism is still deliberately plain
core.hooksPathshell scripts. The script revision keeps v1/v2/v3 and is now at v3. They had collided at "v2"; the mechanism axis was the one renamed because the script numbers are load-bearing in 46 places (board rows incl. WR-1114,deferred.md, spy memory, briefings) while the stages were referenced in four and describe nothing built. "hooks v2" always means the script revision. Complete + disk-verified 2026-07-11: canonical/templates/githooks/, war-room itself, isms, brick-inventory-orchestrator, kendo, codebook, town-crier, wijs. ✅ RESOLVED — was STALE, verified 2026-07-27, applied to the page 2026-08-18 (all three now Complete): emmie / entreezuil / ublgenie had been recorded In Review as of 2026-07-11; all three PRs have since merged — emmie#637 (2026-07-13), entreezuil#288 (2026-07-11), ublgenie-app#467 (2026-07-13). Flip all three to Complete. Not Started: daymate-api (Laravel 9 / PHP 8.2 — confirm hook scripts first), fs-packages + phpstan-warroom-rules (single-root repos), the-laboratory (per-child-app question, deferred to a recon mission). SCRIPT REVISIONS — v2 2026-08-28, v3 2026-08-31. v2 replaced v1's hardcoded script names with per-gate resolution against a candidate list, because the fleet agreed on none of them: composerstanwas present on 2/11 hook-carrying territories,pint:checkon 3/10, npmvue-tscon 4/11 — those gates could not pass on any machine in any tree, and theirnpm error Missing scriptoutput reads like a lint failure. v2 also refuses a resolved script that is a writer (pint,format), which would rewrite the tree from a pre-commit hook. v3 (template + reference consumer lokalekeuze landed 2026-08-31; the other 9 territories are WR-1114 and NOT yet propagated) closes four measured defects: (1)pre-pushnever read its stdin, so a branch deletion ran the full gate set — v3 skips a deletion-only push and fails closed on no stdin (WR-1118); (2) under WSL on a non-interactive PATHnpmresolves to the Windows binary and fabricates a CMD.EXE build failure — 21 hook files across 11 territories were unguarded, only war-room's ownpre-pushhad the fix, and v3 is the first revision to guardpre-committoo (WR-0879); (3) the mandatory Pest gate was labelledFeature + Unit + Architecturewhile invoking onlycomposer test— a Claim-Gate violation that terminates the search, now relabelled to name the config that decides coverage, with an optionaltest:archgate (WR-1133); (4) an absent runner was reported as a missing script or as a lint failure — v3 checksphp/composer/npm/nodebefore each gate and treats exit 127 as command-not-found (WR-1122). Outcome vocabulary is now three-valued (FAILED / MISSING / COULD NOT RUN) and a run in which nothing ran never prints "Fix the issue". Propagation prerequisite (WR-1114 blocker): 6 territories have notypecheckscript and 2 no aggregatecomposer test, so v3 would newly block every commit there — add the scripts first, per territory. War-room relevance: this ADR's hook is the only control that can prevent a brokenpresentation/commit reachingmain, since the repo is private on a free plan and cannot be branch-protected —/musterre-checkscore.hooksPathevery run.) - 0029 — Audit Row Durability Contract (Cross-Project + Universal, 2026-05-28, amended 2026-06-26 — Actor & Originator Write-Once Durability. Compliance ISO 27001 A.5.33 + A.8.15. Uses a custom status legend, and two rows sit off even that: kendo=Violations Present (Sapper sweep 2026-06-04, 54/54 — 3 HIGH, 3 Medium incl. KD-0718, 3 Low; broadcasts clean; pins
phpstan-warroom-rules ^0.2soEnforceAuditTransactionScopeRule(0.3.x) is not adopted; no CLAUDE.md projection, no->ordered()contracts; remediation routed Medic/Engineer) and emmie=Violations Present (19/19 — 1 MediumUpdateClientLocationAction:45-50; multi-tenant clean; documented rule-coverage gap — the blocklist would NOT catch this custom-contract case). isms=Complete (corrected 2026-08-20 — #7 MERGED 2026-05-28;->ordered()contracts across four unit tests); was In Progress (first to land, PR #7f1d357b;->ordered()Mockery contracts in 3 unit tests; projection landed). codebook=Pre-Adoption Blocking — the next audit-landing dispatch MUST carry the projection + reference shapes. entreezuil / ublgenie / brick-inventory=Currently Safe–Doctrine Pending; daymate=Not Started. Amendment: adds failure mode 3 (post-hoc patching of the audit row's actor, structurally impossible on an append-only hash chain); actor + originator are written once, inside the transaction, as hashed material. Sequencing is prose, not a table — emmie rides the β4 Product port with no standalone fleet migration before it; kendo gets relation-resolved originator on theissue_audit_logssubset plus a banked class-D fix (pruneStuckRunningbypasses the logger hourly;Scheduler/CliActorType cases defined-but-unwired); entreezuil's Kiosk typed-FK + byte-compatible hash extension is the sanctioned non-Useractor precedent; isms deferred to audit slice 2. The post-hoc-patch prohibition is a candidate arch test — not built. The^0.2pins on kendo and emmie are the actionable item here — the rule that would catch this class exists and is not loaded. Note the fleet is at^0.7today, so re-verify these two rows at HEAD before acting.) - 0030 — Workflow Orchestration Dispatch Mode (internal — not published. Accepted 2026-05-29. Deterministic JS orchestration via the Workflow tool: NOWRITE for all agents, schema-forced output, ~110K tokens/agent — explicitly not for casual firing. Runbook lives in the
dispatch-modesskill.) - 0031 — Datetime Instant-vs-Wall-Clock Classification (Emmie pilot + Universal, 2026-06-02. Compliance ISO 27001 A.5.33 temporal record integrity, AVG, NEN 7510. The scope is split and the split is the point: §2a immutable instant hydration is fleet-wide NOW by Commander directive (amended 2026-07-03); only the wall-clock mechanism (§1a/R3/R2) stays pilot-then-propagate. §2a per territory: town-crier=Complete (PR #131 merged 2026-07-03 — the proving ground:
Date::use(CarbonImmutable::class)+immutable_*casts + both gates,DateImmutabilityTestteeth-proven RED and aModelsTestcast scan); Fleet=In Progress under WR-0310, one Armorer dispatch per Laravel territory, riskiest last (emmie/kendo) — and the runtime guard is a precondition of each flip, not a follow-up. Three migration hazards documented from the town-crier flip:CarbonImmutableis NOTinstanceof Illuminate\Support\Carbon; PHPStan is blind onnow(); unit mocks prove nothing. emmie legs: EMMIE-0317 point fix Complete (PR #303 — three->setTimezone()calls removed fromCalculateRevenueTotalsAction, RED→GREEN DB-backed canary 0→500, applied ahead of the ADR); classification doctrine §1, backend mechanism R1/R3/R4/R5, and the wire change §1a + frontend Temporal helper R2 all Not Started — and §1a/R2 are coupled: the casts flip the wire to naive, sotemporal-polyfill+dates.ts+ a ~187-site migration must land in the SAME release (WP-echo pre-flight grep required). A cross-territory PHPStan rule is deferred with an explicit gate: "second territory adopts", not "emmie proven".) - 0032 — Cached-Adapter-Store Hash-Bumping Protocol (Subscribe-via-Header) (Cross-Project + Universal, 2026-06-08. Compliance ISO 27001 A.5.33 — the stamped hash + authorization filter are an information-disclosure surface. ✅ RESOLVED — was STALE, verified 2026-07-27, applied to the page 2026-08-18 (kendo now Complete, follow-up discharged): kendo had been recorded In Progress on backend keystone PR #1440 with a note reading "CI green (Feature Tests finishing)";
script-development/kendo#1440MERGED 2026-06-10, 47 days ago. Flip to Complete and discharge the recorded follow-up (memoizemakeLabelStoreForProjectafter merge). fs-packages=Complete (corrected 2026-08-20 — #114 MERGED 2026-06-09, package published at 0.2.5); was In Progress (outbound subscribe-header middleware D1 + reuse-registry +as HttpServicecast, minor0.2.0, PR #114, 8 gates green locally, mutation 95.5%). wijs="Phase 0 merged" — a non-standard state, and the interesting one: under the Scope Amendment (2026-06-19) a single-tenant territory adopts the invariants (DB-stored hash read in one query from a dedicatedcache_hashes(key, hash, updated_at)table; an explicitBump{Entity}HashActioninside the mutating Action's transaction, no observers; a stamp middleware whose transport is not load-bearing) and explicitly does NOT adopt thex-fs-cache-hashes-subscribeheader, the per-key authz loop, or the N+1 subscribe-resolution guard. The one control single-tenant retains: the stamp must still be authorization-filtered and auth-scoped — that is a compliance control (A.5.33 / AVG), not an N+1 mitigation. wijs Phase 0 = PR #56 merged 2026-06-20; the homegrown event-drivenModelHashCookieloop retires across a 4–6-dispatch campaign (Phases 1–3 Question/Location/Document → Setting/User → Resident, Phase 4 teardown gated on all 7). Option C (denormalized tenant-scoped hash row + Redis mirror) recorded as a Deferred fallback.) - 0033 — AVG Erasure by Anonymization-in-Place (Cross-Project + Universal, 2026-06-17. Compliance AVG/GDPR Art. 17, NEN 7510 (codebook ingests minors' data into the emmie care surface), ISO 27001 A.5.33. Transferability is carefully bounded: the completeness methodology is universal, the anonymize-vs-hard-delete choice is territory-specific, and the execution discipline once anonymize is chosen is universal. codebook=In Progress (ratifying + first implementation; scrub-set map verified by field report + debrief; four slices — (1) OpenAI
thread_idpersistence [soldier-ready], (2)DeleteFileActionADR-0029 ordering fix [soldier-ready], (3)AnonymizeUserAction+ completeness/arch tests, (4) retireHardDeleteUserAction). emmie=Not Assessed — and it is a blocker, not a gap: the emmie bulk-erase-by-token endpoint is this ADR's cross-territory candidate and an emmie-side prerequisite for codebook's downstream completeness. ublgenie / wijs / daymate share ONE combined row = Not Assessed (AVG territories; the methodology applies if/when erasure is scoped). No amendments. Cross-reference for the reader: the 2026-07-20 personal-domain sweep found no erasure path exists anywhere in the-laboratory estate — that estate is not in this table at all.) - 0034 — Ambulatory Financing Care-Type / Rate-Interval Coupling (Emmie, Territory-Specific, 2026-06-19, amended 2026-06-24 — guard split for Action-pattern compliance. No
## Implementationtable exists — the## Implementation plan (post-ratification)section is a role list, not per-territory states (Engineer: chokepoint Action + exception + reroute sites 1–6 + the projection into emmiebackend/CLAUDE.md; Armorer: Level-1 arch test for invariant + bypass-ban, optional DB CHECK if Open Q2 clears; Scout: frontend affordance recon on the financing form + reassign picker interval filter; data repair gated on Open Q1). Amendment: the original shipped as PR #461 with ONE Action carrying two public methods (execute()+sanitize()) — a Principle #2 violation, made load-bearing by a review-surfaced N+1 (a constant financing id re-resolved per row). It splits into two single-executeActions inApp\Actions\Model\Financing\:AssertAmbulatoryRegistrationFinancingAction(throwsInvalidFinancingForAmbulatoryException; user-initiated attach sites) andSanitizeAmbulatoryRegistrationFinancingAction(never throws; the batch auto-attach pathMarkRegistrationsAsLocationClosedAction). This explicitly supersedes the "two entry points on one Action" framing in §Decision-2/5 and in thebackend/CLAUDE.mdprojection. Open Q1 RESOLVED 2026-06-19 — the Commander ran the corrected query, zero rows across tenants, so the invariant is LATENT not LIVE and no data-repair/backfill migration is required; the chokepoint ships as a pure forward-only guard. Q2 (per-tenantSELECT VERSION()→ DB CHECK feasibility) and Q3 (chokepoint shape) remain open.) - 0035 — Appointment-Slot Inverted-Window DB CHECK Backstop (wijs, Territory-Specific — "no fleet projection", 2026-06-24. wijs="Complete (code) — prod-deploy is the residual." Both rollout steps merged to
developmentwith feature tests: Step 1 repair migration (surgical 9-occupation repoint +DELETEof all 576 inverted rows) + its test; Step 2 constraint migration addingchk_appointment_slots_window(e3628c64) + test, plus a sqlite driver-guard follow-up (0319db1d). Level-4 doctrine line in the wijsCLAUDE.mdslot section — Done. A complementary drop-guard arch test (flagging a future migration that DROPS the constraint) is Not started — left optional per deliberation, promote to the enforcement queue on a second window-invariant regression. Residual: confirm the repair + constraint actually ran against PROD — the 576-row repair is the load-bearing, irreversible step. Note the residual was written against the old manualfly deployvehicle (WR-0104); wijs deploy has been automated since 2026-07-20, so re-read that residual before acting on it. A single atomic clean-then-constrain was explicitly Rejected as too destructive for an AVG care-data territory; CHECK is enforced natively by MySQL 8.0.45.) - 0036 — Cross-Harness Producer Ingress — Bus-Hosted GitHub App (town-crier + Cross-Harness Contract, 2026-06-26. Tracks kendo
TC-0014(script instance, project 13). town-crier=BUILT + PROD-LIVE — PRs #57 (HMAC ingress +pull_requestannounce/resolve), #58 (install persistence + outboundGithubAppClient+ consensus +/github/health), #59 (vue-tscgate fix), all merged and released 2026-06-26; org-installed as Apptown-crier-announce, app_id 4161413, across script-development / Back-to-code / emmie, reach ~40–50 repos; all five §Enforcement Pest tests confirmed present at HEAD (ExternalHttpTimeoutTest,installation_id-keyed token-cache unit + Feature, apull_request/pull_request_reviewwebhook-replay Feature matrix, and an HMAC-fail-closed-on-empty-secret test). producer repos = "Mostly decommissioned — 3 survive": 11 of the original 14 per-repoannounce-pr.ymlproducers removed; daymate, isms and ublgenie still double-announce alongside the App webhook (verified 2026-07-10) — idempotency makes the overlap a no-op, and per §7 step 4 each is removed only after its org's/github/healthsignal is confirmed. The remaining decommission sweep is war-room-authorable — a ready piece of work. Status provenance: Jasper cleared the contract and signed off on trust (TC-0014 comments 2548 + 2550) but declined a separate ADR-text review, soAcceptedmeans decision adopted, not text sign-off. The page carries its own freshness stamp — table and §7 current to 2026-07-10. Push-based observability (bus scheduler + Mattermost webhook) is Deferred; pull-first covers the directive.) - 0037 — fs-http Middleware Guarding by Default (fs-packages; Accepted 2026-07-08 — SHIPPED
0.6.02026-07-11, fleet adopting^0.6.0; supersedes the consumer-guard half of Principle #8 by default on 0.6.0) - 0038 — Daymate Data-Encryption & Privacy Doctrine (daymate; territory-specific; Proposed — pending expert review + 3 operational confirmations)
- 0039 — Cross-Harness Merge Gate — Findings-as-Rows / Derived Gate State / Check-Run Teeth (town-crier; Accepted — TC-0041 built + prod-live;
gate_mode/TC-0054 pending amendment) - 0040 — Cross-Harness Review Thread & Turn-Lock Protocol (town-crier; Accepted — the coordination substrate: serialized announce→claim→submit→resolve thread, no-two-turns, cap/TTL termination, server-stamped invite-based identity; prod-live 4-way)
- 0041 — Cross-Harness Severity Ladder (town-crier; Accepted — TC-0036 shared Blocker/Major/Minor/Nit vocabulary, as-if-true + confidence/provenance tags, R1–R4 riders; enum-backed via TC-0040/ADR-0039)
- 0042 — Per-Repo Read Authorization, Derived from GitHub Access (town-crier; Proposed 2026-07-13 — retires D1 "any member reads all" for a per-repo scope resolved from the member's GitHub login via the App's installation credentials, cached off the hot path, fail-closed; scopes index/show/batch + write verbs; folds in the enact-verb authz question. Awaiting Jasper socialization — shared read-authz contract. Reasoning:
campaigns/town-crier/2026-07-13-per-repo-read-authorization-github-derived.md) - 0043 — Headless + Themeable Shared Vue UI Components (Cross-Project; Accepted 2026-07-16 — shared Vue input components as a headless behavioural core (select/combobox/field — the 4×-reinvented controls) + a structural CSS-var theme contract (34
--ui-*props, palette AND border-width/radius/shadow-shape/label-transform — a colours-only contract fails, spike-proven kendo→BIO) + error-as-prop; newui-*family in the fs-packages Armory (NOTfs-— that's frontend service), pkg@script-development/ui-inputs, peers on fs-theme, graduate-to-own-repo-if-it-grows; phase-1 UnoCSS-core consumers (kendo=donor, BIO=first live consumer), date pickers deferred.ui-inputsLANDED — PR #160 merged +0.2.0published to npm 2026-07-15 (props required-where-meaningful,aria-requiredconveyance,optionsLabel;0.1.0/Fs*deprecated). BIO PILOT LANDED — WR-0431 / PR #284 (2026-07-16): full atom-at-call-site, entire local molecule kit retired (16 consumers, ~30 specs, 8 molecules deleted, −949 lines, all gates green); thebrick-*→--ui-*token map + error-prop contract validated end-to-end against a maximally-divergent design language → the "one live consumer before 1.0" precondition met, flipped to Accepted.0.3.0SHIPPED — WR-0460, PR #162 merged + published to npm 2026-07-17: Number/Date/Textarea atoms +--ui-control-bg-focus/--ui-control-bg-invalidvars. Nullable-value contract settled by emmie recon (the fleet convention for ALL form inputs): backend serializes a nullable column to literalnull; FE typesstring|null/number|null; the component bindsnulldirectly (no?? ''inside) and emits raw''on clear, which Laravel'sConvertEmptyStringsToNullmaps back tonull— soTextInputwidenedstring→string|null;NumberInputis the ONE exception (emitsnullon empty — anumbercan't hold''honestly). BIO ADOPTED — WR-0472, PR #300 MERGED 2026-07-20 (05e2a7d): 11 number/4 date/7 textarea converted, NaN handlers deleted, token-map on the bg-state vars. Bus-reviewed CLEAN on an independent first look (thread #799, zero findings at any tier): nullable contract hand-traced at every conversion site (domain-non-nullquantityuses a decoupled local ref + submit-time?? 1— local-form-state coercion, wire type untouched; already-nullable fields bind straight through with no smuggled?? ''/?? 0), all 7 deleted NaN guards confirmed to have landed their invariant somewhere real (none orphaned), the two relocated hex values byte-identical (pure relocation, not a value change), specs re-narrated rather than weakened. Lessons: theTextInputwiden is NON-breaking (Vuev-modelvariance — spike-proven, no consumer re-type); local-form-state widen ≠ domain-wire-type widen. Follow-ups: combobox AT-focus WR-0441, BIO coverage-scope WR-0461,--ui-control-text-focus(+-invalid) var = WR-0479 (BIO's residual focus-text override). SECOND CONSUMER — isms ADOPTED 2026-07-20 (PR #113 merged): 9 controls across 5 files; isms had no input kit at all (11 raw inline controls), so this stopped one being born rather than retiring one. Playbook correction: the token map is NOT universallyshared/— isms runs two design systems from one repo (Samizdat.app-colleague/ Bunker Brutalism.app-worker) and its owncheck-style-bleed.shrejects a single shared map naming both families (correctly —shared/stays unbranded; the guard greps comments too), so a multi-design-system territory needs one map per app, colocated. Both systems shared one field idiom (bottom-underline, no radius/fill/x-padding) so the maps differ in palette not structure — reached via theborder-widthSHORTHAND (0 0 1px);--ui-field-marginis likewise a shorthand. Mapping ontorgb(var(--bb-*))made thedata-watchday/night flip travel free (the BIO light/dark dividend). Pinned^0.3.0→ WR-0513 bump landed as isms PR #115 (0.4.0 published to npm 2026-07-21).0.4.0= WR-0441 combobox a11y (PR #171 MERGED + published to npm 2026-07-21):aria-activedescendant+ position-keyed option ids +aria-selectedon the committed value, plusaria-controls(which WR-0441 omitted and without which the fix is inert — the trigger is a<button>, the listbox its sibling). Two foreign harnesses correctly refuted our descope of a dangling-index defect: "pre-existing" fails when the diff WIDENS the trigger surface (keypress-gated → every-render) — see memoryfeedback_severity_preexisting_not_downtier. Contract gaps are now a pattern → WR-0512 (one coherent state-variant pass folding WR-0479):border-color/width-focus+--ui-control-font-size(the subtle one —font: inheritis a shorthand that also resets font-size, and the package stylesheet wins the source-order tie against utility classes). Also WR-0514 (ui-inputs is the only package of twelve with no docs page — the playbook lives only in campaigns) + WR-0515 (isms preview-bb showcase). ublgenie DEMOTION RESCINDED 2026-07-21 (was stale) — RE-PROMOTED. The demotion rested oneditorial/FilterSelectbeing more accessible than ourSingleSelectwas: it carriesaria-activedescendant+ committed-valuearia-selected+ roving nav, which pre-0.4.0 SingleSelect lacked. WR-0441/0.4.0 added exactly those → a11y PARITY, so the regression argument is dead. (FilterSelect is a plain button+listbox — the name misleads; it does NOT type-to-filter, so no feature gap either.) Churn is small — 7 direct FilterSelect importers, dissolved by the same thin-adapter pattern (reshapeeditorial/FilterSelect/editorial/Select→SingleSelectadapters, importers untouched; the twoMultiselects stay out-of-scope; the legacy root tier is dead/0-importer). Adopting ublgenie next (2026-07-21 Commander ruling). Adopted 2026-07-21 — engine-independence PROVEN across THREE CSS engines against the one--ui-*contract: entreezuil (Bootstrap 5, PR #322 — but note it HAS_tokens.scss/--ent-*, the ladder's "zero own tokens" was wrong; map source =--ent-*+ Bootstrapform-selectdefaults), scripthub (Tailwind v4, PR #48 — Arman's proposal, ally-gated + avue 3.5.34→3.5.40bump), wijs (UnoCSS, PR #213 — pushed--no-verify, CI-authoritative on the backend). Each fresh adopter keeps its homegrown component as a thin adapter over the ui-inputs atom (preserves the call-site API + absorbs value-type/boolean impedance via index-keyed ids; see [[reference_ui_inputs_04_bump_lockfile_graft]] + the hub memory). Remaining: emmie last (28 components, ~550 sites, 100%×4 + Stryker — a major campaign, NOT a quick adoption); ublgenie stays DEMOTED (adopting = an a11y regression vs its own more-accessibleeditorial/FilterSelect). Recon+spike:campaigns/war-room/2026-07-14-vue-input-component-library-recon.md; review→publish:campaigns/war-room/2026-07-15-ui-inputs-160-review-merge-publish.md; pilot:campaigns/war-room/2026-07-16-ui-inputs-bio-pilot-wr0431.md; 0.3.0+adoption:campaigns/war-room/2026-07-17-ui-inputs-0.3.0-atoms-and-bio-adoption.md; 2nd consumer + WR-0441:campaigns/war-room/2026-07-20-ui-inputs-second-consumer-isms-and-wr0441.md; 0.7.0 (MultiSelect, WR-0523) + 0.8.0 (checkbox family, WR-0538) BOTH SHIPPED 2026-07-22 → same-day fleet bump^0.4.0→^0.7.0(5 PRs: BIO #321 / wijs #214 / isms #116 / ublgenie #537 / entreezuil #324; scripthub excluded, #48 still ally-gated) + ublgenieeditorial/Multiselectadapter #539 (stacked; Commander-accepted search-box divergence → WR-0539 restore path) + lab expansion: zmuuzn-auth #143 (Gatekeeper — Blade auth forms structurally out of reach, Vue half only) + puppeteers-workshop #1 (35/35, the first FULL adoption + first checkbox consumer) — consumers 6→8; kendo donor-verdict EXPIRED (a11y flipped — its selects lack the whole WR-0441 layer): two-release path WR-0542 (fat minor + the dead floating-uihide()fix — grouped-options did NOT ship in it despite the original filing intent; that gap is WR-0574) → WR-0539 (MultiCombobox); day record:campaigns/war-room/2026-07-22-ui-inputs-0.7-fleet-bump-kendo-lab-adoption.md. Same day: WR-0532 coverage gate RESTORED (PR #182 merged) — vitest 4 had killeddefineWorkspace, leaving the Armory's 100% gate print-only; migrated totest.projects+ 13 named glob-scoped threshold groups (coverage is ROOT-only under projects — per-project thresholds verified ignored) + global-100 backstop; teeth-proven 0→1→0. 0.8.0 checkbox family = WR-0538/PR #183 (native chassis; boolean models non-nullable; ARIA asymmetry:aria-requiredillegal ongroup, legal onradiogroup). 0.9.0 SHIPPED (WR-0542 + WR-0537 folded; PR #184 merged + published to npm 2026-07-22 evening): per-option scoped slot, committing clear entry (pre-list, outside the index space),mutedOptions, width/touch/typography vars ×10 (incl. WR-0537's--ui-menu-font-size+--ui-control-line-height), MultiSelect selected-state CSS, and the dead floating-uihide()fix (referenceHidden never consumed — live in every consumer until it bumps; fixed under the unchangedfloatingStylesname). WR-0524 wave OPEN at^0.9.0same evening — 7 consumer PRs (BIO #323 / wijs #216 / isms #117 incl. the WR-0537 line-height RESIDUAL discharge / ublgenie #541 / entreezuil #324 retargeted in place / zmuuzn-auth #145 / puppeteers-workshop #2 — the last also proved 0.8.0-family compat, and its committed-bundle convention means fleet bumps there must rebuild+commitstatic/); peers byte-identical 0.7.0↔0.9.0 so every lock delta was a single entry, no grafts; scripthub excluded (#48 ally-gated). Same evening: WR-0348 step-3 touch-ups landed as PRs (town-crier #232 guard redirect-object collapse + the 3 restored replace-bounces; BIO #324 registerAuthGuard collapse) — the fs-router 0.2.0 API is now actually consumed, not just pinned. Session record:campaigns/war-room/2026-07-22-ui-inputs-checkbox-family-and-kendo-readiness.md. 0.10.0 SHIPPED (WR-0539 MultiCombobox + WR-0521 Home/End+aria-live; PR #185 merged + published 2026-07-23) — input-as-trigger APG shape (Commander ruling; kendo SelectSearchInput parity; filterable-prop variant ruled out),#optionforwarded (LabelPicker unlock); the 3-party review cycle (our R1 + dmooibroek's rig + our R2) also root-caused a 3-strike "browser-test flake" into a REAL shipped defect: hover (0,3,0) masked the:focus-visible/.is-open/.is-invalidbox-shadows in every consumer →:where()specificity-drop fix + regression test rode #185.^0.10.0fleet wave 2026-07-23 (7 PRs: BIO #325 / entreezuil #326 / zmuuzn-auth #147 / wijs #220 / isms #119 hand-grafted-lock — unrelated oxlint-1.75 ERESOLVE landmine noted / puppeteers-workshop #4 static-rebuilt / ublgenie #543 = bump +searchableLIVE→MultiCombobox, default-off, the WR-0539 restore path; scripthub #48 still ally-gated). kendo ADOPTION CAMPAIGN OPENED 2026-07-23 (campaigns/kendo/2026-07-23-ui-inputs-adoption-campaign.md; adapter-first, 3 phases): Phase A = kendo#1823 (map + SingleSelect/SearchableSelect adapters, 27 call sites untouched, KD-0721 touch clamps as map vars,modal.css dialog{overflow:initial}invariant documented) — it surfaced WR-0576 (Combobox opened filtered to committed label — fleet-wide browse-to-change defect since 0.6.0) fix authored in fs#186 (ui-inputs 0.10.1— equality-disengaged filter + select-all-on-open; MultiCombobox symmetric-unaffected) — #186 MERGED 2026-07-24 (corrected 2026-08-20; ui-inputs is at 0.10.2 today). It had been recorded OPEN / UNMERGED after Warden F-0 caught the record overstating it as shipped — the correction then went stale in the other direction and sat 27 days; merge is Commander-gated (fs-packagesmain= release branch → fleet bump). So 0.10.1 is NOT published and WR-0576 (browse-to-change: Combobox opens filtered to its committed label) remains LIVE in the shipped 0.10.0 across all 8 consumers. Disposition: review + drain #186 to close — it is review-ready, not broken. Phase B (MultiSelect/MultiCombobox + LabelPicker) gated on #1823; Phase C (GroupSelect +items/*retirement + KD-0721 restatement) gated on WR-0574 (grouped options). Residue: WR-0569 (n=4useOptions/LiveRegion extraction + MultiSelect chip-focus sibling).) - 0044 — Collection Response Shape — Bare Arrays (Bounded) vs Cursor Pagination (Unbounded) (Cross-Project; Accepted 2026-07-16) — codifies de-facto fleet practice for list responses: BOUNDED sets (known ceiling) return a bare JSON array + client-side pagination (kendo/emmie
JsonResource::withoutWrapping()+Resource::collect(), isms array-backed spatie Data — isms is the norm, not the outlier); UNBOUNDED DB-backed registers return a LaravelCursorPaginatorenvelope ({data,next_cursor,prev_cursor,per_page}) — cursor MANDATED over offset (stable under concurrent inserts on append-heavy compliance registers; BIOGetFamilyPartsActionprecedent; per_page cap 100). Tier is a design-time per-endpoint call keyed on unbounded-growth potential (semantic, not a row-count threshold); the two shapes coexist permanently and a bounded list is never retrofitted to an envelope. Commander-accepted trade-off (2026-07-16): a bounded list that unexpectedly outgrows FE pagination takes a one-time breaking shape bump (vs the rejected{data}-everywhere fleet churn). Closes the war-room "no pagination ADR" open item + structurally dissolves the isms Liaison collection-envelope forward-risk. Recon+reasoning:campaigns/war-room/2026-07-16-collection-envelope-pagination-adr.md. First live enforcement — kendo#1807 (2026-07-21): an ally-harness PR (Eoghan) shipped offset pagination on the unified central audit-log read API — the exact append-heavy-audit case the ADR names — plus a reusablePaginatedResourceDataoffset envelope whose docblock recruits the shape fleet-wide; reversed our own 3-round APPROVE with a REQUEST_CHANGES (the prior rounds checked correctness, never doctrine-conformance — see [[feedback_rereview_moved_pr_verify_at_head]]). Resolution =CursorPaginator+ a separately-computedtotal— the key insight is thattotalis separable from the page mechanism (bolt the existingcountAll()onto a cursor envelope; note BIO'sCursorPaginatorcarries no total, so this is a small new shape), and offset's only exclusive capability — absolute page-jump — is semantically incoherent on a prepend-heavy feed (page N names a different set every insert), so nothing real is lost. Narrow Option-B amendment (offset permitted only for a viewer hard-bounded by a default filter/time-window, making it bounded-per-view) named as the only carve-out the General would sign, but not available on the current PRs (the endpoint takes onlypage/per_page, no filter). Amendment analysis:campaigns/war-room/2026-07-21-adr-0044-offset-vs-cursor-audit-viewer-amendment-analysis.md. Root cause (allied harnesses don't track our cross-project ADRs) parkeddeferred.md [doctrine] cross-harness-adr-propagation-to-ally-harnesses. Resolution LANDED + verified (2026-07-23): kendo#1807 re-worked to a hand-rolled keyset cursor over the(created_at, id, source_table)total order + separately-computedtotal; approved at head after a Commander-ordered full re-trace (hand-rolling justified — native union+cursor applies keyset/limit outer-only and breaks backward paging); the fleet-recruiting offset envelope DELETED, replaced by the reusableCursorPaginatedResourceData— now the large-tier reference implementation. Residual hardening (crafted-cursor→500 guard as a shared decode helper,countAll()TTL cache, second-precision schema pin — the'Y-m-d H:i:s'cursor is lossless ONLY on second-precision columns) = kendo KD-1059; review lens for future adopters in memoryreference_cursor_keyset_pagination_review_lens. - 0045 — The War Tent — Commander's Field Command Post (war-room; Accepted 2026-07-17 — ratified on Phase 1's seats landing. Tauri v2 + Vue 3 Windows-native/WSL2-bridged desktop command post on the Mezzanine substrate line; rulings: name (war-table collides with a lab codename), six fixed seats as config, spy
Score: N/10stamps forward (8 SOPs amended), design via lab campaign, updater keys Commander-gated. Phase 1 (The Seats) COMPLETE 2026-07-17 (PRs #6–#12): pty substrate/live seats/xterm/first-run wizard, smoke-tested live. Phase 2 (The Map Table) COMPLETE 2026-07-17: Slice 1 #13 bridge readerresolve_for_std_fs, Slice 2 #15list_territory_coveragescan, Slice 3 #16 Vue tab (allied Illusionist, Fable 5) mergede407de4after the Commander's live WebView2 smoke-test (#16 review's Major+Minor fold into WR-0477). Phase 3 (The Update — Ascent port) COMPLETE 2026-07-17 — signed-updater port sliced by the keypair gate: Slice A version lockstep #19, Slice B updater plugin + baked pubkey218A383BEBD51D3#20, Slice C signed-release workflow (SHA-pinned actions) #21; keypair Commander-minted, General read only the.pub; follow-ups WR-0490/0491. Phases 1–3 all complete. Updater ratification in progress (2026-07-18, WR-0492): v0.1.0 cut green, but private-repo → updater-404 forced a public artifact repo (Goosterhof/war-tent-releases; Option A — signature-is-integrity, source stays private) — endpoint repointed +release.ymlcross-repo-publish reworked in PR #25; Commander-gated on aWAR_TENT_RELEASES_TOKENPAT + merge, then baseline re-cut + live raise. Founding:campaigns/war-room/2026-07-16-war-tent-founding.md; records:…-phase-1-the-seats.md+…-phase-2-the-map-table.md+…-phase-3-the-update.md+…/2026-07-18-war-tent-updater-ratification-private-repo-fix.md) - 0046 — War-Room Board: Stores → Events + Views (war-room; Accepted 2026-07-16/17; internal — not published) — kills the reconcile treadmill at the source:
CLOSEhad no automatic trigger so five hand-maintained records grew monotonically (the/muster2026-07-17 double-lapse cluster). Decision: kill[ally-pr]as a stored category (derivable + already watched by/sentry/bus//stack-drain); board stores intent only (status re-derived live by/warpath//sitrep//sentry); two-tier event-close = town-crier bus merge-signal fast-path + authoritativeghmerge-state backstop (Kendo's native close-on-merge, driven war-room-side without wiring project 2 cross-org); reconcilers shrink to the no-event tail with evidence-required re-dating (auto-drop-on-second-lapse). Recon-validated (Surveyor + fresh debrief): the busstatus=doneis a settlement signal not merge (F-C1), announce-gated (F-M1), and consuming it welds to WR-0404/ADR-0042 fail-closed reads (F-M2 —the-generalGitHub-identity link is a hard precondition). Ally-dependent leg: a structured merge-signal enhancement on town-crier (must persist the merge fact even on an already-settled thread) — pending Jasper socialization, sequenced against the live WR-0404 branch. War-room-side build (legs A/B/D/E) LANDED 2026-07-17 (6d7e2a0/c68c5b2/d251753):[ally-pr]retired as a filing category (drain-don't-delete),/board-reconcile+check-queue-resolved.py --verifycascade-echo (the event-close engine already existed — cascade-echo was the gap),AUTO_DROPsecond-lapse scanner in both muster deferral scanners with evidence-required re-dating; first operational pass drained all 10AUTO_DROPitems. Leg C (bus fast-path CONSUMER, WR-0471 Part B) LANDED 2026-07-18 (818393d) once the ally precondition cleared (town-crier #217 merge-signal → #218 release → v55 deploy):fetch-crier-merged.shpulls the bus merged set (resolution_reason==merged, NOTmerged_at— null on some merged rows, per Jasper's edge-(b) contract) +seed_bus_cache()pre-seeds/board-reconcile's PR-state cache so bus-known-merged PRs skip the per-rowgh(fail-open → pureghbackstop if the bus is down; trust the merge FACT, not closeability — the confirm gate is unchanged). ADR-0046 now FULLY BUILT (5 legs A–E). First live two-tier run (2026-07-18): 517 seeded, ~2.2× faster, 13 CLOSEABLE → 1 close + 12 held — the reconciler-yield-collapse finding (an intent row's title-#Nis the origin/gate PR, never its completion; validates candidate-feeder-not-auto-closer, expect near-zero soldier-row yield post-migration). AMENDMENT 1 — 2026-07-20 (/muster+ queue-reconcile precision fix). The "fully built" verdict verified coverage, never precision or input validity; both gaps were load-bearing. Decision 6 — derivable-key filing invariant: any board / queue /deferred.mdrow asserting in-flight or completed work MUST cite a PR number or URL, never a branch name or bare SHA — both tiers of the event-close key on PR identity, so a keyless row falls out of the mechanism entirely (seed: queue #46 cited a branch +fac4264while the work had shipped as phpstan-warroom-rules#49, merged 2026-07-03). Filing-gate parity withResolve By; enforced by Mode C incheck-queue-resolved.py(default offline scan, tieredC1_KEYLESS_CLAIMvs advisoryC2_NO_PR_WORK— keyless ≠ defective: doctrine-landed work legitimately has no PR, and a flat scan emitted 9 false positives out of 10). Decision 7 — precision is a gating property of any candidate-feeder: (1) measure a class's precision on a live run BEFORE automating apply — auto-applying a noisy signal actively damages the record; (2) port precision fixes to every sibling sharing the mechanism (audited: only/pulse-reconcile+/queue-reconcilepair phrase-to-ref; board/front-door structurally cannot). Root cause: the open-claim signal was computed once over the whole ~7,000-char Status cell and applied to every PR in the row → ~27% precision, which meant the feeder imposed the labor it exists to remove — the real reason row #140 sat Active for 4 days carrying its own correct, dated, verified "trigger FIRED" note. Fixes: 180-char proximity window + word-boundary phrases + resolution-span veto + semicolon clause-separator + Status-cell-only + all-occurrence tracking. Confirm-set 24 → 8; STALE_PR_CLAIM 15 → 1 at 5/5 precision; offline path unchanged. Auto-apply deliberately NOT enabled — the strict "no other open leg" gate matched zero live rows (dead code); re-ask parked indeferred.md [adr] adr-0046-auto-apply-reask-on-clean-signal. ADR:campaigns/war-room/2026-07-17-adr-0046-war-room-board-stores-to-events.md(Amendment 1 appended); reasoning:campaigns/war-room/2026-07-17-reconcile-loop-stores-to-events-and-views.md; session record:campaigns/war-room/2026-07-20-muster-and-queue-reconcile-precision-fix.md; design note:campaigns/town-crier/2026-07-17-merge-signal-design-note.md. AMENDMENT 2 — 2026-07-21 (/muster— the WAITING class). The "every muster opens with 30+ LAPSED" nag is NOT what/reconcilefixes: measured live, board CLOSEABLE (15, merge-keyed) vs LAPSED (30, date-keyed) overlap by exactly 1 — near-disjoint populations — and the CLOSEABLE set is itself mostly the trigger-PR trap (7/7 spot-checked were origin/gate PRs, not completions; genuine reconcile yield ~2). Decision 8 — the WAITING class: a trigger-gated intent row (itsResolve Bynames an external gate — ally/Commander/phase/dispatch — the ISO date only a backstoplongstop) has no date-derivable completion, so its longstop always lapses and re-dating just re-arms it (the treadmill). Both offline date scanners (check-kendo-deferrals.py1.5e,check-deferred-lapses.py1.5f) now class such a lapsed-but-gated rowWAITING(NOT a finding) — withSTALE_TRIGGERteeth at >60d-past-longstop (dead gate → dispatch/drop, never re-date) — leavingLAPSEDto mean only genuine non-gated overdue commitments. This finishes ADR-0046's own stores→events principle on the date field: overdue-ness for a gated row is derived from whether the gate fired (watched live by/reconcile//sentry/bus), not a stored date; muster asks "overdue commitment?", reconcile asks "work shipped?". Validated live: board 30→18 LAPSED+13 WAITING, deferred.md 32→11 LAPSED+21 WAITING, zero false reclassification in the spot-check. Supersedes the parked "widen 1.5f hard-announce" proposal (that made the treadmill louder; this takes gated rows off it). Amendment appended to the ADR record; SKILL.md 1.5e/1.5f + report-surface sections updated. AMENDMENT 3 — 2026-07-22 (the Sprint — a weekly commitment view replaces per-item dates on the doable class). Amd 2 took the gated class off the date treadmill; the residualLAPSEDnoise was the doable class, whose per-itemResolve Bydates were commitment theater (reflex dates never chosen against capacity, re-litigated individually every muster) — and the war room lacked a selection layer (nothing named "the chosen set for this week"). Decision 9: the board gains a weekly Kendo sprint (project 2 native sprints, planned by/sprint-plan) — sprint membership replaces the per-item date as the commitment signal for doable work; 5–8 items deliberately under capacity; a sprinteddeferred.mdgovernance entry is promoted to a thinWR-####row citing its slug. Decision 10:Resolve Byretreats to the gated class — doable rows/entries carry NO line (new scanner classBACKLOG, not a finding;NO_DATEretired); gated rows keep trigger+longstop (WAITING/STALE_TRIGGER unchanged); the filing hard gate reworded (accepted risk: a gated row filed lineless reads BACKLOG until sprint planning discovers the block). Decision 11: carried twice → dropped (body-stamped(carried YYYY-MM-DD); the anti-treadmill defense) + weekly backlog hygiene (>60d untouched → named drop-candidates) replaces per-item aging. Decision 12 (cadence anchors ride the strong habits):/reconcile= mandatory Step 1 of/sprint-plan(its weekly structural anchor;/intelflagged >14d stale);/muster1.5k = cheap sprint-freshness nag (stale >7d → "run/sprint-plan"; muster stays read-only);/return-to-basePhase 5b = sprint-tick (shipped items → Done between plans). Migration: existing dated doable rows groomed not bulk-edited — muster's LAPSED disposition menu gains "de-date to backlog" as the doable-row default; the first/sprint-plangrooms the standing LAPSED set. Expected steady state: musters open with STALE_TRIGGER + rare deliberate dated commitments + one sprint line — measure across two musters. Measurement #1 (muster 2026-07-23): board scan opened 0 AUTO_DROP / 0 LAPSED / 0 STALE_TRIGGER (first clean board since Amd 2/3); deferred.md opened 1 AUTO_DROP + 2 LAPSED — all second-lapse rows, all dispositioned same session (promote-to-board/drop, never a third date); post-session both scans fully clean. Measurement #2 = next muster. (Record:campaigns/war-room/2026-07-23-muster-graduation-sitting-engine-fixes-isms-wave.md.) - 0047 — Deferred-Work Registry Split: Governance In-Repo, Actionable On the Board (war-room; Accepted 2026-08-19; internal — not published) — ratifies the 2026-06-09 pilot after 71 days: keep the split. Actionable slice (
[soldier-dispatch];[ally-pr]retired as a filing category by ADR-0046) lives on the Kendo war-room board, project 2,WR-####; governance slice ([debrief]/[refresh]/[graduation]/[adr]/[doctrine]/[infra]) stays indeferred.md, where in-repo locality is load-bearing because spies, soldiers and skills read it directly. Supersedes nothing; related ADR-0046, ADR-0005, ADR-0030. Durability discharged by Commander ruling — Kendo carries database backups because Kendo is itself in the ISMS; restore granularity / per-tenant RPO remains unmeasured and is recorded as a residual in the ADR. Doc:.claude/decisions/adr-0047-deferred-work-registry-split.md— one of only two internal ADRs that have a document at all (0005 is the other; 0007/0010/0030/0046 remain campaign-report-only) — superseded 2026-09-10: four now (0010 gained its document at Amd 1 on 2026-08-31, 0049 was born with one); 0007/0030/0046 remain campaign-report-only. Added to this index 2026-08-20 — it was accepted on the 19th and this file did not mention it for a day, while the front door instructs readers to consult this index before acting on any ADR's state. - 0048 — Error Feedback Must Reach the User — the Silent-Failure Contract (Cross-Project + Universal; Proposed 2026-08-25, amended 2026-08-31 (incident 5 on emmie
prod-script: rule 5 widened, rule 8 added, adoption order revised to emmie → wijs → entreezuil → rest-on-next-touch), Accepted 2026-09-02 by Commander ruling as written, on the evidence of one day's crit review on lokalekeuze where 8 of 22 PRs carried the exact defect — afailedstate rendered as empty or complete). Implementation table added 2026-09-07 (the page was Accepted five days with no tracker — muster finding): lokalekeuze = In Progress (first adoption, LK-0322, the failing-toast contract, Builder lane); emmie = Not Started (first in the revised order); wijs = Not Started (WR-0956useLoadingStateunhandled rejection / no 5xx handler is its first leg); entreezuil = Partial (point-fixed at #301; the arch test that makes it durable is still owed); kendo · ublgenie · codebook · isms · scripthub · BIO · daymate · time-machine · techniekwerkt = Not Started (adopt on next touch of an error path, per the ADR's own rollout stance). Open on the page § What needs deciding: the Armory predicate's home (fs-http vs a sibling), whether the Level-2 PHPStan rule ships at n=1, rule 8's enforcement split (phrase-ban CI gate vs territory doctrine), and rule 5a's mechanism. Page:presentation/decisions/error-feedback-reaches-the-user.md. - 0049 — Construction: a Fifth Campaign Type, on Named Authorship Territories (war-room; Proposed 2026-08-31 → Accepted 2026-08-31; internal — not published) — the no-expansion rule assumed an ally holds the pen; on a greenfield territory where the war room itself holds authorship there is nothing to map, reform, fortify or enforce until someone builds it, so Construction is permitted there and only there, executed by the Builder soldier one Kendo ticket per dispatch. Authorisation is per-territory and BY NAME — ownership, greenfield-ness and "personal domain" qualify no repo (the-laboratory's experiments qualify on every inferable axis and carry Art. 9 data). Ratification gate FIRED the same day: reviewer canary round 2 scored 2/3 (S1 + S3) against the sealed ≥2/3 threshold, so the 36 first-pass-clean rounds are interpretable evidence (lane caveat: LOCAL runner
8086e80, Sonnet-5 seats; hosted daemon unmeasured). Measured basis: 53 dispatches, 48 crit-reviewed PRs, 75 % first-pass issue-free, 0 unasked-for files surviving an attribution attack. Authorised today: lokalekeuze (2026-08-28, the pilot); emmie — epic 26 Financieringsroute only (Amendment 1, 2026-09-02: the war room builds ally Bert's 25 tickets because it holds the production-data access he lacks; Bert owns every domain ruling, Jasper approves, Emiel reviews declarations/VECOZO; coupling hazard closed by sequencing); war-tent (Amendment 2, 2026-09-02 — whole territory, no personal data verified, the pen held since ADR-0045); isms — ISMS-0036 only (Amendment 3, 2026-09-03, the framework dimension on controls per ADR-0018 Amd 1) + the files half of ISMS-0014 (Amendment 4, 2026-09-10 —fly.toml, Dockerfile + vendored.flyruntime contract, deploy workflow,.env.exampleparity, smoke test; provisioning itself stays the Commander's). Every other soldier's "no new features" ROE stands. Doc:.claude/decisions/adr-0049-construction-campaign-type-authorship-territories.md(with 0005, 0010 and 0047 one of the four internal ADRs that have a document; 0007/0030/0046 remain campaign-report-only); reasoning:campaigns/lokalekeuze/2026-08-31-builder-pilot-verdict-measured-against-its-own-thresholds.md. Added to this index 2026-09-10. - 0050 —
fs-auth— the Armory's Sanctum SPA Session Package (Cross-Project + Universal; Proposed 2026-09-14 on a Commander ruling, WR-1384, that overruled the General's not-yet). One package owning the Sanctum SPA-cookie SESSION:createSessionStore({guard, http, endpoints, parseUser, timeoutMs, csrf?})with an EXPLICIT endpoint map (kendo's factory hardcodes 16 path literals and its 9-field option bag has zero live overrides), a four-state machine the store alone writes, outcome-returninglogin/logout(ADR-0048),onSessionEndfired once per session epoch, a hardenedresolveSafeRedirect(kendo's accepts tab/LF/CR, which browsers strip →//evil.comat alocation.hrefsink), and the two guard registrars on fs-router/fs-http. 401 + 419 = one class, one action; 419 is dev-only on a same-origin SPA (Laravel 13PreventRequestForgery::hasValidOrigin, verified at vendor source). The package never navigates and never renders copy. Stays territory-side: permissions, 2FA, OAuth, inactivity timer, sentences. Four contract rulings RECEIVED 2026-09-14, all as recommended (failed logout → state moves on success only + outcome names the failure + no probe; expiry event carriesreturnTo;userread-only +setUser; package fires / consumer navigates) — recorded under Resolved Questions; still open before acceptance: who tells Jasper, and the Commander's press (kendo's file is co-authored 44 % / 38 %). Adoption: lokalekeuze first (WR-1383 becomes the adoption), kendo second, wijs/ublgenie forks, laravel-skeleton casts with it (backend half WR-1406), rest on next touch; two consumers on branches before0.1.0. Evidence: fleet surveycampaigns/lokalekeuze/2026-09-12-the-login-flow-fleet-survey-and-why-pr-220-cannot-be-fixed-into-green.md§ 2; kendo Surveyor deep dive + debriefreports/kendo/{field,debrief}/2026-09-14-surveyor-auth-session-layer-fs-auth-extraction-recon*.md. Page:presentation/decisions/shared-spa-session-package-fs-auth.md.