@starci/hfs 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/ci/cli.mjs +64 -0
  4. package/ci/github.mjs +41 -0
  5. package/ci/secret.mjs +28 -0
  6. package/ci/vars.mjs +33 -0
  7. package/ci/verify.mjs +36 -0
  8. package/db/backup-receipt.mjs +129 -0
  9. package/db/dump.mjs +66 -0
  10. package/db/migrate.mjs +8 -5
  11. package/db/post-cutover.mjs +4 -4
  12. package/db/reset.mjs +125 -0
  13. package/emit/contracts.mjs +2 -2
  14. package/emit/db-types.mjs +100 -7
  15. package/lint/run.mjs +30 -8
  16. package/package.json +2 -1
  17. package/release/ci-red.mjs +70 -0
  18. package/release/gate.mjs +53 -13
  19. package/release/index.mjs +8 -6
  20. package/release/push.mjs +1 -1
  21. package/report/sonar.mjs +1 -1
  22. package/runtime/config.example.yaml +7 -6
  23. package/runtime/engine/config.mjs +10 -18
  24. package/runtime/engine/removed-vocabulary.mjs +0 -2
  25. package/runtime/knowledge/hfs/canon-pins.yaml +4 -4
  26. package/runtime/knowledge/hfs/rules.yaml +505 -971
  27. package/runtime/knowledge/hfs/slots.yaml +13 -24
  28. package/runtime/modules/kernel/failure-codes.yaml +60 -22
  29. package/runtime/modules/kernel/removed-vocabulary.yaml +30 -0
  30. package/runtime/modules/models/runtimes.yaml +4 -6
  31. package/runtime/modules/schemas/application-stacks.schema.yaml +131 -1
  32. package/runtime/packages/cli/src/catalog.generated.mjs +286 -398
  33. package/runtime/scripts/api/git/lib.mjs +3 -3
  34. package/runtime/scripts/api/sops/lib.mjs +1 -1
  35. package/runtime/scripts/hfs/app-wiring.mjs +2 -2
  36. package/runtime/scripts/hfs/architecture/config.mjs +1 -1
  37. package/runtime/scripts/hfs/architecture/index.mjs +1 -1
  38. package/runtime/scripts/hfs/architecture/supabase.mjs +1 -1
  39. package/runtime/scripts/hfs/architecture/tiers.mjs +1 -1
  40. package/runtime/scripts/hfs/architecture.mjs +1 -1
  41. package/runtime/scripts/hfs/ci-declaration.mjs +102 -0
  42. package/runtime/scripts/hfs/coverage-from.mjs +1 -1
  43. package/runtime/scripts/hfs/coverage-scope.mjs +1 -1
  44. package/runtime/scripts/hfs/example-secrets.mjs +1 -1
  45. package/runtime/scripts/hfs/manifest-shape.mjs +3 -3
  46. package/runtime/scripts/hfs/param-names.mjs +1 -1
  47. package/runtime/scripts/hfs/rule-catalog.mjs +3 -1
  48. package/runtime/scripts/hfs/rules/a15-findings.mjs +10 -1
  49. package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +10 -0
  50. package/runtime/scripts/hfs/rules/assets.mjs +1 -1
  51. package/runtime/scripts/hfs/rules/ci-custody.mjs +104 -0
  52. package/runtime/scripts/hfs/rules/cli.mjs +1 -1
  53. package/runtime/scripts/hfs/rules/contract-compat.mjs +1 -1
  54. package/runtime/scripts/hfs/rules/contract.mjs +1 -1
  55. package/runtime/scripts/hfs/rules/deploy-workflow.mjs +6 -19
  56. package/runtime/scripts/hfs/rules/fe-build-args.mjs +142 -0
  57. package/runtime/scripts/hfs/rules/frontend-tree.mjs +2 -2
  58. package/runtime/scripts/hfs/rules/supabase-secrets.mjs +1 -1
  59. package/runtime/scripts/hfs/rules/supply-chain.mjs +40 -3
  60. package/runtime/scripts/hfs/rules/workflow-contexts.mjs +103 -0
  61. package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +2 -2
  62. package/runtime/scripts/hfs/slots.mjs +2 -2
  63. package/runtime/scripts/hfs/typescript-programs.mjs +0 -8
  64. package/runtime/scripts/lib/env.mjs +2 -2
  65. package/runtime/scripts/lib/git.mjs +1 -1
  66. package/runtime/scripts/lib/i18n.mjs +0 -2
  67. package/runtime/scripts/lib/language.mjs +1 -1
  68. package/runtime/scripts/lib/roots.mjs +2 -4
  69. package/runtime/scripts/lib/secret-patterns.mjs +2 -2
  70. package/scaffold/add-fe-overlay.mjs +0 -121
  71. package/scaffold/add-fe-page.mjs +0 -268
  72. package/scaffold/supabase-ports.mjs +1 -1
  73. package/src/main.mjs +17 -6
  74. package/stack/age-install.mjs +1 -1
  75. package/stack/cli.mjs +2 -2
  76. package/stack/context.mjs +14 -2
  77. package/stack/digest.mjs +1 -1
  78. package/stack/docker-transport.mjs +93 -15
  79. package/stack/edge-alias.mjs +1 -1
  80. package/stack/image-scan.mjs +1 -1
  81. package/stack/ingress-create.mjs +2 -2
  82. package/stack/ingress.mjs +3 -3
  83. package/stack/release-store.mjs +12 -7
  84. package/stack/remote.mjs +16 -8
  85. package/stack/sealed.mjs +5 -5
  86. package/stack/ssh-session.mjs +178 -0
  87. package/sync/ci-commands.mjs +103 -1
  88. package/sync/format.mjs +1 -1
  89. package/sync/hygiene.mjs +1 -1
  90. package/sync/index.mjs +43 -18
  91. package/sync/quality-services.mjs +61 -0
  92. package/sync/readme-badges.mjs +44 -0
  93. package/sync/stack-images.mjs +31 -5
  94. package/templates/app/ci-workflows/github/workflows/ci.yml +26 -24
  95. package/templates/app/ci-workflows/github/workflows/images.yml +24 -2
  96. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +8 -2
  97. package/templates/app/ci-workflows/install-steps.yml +21 -0
  98. package/templates/app/ci-workflows/sonar-steps.yml +3 -9
  99. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +28 -35
  100. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +2 -1
  101. package/templates/app/ci-workflows-lite/github/workflows/images.yml +24 -2
  102. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +8 -2
  103. package/templates/app/quality-config/codecov.yml +6 -6
  104. package/templates/app/quality-config/sonar-project.properties +1 -0
  105. package/templates/app/readme-badges/README.md +1 -0
  106. package/templates/app/skeleton/.github/dependabot.yml +1 -14
  107. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +61 -3
  108. package/templates/app/skeleton/README.md +6 -0
  109. package/templates/app/skeleton-lite/.github/dependabot.yml +1 -14
  110. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +57 -3
  111. package/templates/app/skeleton-lite/README.md +6 -0
  112. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +52 -1
  113. package/upgrade/index.mjs +1 -1
@@ -1,7 +1,7 @@
1
1
  // GENERATED by scripts/cli/gen-catalog.mjs — do not edit
2
2
  export const CATALOG = {
3
3
  "schema": "starci/cli-catalog@1",
4
- "hash": "757ac9945db2a2b217a5dea8be2cd2c0fcb895230762eb9cd15700b8a44bce49",
4
+ "hash": "d230745d3aa5cfe65f75cb5fb2872924b935f1b4610c0b72db2f729572386404",
5
5
  "global": [
6
6
  {
7
7
  "name": "json",
@@ -176,8 +176,91 @@ export const CATALOG = {
176
176
  "impl": null,
177
177
  "runtimeSide": "host"
178
178
  },
179
+ "ci": {
180
+ "summary": "set declared GitHub CI secrets and variables and verify their custody",
181
+ "owner": "@starci/hfs",
182
+ "positional": [
183
+ {
184
+ "name": "action",
185
+ "enum": [
186
+ "secret",
187
+ "var",
188
+ "verify"
189
+ ],
190
+ "required": true,
191
+ "variadic": false
192
+ },
193
+ {
194
+ "name": "operation",
195
+ "enum": [
196
+ "set",
197
+ "sync"
198
+ ],
199
+ "required": false,
200
+ "variadic": false
201
+ },
202
+ {
203
+ "name": "name",
204
+ "required": false,
205
+ "variadic": false
206
+ }
207
+ ],
208
+ "flags": [
209
+ {
210
+ "name": "env",
211
+ "type": "string",
212
+ "summary": "select the declared GitHub environment"
213
+ },
214
+ {
215
+ "name": "dependabot",
216
+ "type": "boolean",
217
+ "summary": "select the Dependabot secret store"
218
+ },
219
+ {
220
+ "name": "repo",
221
+ "type": "string",
222
+ "summary": "override the app repository with owner/name"
223
+ },
224
+ {
225
+ "name": "value",
226
+ "type": "string",
227
+ "summary": "public variable value that must agree with the manifest"
228
+ },
229
+ {
230
+ "name": "execute",
231
+ "type": "boolean",
232
+ "summary": "apply the variable sync plan"
233
+ },
234
+ {
235
+ "name": "json",
236
+ "type": "boolean",
237
+ "summary": "print verification findings as JSON"
238
+ }
239
+ ],
240
+ "exit": {
241
+ "0": "action completed or verification clean",
242
+ "1": "verification findings",
243
+ "2": "refusal or bad usage"
244
+ },
245
+ "json": "flag",
246
+ "examples": [
247
+ "starci app ci secret set SONAR_TOKEN",
248
+ "starci app ci secret set VPS_SSH_KEY --env production",
249
+ "starci app ci secret set NPM_TOKEN --dependabot",
250
+ "starci app ci var set SONAR_HOST_URL",
251
+ "starci app ci var sync",
252
+ "starci app ci var sync --execute",
253
+ "starci app ci verify --json"
254
+ ],
255
+ "editions": [
256
+ "full",
257
+ "lite"
258
+ ],
259
+ "impl": null,
260
+ "runtimeSide": "host"
261
+ },
179
262
  "db": {
180
- "summary": "preview or apply a migration baseline, restamp, history migration or post-cutover step",
263
+ "summary": "preview or apply database migrations, encrypted backups and guarded linked resets",
181
264
  "owner": "@starci/hfs",
182
265
  "positional": [
183
266
  {
@@ -187,13 +270,40 @@ export const CATALOG = {
187
270
  "restamp",
188
271
  "plan",
189
272
  "migrate",
190
- "post-cutover"
273
+ "post-cutover",
274
+ "dump",
275
+ "reset"
191
276
  ],
192
277
  "required": true,
193
278
  "variadic": false
194
279
  }
195
280
  ],
196
281
  "flags": [
282
+ {
283
+ "name": "out",
284
+ "type": "string",
285
+ "summary": "dump: destination outside the app and every Git worktree"
286
+ },
287
+ {
288
+ "name": "schema-only",
289
+ "type": "boolean",
290
+ "summary": "dump: omit data parts; this backup cannot authorize reset"
291
+ },
292
+ {
293
+ "name": "auth",
294
+ "type": "string",
295
+ "summary": "reset: required keep or drop; drop deletes users and identities"
296
+ },
297
+ {
298
+ "name": "storage",
299
+ "type": "string",
300
+ "summary": "reset: required keep or drop; drop empties objects metadata but does not delete backend files"
301
+ },
302
+ {
303
+ "name": "backup",
304
+ "type": "string",
305
+ "summary": "reset: existing full encrypted backup receipt for this project, younger than database.reset.backupMaxAgeHours (default 24)"
306
+ },
197
307
  {
198
308
  "name": "stamp",
199
309
  "type": "string",
@@ -217,17 +327,17 @@ export const CATALOG = {
217
327
  {
218
328
  "name": "execute",
219
329
  "type": "boolean",
220
- "summary": "migrate, post-cutover: apply the plan (also needs STARCI_DB_ARMED=1); without it both are read-only"
330
+ "summary": "migrate, post-cutover, reset: apply the plan (also needs STARCI_DB_ARMED=1); otherwise read-only"
221
331
  },
222
332
  {
223
333
  "name": "linked",
224
334
  "type": "boolean",
225
- "summary": "migrate, post-cutover: use the project the app is linked to (the default)"
335
+ "summary": "use the linked project; required explicitly for reset and one of the dump target choices"
226
336
  },
227
337
  {
228
338
  "name": "url-env",
229
339
  "type": "string",
230
- "summary": "migrate, post-cutover: name of the environment variable that holds the connection string"
340
+ "summary": "migrate, post-cutover, dump: environment variable holding the connection string"
231
341
  },
232
342
  {
233
343
  "name": "green-at",
@@ -242,16 +352,19 @@ export const CATALOG = {
242
352
  {
243
353
  "name": "json",
244
354
  "type": "boolean",
245
- "summary": "plan, migrate, post-cutover: print the result as JSON"
355
+ "summary": "plan, migrate, post-cutover, dump, reset: print the result as JSON"
246
356
  }
247
357
  ],
248
358
  "exit": {
249
359
  "0": "preview or action completed with no drift",
250
- "1": "database plan drift",
251
- "2": "refusal or bad usage"
360
+ "1": "database plan drift or failed tool/verification",
361
+ "2": "refusal or bad usage",
362
+ "3": "database mutation is not armed"
252
363
  },
253
364
  "json": "flag",
254
365
  "examples": [
366
+ "starci app db dump --linked --out /var/backups/my-app",
367
+ "starci app db reset --linked --auth keep --storage keep --backup /var/backups/my-app/backup.receipt.json",
255
368
  "starci app db baseline",
256
369
  "starci app db baseline --stamp 20261014000000 --apply",
257
370
  "starci app db restamp --map restamp.yaml",
@@ -267,6 +380,17 @@ export const CATALOG = {
267
380
  ],
268
381
  "impl": null,
269
382
  "conventions": [
383
+ "Owner ruling 2026-10-17 alpha.20: \"add a canon DB reset/backup verb design ...",
384
+ "at least starci app db dump (encrypted, outside repo) and starci app db reset --linked with explicit auth/storage behaviour flags\"",
385
+ "Owner ruling main 2026-10-17: reset \"must require --backup <receipt> pointing at an existing encrypted dump made in the last N hours,",
386
+ "and must refuse without explicit --auth/--storage choices\"",
387
+ "dump requires exactly one target; archives roles, schema, auth/storage schema, data and rowcounts;",
388
+ "age encrypts to .sops.yaml recipients and deletes plaintext even on failure",
389
+ "dump verifies age archive header, size and sha256; owner identity is required for a separate decryption proof",
390
+ "reset is linked only, dry run by default, and requires STARCI_DB_ARMED=1 with --execute; local reset stays npm run db:reset",
391
+ "reset keep encrypts auth/storage data before reset, proves identity access, restores transactionally and verifies fingerprints and migration head;",
392
+ "requires Supabase db query --file and SOPS_AGE_KEY or SOPS_AGE_KEY_FILE",
393
+ "reset keeps encrypted temporary recovery parts after a reset/restore failure and reports their directory; plaintext is always deleted",
270
394
  "baseline accepts --stamp; restamp requires --map; both preview without --apply",
271
395
  "plan is always read-only and supports --json; it compares migrations, cron, queues and Vault names",
272
396
  "migrate and post-cutover read the optional database block of application-stacks.yaml; both are dry runs without --execute",
@@ -355,6 +479,15 @@ export const CATALOG = {
355
479
  "type": "string",
356
480
  "summary": "one frontend workspace to judge"
357
481
  },
482
+ {
483
+ "name": "side",
484
+ "type": "enum",
485
+ "enum": [
486
+ "be",
487
+ "fe"
488
+ ],
489
+ "summary": "judge one side (root findings belong to be; not with --sonar)"
490
+ },
358
491
  {
359
492
  "name": "fix",
360
493
  "type": "boolean",
@@ -467,6 +600,11 @@ export const CATALOG = {
467
600
  "type": "string",
468
601
  "summary": "gate: release tag prefix (default from release.tagPrefix, v)"
469
602
  },
603
+ {
604
+ "name": "sonar",
605
+ "type": "boolean",
606
+ "summary": "gate: append a local Sonar scan using services.sonar host and the token environment variable named by ci.token (default SONAR_TOKEN)"
607
+ },
470
608
  {
471
609
  "name": "remote",
472
610
  "type": "string",
@@ -481,12 +619,13 @@ export const CATALOG = {
481
619
  "exit": {
482
620
  "0": "gate green or push done or nothing to do",
483
621
  "1": "a gate is red or the push was refused by the hook",
484
- "2": "refusal or bad usage"
622
+ "2": "refusal or bad usage including RELEASE_CI_RED and RELEASE_SONAR_UNAVAILABLE"
485
623
  },
486
624
  "json": "flag",
487
625
  "examples": [
488
626
  "starci app release gate",
489
627
  "starci app release gate --execute",
628
+ "starci app release gate --sonar --execute",
490
629
  "starci app release push --remote origin",
491
630
  "starci app release push --execute"
492
631
  ],
@@ -496,7 +635,16 @@ export const CATALOG = {
496
635
  ],
497
636
  "impl": null,
498
637
  "conventions": [
499
- "the gate list is release.gates of application-stacks.yaml (argument arrays), else the app check plus the managed package scripts",
638
+ "the gate list is release.gates of application-stacks.yaml (argument arrays), else app-check, audit, then the managed package scripts",
639
+ "audit runs npm audit --omit=dev --audit-level=high by default; services.audit.level and omitDev configure it,",
640
+ "and an explicit audit.in without release-gate omits it;",
641
+ "declared release.gates gets audit appended if missing",
642
+ "--sonar appends @sonar/scan@4.3.0 against services.sonar.host (host.public for a host mapping), plus organization for sonarcloud;",
643
+ "disabled or unavailable Sonar or an unset token refuses RELEASE_SONAR_UNAVAILABLE",
644
+ "gate checks the newest completed ci.yml run on the default branch, including reachable push/tag runs;",
645
+ "failure, cancelled or timed_out refuses RELEASE_CI_RED with its URL and SHA;",
646
+ "unreadable GitHub or no run warns RELEASE_CI_UNKNOWN and continues",
647
+ "only the owner's starci release ci-override --sha <sha> --reason <text> record can override red CI; there is no --no-ci-check flag",
500
648
  "gate refuses a dirty tree, HEAD other than --source, a moved HEAD and a tree dirtied by the gates; record and tag only when all gates are green",
501
649
  "a gate with summary jest is red on failed tests and on a coverage threshold miss even when the process exits 0",
502
650
  "push needs the annotated tag and L4 record of HEAD, runs git push --dry-run --atomic first and never uses --no-verify"
@@ -2073,35 +2221,6 @@ export const CATALOG = {
2073
2221
  },
2074
2222
  "runtimeSide": "tree"
2075
2223
  },
2076
- "runtime-coverage": {
2077
- "summary": "run the runtime spec suite under Node coverage and write coverage/lcov.info",
2078
- "owner": "runtime",
2079
- "positional": [
2080
- {
2081
- "name": "specs",
2082
- "required": false,
2083
- "variadic": true
2084
- }
2085
- ],
2086
- "flags": [],
2087
- "exit": {
2088
- "0": "the suite is green",
2089
- "1": "a spec failed",
2090
- "2": "bad usage"
2091
- },
2092
- "json": "none",
2093
- "examples": [
2094
- "starci gate runtime-coverage",
2095
- "starci gate runtime-coverage tests/cli/catalog.spec.mjs"
2096
- ],
2097
- "editions": [
2098
- "full"
2099
- ],
2100
- "impl": {
2101
- "script": "scripts/gates/runtime-coverage.mjs"
2102
- },
2103
- "runtimeSide": "tree"
2104
- },
2105
2224
  "sonar": {
2106
2225
  "summary": "inspect, provision, run and start the local Sonar quality gate",
2107
2226
  "owner": "runtime",
@@ -2230,7 +2349,7 @@ export const CATALOG = {
2230
2349
  {
2231
2350
  "name": "public",
2232
2351
  "type": "boolean",
2233
- "summary": "up or stop: include the public Cloudflare tunnel (needs CLOUDFLARE_TUNNEL_TOKEN)"
2352
+ "summary": "up or stop: activate profile public; up verifies the tunnel is running (needs CLOUDFLARE_TUNNEL_TOKEN)"
2234
2353
  }
2235
2354
  ],
2236
2355
  "exit": {
@@ -2252,6 +2371,12 @@ export const CATALOG = {
2252
2371
  "impl": {
2253
2372
  "script": "scripts/gates/sonar-local.mjs"
2254
2373
  },
2374
+ "conventions": [
2375
+ "up --public retries the tunnel running check for up to 30 seconds; SONAR_TUNNEL_NOT_RUNNING refuses with container state and the last 20 scrubbed log lines",
2376
+ "SONAR_DB_PASSWORD_MISMATCH: the starci-sonarqube-postgres-data volume has another password than SONARQUBE_DB_PASSWORD in secret.env",
2377
+ "(Compose supplies SONAR_JDBC_PASSWORD and POSTGRES_PASSWORD);",
2378
+ "restore the old password or export a backup before recreating the volume"
2379
+ ],
2255
2380
  "runtimeSide": "tree"
2256
2381
  },
2257
2382
  "starcistacks": {
@@ -2532,16 +2657,6 @@ export const CATALOG = {
2532
2657
  }
2533
2658
  ],
2534
2659
  "flags": [
2535
- {
2536
- "name": "verified",
2537
- "type": "string",
2538
- "summary": "an earlier verified tip that must be an ancestor of ref"
2539
- },
2540
- {
2541
- "name": "verified-log",
2542
- "type": "string",
2543
- "summary": "the earlier verification log whose prior-red specs must rerun"
2544
- },
2545
2660
  {
2546
2661
  "name": "dry-run",
2547
2662
  "type": "boolean",
@@ -2556,23 +2671,16 @@ export const CATALOG = {
2556
2671
  "name": "kernel-note",
2557
2672
  "type": "string",
2558
2673
  "summary": "one line, what a Kernel must do differently after this land; the land record carries it and the runtime delivers it verbatim with the Kernels' next wake (absent: no line)"
2559
- },
2560
- {
2561
- "name": "concurrency",
2562
- "type": "number",
2563
- "default": 4,
2564
- "summary": "dependent spec file concurrency"
2565
2674
  }
2566
2675
  ],
2567
2676
  "exit": {
2568
2677
  "0": "the verification passed and local main fast-forwarded, or a dry run passed without moving it",
2569
- "1": "refused at a named gate, check, spec, lock or fast-forward step",
2678
+ "1": "refused at the verify receipt, a named gate, the check, the lock or the fast-forward step",
2570
2679
  "2": "bad usage"
2571
2680
  },
2572
- "json": "starci/git-land@1",
2681
+ "json": "starci/git-land@2",
2573
2682
  "examples": [
2574
2683
  "starci git land <worktree> <ref>",
2575
- "starci git land <worktree> <ref> --verified <sha> --verified-log <file> --concurrency 2",
2576
2684
  "starci git land <worktree> <ref> --dry-run --json",
2577
2685
  "starci git land <worktree> <ref> --kernel-note \"settle needs --evidence now\""
2578
2686
  ],
@@ -2589,10 +2697,10 @@ export const CATALOG = {
2589
2697
  "owner"
2590
2698
  ],
2591
2699
  "conventions": [
2592
- "land only after starci test run --level L2 --against <ref> is green",
2593
- "lands are serial and hold the host land lock through the gate, check, specs and local merge",
2594
- "local main is the only destination; a land never pushes, tags or touches origin",
2595
- "delta lands use --verified with the matching --verified-log and always rerun prior-red spec files"
2700
+ "land only a tip `starci runtime verify` proved (check, package clean-test, scaffold e2e on that exact commit)",
2701
+ "the runtime has no specs of its own (owner ruling no-runtime-specs)",
2702
+ "lands are serial and hold the host land lock through the receipt, gate, full check and local merge",
2703
+ "local main is the only destination; a land never pushes, tags or touches origin"
2596
2704
  ],
2597
2705
  "runtimeSide": "host"
2598
2706
  },
@@ -7196,12 +7304,12 @@ export const CATALOG = {
7196
7304
  "runtimeSide": "host"
7197
7305
  },
7198
7306
  "install": {
7199
- "summary": "add exact dependencies from canon pins under the host lock",
7307
+ "summary": "install exact dependencies and move StarCi pins with the target CLI",
7200
7308
  "owner": "runtime",
7201
7309
  "positional": [
7202
7310
  {
7203
7311
  "name": "package",
7204
- "required": true,
7312
+ "required": false,
7205
7313
  "variadic": true
7206
7314
  }
7207
7315
  ],
@@ -7210,17 +7318,24 @@ export const CATALOG = {
7210
7318
  "name": "dev",
7211
7319
  "type": "boolean",
7212
7320
  "summary": "save the packages as development dependencies"
7321
+ },
7322
+ {
7323
+ "name": "canon",
7324
+ "type": "boolean",
7325
+ "summary": "install the target CLI and all of its exact StarCi canon pins"
7213
7326
  }
7214
7327
  ],
7215
7328
  "exit": {
7216
- "0": "exact dependencies were installed",
7217
- "1": "npm, Git or the host lock failed",
7218
- "2": "the package or worktree was refused"
7329
+ "0": "exact dependencies and any requested canon pins were installed",
7330
+ "1": "npm, Git, target canon loading or the host lock failed",
7331
+ "2": "the package, target pin or worktree was refused"
7219
7332
  },
7220
7333
  "json": "starci/npm-install@1",
7221
7334
  "examples": [
7222
7335
  "starci npm install typescript",
7223
- "starci npm install left-pad@1.3.0 --dev"
7336
+ "starci npm install left-pad@1.3.0 --dev",
7337
+ "starci npm install @starci/cli --dev",
7338
+ "starci npm install --canon --dev"
7224
7339
  ],
7225
7340
  "editions": [
7226
7341
  "full"
@@ -7236,7 +7351,12 @@ export const CATALOG = {
7236
7351
  ],
7237
7352
  "conventions": [
7238
7353
  "bare package names resolve only from knowledge/hfs/canon-pins.yaml and never through a registry lookup",
7239
- "explicit versions use exact x.y.z form and must agree with the canon pin when one exists",
7354
+ "explicit versions use exact x.y.z form and must agree with the canon pin when one exists, except the target CLI version on a canon upgrade",
7355
+ "naming @starci/cli or passing --canon installs the exact target CLI first,",
7356
+ "then reads its installed HFS runtime canon-pins.yaml and installs every pinned @starci package in the same host lock",
7357
+ "--canon without a CLI positional uses the running runtime's exact CLI pin as the target",
7358
+ "target pins never fall back to the running runtime when the target pin file is missing or inconsistent",
7359
+ "each target StarCi pin is reported as moved or refused with a reason; a failed canon phase exits nonzero even when the first CLI install succeeded",
7240
7360
  "installs always use --save-exact and report the package.json and package-lock.json diff stat"
7241
7361
  ],
7242
7362
  "runtimeSide": "host"
@@ -7655,6 +7775,53 @@ export const CATALOG = {
7655
7775
  },
7656
7776
  "runtimeSide": "tree"
7657
7777
  },
7778
+ "ci-override": {
7779
+ "summary": "the owner accepts red CI for one SHA and records who and why",
7780
+ "owner": "runtime",
7781
+ "flags": [
7782
+ {
7783
+ "name": "sha",
7784
+ "type": "string",
7785
+ "summary": "required full 40 lowercase hex SHA of the red CI run"
7786
+ },
7787
+ {
7788
+ "name": "reason",
7789
+ "type": "string",
7790
+ "summary": "required nonempty owner reason, recorded verbatim after trimming"
7791
+ },
7792
+ {
7793
+ "name": "repo",
7794
+ "type": "string",
7795
+ "summary": "repository receiving the override (default current directory)"
7796
+ }
7797
+ ],
7798
+ "exit": {
7799
+ "0": "the override record and runtime owner ruling were written",
7800
+ "2": "RIGHTS_OWNER_ONLY (a bound role or non-TTY stdin), bad usage, confirmation mismatch, or write failure"
7801
+ },
7802
+ "json": "none",
7803
+ "examples": [
7804
+ "starci release ci-override --sha 0123456789abcdef0123456789abcdef01234567 --reason \"Owner accepts this CI failure for the release\"",
7805
+ "starci release ci-override --repo ../my-app --sha 0123456789abcdef0123456789abcdef01234567 --reason \"Owner accepts the failed run\""
7806
+ ],
7807
+ "editions": [
7808
+ "full"
7809
+ ],
7810
+ "impl": {
7811
+ "script": "scripts/supervisor/release-ci-override-cli.mjs"
7812
+ },
7813
+ "conventions": [
7814
+ "OWNER RULING 2026-10-17 (chat to main, relayed): alpha.20 \"cut refuses when the latest CI on main is red, with a documented owner override verb\";",
7815
+ "the override is owner-only, records who and why in the owner rulings, and agents cannot run it.",
7816
+ "Every bound role is refused by the command guard and by this script. The owner must use a terminal and type the first 12 SHA characters exactly.",
7817
+ "Writes <git-common-dir>/starci-release/<sha>.ci-override.json, schema starci/ci-override@1,",
7818
+ "with sha, reason, by (git user.name and OS user), at, and runUrl (empty if GitHub is unavailable).",
7819
+ "For the runtime, appends ci-override-<sha12> under rulings before the top-level supersedes key in modules/kernel/owner-rulings.yaml.",
7820
+ "Commit that entry into the tree being cut. App repositories receive only the record.",
7821
+ "An override applies only to its exact SHA. It does not permit a cut when CI is unknown. Existing ruling IDs with another reason refuse."
7822
+ ],
7823
+ "runtimeSide": "tree"
7824
+ },
7658
7825
  "ci-status": {
7659
7826
  "summary": "the verdict of the GitHub ci workflow, Codecov and Sonar for a release; red is recorded for Debug",
7660
7827
  "owner": "runtime",
@@ -7774,14 +7941,14 @@ export const CATALOG = {
7774
7941
  ],
7775
7942
  "exit": {
7776
7943
  "0": "the release was cut and main plus its tag were pushed atomically, or --plan found nothing missing",
7777
- "1": "refused (dirty tree, no or wrong tag, release notes incomplete, version not moved past the remote main, suite red, main moved, secret scan) and nothing was pushed",
7944
+ "1": "refused (RELEASE_CI_RED, RELEASE_CI_UNKNOWN, dirty tree, no or wrong tag, release notes incomplete, version not moved past the remote main, suite red, main moved, secret scan) and nothing was pushed",
7778
7945
  "2": "bad usage"
7779
7946
  },
7780
7947
  "json": "flag",
7781
7948
  "examples": [
7782
7949
  "starci release cut",
7783
7950
  "starci release cut --plan --tag v1.0.0-alpha.9",
7784
- "starci release cut --tag v1.0.0-alpha.9 --rows \"npm test,linux-parity\"",
7951
+ "starci release cut --tag v1.0.0-alpha.9 --rows \"npm run test:e2e,linux-parity\"",
7785
7952
  "starci release cut --repo <path> --tag v1.0.0-alpha.9 --json"
7786
7953
  ],
7787
7954
  "editions": [
@@ -7790,42 +7957,15 @@ export const CATALOG = {
7790
7957
  "impl": {
7791
7958
  "script": "scripts/supervisor/release-cut-cli.mjs"
7792
7959
  },
7793
- "runtimeSide": "tree"
7794
- },
7795
- "env-test": {
7796
- "summary": "run the runtime spec suite under the release cut's own conditions",
7797
- "owner": "runtime",
7798
- "flags": [
7799
- {
7800
- "name": "lane",
7801
- "type": "boolean",
7802
- "summary": "a lane clone is no Orca terminal: leave out STARCI_REQUIRE_ORCA_LIVE and the host check, keep everything else of the cut"
7803
- },
7804
- {
7805
- "name": "reuse-installs",
7806
- "type": "boolean",
7807
- "summary": "keep an example app whose node_modules exists instead of a fresh npm ci"
7808
- }
7809
- ],
7810
- "exit": {
7811
- "0": "the suite is green and no skip fails the evidence rule",
7812
- "1": "a step is red or a skipped test ran in no leg",
7813
- "2": "the host lacks a prerequisite of the cut, or bad usage"
7814
- },
7815
- "json": "none",
7816
- "examples": [
7817
- "starci release env-test",
7818
- "starci release env-test --lane --reuse-installs"
7819
- ],
7820
- "editions": [
7821
- "full"
7822
- ],
7823
- "impl": {
7824
- "script": "scripts/supervisor/release-env-test.mjs"
7825
- },
7826
7960
  "conventions": [
7827
- "the suite is the cut's own spec leg, so a red the cut would find shows here first; it takes minutes to an hour and writes each step to a log",
7828
- "without --lane it refuses (exit 2) unless the host has an Orca terminal, a reachable Orca and a Docker daemon, the same prerequisites the cut refuses on"
7961
+ "OWNER RULING 2026-10-17 (chat to main, relayed): alpha.20 \"cut refuses when the latest CI on main is red, with a documented owner override verb\";",
7962
+ "the override is owner-only, records who and why in the owner rulings, and agents cannot run it.",
7963
+ "Before the suite, including --plan, read the newest completed CI workflow run on main.",
7964
+ "Only success continues; every other conclusion refuses RELEASE_CI_RED and names the run URL and headSha.",
7965
+ "Unreadable GitHub or no completed run refuses RELEASE_CI_UNKNOWN: a cut must not proceed blind, including under suite ci.",
7966
+ "The owner may run starci release ci-override --sha <headSha> --reason <text>.",
7967
+ "A red run requires both starci-release/<headSha>.ci-override.json in the git common dir and ci-override-<sha12>",
7968
+ "in modules/kernel/owner-rulings.yaml of the tree being cut. Commit the ruling before cutting."
7829
7969
  ],
7830
7970
  "runtimeSide": "tree"
7831
7971
  },
@@ -7891,75 +8031,6 @@ export const CATALOG = {
7891
8031
  ],
7892
8032
  "runtimeSide": "tree"
7893
8033
  },
7894
- "launch-smoke": {
7895
- "summary": "prove live nested-agent launch paths on an Orca host",
7896
- "owner": "runtime",
7897
- "positional": [
7898
- {
7899
- "name": "action",
7900
- "enum": [
7901
- "stage",
7902
- "mark"
7903
- ],
7904
- "required": false,
7905
- "variadic": false
7906
- }
7907
- ],
7908
- "flags": [
7909
- {
7910
- "name": "app-repo",
7911
- "type": "string",
7912
- "summary": "scratch app main checkout registered in Orca"
7913
- },
7914
- {
7915
- "name": "entry",
7916
- "type": "string",
7917
- "summary": "plain entry terminal for the smoke"
7918
- },
7919
- {
7920
- "name": "timeout-ms",
7921
- "type": "number",
7922
- "summary": "smoke deadline in milliseconds"
7923
- },
7924
- {
7925
- "name": "out",
7926
- "type": "string",
7927
- "summary": "write the smoke result to this file"
7928
- },
7929
- {
7930
- "name": "as",
7931
- "type": "enum",
7932
- "enum": [
7933
- "supervisor",
7934
- "worker",
7935
- "kernel",
7936
- "op",
7937
- "opFe",
7938
- "opFail",
7939
- "critic"
7940
- ],
7941
- "summary": "internal smoke role for stage or mark"
7942
- }
7943
- ],
7944
- "exit": {
7945
- "0": "smoke or role action passed",
7946
- "1": "smoke or role action failed",
7947
- "2": "bad usage or no entry terminal"
7948
- },
7949
- "json": "always",
7950
- "examples": [
7951
- "starci release launch-smoke --app-repo <scratch-app>",
7952
- "starci release launch-smoke stage --as kernel",
7953
- "starci release launch-smoke mark --as op"
7954
- ],
7955
- "editions": [
7956
- "full"
7957
- ],
7958
- "impl": {
7959
- "script": "scripts/kernel/launch-smoke.mjs"
7960
- },
7961
- "runtimeSide": "tree"
7962
- },
7963
8034
  "notes": {
7964
8035
  "summary": "print or write the release notes of a tag, its CHANGELOG section",
7965
8036
  "owner": "runtime",
@@ -8136,6 +8207,32 @@ export const CATALOG = {
8136
8207
  ],
8137
8208
  "runtimeSide": "tree"
8138
8209
  },
8210
+ "scaffold-e2e": {
8211
+ "summary": "run the scaffold end-to-end proof (full and lite scaffolds installed, built and run for real)",
8212
+ "owner": "runtime",
8213
+ "flags": [],
8214
+ "exit": {
8215
+ "0": "every scaffold e2e test ran and passed",
8216
+ "1": "a scaffold e2e test failed, was cancelled or was skipped",
8217
+ "2": "the run could not start or bad usage"
8218
+ },
8219
+ "json": "none",
8220
+ "examples": [
8221
+ "starci release scaffold-e2e"
8222
+ ],
8223
+ "editions": [
8224
+ "full"
8225
+ ],
8226
+ "impl": {
8227
+ "script": "scripts/gates/scaffold-e2e.mjs"
8228
+ },
8229
+ "conventions": [
8230
+ "With release clean-test, the real test proof of the runtime (owner ruling no-runtime-specs): the runtime has no specs.",
8231
+ "A skipped test is red: every scaffold test must run (Docker, npm and the source canon registry are prerequisites).",
8232
+ "Builds the grammar and heroicons dist first when they are stale, from their own lockfiles: a fresh lane needs no build step."
8233
+ ],
8234
+ "runtimeSide": "tree"
8235
+ },
8139
8236
  "sync-runtime": {
8140
8237
  "summary": "refresh or check package runtime copies and optionally prepare grammar",
8141
8238
  "owner": "runtime",
@@ -8440,7 +8537,7 @@ export const CATALOG = {
8440
8537
  "owner"
8441
8538
  ],
8442
8539
  "conventions": [
8443
- "refuses unless the source is clean, a fast-forward of the host and its check and affected specs are proven by a receipt on that commit",
8540
+ "refuses unless the source is clean, a fast-forward of the host and its check, package clean-test and scaffold e2e are proven by a receipt on that commit",
8444
8541
  "refuses while a release cut holds the host lock; waits for settles, Critic runs and prepared decisions in flight, stops none",
8445
8542
  "several commits are one revision change, with one fast-forward, installed artefacts migrated, one engine restart, then verified",
8446
8543
  "journals one runtime-deployed event; --plan prints every step and refusal and changes nothing",
@@ -9074,7 +9171,7 @@ export const CATALOG = {
9074
9171
  "runtimeSide": "tree"
9075
9172
  },
9076
9173
  "verify": {
9077
- "summary": "verify a committed revision - the check AND the affected specs on one commit, one receipt",
9174
+ "summary": "verify a commit - the check, package clean-test and scaffold e2e on one commit, one receipt",
9078
9175
  "owner": "runtime",
9079
9176
  "positional": [],
9080
9177
  "flags": [
@@ -9090,12 +9187,11 @@ export const CATALOG = {
9090
9187
  }
9091
9188
  ],
9092
9189
  "exit": {
9093
- "0": "verified: check and every affected spec passed on the exact commit, receipt written",
9094
- "1": "NOT VERIFIED: dirty tree, no base, red check, or a red spec file",
9095
- "2": "bad usage",
9096
- "3": "PARTIAL: nothing red, the lane's own specs ran, some were not started inside the budget (fit to land, not to deploy)"
9190
+ "0": "verified: check, package clean-test and scaffold e2e passed on the exact commit, receipt written",
9191
+ "1": "NOT VERIFIED: dirty tree, no base, red check, a red or unrun package, or a failed or skipped scaffold e2e test",
9192
+ "2": "bad usage"
9097
9193
  },
9098
- "json": "starci/runtime-verify@1",
9194
+ "json": "starci/runtime-verify@2",
9099
9195
  "examples": [
9100
9196
  "starci runtime verify --base <tip>",
9101
9197
  "starci runtime verify --json"
@@ -9116,11 +9212,11 @@ export const CATALOG = {
9116
9212
  "owner"
9117
9213
  ],
9118
9214
  "conventions": [
9119
- "A branch is verified only by this receipt: check N of N and affected specs N of N for base..tip, on the exact commit.",
9120
- "A fix lane reports the last line of this verb, not the line of starci runtime check (which never runs a spec).",
9215
+ "A branch is verified only by this receipt: check N of N, the clean-test of every package base..tip touches, the scaffold e2e.",
9216
+ "The runtime has no specs of its own (owner ruling no-runtime-specs): package specs and the scaffold e2e decide.",
9217
+ "A fix lane reports the last line of this verb, not the line of starci runtime check (which runs no test).",
9121
9218
  "Refuses a tree with uncommitted or untracked changes; the receipt binds a commit.",
9122
- "starci git land accepts a partial receipt (0 failed, the lane's changed specs ran, not-started counted); deploy and release need all of them.",
9123
- "A spec whose inputs are unchanged since a proven green run is reused; the receipt counts the reused files."
9219
+ "starci git land, starci runtime deploy and the release read the same receipt: every proof passed."
9124
9220
  ],
9125
9221
  "runtimeSide": "tree"
9126
9222
  },
@@ -9864,21 +9960,6 @@ export const CATALOG = {
9864
9960
  "type": "string",
9865
9961
  "summary": "comma-separated commit shas to land"
9866
9962
  },
9867
- {
9868
- "name": "specs",
9869
- "type": "string",
9870
- "summary": "spec files or touching, direct, all, or none"
9871
- },
9872
- {
9873
- "name": "reason",
9874
- "type": "string",
9875
- "summary": "reason required when no spec applies"
9876
- },
9877
- {
9878
- "name": "full-by-push-git",
9879
- "type": "boolean",
9880
- "summary": "authorize the full suite from the push flow"
9881
- },
9882
9963
  {
9883
9964
  "name": "lane",
9884
9965
  "type": "string",
@@ -9914,7 +9995,7 @@ export const CATALOG = {
9914
9995
  "examples": [
9915
9996
  "starci supervisor land --status",
9916
9997
  "starci supervisor land --job <job-id>",
9917
- "starci supervisor land --commit <sha> --specs touching --lane <name>"
9998
+ "starci supervisor land --commit <sha> --lane <name>"
9918
9999
  ],
9919
10000
  "editions": [
9920
10001
  "full"
@@ -9960,20 +10041,10 @@ export const CATALOG = {
9960
10041
  "type": "string",
9961
10042
  "summary": "source lane name"
9962
10043
  },
9963
- {
9964
- "name": "specs",
9965
- "type": "string",
9966
- "summary": "comma-separated specs for the land gate"
9967
- },
9968
- {
9969
- "name": "wrongly-blocked",
9970
- "type": "string",
9971
- "summary": "spec proving the prior gate was wrong"
9972
- },
9973
10044
  {
9974
10045
  "name": "reason",
9975
10046
  "type": "string",
9976
- "summary": "reason when no spec applies"
10047
+ "summary": "why the experiment is landed"
9977
10048
  },
9978
10049
  {
9979
10050
  "name": "wait-ms",
@@ -10937,189 +11008,6 @@ export const CATALOG = {
10937
11008
  }
10938
11009
  }
10939
11010
  },
10940
- "test": {
10941
- "summary": "run the bounded L1-L4 test ladder without accidental whole-suite work",
10942
- "owner": "runtime",
10943
- "verbs": {
10944
- "affected": {
10945
- "summary": "the specs related to the changed functions (--by file: every importer); --run runs each once",
10946
- "owner": "runtime",
10947
- "positional": [],
10948
- "flags": [
10949
- {
10950
- "name": "base",
10951
- "type": "string",
10952
- "summary": "ref to diff against (default: the merge-base with main, else origin/main)"
10953
- },
10954
- {
10955
- "name": "changed",
10956
- "type": "list",
10957
- "summary": "explicit changed repository paths instead of the diff"
10958
- },
10959
- {
10960
- "name": "by",
10961
- "type": "string",
10962
- "summary": "symbol (default: the specs related to the changed functions) or file (every spec importing a changed file)"
10963
- },
10964
- {
10965
- "name": "run",
10966
- "type": "boolean",
10967
- "summary": "run the selected spec files, one per process, inside the time budget"
10968
- },
10969
- {
10970
- "name": "plan",
10971
- "type": "boolean",
10972
- "summary": "print the selected files with the reason each is in the set; run nothing"
10973
- },
10974
- {
10975
- "name": "receipt-file",
10976
- "type": "string",
10977
- "summary": "with --run, write the receipt to this file; the answer carries its path (a gate reads the file, not the output)"
10978
- },
10979
- {
10980
- "name": "no-cache",
10981
- "type": "boolean",
10982
- "summary": "run every selected file; ignore the per-spec result cache"
10983
- },
10984
- {
10985
- "name": "concurrency",
10986
- "type": "number",
10987
- "summary": "override automatic file concurrency with a positive integer"
10988
- },
10989
- {
10990
- "name": "root",
10991
- "type": "string",
10992
- "summary": "repository root (default: the command cwd)"
10993
- }
10994
- ],
10995
- "exit": {
10996
- "0": "selection printed, or every selected file passed",
10997
- "1": "a selected spec file was red",
10998
- "2": "no base to diff against, or the time budget ended before every selected file started"
10999
- },
11000
- "json": "starci/test-affected@1",
11001
- "examples": [
11002
- "starci test affected",
11003
- "starci test affected --run",
11004
- "starci test affected --changed scripts/machine/ladder-test.mjs --run"
11005
- ],
11006
- "editions": [
11007
- "full"
11008
- ],
11009
- "impl": {
11010
- "module": "scripts/supervisor/affected-test.mjs",
11011
- "export": "testAffected"
11012
- },
11013
- "effect": "host",
11014
- "roles": [
11015
- "worker",
11016
- "lead",
11017
- "coordinator",
11018
- "release",
11019
- "owner"
11020
- ],
11021
- "conventions": [
11022
- "Everyday verification after npm run check; the whole suite is the merged-tree run and the release cut.",
11023
- "The set is computed - each changed .mjs symbol is followed by name through its importers, callers and CLI verbs.",
11024
- "What cannot be followed by name (yaml, templates, load-time statements, no base, the depth bound) keeps the file-level rule, named in the report.",
11025
- "Selection and --plan JSON carry every symbol, its specs and reasons, and file-level fallbacks; the set is never larger than --by file.",
11026
- "A --run machine answer carries the complete selected set, every result and the receipt; the diagnostic graph remains available through --plan.",
11027
- "A large set is never refused; it runs in parallel shards inside the printed time budget, and files not started when it ends are listed.",
11028
- "The --plan flag prints each selected file with the reason it is in the set; a --run answer carries a receipt (base, tip, passed, total) a gate can require.",
11029
- "A generated output maps to its generator's specs; an append-only change to a data file to the specs that name it or its readers.",
11030
- "A red file is fixed and run again, then the affected set once; never the whole suite.",
11031
- "A spec whose key (import closure, data it names, runner) is unchanged since a green run is reused; the receipt counts reused files; --no-cache runs all.",
11032
- "Each file is its own low-priority node process with the four preloads, at the concurrency of test-concurrency.yaml."
11033
- ],
11034
- "runtimeSide": "tree"
11035
- },
11036
- "run": {
11037
- "summary": "run the specs selected for one local ladder level",
11038
- "owner": "runtime",
11039
- "positional": [],
11040
- "flags": [
11041
- {
11042
- "name": "level",
11043
- "type": "enum",
11044
- "enum": [
11045
- "L1",
11046
- "L2",
11047
- "L3",
11048
- "L4"
11049
- ],
11050
- "required": true,
11051
- "summary": "bounded local test level"
11052
- },
11053
- {
11054
- "name": "changed",
11055
- "type": "list",
11056
- "summary": "changed repository paths used for L1 selection"
11057
- },
11058
- {
11059
- "name": "against",
11060
- "type": "string",
11061
- "default": "main",
11062
- "summary": "local main ref used for L2 and L3 selection"
11063
- },
11064
- {
11065
- "name": "spec",
11066
- "type": "list",
11067
- "summary": "explicit spec files at L1 only"
11068
- },
11069
- {
11070
- "name": "concurrency",
11071
- "type": "number",
11072
- "summary": "override automatic CPU/RAM file concurrency with a positive integer"
11073
- },
11074
- {
11075
- "name": "root",
11076
- "type": "string",
11077
- "summary": "repository root (default is the command cwd)"
11078
- },
11079
- {
11080
- "name": "release-cut",
11081
- "type": "boolean",
11082
- "summary": "confirm an owner or release-role L4 release-cut run"
11083
- }
11084
- ],
11085
- "exit": {
11086
- "0": "selected specs passed",
11087
- "1": "a check or spec was red",
11088
- "2": "usage or ladder policy refusal"
11089
- },
11090
- "json": "starci/test-run@1",
11091
- "examples": [
11092
- "starci test run --level L1 --changed scripts/machine/ladder-test.mjs",
11093
- "starci test run --level L2 --against main --json",
11094
- "starci test run --level L3 --against main"
11095
- ],
11096
- "editions": [
11097
- "full"
11098
- ],
11099
- "impl": {
11100
- "module": "scripts/machine/ladder-test.mjs",
11101
- "export": "testRun"
11102
- },
11103
- "effect": "host",
11104
- "roles": [
11105
- "worker",
11106
- "lead",
11107
- "coordinator",
11108
- "release",
11109
- "owner"
11110
- ],
11111
- "conventions": [
11112
- "Use L1 while working, L2 before asking for a land, and L3 when an IO slot changed.",
11113
- "Never run the whole suite outside L4; L4 belongs to starci release cut and L5 belongs to CI.",
11114
- "L2 and L3 need a clean committed tree, run the full check first, and hold the one host test lock.",
11115
- "A red L2 or L3 selection is re-run once serially; a green re-run is recorded as a flake, never skipped.",
11116
- "File concurrency uses fresh idle CPU and free RAM under modules/supervisor/test-concurrency.yaml; --concurrency overrides it.",
11117
- "The result and spec log retain the concurrency decision and host measurements."
11118
- ],
11119
- "runtimeSide": "tree"
11120
- }
11121
- }
11122
- },
11123
11011
  "typecheck": {
11124
11012
  "summary": "typecheck only the projects selected by the test ladder",
11125
11013
  "owner": "runtime",