Architecture governance
MMCA.Store — Architecture Remediation Backlog
Derived from ArchitectureScorecard.md (two-axis: Maturity 98.4% / Implementation 83.6%, full re-score 2026-07-17, framework pin v1.117.0).
Items are categories scoring below 4 (maturity) or with a notable implementation gap, ranked by
priority = (4 − maturity) × weight (and impl-gap items called out separately). This is Store's first
in-repo remediation ledger; the scorecard is the source of truth for scores, ../MMCA.Common/FACTS.md
for framework-wide facts, and ../Docs/Architecture/ArchitectureRemediation.md
for the cross-repo [C→A] roll-up.
Status legend: ☐ open · ◐ in progress · ☑ done
🔴 Priority — a11y / E2E merge gate (#21, #28, #22)
The former single biggest maturity lever: #28 cleared 2026-07-03; #22 cleared on the 2026-07-17 re-score (the gate flip verified live). Only #21 remains open (priority (4-3)×3 = 3, the highest open lever), pending a recorded screen-reader pass.
- [~] #21 Accessibility, maturity 4 corrected back to 3 (2026-07-11, drift plan D6); impl 7 → 8 DONE. The axe + Playwright suite gates the deploy (
e2e-gate, chromium,workflow_callintoe2e.yml, indeploy.yml'sneeds), and the axe scans broadened 10 → 22 pages (public, shopper, and Catalog/Sales/Identity admin surfaces), lifting impl 7 → 8. The prior maturity-4 was an over-claim: the rubric pairs axe-in-CI with a recorded manual screen-reader pass, so honest maturity is 3, matching ADC on the same rubric. A newACCESSIBILITY-SCREENREADER-PASS.mdrunbook shipped, but its results log is still empty. Maturity 3 → 4 lever: record a dated manual SR pass in the new runbook (needs a human + NVDA/VoiceOver against the running Aspire app; cannot be done headless). - #28 Front-End Testing, maturity 3 → 4 DONE (2026-07-03) / impl 6 → 8 DONE (2026-07-11, drift plan D7). The E2E + axe deploy gate shipped with #21; bUnit breadth grown to 214
[Fact]/[Theory]across 40 files (Catalog 63 / Sales 126 / Identity 25) with loading/empty/error/edge state coverage, the full CI gate green at 1393/1393. - #22 Responsive & Cross-Browser, maturity 3 → 4 DONE (GRANTED on the 2026-07-17 re-score; adversarially verified against live workflow files:
e2e.yml:76scopescontinue-on-errorto scheduled non-chromium runs only,deploy.yml:315invokes all three engines,deploy.yml:429putse2e-gatein deployneeds). Scorecard §22 is M4/I8; moved to the protect list. History of the reopen-and-fix below. The wave-5 change passedbrowsers: ["chromium", "firefox", "webkit"]into thee2e-gatecall, so all three engines RUN in the gate, but the non-chromium legs cannot FAIL it:e2e.yml:71still setscontinue-on-error: ${{ matrix.browser != 'chromium' }}, anddeploy.yml:433's own inline comment describes e2e-gate as chromium-only. The 2026-07-16 re-score held maturity 3 on exactly this evidence and the candidacy was declined. The green-soak history (2026-07-09 through 2026-07-11, plus thed057afcthree-engine catch) still stands as soak evidence. Maturity 3 → 4 lever: remove thecontinue-on-errorconditional for the gate-invoked firefox/webkit legs (or gate them behind their own required jobs) once the soak is judged sufficient; nightly-matrix legs may stay advisory. Lever SHIPPED same day (2026-07-16):continue-on-erroris nowgithub.event_name == 'schedule' && matrix.browser != 'chromium', so all three engines the gate invokes (deploy.yml:315) CAN fail a deploy while nightly non-chromium legs stay advisory flake alarms; the stale chromium-only comments ine2e.yml/deploy.ymlcorrected. Soak judged sufficient: job-level green nightly matrices 2026-07-09 through 2026-07-16, with the sole 2026-07-12 red being the all-three-engines product defect fixed ind057afc(a true positive, not flake). Maturity 3 → 4 candidacy recorded for the next re-score.
🟠 Priority — execution-quality gaps (impl, not maturity)
- #14 Testability, impl 6 → 9. DONE (2026-07-01 wave, re-scored 2026-07-02). The floor step now measures Store's own code (reportgenerator
+MMCA.Store.*;-*.Tests) at floor 42.0 with46% actual (54% measured) after Stripe money-path, Sales UI, and GDPR-handler unit tests. Integration-coverage expansion (2026-07-06): ~100 new integration tests over real SQL closed the money-path gaps (Stripe webhook signature contract, order state machine, deliberate 404-not-403 order ownership), GDPR erasure/export end-state, refresh-token rotation, preferences, cross-servicedeploy.yml:82-86), the ADC-parity self-filtered gate; bUnit page-level breadth reached ADC parity (8 files). Unit-coverage program (2026-07-05): floor ratcheted 42.0 to 51.6 (ProductVariantChangedconsistency, checkout concurrency, contract guards (OpenAPI + RFC 9457) for Sales/Identity, and the ProductImages/PUT leftovers;[Idempotent]was wired onto the Sales money POSTs with a replay contract test. The Catalog+Sales fixtures were consolidated ontoSqlServerIntegrationTestFixtureBase. Cross-service broker tier (2026-07-11, drift plan D5): a non-gating nightlyMMCA.Store.CrossService.IntegrationTests(Testcontainers RabbitMQ + SQL,cross-service-tests.yml) now exercises the genuine outbox-to-broker-to-consumer round-trip (CatalogProductVariantChangedto Sales' zero-stockInventoryItem); the first run needs a manualworkflow_dispatch(done 2026-07-11, green). Gated by recency same day (remediation wave 6): across-service-freshnessjob indeploy.needsfails a deploy when the latest successful nightly is older than 3 days (mirrors ADC TD-02; the Testcontainers workflow itself stays out of the deploy chain). Deliberately skipped: dedicated rate-limit fixtures (the WAFs neutralize the limiter; a tight-limit variant is low value for the volume, revisit only if abuse is observed). - #23 Front-End Performance, impl 6 → 8. DONE (2026-07-03, drift plan D4 + D10). Public
CatalogBrowsemoved to server-side paging (GetPagedAsync+ boundedMobileInfiniteScrollList); cart enrichment resolves names via the targetedproducts/variant-lookupbatch endpoint (CartStateService.cs:282-296); Core Web Vitals (LCP/CLS/TTFB/FCP) are measured per E2E run and uploaded as CI artifacts (Workflows/WebVitalsTests.cs). Accepted trade-offs (2026-07-02 approval): price sorts fall back to Newest; search is Name-contains.
🟡 Priority — minor / accept-or-polish
- #32 Dependency & Supply-Chain, impl 7 → 8. DONE (2026-07-03, drift plan D8 + D9). Vulnerability gate is NuGetAudit +
TreatWarningsAsErrorsat restore, which failsbuild-and-test(aneeds:ofdeploy) and every Docker image build; accepted advisories are the documentedNuGetAuditSuppressset (Directory.Build.props:16,8-12,38-40). The SBOM became a hard gate in43d733fwithsupply-chainadded to deploy'sneeds. All three CI restores now run--locked-mode(committed-lock drift fails the build) and the vuln report is promoted to the suppress-aware gating audit mirroring ADC. - [~] #20 Design System, impl 7 → 8 lever OPEN (marker corrected 2026-07-17: the wave-6 done-claim over-reached; the 2026-07-16 and 2026-07-17 re-scores both hold §20 at M4/I7 because the recorded MudBlazor
Style=/CellStyle=residuals below still hold impl at 7,ProductList.razor:118). Maturity 4 stands (2026-07-01). The brand-color token guardBrandColorTokenTestsshipped in5fbd003(CI-enforced, both UI hosts' home CSS repointed tovar(--mmca-primary)). The remaining impl lever landed: every plain-HTML inlinestyle=in Catalog.UI and Sales.UI moved verbatim into 17 new scoped.razor.cssfiles as semantic classes (cart drawer, product images/variants, catalog cards, order/inventory pages; classes only added, DOM structure unchanged). Recorded residuals: MudBlazorStyle=/CellStyle=parameters on components with no plain-HTML ancestor in their own markup, which Blazor CSS isolation cannot target without a DOM-changing wrapper (list in the wave-6 commit); no hard-coded brand hex anywhere. CI.slnf 1397 green incl. all fitness gates. - #9 API & Contract, impl 8 → 9. DONE (2026-07-03, drift plan D16). The v2 demonstration shipped:
ServiceInfoControllercarries[ApiVersion("1.0", Deprecated = true)]+[ApiVersion("2.0")]mirroring ADC, and the two deploy-gating contract-guard integration tests (Contract/ApiVersioningTests+Contract/OpenApiContractTests, mirroringMMCA.ADC.Conference.IntegrationTests/Contract/) run in theintegration-testsjob. (Scorecard §9 refreshed to M4/I9 on 2026-07-11, drift plan D12.) - [~] #24 Forms, maturity 3 → 4 DONE (2026-07-11, drift plan D11); impl 8 → 9 lever OPEN (marker corrected 2026-07-17: the wave-6 done-claim over-reached; the 2026-07-16 and 2026-07-17 re-scores both hold §24 at M4/I8 because client validation stays MudForm-level, not full FluentValidation parity with the server rules). Maturity 4 is earned by the CI-gated
FormsConventionTests(MinimumCreateForms=4) machine-enforcing the four create forms' guard/dirty/validated-MudForm/Requiredmarkers, matching ADC. The impl lever landed: client-side parity added where server rules were genuinely unmirrored: email-format validation (mirroringCustomerEmailRules' exact algorithm) on CustomerCreate + CustomerDetail, and per-field NewPassword min-length/128-cap plus confirm-match on Profile change-password (localized en+es keys). Audited-and-already-covered rules (Product/Category/Inventory lengths, ranges, SKU cap) and deliberately server-only rules (SKU uniqueness needs the DB) recorded in the wave-6 commit. No FormsConventionTests markers weakened. #7 Microservices / single shared DB— NOT A GAP (corrected): Store runs database-per-service (Store_Catalog/Store_Sales/Store_Identity); the legacyMMCAStoreDB is a retained read-only archive only.
🐞 Defect-fix wave (2026-07-05)
Four reviewed product defects fixed in one wave; every behavior change flipped its pinning test in the same change.
- S-1 Stripe network errors escaped the Result pattern.
StripePaymentServicenow handlesHttpRequestExceptionin both resilience predicates (retry + circuit breaker) and maps it toPayment.Stripe.SessionCreationFailed/Payment.Stripe.SessionRetrievalFailedinstead of letting it propagate past the catch blocks. - S-2 Zero-decimal currency guard. Checkout-session creation validates the currency against a deliberate two-decimal allow-list (USD, EUR; must be extended together with
Currency.All) before the* 100smallest-unit conversion, returning the newPayment.Stripe.UnsupportedCurrencyerror, and roundsAwayFromZeroinstead of truncating fractional cents. - S-3 BuyNow drawer half-failure parity.
CheckoutAndPayAsyncnow returnsCheckoutOutcome(StripeUri, OrderId); on a payment-session failure it also persists the orphan-recovery token (previously only the success path did) andCartDrawernavigates to/orders/{id}with the order-id warning, matching Catalog's BuyNow fallback. - S-4 Case-sensitive Admin check in the GDPR handlers.
DeleteUserHandler/ExportUserDataHandleruse the new case-insensitiveUserRole.IsAdmininstead of!= UserRole.Admin, so a lowercaseadminrole claim authorizes the cross-user path. - Reviewed, not fixed (deliberate):
CartStateService.InitializeAsyncloading the cart without raisingOnChangestays pinned intended behavior (initialization is silent; only user-visible mutations notify).OrderDetail's missing[Authorize]remains a recorded deliberate choice (E2E gap program review), out of scope for this wave.
Deliberate / accepted (record the choice; don't silently leave low)
- ADR-042 device capability abstraction (latent, drift plan D8). The core seam is converged (Store wires browser + MAUI capabilities via
UseMauiDeviceCapabilities/AddBrowserDeviceCapabilitiesand renders the sharedOfflineBanner), but Store consumes no further capability in its own product UI: noExternalLink, noDeviceUIModule/DeepLinkListener, no app actions. Because no Store product page carries an external anchor today, the WebView dead-end risk is LATENT, not a live defect, so there is nothing to convert now. AdoptExternalLinkon any future Store product page that grows an external anchor, and register a StoreIUIModulewithDeepLinkListener(the way ADC'sDeviceUIModuledoes) if a Store MAUI feature surface is ever wanted. The framework side is complete in Common (18 capability contracts + theMMCA.Common.UI.Mauipackage), so this is consumer-side only, not[C→A]. #5 Vertical Slice (M3)RESOLVED (2026-07-17 re-score): §5 is M4/I8, granted on the CI-gatedSliceCohesionTests(sealed subclass of the shared non-vacuous base, in the deploy-gatingMMCA.Store.CI.slnf:52), the identical gate ADC credits at M4/I8. The layered-by-project hybrid remains a deliberate design choice, now correctly recorded as an implementation-axis cap (holds impl at 8), not a maturity deduction. Moved to the protect list.#27 Internationalization N/ARETIRED (2026-07-02): ADR-027 superseded ADR-011; Store ships full en-US + es localization with the CI-gatedTranslationCompletenessTests. §27 is scored and included in the indices. Updated 2026-07-03 (i18n completion sweep): §27 is M4/I8 with zero residual hard-coded literals (35 snackbars incl. cart/checkout/Stripe, 33 breadcrumb labels, nav items, both StoreHome hosts), a second CI gate (LocalizedTextConventionTests), the completeness floor raised 20→25, and MudBlazor chrome localized via the framework'sResxMudLocalizer. Impl 8→9 lever DONE (2026-07-11, remediation wave 6):Tests/E2E/MMCA.Store.E2E.Tests/Workflows/PseudoLocalizationTests.csextends the pseudo-loc text-expansion evidence to Store's own public pages (/,/catalog,/login): activatesqps-Plocvia the production/culture/setcookie mechanism (the circuit handshake carries cookies, not query strings), asserts the[!!sentinel, Common's exact no-horizontal-overflow expression, and a per-page resx-owned en-US leak probe, plus a default-culture sentinel guard. No host/AppHost change needed; rides the deploy-gating chromium e2e-gate (first genuine run in CI). §27 Implementation 8→9 candidacy recorded for the next re-score. Candidacy GRANTED on the 2026-07-17 re-score (user-adjudicated: the lever's test is real and rides the deploy-gating chromium e2e-gate): §27 is M4/I9.- Single-region deployment — accepted in
infra/DISASTER-RECOVERY.md(real load doesn't justify multi-region cost). - All per-service DBs on one physical SQL server — logical isolation complete; shared server for cost (minor §7/§8).
- 2026-07-16 re-verification note: #9 (M4/I9) and #32 came back FLAG on the full re-score (first-pass scorers proposed regressions that the adversarial verify pass disproved against committed evidence). #9 stands at M4/I9. #32 was re-adjudicated the same day by the drift-analysis fold: a capability-level ADC comparison (adversarially verified) found no mechanism behind ADC's I9 that Store lacks, so §32 is now M4/I9; the earlier FLAG had reasoned from stale scorecard text (including a stale 49 lock-file count, actual 55).
- ADR-043 adoption (mobile deep links / app association / native OAuth callback): recorded DEFERRED (2026-07-16 drift fold). The drift analysis lands this in Store, but adoption is feature-scale (Store-scheme deep links, iOS/Android manifest entries, associated domains) and rides the same trigger as the recorded ADR-042 latency: adopt when a Store MAUI surface is actively wanted. Not scheduled; revisit with the ADR-042 entry above.
- #33 broker-parity tier SHIPPED (2026-07-16, mirrors ADC):
Tests/Integration/MMCA.Store.ServiceBusEmulator.IntegrationTestsruns MassTransit v8 against the official Service Bus emulator (pinned 2.0.1) with the realProductVariantChangedcontract, proving admin-plane topology creation + the AMQP round-trip nightly incross-service-tests.yml(new job, samecross-service-freshnessdeploy gate). Closes the local-RabbitMQ vs prod-Service-Bus red flag with automation instead of documentation; §33 I8→9 candidacy recorded for the next re-score. - ADR-044 adoption (native push, third notification channel): recorded DEFERRED (2026-07-16 drift fold). Store has no user-notification pipeline at all (no ADR-024 inbox, no SignalR channel), so ADR-044 adoption means adopting the whole notification stack first: a product decision, not remediation. Record here so the gap is conscious; schedule only if Store wants user notifications.
🟠 Below-maturity-4 tracking (inclusion policy: categories scoring < 4 maturity)
These categories score maturity 3; the ledger records them per its own line-4 inclusion policy (mirrors ADC's equivalent entries).
- #19 · State Management & Data Flow · maturity 3 → 4 (weight 3). DONE (2026-07-11, remediation wave 2). The §19 fitness gate now runs in the CI.slnf arch tier:
StateManagementConventionTests(sealed subclass of the shared v1.115.0StateManagementConventionTestsBase) reflects over the three module UI assemblies (now registered asLayer.UiinStoreArchitectureMap) failing the build on any mutable static field or settable static property, plus a source scan forbidding singleton*StateService/*StateContainerregistrations. Verified non-vacuous: a seeded mutable static in Catalog.UI failed the gate with the exact offender name, then green after removal. Maturity 4 GRANTED on the 2026-07-16 re-score (two-pass, adversarially verified; the proposed impl bump to 9 was rejected as an enforcement gain, not substance). Scorecard §19 is M4/I8; moved to the protect list. - #18 · UI Architecture & Components · maturity 3 → 4 (weight 3). DONE (2026-07-11, remediation wave 2). The §18 fitness gate now runs in the CI.slnf arch tier:
UIArchitectureConventionTests(sealed subclass of the shared v1.115.0UIArchitectureConventionTestsBase) caps every*.razor.csunder Source/ at 400 lines and inline@codeblocks at 120 lines. Conformance shipped with the gate:OrderDetail.razor.cs500 → 361 (extractedOrderSummaryPanel+OrderLinesPanel) andProductDetail.razor.cs491 → 340 (extractedProductVariantsPanel), markup moved verbatim (DOM identical for the E2E selectors), all bUnit suites green. Verified non-vacuous via a seeded 402-line file. Maturity 4 GRANTED on the 2026-07-16 re-score (two-pass, adversarially verified; the proposed impl bump to 9 was rejected, impl holds 8 on the residual inline-style logic). Scorecard §18 is M4/I8; moved to the protect list. - #12 · Performance & Scalability · maturity 3 → 4 (weight 2). DONE (2026-07-11, remediation wave 3). Both halves of the lever are now enforced deploy preconditions: (a) a
load-freshnessjob indeploy.yml'sneedsfails the deploy when the latest successful monthlyload-test.ymlrun is older than 35 days (the dr-freshness pattern; latest run 2026-07-01, green), and (b) the WebVitals budgets were tightened from catastrophic-only (LCP 8000) to the Core Web Vitals "good" band (LCP 2500 / FCP 1800 / TTFB 800 / CLS 0.1 / INP 500), calibrated against measured CI maxima (LCP 172ms, 10-30x headroom), asserted inside the deploy-gating chromiume2e-gate. Maturity candidacy DECLINED on the 2026-07-16 re-score: the k6 load test itself runs monthly/on-demand, so it is capacity-planning evidence rather than a merge gate; the freshness gate bounds staleness but does not gate regressions. §12 stays M3/I8, lever OPEN: either record the monthly cadence as the accepted posture (ADC's stance) or add a latency-regression check to the merge path. §23 split out and RESOLVED same day (drift-analysis fold, adversarially verified): its CWV budget assertions are per-deploy enforcement independent of k6's cadence, the identical evidence ADC's twentieth cycle credited, so scorecard §23 is M4/I8 and moves to the protect list. - #13 · Observability & Operability · maturity 3 → 4 (weight 2). DONE (2026-07-11, remediation wave 6). The dashboard half already existed (the saved
store-slo-workbookAzure Monitor workbook mirrors the three SLO alerts per service); the missing runbook half landed asinfra/OPERATIONS.md: each provisioned alert (failed-requests,server-response-time,dependency-failures) mapped to concrete triage steps (workbook pane, App Insights drill path, container logs, the Stripe/gRPC/outbox failure classes) plus fast-reference recovery moves (revision rollback, PITR restore, the freshness gates) and a pair-with-sloAlertSpecsgovernance note. Split verdict on the 2026-07-16 re-score: Implementation 8 → 9 GRANTED (both prior deductions closed: workbookinfra/main.bicep:274+ runbookinfra/OPERATIONS.md), but the maturity candidacy was DECLINED: dashboards/runbooks are IaC/review-enforced, and nothing in CI fails when an alert loses its runbook pairing. §13 stays M3/I9, lever OPEN: add a CI gate asserting thesloAlertSpecs-to-OPERATIONS.mdpairing (mirrors ADC's reopened #13; one shared gate design can serve both repos). Gate SHIPPED same day (2026-07-16):Tests/Architecture/MMCA.Store.Architecture.Tests/ObservabilityConventionTests.cs(mirror of ADC's) machine-enforces the pairing in the CI.slnf arch gate: everysloAlertSpecskey needs a### ...-alert-<key>runbook section carrying the alert's current(sev N), orphans fail, 3-spec non-vacuity floor, both files embedded. Verified red on a seeded severity drift, green on the real files. Maturity 3 → 4 candidacy recorded for the next re-score. Maturity 4 GRANTED on the 2026-07-17 re-score (ObservabilityConventionTests.cs:24,34verified live in the CI.slnf arch gate,MMCA.Store.CI.slnf:52): §13 is M4/I9; moved to the protect list.
🟢 Resolved this cycle (2026-07-11 drift-convergence, drift plan D1-D13)
- #29 DR gates (drift plan D3).
dr-freshnessis now indeploy.needs(fails a deploy when the last successfuldr-drillis stale),dr-drill.ymlgained a weekly cron, andGracefulShutdownTests(inMMCA.Store.Gateway.Tests,MMCA.Store.CI.slnf) is CI-gated, so scorecard §29 legitimately holds M4 and lifts Implementation 8 → 9. The former honest residual (stale 2026-06-22 drill) is resolved: the weeklydr-drill.ymlcron runs green, most recently 2026-07-13, sodr-freshnessis satisfied. - #31 cost-guard deploy gate (drift plan D4).
cost-guard.ymlgained aworkflow_calltrigger and is invoked as acost-guardjob indeploy.needs, so an un-reverted surge blocks the deploy (previously weekly-cron-only). Prerequisite for a clean first gated deploy: a green latest scheduled cost-guard run. - #1 SOLID, impl 8 → 9 (drift plan D9). Scorecard §1 refreshed to cite the CI-gated
ConstructorDependencyCountTests(ceiling 7, the 8+-dependency red flag cleared) +TimeProviderinjection. - #17 DevOps, MI-SQL ACTIVATED in prod (2026-07-12; wiring landed inert 2026-07-11 as drift plan D2). The full
infra/SQL-MANAGED-IDENTITY.mdsequence is complete: Stage 1 Entra admin live on the server (SQL_AAD_ADMIN_*repo vars), Stage 2 grants verified in all three DBs (mmca-prod-apps-identityas EXTERNAL_USER +db_ownerinStore_Catalog/Store_Sales/Store_Identity), Stage 3USE_MANAGED_IDENTITY_SQL=truedeployed green (run 29192048197, full gate chain + post-deploy smoke). All three services now run passwordlessAuthentication=Active Directory Managed Identity; the SQL password path remains only as the documented dual-auth rollback. Mirrors ADC's 2026-06-28 activation; §17 Implementation 8→9 BANKED on the 2026-07-16 re-score (repo variableUSE_MANAGED_IDENTITY_SQL=true+ green run 29192048197 re-verified directly; the scorecard's stale inert claim corrected). The SQL public-network-access acceptance (no VNet) stands as documented.
✅ Already at level 4 (protect, don't regress)
SOLID (#1), Design Patterns (#2), Clean Architecture (#3), DDD (#4), Vertical Slice (#5), CQRS (#6), Microservices (#7), Data (#8), API (#9), Cross-Cutting (#10), Security (#11), Observability (#13), Testability (#14), Code Quality (#15), Maintainability (#16), DevOps (#17), UI Architecture (#18), State Management (#19), Design System (#20), Responsive (#22), Front-End Performance (#23), Forms (#24), Navigation (#25), Front-End Security (#26), i18n (#27), Front-End Testing (#28), Resilience (#29), Compliance/Privacy (#30), FinOps (#31), Dependency & Supply-Chain (#32), DevEx (#33), Architecture Governance (#34): all maturity 4. (#18 and #19 reached maturity 4 on the 2026-07-16 re-score via the CI-gated convention fitness tests; #5, #13, and #22 reached maturity 4 on the 2026-07-17 re-score, leaving only #12 and #21 below 4.) Most also score impl 8-9; preserve via the shared fitness functions + CI gates. (#28 reached maturity 4 on 2026-07-03 via the E2E/axe deploy gate, and #24 reached maturity 4 on 2026-07-11 via FormsConventionTests (D11); #21 Accessibility was corrected back to maturity 3 on 2026-07-11 (D6), pending a recorded screen-reader pass; #16/#20/#25/#27 reached maturity 4 in the 2026-07-02 docs re-score on gates shipped 2026-07-01; #32 and #34 reached maturity 4 on 2026-06-26.)
#34 caveat realized (2026-07-02): both governance ledgers are committed and kept current per release (§34 impl re-scored 7 → 9), and the arch fitness suite has grown to 22 test classes. Record future tactical deferrals here as
TD-NNsub-items under their category rather than in a separate file (the single-ledger model ADC adopted 2026-06-26).