Skip to content

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 KendoCross-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-safety opt-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.6 assertWithinTransaction connection-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 via CreateAiPromptAction, and Juvoly via MapEvaluationTranscriptAction; tenant-scoped ai_outbound_logs on native App\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_ORGANIZATION resolves 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-0005 resolved to nothing. /muster 1.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; CheckPermission resolution engine in app/Policies/. Phase 2 replaced the static UserRoleEnum with a granular RBAC matrix (16 resources × 4 actions, multi-role union, 6-step algorithm, admin + project-owner bypasses, frontend usePermission() 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 /muster 2026-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 Status saying so): a 5-phase ladder splitting TenantManager into TenantContext (request-scoped) + TenantSwitcher (stateless) → full Octane readiness; 13 files reference TenantManager. 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 from from()/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 on ReviewRequestResourceData with ReviewRequestSummaryData documenting a load-bearing collection() 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 (95 DTOResource subclasses + 25 raw JsonResource; the earlier "178" count was wrong; relation-safety is a latent CI regression-guard, not an active bleed). Enforcement: L1 arch test banning loadMissing(/->load(/loadCount(/loadSum( inside app/Http/Resources/**, L1 Hydrator structure test, L2 deptrac Hydrators layer. Canonical base pinned with provenance — kendo backend/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-base ComputedResourceData carve-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, with AuditLogWriter the documented infrastructure-layer exception. Scope boundary is narrow and deliberate — app/Http/* ONLY; app/Jobs/* and app/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; EnforceActionTransactionsRule walks execute()); BIO + the-laboratory=Evergreen but HTTP-layer txn audit not yet performed; ublgenie=Partial (13 Actions extracted PRs #7–9; still DatabaseManager not ConnectionInterface, static model calls, facades; 3 HTTP-layer txns in AuthController awaiting 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 at tests/Arch/FormRequestsTest.php:30. Was: PR #17 — 7 DTOs, 6 FormRequests with toDto(), 8 Actions converted; ProcessInboundInvoice deferred because it takes an UploadedFile). 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 ### States vocabulary 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.php enforcing); entreezuil=Complete (4 migrated PR #16, ConfigTest.php enforcing); ublgenie=Partial — 2 of 6 migrated (PR #24), and the remaining 4 are BLOCKED, not pending: LogicTokenService, LogicAPIService and a manually-new'd (not container-resolved) Invoice model 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 on ResetPassword.spec.ts); this looks like a Complete row nobody flipped. kendo=Not Started (43 domain pages — 32 tenant + 11 central; asyncShallowMount helper 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 HEAD c05555d — 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 ## Implementation heading 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_days restored. 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 $fillable and tests/Arch/ModelsTest.php enforces it. Was: PR #89, 6 of 9 models remaining, no ModelsTest.php yet). 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 — root DataTransferObject deptrac 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 Checklist still 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.7 as 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#195 MERGED 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 caught ScheduleReport.php:80 missing 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#218 MERGED 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 + DomainPolicy all 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 behind DomainAuditLogger, a DomainPolicy + RoutesAuthorizationTest central-route extension, and KD-0596. ublgenie needs a Cartographer pass before scoping; emmie's CreateAwsBucket.php predates 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 — caching getInstallationToken per-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 ## Implementation section is a three-phase plan, not per-territory states: Phase 1 retrofit on PR #240 (revert the caller-side guard in UpdateVacationAction:91-109 from 8ffae54f44, apply the atomic conditional, add a behavior test, author tests/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, missing Audit/); kendo=Partial (tests at Arch/ 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 ## Implementation table 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.ts under tests/, no globals), happy-dom/v8 Partial (wijs istanbul is a documented deliberate override), templates/vitest.config.ts Complete — explicitly Level 4 + template, NOT Level 1, no CI teeth; the path to teeth is a /canon-check drift axis, noted as a follow-up. Amendment 2026-07-14 IS Level 1 (runs via composer test:archci-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.hooksPath shell 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: composer stan was present on 2/11 hook-carrying territories, pint:check on 3/10, npm vue-tsc on 4/11 — those gates could not pass on any machine in any tree, and their npm error Missing script output 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-push never 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 PATH npm resolves to the Windows binary and fabricates a CMD.EXE build failure — 21 hook files across 11 territories were unguarded, only war-room's own pre-push had the fix, and v3 is the first revision to guard pre-commit too (WR-0879); (3) the mandatory Pest gate was labelled Feature + Unit + Architecture while invoking only composer test — a Claim-Gate violation that terminates the search, now relabelled to name the config that decides coverage, with an optional test:arch gate (WR-1133); (4) an absent runner was reported as a missing script or as a lint failure — v3 checks php/composer/npm/node before 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 no typecheck script and 2 no aggregate composer 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 broken presentation/ commit reaching main, since the repo is private on a free plan and cannot be branch-protected — /muster re-checks core.hooksPath every 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.2 so EnforceAuditTransactionScopeRule (0.3.x) is not adopted; no CLAUDE.md projection, no ->ordered() contracts; remediation routed Medic/Engineer) and emmie=Violations Present (19/19 — 1 Medium UpdateClientLocationAction: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 #7 f1d357b; ->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 the issue_audit_logs subset plus a banked class-D fix (pruneStuckRunning bypasses the logger hourly; Scheduler/Cli ActorType cases defined-but-unwired); entreezuil's Kiosk typed-FK + byte-compatible hash extension is the sanctioned non-User actor precedent; isms deferred to audit slice 2. The post-hoc-patch prohibition is a candidate arch test — not built. The ^0.2 pins 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.7 today, 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-modes skill.)
  • 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, DateImmutabilityTest teeth-proven RED and a ModelsTest cast 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: CarbonImmutable is NOT instanceof Illuminate\Support\Carbon; PHPStan is blind on now(); unit mocks prove nothing. emmie legs: EMMIE-0317 point fix Complete (PR #303 — three ->setTimezone() calls removed from CalculateRevenueTotalsAction, 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, so temporal-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#1440 MERGED 2026-06-10, 47 days ago. Flip to Complete and discharge the recorded follow-up (memoize makeLabelStoreForProject after 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 HttpService cast, minor 0.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 dedicated cache_hashes(key, hash, updated_at) table; an explicit Bump{Entity}HashAction inside the mutating Action's transaction, no observers; a stamp middleware whose transport is not load-bearing) and explicitly does NOT adopt the x-fs-cache-hashes-subscribe header, 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-driven ModelHashCookie loop 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_id persistence [soldier-ready], (2) DeleteFileAction ADR-0029 ordering fix [soldier-ready], (3) AnonymizeUserAction + completeness/arch tests, (4) retire HardDeleteUserAction). 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 ## Implementation table 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 emmie backend/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-execute Actions in App\Actions\Model\Financing\: AssertAmbulatoryRegistrationFinancingAction (throws InvalidFinancingForAmbulatoryException; user-initiated attach sites) and SanitizeAmbulatoryRegistrationFinancingAction (never throws; the batch auto-attach path MarkRegistrationsAsLocationClosedAction). This explicitly supersedes the "two entry points on one Action" framing in §Decision-2/5 and in the backend/CLAUDE.md projection. 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-tenant SELECT 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 development with feature tests: Step 1 repair migration (surgical 9-occupation repoint + DELETE of all 576 inverted rows) + its test; Step 2 constraint migration adding chk_appointment_slots_window (e3628c64) + test, plus a sqlite driver-guard follow-up (0319db1d). Level-4 doctrine line in the wijs CLAUDE.md slot 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 manual fly deploy vehicle (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_request announce/resolve), #58 (install persistence + outbound GithubAppClient + consensus + /github/health), #59 (vue-tsc gate fix), all merged and released 2026-06-26; org-installed as App town-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, a pull_request/pull_request_review webhook-replay Feature matrix, and an HMAC-fail-closed-on-empty-secret test). producer repos = "Mostly decommissioned — 3 survive": 11 of the original 14 per-repo announce-pr.yml producers 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/health signal 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, so Accepted means 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.0 2026-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; new ui-* family in the fs-packages Armory (NOT fs- — 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-inputs LANDED — PR #160 merged + 0.2.0 published to npm 2026-07-15 (props required-where-meaningful, aria-required conveyance, 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); the brick-*--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.0 SHIPPED — WR-0460, PR #162 merged + published to npm 2026-07-17: Number/Date/Textarea atoms + --ui-control-bg-focus/--ui-control-bg-invalid vars. Nullable-value contract settled by emmie recon (the fleet convention for ALL form inputs): backend serializes a nullable column to literal null; FE types string|null/number|null; the component binds null directly (no ?? '' inside) and emits raw '' on clear, which Laravel's ConvertEmptyStringsToNull maps back to null — so TextInput widened stringstring|null; NumberInput is the ONE exception (emits null on empty — a number can'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-null quantity uses 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: the TextInput widen is NON-breaking (Vue v-model variance — 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 universally shared/ — isms runs two design systems from one repo (Samizdat .app-colleague / Bunker Brutalism .app-worker) and its own check-style-bleed.sh rejects 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 the border-width SHORTHAND (0 0 1px); --ui-field-margin is likewise a shorthand. Mapping onto rgb(var(--bb-*)) made the data-watch day/night flip travel free (the BIO light/dark dividend). Pinned ^0.3.0WR-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-selected on the committed value, plus aria-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 memory feedback_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: inherit is 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 on editorial/FilterSelect being more accessible than our SingleSelect was: it carries aria-activedescendant + committed-value aria-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 (reshape editorial/FilterSelect/editorial/SelectSingleSelect adapters, importers untouched; the two Multiselects 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-* + Bootstrap form-select defaults), scripthub (Tailwind v4, PR #48 — Arman's proposal, ally-gated + a vue 3.5.34→3.5.40 bump), 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-accessible editorial/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) + ublgenie editorial/Multiselect adapter #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-ui hide() 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 killed defineWorkspace, leaving the Armory's 100% gate print-only; migrated to test.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-required illegal on group, legal on radiogroup). 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-ui hide() fix (referenceHidden never consumed — live in every consumer until it bumps; fixed under the unchanged floatingStyles name). WR-0524 wave OPEN at ^0.9.0 same 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+commit static/); 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), #option forwarded (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-invalid box-shadows in every consumer:where() specificity-drop fix + regression test rode #185. ^0.10.0 fleet 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 + searchable LIVE→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-packages main = 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=4 useOptions/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 Laravel CursorPaginator envelope ({data,next_cursor,prev_cursor,per_page}) — cursor MANDATED over offset (stable under concurrent inserts on append-heavy compliance registers; BIO GetFamilyPartsAction precedent; 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 reusable PaginatedResourceData offset 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-computed total — the key insight is that total is separable from the page mechanism (bolt the existing countAll() onto a cursor envelope; note BIO's CursorPaginator carries 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 only page/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) parked deferred.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-computed total; 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 reusable CursorPaginatedResourceData — 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 memory reference_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/10 stamps 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 reader resolve_for_std_fs, Slice 2 #15 list_territory_coverage scan, Slice 3 #16 Vue tab (allied Illusionist, Fable 5) merged e407de4 after 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 pubkey 218A383BEBD51D3 #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.yml cross-repo-publish reworked in PR #25; Commander-gated on a WAR_TENT_RELEASES_TOKEN PAT + 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: CLOSE had no automatic trigger so five hand-maintained records grew monotonically (the /muster 2026-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 + authoritative gh merge-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 bus status=done is 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-general GitHub-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 --verify cascade-echo (the event-close engine already existed — cascade-echo was the gap), AUTO_DROP second-lapse scanner in both muster deferral scanners with evidence-required re-dating; first operational pass drained all 10 AUTO_DROP items. 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.sh pulls the bus merged set (resolution_reason==merged, NOT merged_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-row gh (fail-open → pure gh backstop 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-#N is 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.md row 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 + fac4264 while the work had shipped as phpstan-warroom-rules#49, merged 2026-07-03). Filing-gate parity with Resolve By; enforced by Mode C in check-queue-resolved.py (default offline scan, tiered C1_KEYLESS_CLAIM vs advisory C2_NO_PR_WORKkeyless ≠ 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-reconcile pair 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 in deferred.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 /reconcile fixes: 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 (its Resolve By names an external gate — ally/Commander/phase/dispatch — the ISO date only a backstop longstop) 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.py 1.5e, check-deferred-lapses.py 1.5f) now class such a lapsed-but-gated row WAITING (NOT a finding) — with STALE_TRIGGER teeth at >60d-past-longstop (dead gate → dispatch/drop, never re-date) — leaving LAPSED to 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 residual LAPSED noise was the doable class, whose per-item Resolve By dates 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 sprinted deferred.md governance entry is promoted to a thin WR-#### row citing its slug. Decision 10: Resolve By retreats to the gated class — doable rows/entries carry NO line (new scanner class BACKLOG, not a finding; NO_DATE retired); 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; /intel flagged >14d stale); /muster 1.5k = cheap sprint-freshness nag (stale >7d → "run /sprint-plan"; muster stays read-only); /return-to-base Phase 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-plan grooms 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 in deferred.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 — a failed state 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-0956 useLoadingState unhandled 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 .fly runtime contract, deploy workflow, .env.example parity, 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.
  • 0050fs-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-returning login/logout (ADR-0048), onSessionEnd fired once per session epoch, a hardened resolveSafeRedirect (kendo's accepts tab/LF/CR, which browsers strip → //evil.com at a location.href sink), 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 13 PreventRequestForgery::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 carries returnTo; user read-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 before 0.1.0. Evidence: fleet survey campaigns/lokalekeuze/2026-09-12-the-login-flow-fleet-survey-and-why-pr-220-cannot-be-fixed-into-green.md § 2; kendo Surveyor deep dive + debrief reports/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.

Architecture documentation for contributors and collaborators.