Resolves #13939
Strengthens the turn-loaded ADR-19 trigger and makes the recurring AiConfig boundary failures mechanical without banning valid local Provider subtree references. The existing ai:lint-config-template-ssot command now also scans ai/ implementation files for conservative ADR-19 SSOT violations: config-shaped pass-through across method/module boundaries, parameter-default config seams, exported AiConfig values, defensive optional chaining, hidden defaults, and type coercions around AiConfig reads.
Evidence: L2 (focused Playwright unit coverage plus the wired lint command) -> L2 required (static/lint substrate ACs). No residuals.
Deltas from ticket
- Corrected the initial ticket phrasing: local Provider subtree variables such as
const bridgeConfig = AiConfig... are allowed; cross-boundary config pass-through remains forbidden.
- Added explicit detection for the
Number(AiConfig...) || <default> class as two failures: type-coercion and hidden-default.
- Kept existing live debt in an explicit burndown baseline so the command blocks new violations without turning this quick win into a broad cleanup PR.
- Rewrote the AGENTS AiConfig trigger as a byte-negative STOP trigger; current size is 24,438 bytes under the 24 KiB cap.
- Clean diff: this PR intentionally does not modify
DeploymentStateBridgeService.mjs.
Substrate Slot Rationale
Modified AGENTS.md edge-case trigger: disposition stays compress-to-trigger, but the trigger is rewritten. Trigger-frequency is every ai/ config code/review touch; failure-severity is high because ADR-19 misses can route config through stale cross-boundary seams or hidden fallback logic; enforceability is now split between the L1 trigger and the L4 lint command. The change is byte-negative, so it reduces loaded substrate while making the recurring failure shape visible.
Test Evidence
node --check ai/scripts/lint/lint-config-template-ssot.mjs
node --check test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs
npm run ai:lint-config-template-ssot
npm run test-unit -- test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs (16 passed)
npm run agent-preflight -- ai/scripts/lint/lint-config-template-ssot.mjs test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs
git diff --check
wc -c AGENTS.md -> 24438 AGENTS.md
- Pre-commit hooks passed on
50e9064de7.
Post-Merge Validation
Commits
50e9064de7 — feat(ai): harden ADR-19 config lint (#13939)
Related: #12456
Authored by Euclid (GPT-5, Codex Desktop). Session 02b1972b-2925-4458-89c7-287df50c726e.
PR Update — rebase onto current dev
Rebased onto current origin/dev and removed four stale AI_CONFIG_IMPLEMENTATION_BASELINE rows that later cleanup had already retired. This keeps the ADR-19 lint convergent instead of carrying obsolete burndown rows.
Commit: befcf6c306.
Validation:
node ai/scripts/lint/lint-config-template-ssot.mjs — passed (0 inline-env leaf defaults, 4 AiConfig implementation SSOT hits, all baselined)
npm run test-unit -- test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs — 16 passed
npm run agent-preflight -- --no-fix AGENTS.md ai/scripts/lint/lint-config-template-ssot.mjs test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs — passed
git diff --check — passed
CI is running on the rebased head.
Resolves #13939
Strengthens the turn-loaded ADR-19 trigger and makes the recurring AiConfig boundary failures mechanical without banning valid local Provider subtree references. The existing
ai:lint-config-template-ssotcommand now also scansai/implementation files for conservative ADR-19 SSOT violations: config-shaped pass-through across method/module boundaries, parameter-default config seams, exported AiConfig values, defensive optional chaining, hidden defaults, and type coercions aroundAiConfigreads.Evidence: L2 (focused Playwright unit coverage plus the wired lint command) -> L2 required (static/lint substrate ACs). No residuals.
Deltas from ticket
const bridgeConfig = AiConfig...are allowed; cross-boundary config pass-through remains forbidden.Number(AiConfig...) || <default>class as two failures:type-coercionandhidden-default.DeploymentStateBridgeService.mjs.Substrate Slot Rationale
Modified
AGENTS.mdedge-case trigger: disposition stayscompress-to-trigger, but the trigger is rewritten. Trigger-frequency is everyai/config code/review touch; failure-severity is high because ADR-19 misses can route config through stale cross-boundary seams or hidden fallback logic; enforceability is now split between the L1 trigger and the L4 lint command. The change is byte-negative, so it reduces loaded substrate while making the recurring failure shape visible.Test Evidence
node --check ai/scripts/lint/lint-config-template-ssot.mjsnode --check test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjsnpm run ai:lint-config-template-ssotnpm run test-unit -- test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs(16 passed)npm run agent-preflight -- ai/scripts/lint/lint-config-template-ssot.mjs test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjsgit diff --checkwc -c AGENTS.md->24438 AGENTS.md50e9064de7.Post-Merge Validation
npm run ai:lint-config-template-ssotremains green on updateddev.Commits
50e9064de7—feat(ai): harden ADR-19 config lint (#13939)Related: #12456
Authored by Euclid (GPT-5, Codex Desktop). Session 02b1972b-2925-4458-89c7-287df50c726e.
PR Update — rebase onto current
devRebased onto current
origin/devand removed four staleAI_CONFIG_IMPLEMENTATION_BASELINErows that later cleanup had already retired. This keeps the ADR-19 lint convergent instead of carrying obsolete burndown rows.Commit:
befcf6c306.Validation:
node ai/scripts/lint/lint-config-template-ssot.mjs— passed (0inline-env leaf defaults,4AiConfig implementation SSOT hits, all baselined)npm run test-unit -- test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs— 16 passednpm run agent-preflight -- --no-fix AGENTS.md ai/scripts/lint/lint-config-template-ssot.mjs test/playwright/unit/ai/scripts/lint/lintConfigTemplateSsot.spec.mjs— passedgit diff --check— passedCI is running on the rebased head.