Repository navigation
Commit d82f867
fix(scripts): check:i18n-coverage declares the example configs and their src trees to the dispatch derivation (#21271)
Fixes #21011
Clause-②: no
## What
`check:i18n-coverage` now declares what it reads to the dispatch
derivation, so an edit under an example app derives the gate locally. CI
already ran it on the same diff.
- `scripts/check-i18n-coverage.mjs`: `const ROOT_DIR_WATCH_HINTS =
['examples/*/objectstack.config.ts', 'examples/*/src/**'];` beside
`EXAMPLES_DIR`, plus a new `--self-test` battery that holds the
declaration against the live tree (details below). What the gate judges
is unchanged.
- `scripts/pm/bare-root-worklist.mjs`: the `check-i18n-coverage.mjs
EXAMPLES_DIR examples` row is re-decided from `SPELLABLE-UNDECLARED` to
`DECLARED-NARROWER`. Its recorded spelling is re-measured as the two
hints above, and its old single-hint spelling entry is replaced.
- `scripts/pm/dispatch-gates.mjs` is **not touched**. It is frozen under
ruling 208 R6, and its self-test stayed green with the declaration in
place (see Gates).
## Why this spelling and not `examples/**`
The gate runs `os lint` on each example config. `os lint` loads the
config through bundle-require: esbuild bundles every relative import,
and `@objectstack/*` plus the driver modules stay external
(`BUNDLE_REQUIRE_EXTERNALS` in `packages/cli/src/utils/config.ts`). So
the count moves with anything in the config's relative import graph.
Measured with esbuild and those externals at `30c530e5`:
| | tracked files | of which in the 4 configs' import closures |
|---|---|---|
| closure (the real read) | 153 | 153 |
| declared: `examples/*/objectstack.config.ts` + `examples/*/src/**` |
170 | 153 (complete, 90% precise) |
| `examples/**` (bare-root spelling) | 256 | 153 (60% precise) |
Every closure file is either a config or a file under that same
example's `src/`. Here are the 17 declared files that no config imports:
- 11 `src/docs/*.md` pages. `os lint` reads them, but only through
`docs/*` rules, and the gate counts `i18n/` rules alone.
- 2 `*.test.ts` files under `app-todo/src`.
- 3 unimported files under `app-showcase/src`.
- the `src/` of `embed-objectql`, which has no config.
`examples/**` would add the test suites, e2e specs, READMEs, changelogs
and manifests. That is 86 more files, none of which a config imports.
## Pins (in the gate's own `--self-test`, new battery, 10 cases)
The battery imports the derivation's own `extractWatchHints` and
`hintCovers`. The import is dynamic and sits inside `selfTest`, which
the extractor masks. So the gate's own extracted hints gain exactly the
two declared literals, and its import follow is unchanged: before
`[cli-build-prerequisite.mjs, import-prerequisite.mjs]`, after the same.
- The derivation reads both declared hints off this source.
- Positive: the three showcase source files of PR #20998 derive the
gate, and so does every config `discoverExamples()` finds (4).
- Completeness: no relative import in a config or in a non-test file
under its `src/` resolves outside that example's `src/`. On this tree
that is 177 edges and 0 escapes. A negative control proves the scan
still sees an escape.
- Precision: these do not derive through this declaration:
`examples/app-showcase/test/gap-fill.test.ts`, `examples/README.md`, and
the two `packages/` paths of PR #20998. Controls show that the extractor
drops a computed spelling, and that `examples/**` would have named the
test file.
## Measured end to end with `dispatch-gates --commands`
Before is base `30c530e5`, after is head `61bd05aa`.
| change set | before | after |
|---|---|---|
| PR #20998's full file list (15 paths) | 116 commands, no
`check:i18n-coverage` | 117, the only addition is `pnpm
check:i18n-coverage` |
| its 4 `examples/app-showcase/**` paths alone | 40, absent | 41,
present |
| its 2 `packages/` paths alone
(`packages/spec/src/data/analytics.zod.ts`,
`packages/services/service-analytics/README.md`) | 74, absent | 74,
byte-identical list |
| `examples/app-showcase/test/gap-fill.test.ts` alone | (not measured) |
38, absent |
## Ablations
All four were run through `scripts/ablation-replace.mjs` against the
committed head. Each mutation was proven on disk by its anchor count and
blob hash, and each restore was proven by `blob == HEAD` and an empty
`git diff HEAD`:
1. Declaration replaced by `['examples/**']`: the self-test goes red, 1
failure. The precision case names the test file and
`examples/README.md`.
2. Declaration computed from `EXAMPLES_DIR`: red, 4 failures. The
extracted hints fall back to
`["scripts/i18n-coverage-baseline.json","i18n","node_modules"]`.
3. `src/**` hint dropped: red, 2 failures (the showcase edit and the
import targets are no longer derived).
4. Same mutation as 3, run against `bare-root-worklist.mjs --self-test`:
red, 1 failure, "NOT DECLARED: examples/*/src/**". The map and the gate
cannot drift apart silently.
## Gates (all at head `61bd05aa`)
The family list came from `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` (no paths, change set from the
merge base). It names the same 30 the dispatch listed, and all 30 exited
0. `--ran` reconciliation: "30 derived famil(ies) accounted for — 30
run, 0 NOT-MEASURED".
- `node scripts/check-i18n-coverage.mjs --self-test` passed, then the
gate itself: `check-i18n-coverage: OK (13 config(s), 621 baselined
untranslated string(s), none new)`. It ran after the gate's own closure
build under the verify lock (`VERDICT command-exit 0`).
- `node scripts/pm/bare-root-worklist.mjs --self-test`: OK. There are
now 12 DECLARED-NARROWER records held set-equal to their gates' arrays;
there were 11.
- `pnpm check:pm-dispatch-gates`: `dispatch-gates self-test: 1976 cases
pass`, run detached for 825.6s. No pin moved, and the frozen file is not
in the diff.
- Not on the derived list, run anyway because it judges declarations:
`node scripts/check-declared-population-live.mjs` passed with 266 of 326
families live.
- The other 27 derived families were all exit 0: ci-filter-parity,
closing-keyword-parity (+self-test), comment-mask-corpus,
declaration-mirrors (+self-test), scripts-symbol-anchors (+self-test),
self-test-wired (+self-test), self-test-workflow-commands (+self-test),
whole-set-label-write (+self-test), agent-test-spelling, bash32-floor,
cli-command-ids, cross-package-test-inputs, driver-memory-census,
entry-guard, gitlink-declared, nul-bytes, parse-guard,
pnpm-filter-targets, ratchet-remedy-authority, refd-timer-probe and
watch-hint-literal.
- Lint, narrowed and declared as narrowed: `eslint --no-inline-config
--format json` over the 2 changed files returned 2 files, 0 errors and 0
warnings. `eslint.config.mjs` enables no type-aware linting (no
`parserOptions.project`), so this diff cannot move the verdict on any
untouched file. The full `pnpm lint` is left to CI.
## Acceptance notes
- **The PACKAGES half is out of scope, on purpose.** `PACKAGES_DIR`
stays undeclared, and its worklist row keeps `SPELLABLE-UNDECLARED` (9
extract configs share one spelling with `check:i18n-bundles` and
`check:i18n-stale-fill`, deferred together). The gate's closure also
reaches every workspace package a config imports by name, so a
`packages/spec` edit can move this count too. Declaring that would be
the `packages/` root wholesale, the REFUSE-WIDE shape. The CLI half
already reaches this gate through `cli-build-prerequisite.mjs`.
- **The dispatch premise was off by one verdict.** The dispatch and
claim describe the worklist record as REFUSE-UNSPELLABLE, and so does
the gate's old header comment. On `main` the row was
`SPELLABLE-UNDECLARED` with "Deferred: no consumer has asked". This card
is that consumer, and moving the row to DECLARED-NARROWER follows the
split criterion of the 2026-08-26 ruling recorded in the worklist
header. A paragraph there records the re-decision. The stale header
comment in the gate is replaced.
- `selfTest` in `check-i18n-coverage.mjs` became `async`, because it
needs the dynamic import. The dispatch reads `(await selfTest()) !==
SELF_TEST_VERDICT`, a spelling other gates already use. Self-test
runtime went from about 0.11s to about 0.2s.
- `skip-changeset`: `scripts/**` publishes nothing from any package.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FNKm1SmPpuJASnbjxWGtsJ)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 95b91cc commit d82f867
2 files changed
Lines changed: 240 additions & 28 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
184 | 184 | | |
185 | 185 | | |
186 | 186 | | |
187 | | - | |
| 187 | + | |
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
| |||
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
| 224 | + | |
224 | 225 | | |
225 | 226 | | |
226 | 227 | | |
227 | 228 | | |
228 | | - | |
| 229 | + | |
229 | 230 | | |
230 | 231 | | |
231 | 232 | | |
| |||
246 | 247 | | |
247 | 248 | | |
248 | 249 | | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
259 | 296 | | |
260 | 297 | | |
261 | 298 | | |
| |||
709 | 746 | | |
710 | 747 | | |
711 | 748 | | |
712 | | - | |
| 749 | + | |
713 | 750 | | |
714 | 751 | | |
715 | 752 | | |
| |||
1275 | 1312 | | |
1276 | 1313 | | |
1277 | 1314 | | |
| 1315 | + | |
| 1316 | + | |
| 1317 | + | |
| 1318 | + | |
| 1319 | + | |
| 1320 | + | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
| 1332 | + | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + | |
| 1336 | + | |
| 1337 | + | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
| 1343 | + | |
| 1344 | + | |
| 1345 | + | |
| 1346 | + | |
| 1347 | + | |
| 1348 | + | |
| 1349 | + | |
| 1350 | + | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
| 1373 | + | |
| 1374 | + | |
| 1375 | + | |
| 1376 | + | |
| 1377 | + | |
| 1378 | + | |
| 1379 | + | |
| 1380 | + | |
| 1381 | + | |
| 1382 | + | |
| 1383 | + | |
| 1384 | + | |
| 1385 | + | |
| 1386 | + | |
| 1387 | + | |
| 1388 | + | |
| 1389 | + | |
| 1390 | + | |
| 1391 | + | |
| 1392 | + | |
| 1393 | + | |
| 1394 | + | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
| 1412 | + | |
| 1413 | + | |
| 1414 | + | |
| 1415 | + | |
| 1416 | + | |
| 1417 | + | |
| 1418 | + | |
| 1419 | + | |
| 1420 | + | |
| 1421 | + | |
| 1422 | + | |
| 1423 | + | |
| 1424 | + | |
| 1425 | + | |
| 1426 | + | |
| 1427 | + | |
| 1428 | + | |
| 1429 | + | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
1278 | 1450 | | |
1279 | 1451 | | |
1280 | 1452 | | |
| |||
1331 | 1503 | | |
1332 | 1504 | | |
1333 | 1505 | | |
1334 | | - | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
1335 | 1509 | | |
1336 | 1510 | | |
1337 | 1511 | | |
1338 | 1512 | | |
1339 | 1513 | | |
1340 | 1514 | | |
1341 | | - | |
| 1515 | + | |
1342 | 1516 | | |
1343 | 1517 | | |
1344 | 1518 | | |
| |||
0 commit comments