Description
The diff-scoped strict typecheck gate exists on main and has never executed once.
PR #37403 (spike #37401) merged on 2026-09-08. It added 37 files: 31 under core-web/tools/scripts/strict-gate/ and 6 under specs/37401-diff-scoped-strict-typecheck-gate/. It touched zero files under .github/ and zero lines of core-web/pom.xml. The harness README says so plainly: "The spike wires the harness into nothing."
Verified on origin/main @ de342798f4
| Check |
Result |
git grep -l "strict-gate" outside its own directory and spec dir |
no matches |
<execution> ids in core-web/pom.xml |
validate-dist-paths, pnpm-install, lint-test, format-test, build-test, build-analytics, unit-test, nx-reset, prod, do-nx-reset, validate, format, auto-format, auto-lint — no strict-gate |
core-web/lint-staged.config.mjs |
only nx affected -t lint / nx format:write — no strict-gate |
Any workflow in .github/workflows/ mentioning strict |
none |
Consequence: since 2026-09-08 no pull request has been annotated, reported on, or blocked by the gate. It is dead code on main, and main has kept accumulating strict debt exactly as before the spike.
Why this is worth finishing rather than deleting
The obvious objection is "#37198 turns the whole workspace strict, so drop it." DECOMMISSION.md §2 documents why that does not close the hole:
Declaring strict: true does not mean anything compiles it.
| Fact |
Value |
Nx projects in core-web |
57 |
…with a build target |
18 — the other 39 have nothing that compiles them |
…with a typecheck target |
5, all inferred by @nx/vite/plugin, 0 declared in a project.json |
Does the build see .spec.ts? |
No — tsconfig.lib.json carries exclude: ["src/**/*.spec.ts", …] |
| Where the spike's findings lived |
8 of 11 in .spec.ts (73 %) |
#37198 changes tsconfigs, .ts and .html files — no project.json, no nx.json, no pom.xml, no workflow. It makes the baseline strict and fixes existing violations, but adds no mechanism that runs a type-check over the 39 projects with no build plus every .spec.ts. Lint does not type-check.
So either this gate ships as the interim mechanism, or #37198 grows a typecheck target. Doing neither leaves the gap open in both directions.
Scope decision
Non-blocking (reporting only) in this issue. The blocking flip stays out of scope: measured runtime is 8.4–9.4 s average with a 12 s tail against the 10 s budget SC-005 set to protect what ADR-0013 bought (frontend merge time ~45 min → ~15 min). Templates are a separate no-go (2.2× compiler time on the largest app) and are excluded entirely.
This issue supersedes #37448, which carries the same scope but was never picked up (opened 2026-09-07, no assignee, no milestone, 0 comments).
Acceptance Criteria
Priority
Medium
Additional Context
No workflow change is required
cicd_comp_test-phase.yml already fetches origin/main (the Frontend Unit Tests job needs it for nx affected), and .github/filters.yaml already carries the frontend filter (core-web/**). The hook belongs in core-web/pom.xml like every other frontend gate — this is why grepping the workflows for "strict" finds nothing and always would.
Shape of the pom.xml execution
Model it on lint-test. The exec plugin's executable is ${node.install.dir}/pnpm, so the arguments start with exec:
<execution>
<id>strict-gate</id>
<goals><goal>exec</goal></goals>
<phase>generate-resources</phase>
<configuration>
<skip>${skip.validate}</skip>
<!-- 0 = clean, 1 = findings (non-blocking for now), 2 = harness failure (must fail) -->
<successCodes>
<successCode>0</successCode>
<successCode>1</successCode>
</successCodes>
<arguments>
<argument>exec</argument>
<argument>node</argument>
<argument>tools/scripts/strict-gate/run.mjs</argument>
<argument>--base=${git.origin.branch}</argument>
<argument>--flags=strict</argument>
<argument>--granularity=line</argument>
<argument>--scope=core-web</argument>
<argument>--format=github</argument>
</arguments>
</configuration>
</execution>
parseArgs in run.mjs splits on =, so the inline --flag=value form used by lint-test works as-is. Unknown options are rejected by name.
Why --flags=strict --granularity=line
strict is the repo convention (strict + noPropertyAccessFromIndexSignature, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch) — the same yardstick as tsconfig.base.json on the strict-mode branch. At line granularity it costs one extra finding over the narrow set across the whole corpus.
line because whole-file makes an author inherit 83 % of what it reports from lines they did not write. New files are unaffected — every line of an added file is a changed line.
Measured evidence from the spike
- 11 findings across a 5-PR corpus, all 11 real, 0 false positives
- 99.1 % of diagnostics discarded on a representative portlet (217 of 219)
- Zero changes to any version-controlled file — strictness is forced in memory, never through a temporary config
- No new dependency; not an Nx project (registering one would put the harness into the graph it measures)
Local repro
cd core-web
nvm use
node tools/scripts/strict-gate/run.mjs --base origin/main --head HEAD
node --test --test-concurrency=1 'tools/scripts/strict-gate/*.test.mjs'
Verification for the reviewer
# Before the PR both come back empty. After it, both must match.
git grep -n "strict-gate" -- core-web/pom.xml core-web/lint-staged.config.mjs
References
Description
The diff-scoped strict typecheck gate exists on
mainand has never executed once.PR #37403 (spike #37401) merged on 2026-09-08. It added 37 files: 31 under
core-web/tools/scripts/strict-gate/and 6 underspecs/37401-diff-scoped-strict-typecheck-gate/. It touched zero files under.github/and zero lines ofcore-web/pom.xml. The harness README says so plainly: "The spike wires the harness into nothing."Verified on
origin/main@de342798f4git grep -l "strict-gate"outside its own directory and spec dir<execution>ids incore-web/pom.xmlvalidate-dist-paths,pnpm-install,lint-test,format-test,build-test,build-analytics,unit-test,nx-reset,prod,do-nx-reset,validate,format,auto-format,auto-lint— nostrict-gatecore-web/lint-staged.config.mjsnx affected -t lint/nx format:write— nostrict-gate.github/workflows/mentioning strictConsequence: since 2026-09-08 no pull request has been annotated, reported on, or blocked by the gate. It is dead code on
main, andmainhas kept accumulating strict debt exactly as before the spike.Why this is worth finishing rather than deleting
The obvious objection is "#37198 turns the whole workspace strict, so drop it."
DECOMMISSION.md§2 documents why that does not close the hole:core-webbuildtargettypechecktarget@nx/vite/plugin, 0 declared in aproject.json.spec.ts?tsconfig.lib.jsoncarriesexclude: ["src/**/*.spec.ts", …].spec.ts(73 %)#37198 changes tsconfigs,
.tsand.htmlfiles — noproject.json, nonx.json, nopom.xml, no workflow. It makes the baseline strict and fixes existing violations, but adds no mechanism that runs a type-check over the 39 projects with no build plus every.spec.ts. Lint does not type-check.So either this gate ships as the interim mechanism, or #37198 grows a
typechecktarget. Doing neither leaves the gap open in both directions.Scope decision
Non-blocking (reporting only) in this issue. The blocking flip stays out of scope: measured runtime is 8.4–9.4 s average with a 12 s tail against the 10 s budget SC-005 set to protect what ADR-0013 bought (frontend merge time ~45 min → ~15 min). Templates are a separate no-go (2.2× compiler time on the largest app) and are excluded entirely.
This issue supersedes #37448, which carries the same scope but was never picked up (opened 2026-09-07, no assignee, no milestone, 0 comments).
Acceptance Criteria
core-web/pom.xmlgains astrict-gate<execution>in thegenerate-resourcesphase, besidelint-test/format-test, gated by<skip>${skip.validate}</skip>so it runs only under-Pvalidatenode tools/scripts/strict-gate/run.mjs --base=${git.origin.branch} --flags=strict --granularity=line --scope=core-web --format=github<successCodes>accepts0and1(findings do not fail the build) but not2— a harness that could not run must still fail loudly. Exit-code contract:contracts/cli.mdcore-webTypeScript shows inline annotations on the diff and a job summary on the run page (--format githubwrites to$GITHUB_STEP_SUMMARY)frontendfilter in.github/filters.yamlalready gates the job oncore-web/**)core-web/lint-staged.config.mjsruns the gate on staged TS files, in a non-overlapping glob key so it does not race the existingnx affected -t linton git'sindex.lock--test-concurrency=1core-web/tools/scripts/strict-gate/README.mdno longer says the gate is wired into nothing; it states where the hook lives and that it is non-blockingPriority
Medium
Additional Context
No workflow change is required
cicd_comp_test-phase.ymlalready fetchesorigin/main(theFrontend Unit Testsjob needs it fornx affected), and.github/filters.yamlalready carries thefrontendfilter (core-web/**). The hook belongs incore-web/pom.xmllike every other frontend gate — this is why grepping the workflows for "strict" finds nothing and always would.Shape of the pom.xml execution
Model it on
lint-test. The exec plugin's executable is${node.install.dir}/pnpm, so the arguments start withexec:parseArgsinrun.mjssplits on=, so the inline--flag=valueform used bylint-testworks as-is. Unknown options are rejected by name.Why
--flags=strict --granularity=linestrictis the repo convention (strict+noPropertyAccessFromIndexSignature,noImplicitOverride,noImplicitReturns,noFallthroughCasesInSwitch) — the same yardstick astsconfig.base.jsonon the strict-mode branch. At line granularity it costs one extra finding over the narrow set across the whole corpus.linebecause whole-file makes an author inherit 83 % of what it reports from lines they did not write. New files are unaffected — every line of an added file is a changed line.Measured evidence from the spike
Local repro
Verification for the reviewer
References
core-web/tools/scripts/strict-gate/README.mdspecs/37401-diff-scoped-strict-typecheck-gate/findings.md(§5 runtime, §6 decisions, §7 templates, §10 go/no-go, §12 follow-up)specs/37401-diff-scoped-strict-typecheck-gate/DECOMMISSION.md(§2 precondition, §3.3 what to remove if promoted)specs/37401-diff-scoped-strict-typecheck-gate/contracts/cli.md(options, exit codes, output formats)