@starci/hfs 4.7.32 → 4.7.34

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 (473) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +13 -6
  3. package/emit/contracts.mjs +4 -3
  4. package/emit/form-bounds-reader.ts.partial +58 -0
  5. package/emit/form-bounds.mjs +155 -0
  6. package/emit/graphql-input-bounds.mjs +97 -0
  7. package/emit/input-bounds.mjs +44 -0
  8. package/emit/operation-schemas.mjs +137 -0
  9. package/emit/operations-worker.mjs +2 -2
  10. package/emit/operations.mjs +52 -16
  11. package/emit/schema-worker.mjs +17 -4
  12. package/emit/type-schema.mjs +17 -5
  13. package/package.json +9 -2
  14. package/release/gate.mjs +18 -23
  15. package/release/index.mjs +1 -1
  16. package/release/push.mjs +4 -5
  17. package/runtime/engine/admission.mjs +331 -0
  18. package/runtime/engine/canonical-json.mjs +14 -0
  19. package/runtime/engine/db/blob.mjs +380 -0
  20. package/runtime/engine/db/event-compact.mjs +73 -0
  21. package/runtime/engine/db/ledger-open.mjs +38 -0
  22. package/runtime/engine/db/ledger-paths.mjs +87 -0
  23. package/runtime/engine/db/ledger.mjs +1068 -0
  24. package/runtime/engine/db/machine-connection.mjs +150 -0
  25. package/runtime/engine/db/machine-open.mjs +60 -0
  26. package/runtime/engine/db/machine-schema.mjs +105 -0
  27. package/runtime/engine/db/machine.mjs +1317 -0
  28. package/runtime/engine/db/provider-reservations.mjs +127 -0
  29. package/runtime/engine/db/provision-authority.mjs +76 -0
  30. package/runtime/engine/db/provision-lock.mjs +29 -0
  31. package/runtime/engine/db/provision-operations.mjs +146 -0
  32. package/runtime/engine/db/ref-value.mjs +67 -0
  33. package/runtime/engine/db/schema/machine.sql +920 -0
  34. package/runtime/engine/db/schema/runtime.sql +1113 -0
  35. package/runtime/engine/refuse.mjs +11 -0
  36. package/runtime/knowledge/hfs/canon-pins.yaml +65 -9
  37. package/runtime/knowledge/hfs/design-truths.yaml +149 -0
  38. package/runtime/knowledge/hfs/fe-stack.yaml +23 -5
  39. package/runtime/knowledge/hfs/rules.yaml +269 -48
  40. package/runtime/knowledge/hfs/slots.yaml +113 -53
  41. package/runtime/knowledge/patterns/be/api.yaml +46 -20
  42. package/runtime/knowledge/patterns/be/event-bus.yaml +19 -12
  43. package/runtime/knowledge/patterns/be/idempotency.yaml +265 -0
  44. package/runtime/knowledge/patterns/be/jobs.yaml +17 -12
  45. package/runtime/knowledge/patterns/be/projections.yaml +2 -2
  46. package/runtime/knowledge/patterns/be/queues.yaml +57 -22
  47. package/runtime/knowledge/patterns/be/reactors.yaml +1 -1
  48. package/runtime/knowledge/patterns/be/realtime.yaml +326 -27
  49. package/runtime/knowledge/patterns/be/saga.yaml +2 -2
  50. package/runtime/knowledge/sonar-gate.yaml +1 -1
  51. package/runtime/modules/kernel/command-policy.yaml +249 -0
  52. package/runtime/modules/kernel/failure-codes.yaml +211 -52
  53. package/runtime/modules/kernel/hook-input.yaml +6 -0
  54. package/runtime/modules/kernel/protected-zone.yaml +81 -0
  55. package/runtime/modules/kernel/removed-vocabulary.yaml +62 -0
  56. package/runtime/modules/kernel/roles.yaml +405 -0
  57. package/runtime/modules/models/registry.yaml +3 -1
  58. package/runtime/modules/models/runtimes.yaml +2 -0
  59. package/runtime/modules/schemas/application-stacks.schema.yaml +10 -2
  60. package/runtime/packages/cli/src/catalog.generated.mjs +46 -59
  61. package/runtime/packages/grammar/scripts/build-stamp.mjs +98 -0
  62. package/runtime/scripts/agent/codex-app-server.mjs +79 -0
  63. package/runtime/scripts/agent/codex-mirror-source.mjs +34 -0
  64. package/runtime/scripts/agent/host-agents.mjs +80 -0
  65. package/runtime/scripts/agent/launch-trust-policy.mjs +53 -0
  66. package/runtime/scripts/agent/trust-launch.mjs +191 -0
  67. package/runtime/scripts/agent/trust.mjs +523 -0
  68. package/runtime/scripts/api/fs/rename-over.mjs +21 -0
  69. package/runtime/scripts/api/fs/temp-path.mjs +8 -0
  70. package/runtime/scripts/api/fs/write-json-file.mjs +10 -0
  71. package/runtime/scripts/api/git/diff-names.mjs +8 -0
  72. package/runtime/scripts/api/git/head-time.mjs +10 -0
  73. package/runtime/scripts/api/git/index-lock.mjs +78 -0
  74. package/runtime/scripts/api/git/is-ancestor.mjs +5 -0
  75. package/runtime/scripts/api/git/log.mjs +5 -0
  76. package/runtime/scripts/api/git/merge-base-query.mjs +5 -0
  77. package/runtime/scripts/api/git/merge-tree.mjs +5 -0
  78. package/runtime/scripts/api/git/rev-list.mjs +5 -0
  79. package/runtime/scripts/api/git/rev-parse.mjs +13 -0
  80. package/runtime/scripts/api/git/status-query.mjs +5 -0
  81. package/runtime/scripts/api/git/worktree-list-query.mjs +5 -0
  82. package/runtime/scripts/api/node/spawn-node.mjs +6 -0
  83. package/runtime/scripts/api/npm/dist-tag.mjs +8 -0
  84. package/runtime/scripts/api/npm/lib.mjs +32 -0
  85. package/runtime/scripts/api/npm/pack-dry-run.mjs +9 -0
  86. package/runtime/scripts/api/npm/run-npm.mjs +6 -0
  87. package/runtime/scripts/api/npm/view.mjs +30 -0
  88. package/runtime/scripts/api/npm/whoami.mjs +8 -0
  89. package/runtime/scripts/api/process/hide-child-windows.mjs +31 -0
  90. package/runtime/scripts/api/process/kill-tree.mjs +22 -0
  91. package/runtime/scripts/api/process/lib.mjs +125 -0
  92. package/runtime/scripts/api/process/probe-guard-command.mjs +74 -0
  93. package/runtime/scripts/api/process/process-list.mjs +28 -0
  94. package/runtime/scripts/api/process/system-tool.mjs +37 -0
  95. package/runtime/scripts/gates/canon-digest.mjs +81 -0
  96. package/runtime/scripts/gates/canon-pins.mjs +16 -0
  97. package/runtime/scripts/gates/commit-proof.mjs +53 -0
  98. package/runtime/scripts/gates/gate-input.mjs +98 -0
  99. package/runtime/scripts/gates/gate.mjs +669 -0
  100. package/runtime/scripts/gates/grammar-dist.mjs +206 -0
  101. package/runtime/scripts/gates/runtime-package-selection.mjs +27 -0
  102. package/runtime/scripts/gates/test-world-run.mjs +254 -0
  103. package/runtime/scripts/gates/type-impact.mjs +277 -0
  104. package/runtime/scripts/gates/type-program.mjs +113 -0
  105. package/runtime/scripts/guards/assigned-command.mjs +12 -0
  106. package/runtime/scripts/guards/call-rights.mjs +47 -0
  107. package/runtime/scripts/guards/command-guard.mjs +468 -0
  108. package/runtime/scripts/guards/command-policy.mjs +342 -0
  109. package/runtime/scripts/guards/critic-reach.mjs +82 -0
  110. package/runtime/scripts/guards/deps-guard.mjs +150 -0
  111. package/runtime/scripts/guards/env-dump-verdict.mjs +89 -0
  112. package/runtime/scripts/guards/git-pathspec.mjs +225 -0
  113. package/runtime/scripts/guards/git-policy.mjs +355 -0
  114. package/runtime/scripts/guards/guards-root.mjs +27 -0
  115. package/runtime/scripts/guards/hook-install.mjs +343 -0
  116. package/runtime/scripts/guards/hook-io.mjs +76 -0
  117. package/runtime/scripts/guards/hook-verdict.mjs +12 -0
  118. package/runtime/scripts/guards/install-verdict.mjs +41 -0
  119. package/runtime/scripts/guards/kernel-seat.mjs +63 -0
  120. package/runtime/scripts/guards/launch-verdict.mjs +74 -0
  121. package/runtime/scripts/guards/op-starci.mjs +16 -0
  122. package/runtime/scripts/guards/op-write-scope.mjs +27 -0
  123. package/runtime/scripts/guards/orca-self-lifecycle.mjs +39 -0
  124. package/runtime/scripts/guards/process-kill-verdict.mjs +106 -0
  125. package/runtime/scripts/guards/protected-zone.mjs +56 -0
  126. package/runtime/scripts/guards/refusals.mjs +27 -0
  127. package/runtime/scripts/guards/release-definition.mjs +185 -0
  128. package/runtime/scripts/guards/release-push-gate.mjs +72 -0
  129. package/runtime/scripts/guards/release-record.mjs +58 -0
  130. package/runtime/scripts/guards/release-suite-mode.mjs +15 -0
  131. package/runtime/scripts/guards/rights.mjs +268 -0
  132. package/runtime/scripts/guards/seat-tools.mjs +47 -0
  133. package/runtime/scripts/guards/shell-commands.mjs +328 -0
  134. package/runtime/scripts/guards/supervisor-seat.mjs +80 -0
  135. package/runtime/scripts/guards/verdict-process.mjs +81 -0
  136. package/runtime/scripts/hfs/architecture/dead-exports.mjs +10 -10
  137. package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +1 -1
  138. package/runtime/scripts/hfs/architecture/operation-contract-roots.mjs +53 -0
  139. package/runtime/scripts/hfs/architecture/reachability.mjs +1 -1
  140. package/runtime/scripts/hfs/architecture/sql-owner.mjs +17 -6
  141. package/runtime/scripts/hfs/architecture/sql-token-forms.mjs +105 -0
  142. package/runtime/scripts/hfs/architecture/sql-tokens.mjs +38 -52
  143. package/runtime/scripts/hfs/architecture/supabase-keys.mjs +261 -0
  144. package/runtime/scripts/hfs/architecture/transport-owner.mjs +49 -3
  145. package/runtime/scripts/hfs/architecture/typescript.mjs +1 -1
  146. package/runtime/scripts/hfs/check.mjs +6 -4
  147. package/runtime/scripts/hfs/coverage-scope.mjs +28 -1
  148. package/runtime/scripts/hfs/db-restamp-verb.mjs +56 -16
  149. package/runtime/scripts/hfs/declaration-shape.mjs +4 -4
  150. package/runtime/scripts/hfs/declaration-slots.mjs +14 -3
  151. package/runtime/scripts/hfs/manifest-shape.mjs +10 -6
  152. package/runtime/scripts/hfs/rule-params-shape.mjs +18 -6
  153. package/runtime/scripts/hfs/rules/a15-findings.mjs +4 -1
  154. package/runtime/scripts/hfs/rules/bypass-markers.mjs +22 -7
  155. package/runtime/scripts/hfs/rules/database-migrations.mjs +69 -14
  156. package/runtime/scripts/hfs/rules/database-queue-sources.mjs +9 -7
  157. package/runtime/scripts/hfs/rules/database-queues.mjs +68 -18
  158. package/runtime/scripts/hfs/rules/edition.mjs +56 -12
  159. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -10
  160. package/runtime/scripts/hfs/rules/fe-stack.mjs +12 -7
  161. package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +1 -1
  162. package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +75 -9
  163. package/runtime/scripts/hfs/rules/stacks-runtime.mjs +1 -1
  164. package/runtime/scripts/hfs/rules/stacks-swarm.mjs +15 -4
  165. package/runtime/scripts/hfs/rules/text-integrity.mjs +73 -0
  166. package/runtime/scripts/hfs/runtime-rules/hook-shape.mjs +74 -0
  167. package/runtime/scripts/hfs/runtime-rules/release-notes.mjs +44 -0
  168. package/runtime/scripts/hfs/sealed-members.mjs +3 -3
  169. package/runtime/scripts/hfs/slot-side-problems.mjs +3 -3
  170. package/runtime/scripts/hfs/slots.mjs +2 -1
  171. package/runtime/scripts/hfs/stack-deploy-config.mjs +22 -5
  172. package/runtime/scripts/hfs/stacks-gate.mjs +28 -7
  173. package/runtime/scripts/hfs/view.mjs +2 -1
  174. package/runtime/scripts/lib/app-data.mjs +11 -0
  175. package/runtime/scripts/lib/bypass-markers.mjs +272 -75
  176. package/runtime/scripts/lib/check-format.mjs +7 -0
  177. package/runtime/scripts/lib/cli-arg.mjs +120 -0
  178. package/runtime/scripts/lib/css-rules.mjs +220 -0
  179. package/runtime/scripts/lib/dom-tree.mjs +4 -0
  180. package/runtime/scripts/lib/escape.mjs +16 -0
  181. package/runtime/scripts/lib/event-items.mjs +22 -0
  182. package/runtime/scripts/lib/failure-code-template-errors.mjs +161 -0
  183. package/runtime/scripts/lib/git-dir.mjs +120 -0
  184. package/runtime/scripts/lib/grammar-vendor-parity.mjs +377 -0
  185. package/runtime/scripts/lib/guard-command.mjs +24 -0
  186. package/runtime/scripts/lib/hook-limits.mjs +5 -0
  187. package/runtime/scripts/lib/interrupt-cleanup.mjs +38 -0
  188. package/runtime/scripts/lib/js-lex.mjs +200 -0
  189. package/runtime/scripts/lib/json-formats.mjs +0 -1
  190. package/runtime/scripts/lib/language.mjs +94 -1
  191. package/runtime/scripts/lib/loosening-budgets.mjs +44 -0
  192. package/runtime/scripts/lib/loosening-config.mjs +361 -0
  193. package/runtime/scripts/lib/loosening-state.mjs +223 -0
  194. package/runtime/scripts/lib/menu-parts.mjs +11 -0
  195. package/runtime/scripts/lib/normalize.mjs +25 -0
  196. package/runtime/scripts/lib/op-gate.mjs +15 -0
  197. package/runtime/scripts/lib/redact.mjs +208 -0
  198. package/runtime/scripts/lib/runtime-location.mjs +21 -0
  199. package/runtime/scripts/lib/runtime-package-inventory.mjs +21 -0
  200. package/runtime/scripts/lib/runtime-package-manifests.mjs +84 -0
  201. package/runtime/scripts/lib/runtime-publication-tags.mjs +99 -0
  202. package/runtime/scripts/lib/seat-env.mjs +43 -0
  203. package/runtime/scripts/lib/secret-patterns.mjs +58 -9
  204. package/runtime/scripts/lib/shell-source.mjs +4 -0
  205. package/runtime/scripts/lib/source-phrases.mjs +34 -0
  206. package/runtime/scripts/lib/sqlite.mjs +21 -0
  207. package/runtime/scripts/lib/swarm-stack.mjs +2 -1
  208. package/runtime/scripts/lib/tar-files.mjs +39 -0
  209. package/runtime/scripts/lib/ts-analysis.mjs +10 -0
  210. package/runtime/scripts/lib/worktree-exclude.mjs +35 -0
  211. package/runtime/scripts/lib/worktree-record.mjs +14 -0
  212. package/runtime/scripts/machine/artifact-hold.mjs +52 -0
  213. package/runtime/scripts/machine/ask-receipts.mjs +113 -0
  214. package/runtime/scripts/machine/evidence-store.mjs +223 -0
  215. package/runtime/scripts/machine/home.mjs +216 -0
  216. package/runtime/scripts/machine/host-lock.mjs +184 -0
  217. package/runtime/scripts/machine/lock-recovery.mjs +55 -0
  218. package/runtime/scripts/machine/roles-contract.mjs +90 -0
  219. package/runtime/scripts/machine/runtime-change.mjs +20 -0
  220. package/runtime/scripts/machine/workflow-tree.mjs +122 -0
  221. package/runtime/scripts/reconciler/checklist-items.mjs +7 -0
  222. package/runtime/scripts/reconciler/guard-row.mjs +25 -0
  223. package/runtime/scripts/work/asset-slot.mjs +284 -0
  224. package/runtime/scripts/work/brand/brand-colour.mjs +125 -0
  225. package/runtime/scripts/work/brand/brand-tokens.mjs +167 -0
  226. package/runtime/scripts/work/brand/brand-value-source.mjs +106 -0
  227. package/runtime/scripts/work/brand/brand.mjs +892 -0
  228. package/runtime/scripts/work/draw/draw-dna-anatomy.mjs +60 -0
  229. package/runtime/scripts/work/draw/draw-dna-findings.mjs +256 -0
  230. package/runtime/scripts/work/draw/draw-dna-selector.mjs +38 -0
  231. package/runtime/scripts/work/draw/draw-dna.mjs +483 -0
  232. package/runtime/scripts/work/draw/draw-layer.mjs +305 -0
  233. package/runtime/scripts/work/draw/draw-rationale-page.mjs +237 -0
  234. package/runtime/scripts/work/draw/draw-rationale-ref.mjs +14 -0
  235. package/runtime/scripts/work/draw/draw-rationale.mjs +353 -0
  236. package/runtime/scripts/work/draw/draw-source.mjs +412 -0
  237. package/runtime/scripts/work/draw/draw-taste.mjs +278 -0
  238. package/runtime/scripts/work/draw/draw-typecheck.mjs +72 -0
  239. package/runtime/scripts/work/draw/rationale-findings.mjs +205 -0
  240. package/runtime/scripts/work/draw-grammar.mjs +175 -0
  241. package/runtime/scripts/work/draw-render-page.mjs +188 -0
  242. package/runtime/scripts/work/draw-render.mjs +626 -0
  243. package/runtime/scripts/work/grammar-proposal.mjs +279 -0
  244. package/runtime/scripts/work/png.mjs +237 -0
  245. package/runtime/scripts/work/render-tools.mjs +64 -0
  246. package/runtime/scripts/work/work-io.mjs +119 -0
  247. package/scaffold/add-inbox-lite.mjs +2 -2
  248. package/scaffold/add-plan.mjs +40 -13
  249. package/scaffold/add-queue-lite.mjs +372 -0
  250. package/scaffold/add.mjs +5 -2
  251. package/scaffold/app.mjs +1 -2
  252. package/scaffold/edition-gate.mjs +11 -7
  253. package/scaffold/lite-exports.mjs +10 -0
  254. package/scaffold/pattern-file-slots.mjs +33 -0
  255. package/scaffold/test-world.mjs +1 -1
  256. package/scaffold/yaml-block-edit.mjs +117 -0
  257. package/src/main.mjs +5 -4
  258. package/stack/deploy.mjs +7 -3
  259. package/stack/post-deploy.mjs +48 -0
  260. package/sync/index.mjs +10 -0
  261. package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +1 -1
  262. package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +1 -1
  263. package/templates/app/codegen-graphql.mjs.partial +59 -12
  264. package/templates/app/hooks/husky/pre-commit +2 -2
  265. package/templates/app/hooks/husky/pre-push +10 -3
  266. package/templates/app/package-scripts/redis-dev.json +3 -0
  267. package/templates/app/package-scripts-lite/package.json +1 -0
  268. package/templates/app/skeleton/.starcistacks/application-stacks.yaml +36 -8
  269. package/templates/app/skeleton/.starcistacks/dev/README.md +1 -1
  270. package/templates/app/skeleton/.starcistacks/production/README.md +10 -9
  271. package/templates/app/skeleton/.starcistacks/production/infra/swarm/postgres-init.sh +21 -0
  272. package/templates/app/skeleton/.starcistacks/production/infra/swarm/recovery/restore-proof.md +1 -1
  273. package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/images.lock.yaml +1 -0
  274. package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +47 -5
  275. package/templates/app/skeleton/.starcistacks/production/runtime/env/KEYS.md +5 -3
  276. package/templates/app/skeleton/README.md +2 -0
  277. package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +5 -0
  278. package/templates/app/skeleton-lite/.starcistacks/dev/README.md +2 -2
  279. package/templates/app/skeleton-lite/.starcistacks/production/README.md +1 -1
  280. package/templates/app/skeleton-lite/README.md +1 -1
  281. package/templates/be/inbox/platform/client-operation-outcomes.sql.tpl +18 -0
  282. package/templates/be/inbox/platform/event-bus/errors/event-bus.error.ts.tpl +16 -0
  283. package/templates/be/inbox/platform/event-bus/event-bus.contracts.ts.tpl +10 -0
  284. package/templates/be/inbox/platform/event-bus/event-bus.port.ts.tpl +1 -1
  285. package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +15 -3
  286. package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +11 -3
  287. package/templates/be/inbox/platform/event-bus/index.ts.tpl +2 -0
  288. package/templates/be/inbox/platform/event-bus/messages/event-bus.messages.ts.tpl +7 -0
  289. package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +2 -2
  290. package/templates/be/inbox/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
  291. package/templates/be/inbox/platform/idempotency/index.ts.tpl +2 -0
  292. package/templates/be/inbox/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
  293. package/templates/be/inbox/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
  294. package/templates/be/inbox/platform/inbox/client-operation.policy.ts.tpl +17 -0
  295. package/templates/be/inbox/platform/inbox/errors/inbox.error.ts.tpl +22 -0
  296. package/templates/be/inbox/platform/inbox/inbox.port.ts.tpl +21 -0
  297. package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +334 -11
  298. package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +55 -4
  299. package/templates/be/inbox/platform/inbox/index.ts.tpl +2 -0
  300. package/templates/be/inbox/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
  301. package/templates/be/inbox/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
  302. package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +26 -0
  303. package/templates/be/inbox/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
  304. package/templates/be/inbox/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
  305. package/templates/be/inbox/platform/migration.sql.tpl +1 -0
  306. package/templates/be/inbox/service.spec.ts.tpl +4 -4
  307. package/templates/be/inbox/service.ts.tpl +3 -1
  308. package/templates/be/inbox/webhook-door.spec.ts.tpl +3 -2
  309. package/templates/be/inbox/webhook-door.ts.tpl +3 -2
  310. package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +3 -0
  311. package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +10 -0
  312. package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +2 -2
  313. package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +16 -3
  314. package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +11 -3
  315. package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +139 -50
  316. package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +25 -2
  317. package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +139 -78
  318. package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +10 -6
  319. package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +262 -159
  320. package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +32 -5
  321. package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +2 -0
  322. package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +5 -1
  323. package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +2 -0
  324. package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +4 -4
  325. package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +1 -0
  326. package/templates/be/patterns/idempotency/platform/idempotency/errors/idempotency.error.ts.tpl +19 -0
  327. package/templates/be/patterns/idempotency/platform/idempotency/index.ts.tpl +2 -0
  328. package/templates/be/patterns/idempotency/platform/idempotency/messages/idempotency.messages.ts.tpl +13 -0
  329. package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.spec.ts.tpl +32 -0
  330. package/templates/be/patterns/idempotency/platform/inbox/client-operation.policy.ts.tpl +17 -0
  331. package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.spec.ts.tpl +66 -0
  332. package/templates/be/patterns/idempotency/platform/inbox/client-outcome-backfill.client.ts.tpl +24 -0
  333. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.spec.ts.tpl +60 -0
  334. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-backfill.client.ts.tpl +12 -0
  335. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.spec.ts.tpl +49 -0
  336. package/templates/be/patterns/idempotency/platform/inbox/delivery-claim-release.client.ts.tpl +12 -0
  337. package/templates/be/patterns/idempotency/platform/inbox/effectful.decorators.ts.tpl +7 -0
  338. package/templates/be/patterns/idempotency/platform/inbox/errors/inbox.error.ts.tpl +22 -0
  339. package/templates/be/patterns/idempotency/platform/inbox/inbox.decorators.ts.tpl +17 -0
  340. package/templates/be/patterns/idempotency/platform/inbox/inbox.module-definition.ts.tpl +7 -0
  341. package/templates/be/patterns/idempotency/platform/inbox/inbox.module.ts.tpl +28 -0
  342. package/templates/be/patterns/idempotency/platform/inbox/inbox.options.ts.tpl +7 -0
  343. package/templates/be/patterns/idempotency/platform/inbox/inbox.port.ts.tpl +44 -0
  344. package/templates/be/patterns/idempotency/platform/inbox/inbox.service.spec.ts.tpl +388 -0
  345. package/templates/be/patterns/idempotency/platform/inbox/inbox.service.ts.tpl +77 -0
  346. package/templates/be/patterns/idempotency/platform/inbox/index.ts.tpl +10 -0
  347. package/templates/be/patterns/idempotency/platform/inbox/messages/inbox.messages.ts.tpl +15 -0
  348. package/templates/be/patterns/idempotency/platform/inbox/persistence/connection.ts.tpl +9 -0
  349. package/templates/be/patterns/idempotency/platform/inbox/persistence/entities/inbox-claim.entity.ts.tpl +25 -0
  350. package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.rows.ts.tpl +33 -0
  351. package/templates/be/patterns/idempotency/platform/inbox/persistence/inbox.sql.ts.tpl +39 -0
  352. package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1789800005000-create-inbox-claims.ts.tpl +21 -0
  353. package/templates/be/patterns/idempotency/platform/inbox/persistence/migrations/1792800000000-client-operation-outcomes.ts.tpl +21 -0
  354. package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.spec.ts.tpl +76 -0
  355. package/templates/be/patterns/idempotency/platform/inbox/request-fingerprint.policy.ts.tpl +36 -0
  356. package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +1 -0
  357. package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +4 -3
  358. package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +2 -0
  359. package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +20 -2
  360. package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +1 -0
  361. package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +4 -0
  362. package/templates/be/patterns/jobs/platform-lite/jobs.index.ts.tpl +10 -0
  363. package/templates/be/patterns/jobs/platform-lite/jobs.sql.tpl +44 -0
  364. package/templates/be/patterns/jobs/platform-lite/persistence.jobs.sql.ts.tpl +33 -0
  365. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +203 -18
  366. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +78 -22
  367. package/templates/be/patterns/queues/platform/errors/queue.error.ts.tpl +19 -0
  368. package/templates/be/patterns/queues/platform/messages/queue.messages.ts.tpl +13 -0
  369. package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +1 -0
  370. package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +4 -0
  371. package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +2 -0
  372. package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +4 -4
  373. package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +14 -2
  374. package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +5 -2
  375. package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +72 -74
  376. package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +1 -1
  377. package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +23 -8
  378. package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +29 -8
  379. package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +7 -3
  380. package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +5 -0
  381. package/templates/be/patterns/queues/platform/queue.index.ts.tpl +2 -0
  382. package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +4 -0
  383. package/templates/be/patterns/queues/platform/queue.module.ts.tpl +2 -1
  384. package/templates/be/patterns/queues/platform/queue.port.ts.tpl +1 -1
  385. package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.spec.ts.tpl +417 -0
  386. package/templates/be/patterns/queues/platform-lite/bullmq-queue-transport.client.ts.tpl +172 -0
  387. package/templates/be/patterns/queues/platform-lite/persistence.queue.sql.ts.tpl +12 -0
  388. package/templates/be/patterns/queues/platform-lite/queue-outbox.sql.tpl +32 -0
  389. package/templates/be/patterns/queues/platform-lite/queue-relay.service.spec.ts.tpl +148 -0
  390. package/templates/be/patterns/queues/platform-lite/queue-relay.service.ts.tpl +51 -0
  391. package/templates/be/patterns/queues/platform-lite/queue-transport.port.ts.tpl +163 -0
  392. package/templates/be/patterns/queues/platform-lite/queue.config.ts.tpl +17 -0
  393. package/templates/be/patterns/queues/platform-lite/queue.error.ts.tpl +25 -0
  394. package/templates/be/patterns/queues/platform-lite/queue.index.ts.tpl +8 -0
  395. package/templates/be/patterns/queues/platform-lite/queue.messages.ts.tpl +21 -0
  396. package/templates/be/patterns/queues/platform-lite/queue.module.ts.tpl +74 -0
  397. package/templates/be/patterns/queues/platform-lite/queue.options.ts.tpl +38 -0
  398. package/templates/be/patterns/queues/queue.queue.ts.tpl +2 -2
  399. package/templates/be/patterns/reactors/application.contracts.ts.tpl +2 -0
  400. package/templates/be/patterns/reactors/consumer.ts.tpl +5 -1
  401. package/templates/be/platform/graphql/graphql.contracts.ts +2 -1
  402. package/templates/be/platform/graphql/localize-errors.mapper.spec.ts +1 -1
  403. package/templates/be/skeleton/apps/__app__/src/compose/platform.ts +6 -1
  404. package/templates/be/skeleton/apps/__app__/src/main.ts +7 -4
  405. package/templates/be/skeleton/apps/cli/src/compose/platform.ts +4 -0
  406. package/templates/be/skeleton/apps/cli/src/main.ts +7 -4
  407. package/templates/be/skeleton/src/modules/platform/database/index.ts +1 -1
  408. package/templates/be/skeleton/src/modules/platform/http/errors/http.error.ts +22 -0
  409. package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.spec.ts +235 -0
  410. package/templates/be/skeleton/src/modules/platform/http/fetch-http-client.client.ts +85 -0
  411. package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.spec.ts +92 -0
  412. package/templates/be/skeleton/src/modules/platform/http/graphql-call.mapper.ts +52 -0
  413. package/templates/be/skeleton/src/modules/platform/http/http.decorators.ts +9 -0
  414. package/templates/be/skeleton/src/modules/platform/http/http.module-definition.ts +7 -0
  415. package/templates/be/skeleton/src/modules/platform/http/http.module.ts +19 -0
  416. package/templates/be/skeleton/src/modules/platform/http/http.options.ts +2 -0
  417. package/templates/be/skeleton/src/modules/platform/http/http.port.ts +40 -0
  418. package/templates/be/skeleton/src/modules/platform/http/index.ts +7 -0
  419. package/templates/be/skeleton/src/modules/platform/http/messages/http.messages.ts +15 -0
  420. package/templates/be/skeleton/src/modules/platform/ids/ids.decorators.ts +9 -0
  421. package/templates/be/skeleton/src/modules/platform/ids/ids.module-definition.ts +7 -0
  422. package/templates/be/skeleton/src/modules/platform/ids/ids.module.ts +19 -0
  423. package/templates/be/skeleton/src/modules/platform/ids/ids.options.ts +2 -0
  424. package/templates/be/skeleton/src/modules/platform/ids/ids.port.ts +5 -0
  425. package/templates/be/skeleton/src/modules/platform/ids/index.ts +4 -0
  426. package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.spec.ts +15 -0
  427. package/templates/be/skeleton/src/modules/platform/ids/system-ids.service.ts +10 -0
  428. package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.spec.ts +59 -0
  429. package/templates/be/skeleton/src/modules/platform/logging/correlation-request.policy.ts +21 -0
  430. package/templates/be/skeleton/src/modules/platform/logging/correlation.contracts.ts +16 -0
  431. package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.spec.ts +150 -0
  432. package/templates/be/skeleton/src/modules/platform/logging/correlation.policy.ts +42 -0
  433. package/templates/be/skeleton/src/modules/platform/logging/correlation.port.ts +15 -0
  434. package/templates/be/skeleton/src/modules/platform/logging/correlation.service.spec.ts +23 -0
  435. package/templates/be/skeleton/src/modules/platform/logging/correlation.service.ts +28 -0
  436. package/templates/be/skeleton/src/modules/platform/logging/index.ts +14 -1
  437. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +39 -6
  438. package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +15 -3
  439. package/templates/be/skeleton/src/modules/platform/logging/logging.decorators.ts +17 -2
  440. package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +13 -1
  441. package/templates/be/skeleton/src/modules/platform/logging/logging.module.ts +13 -3
  442. package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.spec.ts +69 -0
  443. package/templates/be/skeleton/src/modules/platform/logging/nest-logger.service.ts +48 -0
  444. package/templates/be/skeleton/src/modules/platform/primitives/index.ts +1 -0
  445. package/templates/be/skeleton/src/modules/platform/primitives/record.policy.spec.ts +12 -0
  446. package/templates/be/skeleton/src/modules/platform/primitives/record.policy.ts +3 -0
  447. package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +6 -1
  448. package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +4 -0
  449. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +1 -0
  450. package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +14 -1
  451. package/templates/be/skeleton-lite/src/modules/platform/logging/logging.log-events.ts +12 -0
  452. package/templates/be/skeleton-lite/src/modules/platform/primitives/index.ts +2 -0
  453. package/templates/be/test-world/world/test-apps.options.ts.tpl +2 -0
  454. package/templates/be/test-world/world/test-world.config.ts.tpl +1 -0
  455. package/upgrade/check.mjs +12 -135
  456. package/upgrade/file-state.mjs +1 -16
  457. package/upgrade/index.mjs +34 -361
  458. package/runtime/scripts/lib/check-code-loosening.mjs +0 -128
  459. package/runtime/scripts/lib/gate-loosening.mjs +0 -292
  460. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +0 -89
  461. package/templates/app/upgrade-full/.starcistacks/dev/README.md +0 -16
  462. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +0 -13
  463. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +0 -3
  464. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +0 -12
  465. package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +0 -7
  466. package/templates/be/skeleton-lite/apps/api/src/main.ts +0 -26
  467. package/templates/be/upgrade-full/apps/cli/src/app.module.ts +0 -12
  468. package/templates/be/upgrade-full/apps/cli/src/cli.env.ts +0 -7
  469. package/templates/be/upgrade-full/apps/cli/src/compose/cli.ts +0 -5
  470. package/templates/be/upgrade-full/apps/cli/src/compose/platform.ts +0 -9
  471. package/templates/be/upgrade-full/apps/cli/src/main.ts +0 -29
  472. package/templates/be/upgrade-full/src/features/cli/cli.module.ts +0 -7
  473. package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +0 -23
@@ -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": "9ff398eeddb22776cc36e38b7206c0bfe03d3dec2c1e42614fabe349241b53ed",
4
+ "hash": "22aaaddc27f0ed4d795adfbd63deba5f0071f15dcab2a8456f852a20798b622b",
5
5
  "global": [
6
6
  {
7
7
  "name": "json",
@@ -615,7 +615,7 @@ export const CATALOG = {
615
615
  {
616
616
  "name": "no-types",
617
617
  "type": "boolean",
618
- "summary": "skip regenerating the Supabase database types of a lite table"
618
+ "summary": "skip regenerating the Supabase database types after lite table and queue migrations"
619
619
  }
620
620
  ],
621
621
  "exit": {
@@ -986,6 +986,9 @@ export const CATALOG = {
986
986
  "requires Supabase db query --file and SOPS_AGE_KEY or SOPS_AGE_KEY_FILE",
987
987
  "reset keeps encrypted temporary recovery parts after a reset/restore failure and reports their directory; plaintext is always deleted",
988
988
  "baseline accepts --stamp; restamp requires --map; both preview without --apply",
989
+ "restamp: a map value is the new stamp, or { file, to?, applied? } when several active migrations share the old stamp",
990
+ "restamp file names the migration that moves (full name, or the name after the stamp with or without .sql); to defaults to the next free stamp",
991
+ "restamp applied: for a shared stamp it is read from the history (one SELECT of schema_migrations.name; unreadable refuses) and defaults to true otherwise",
989
992
  "plan is always read-only and supports --json; it compares migrations, cron, queues and Vault names",
990
993
  "linked/url-env migrate and post-cutover read application-stacks.yaml's database block and preview without --execute",
991
994
  "linked/url-env migrate skips an applied baseline and forward chain; held-back migrations belong to post-cutover",
@@ -1249,6 +1252,7 @@ export const CATALOG = {
1249
1252
  "green moves the branch and the tag in one atomic push; red refuses RELEASE_CANDIDATE_CI_RED naming the failing jobs",
1250
1253
  "no run, or no end in time, refuses RELEASE_CANDIDATE_CI_TIMEOUT; unreadable GitHub refuses RELEASE_CI_UNKNOWN; nothing reaches the branch",
1251
1254
  "a red candidate never passes: there is no override and no --no-ci-check flag",
1255
+ "the gate tag is always <release.tagPrefix><package.json version>; a taken tag on another commit is red, never another patch number",
1252
1256
  "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",
1253
1257
  "a gate with summary jest is red on failed tests and on a coverage threshold miss even when the process exits 0",
1254
1258
  "push needs the annotated tag and L4 record of HEAD, runs git push --dry-run --atomic first and never uses --no-verify"
@@ -1608,6 +1612,10 @@ export const CATALOG = {
1608
1612
  "impl": null,
1609
1613
  "conventions": [
1610
1614
  "the deploy actions read environments.<env>.deploy of .starcistacks/application-stacks.yaml and nothing app-specific is kept anywhere else",
1615
+ "deploy runs deploy.postDeploy (names of deploy.tasks) after convergence and before verify, in order",
1616
+ "a post-deploy task that exits non-zero or passes its timeoutSeconds (default 600) fails the deploy and rolls back",
1617
+ "deploy never prints the output of a post-deploy task (secret custody); stack task <name> shows it",
1618
+ "verify never writes: an idempotent write a release owes the data (a catalogue sync, a seed upsert) is a post-deploy task",
1611
1619
  "effectful actions are a dry run unless --execute is given; a placeholder (all-zero) image digest is always refused",
1612
1620
  "secret values are decrypted in memory, piped to docker on stdin and never printed or written",
1613
1621
  "docker swarm init runs once: --init-swarm, --execute and --owner-approved (or STARCI_SWARM_INIT_APPROVED=1); never on an active swarm",
@@ -1648,7 +1656,7 @@ export const CATALOG = {
1648
1656
  "runtimeSide": "host"
1649
1657
  },
1650
1658
  "upgrade": {
1651
- "summary": "upgrade a lite app to full (--edition full), or add the test world a full app lacks",
1659
+ "summary": "add the test world a full app lacks; a lite app is refused because editions are fixed at scaffold",
1652
1660
  "owner": "@starci/hfs",
1653
1661
  "flags": [
1654
1662
  {
@@ -1658,14 +1666,13 @@ export const CATALOG = {
1658
1666
  }
1659
1667
  ],
1660
1668
  "exit": {
1661
- "0": "upgraded, completed, or the full app is already complete",
1662
- "2": "refusal or bad usage"
1669
+ "0": "completed, or the full app is already complete",
1670
+ "2": "refusal (a lite app: HFS_UPGRADE_EDITION_FIXED) or bad usage"
1663
1671
  },
1664
1672
  "json": "none",
1665
1673
  "examples": [
1666
1674
  "starci app upgrade",
1667
- "starci app upgrade --plan",
1668
- "starci app upgrade --edition full --plan"
1675
+ "starci app upgrade --plan"
1669
1676
  ],
1670
1677
  "editions": [
1671
1678
  "full",
@@ -1673,6 +1680,7 @@ export const CATALOG = {
1673
1680
  ],
1674
1681
  "impl": null,
1675
1682
  "conventions": [
1683
+ "editions are fixed at scaffold: a lite app refuses HFS_UPGRADE_EDITION_FIXED and there is no lite to full migration",
1676
1684
  "a full app without be/src/tests/world/global-setup.ts gets the test world of a new full app and the test devDependencies it lacks",
1677
1685
  "a world file that exists and differs refuses HFS_UPGRADE_FILE_CONFLICT; nothing is overwritten"
1678
1686
  ],
@@ -3092,6 +3100,16 @@ export const CATALOG = {
3092
3100
  "type": "string",
3093
3101
  "summary": "application root"
3094
3102
  },
3103
+ {
3104
+ "name": "tests",
3105
+ "type": "string",
3106
+ "summary": "Jest test-path regex for a scoped run; requires subjects"
3107
+ },
3108
+ {
3109
+ "name": "subjects",
3110
+ "type": "string",
3111
+ "summary": "app-relative unit-subject regex covering the selected fix reach; requires tests"
3112
+ },
3095
3113
  {
3096
3114
  "name": "out",
3097
3115
  "type": "string",
@@ -3105,7 +3123,8 @@ export const CATALOG = {
3105
3123
  },
3106
3124
  "json": "always",
3107
3125
  "examples": [
3108
- "starci gate unit --root <app> --out unit-run.json"
3126
+ "starci gate unit --root <app> --out unit-run.json",
3127
+ "starci gate unit --root <app> --tests orders --subjects 'be/src/modules/orders/' --out unit-run.json"
3109
3128
  ],
3110
3129
  "editions": [
3111
3130
  "full"
@@ -3255,6 +3274,7 @@ export const CATALOG = {
3255
3274
  },
3256
3275
  "effect": "local-write",
3257
3276
  "roles": [
3277
+ "worker",
3258
3278
  "lead",
3259
3279
  "coordinator",
3260
3280
  "release",
@@ -4083,7 +4103,7 @@ export const CATALOG = {
4083
4103
  {
4084
4104
  "name": "reconcile",
4085
4105
  "type": "boolean",
4086
- "summary": "mode: record the re-verify of a stub sibling against the landed seam; needs --job and --exit-code"
4106
+ "summary": "mode: verify a stub sibling against the landed seam; needs --job and --checks-file"
4087
4107
  },
4088
4108
  {
4089
4109
  "name": "job",
@@ -4126,9 +4146,9 @@ export const CATALOG = {
4126
4146
  "summary": "exit code of the sibling re-verify (--reconcile)"
4127
4147
  },
4128
4148
  {
4129
- "name": "command",
4149
+ "name": "checks-file",
4130
4150
  "type": "string",
4131
- "summary": "the re-verify command that was run (--reconcile)"
4151
+ "summary": "checks and checkSelection envelope for scoped reconcile (--reconcile)"
4132
4152
  },
4133
4153
  {
4134
4154
  "name": "evidence",
@@ -4145,7 +4165,7 @@ export const CATALOG = {
4145
4165
  "examples": [
4146
4166
  "starci kernel cut-seam --repo <path> --publish-interface --job <job> --files <files>",
4147
4167
  "starci kernel cut-seam --repo <path> --release --workflow <workflow> --op <op> --cut-id <cut> --reason <reason>",
4148
- "starci kernel cut-seam --repo <path> --reconcile --job <job> --exit-code 0"
4168
+ "starci kernel cut-seam --repo <path> --reconcile --job <job> --checks-file <file>"
4149
4169
  ],
4150
4170
  "editions": [
4151
4171
  "full"
@@ -6490,7 +6510,7 @@ export const CATALOG = {
6490
6510
  {
6491
6511
  "name": "checks",
6492
6512
  "type": "string",
6493
- "summary": "JSON {checks:[{name,exitCode,command?,evidence?}]}; one of --checks or --checks-file is required"
6513
+ "summary": "JSON checks and checkSelection envelope; one of --checks or --checks-file is required"
6494
6514
  },
6495
6515
  {
6496
6516
  "name": "checks-file",
@@ -6505,7 +6525,7 @@ export const CATALOG = {
6505
6525
  },
6506
6526
  "json": "flag",
6507
6527
  "examples": [
6508
- "starci kernel record-checks --repo <path> --job <job> --checks '{\"checks\":[{\"name\":\"build\",\"exitCode\":0}]}'",
6528
+ "starci kernel record-checks --repo <path> --job <job> --checks-file <selection-and-checks.json>",
6509
6529
  "starci kernel record-checks --repo <path> --job <job> --checks-file <file> --json"
6510
6530
  ],
6511
6531
  "editions": [
@@ -8862,7 +8882,9 @@ export const CATALOG = {
8862
8882
  "the package phase rebinds code patterns, re-pins and installs examples, syncs them and proves every binding",
8863
8883
  "runtime-package publishes root package.json after package publication, committed bindings and finished notes; it proves the real archive and private install",
8864
8884
  "runtime-package refuses changed inputs or registry state after its cold proof and never performs rebind or example writes",
8865
- "publication never commits, pushes or tags; release cut owns those effects"
8885
+ "runtime-package plans the upload channel and release-declared npm dist-tags, repairs stale tags without republishing, and reads every target back",
8886
+ "runtime-package refuses an older release on its line and preserves tags pointing to newer releases on other lines",
8887
+ "publication never commits, pushes or creates Git tags; release cut owns those effects"
8866
8888
  ],
8867
8889
  "runtimeSide": "tree"
8868
8890
  },
@@ -9205,50 +9227,6 @@ export const CATALOG = {
9205
9227
  ],
9206
9228
  "runtimeSide": "tree"
9207
9229
  },
9208
- "benchmark-snapshot": {
9209
- "summary": "append one model-pool snapshot file under benchmark/snapshots",
9210
- "owner": "runtime",
9211
- "flags": [
9212
- {
9213
- "name": "since-hours",
9214
- "type": "number",
9215
- "required": true,
9216
- "summary": "positive scorecard window in hours"
9217
- },
9218
- {
9219
- "name": "repo",
9220
- "type": "list",
9221
- "summary": "product ledger owner path"
9222
- },
9223
- {
9224
- "name": "date",
9225
- "type": "string",
9226
- "summary": "snapshot date as YYYY-MM-DD"
9227
- },
9228
- {
9229
- "name": "dir",
9230
- "type": "string",
9231
- "summary": "snapshot output directory"
9232
- }
9233
- ],
9234
- "exit": {
9235
- "0": "snapshot appended",
9236
- "1": "output exists or snapshot failed",
9237
- "2": "bad usage"
9238
- },
9239
- "json": "flag",
9240
- "examples": [
9241
- "starci runtime benchmark-snapshot --since-hours 24",
9242
- "starci runtime benchmark-snapshot --since-hours 24 --repo <path> --json"
9243
- ],
9244
- "editions": [
9245
- "full"
9246
- ],
9247
- "impl": {
9248
- "script": "scripts/agent/benchmark-snapshot.mjs"
9249
- },
9250
- "runtimeSide": "tree"
9251
- },
9252
9230
  "check": {
9253
9231
  "summary": "judge the runtime tree — node --check, the runtime HFS check, the retained self-checks",
9254
9232
  "owner": "runtime",
@@ -15764,5 +15742,14 @@ export const CATALOG = {
15764
15742
  }
15765
15743
  }
15766
15744
  }
15745
+ },
15746
+ "removedVerbs": {
15747
+ "starci guard input": "starci guard input is removed (the reference-transaction hook reads prepared ref updates directly in its shell loop)",
15748
+ "starci debug pass": "debug pass is removed (`starci debug digest` (read-only) and `starci debug run <probe>`)",
15749
+ "starci test affected": "starci test affected is removed (the runtime has no specs of its own (owner ruling no-runtime-specs): `starci runtime verify` runs the check, `starci release clean-test --base <ref>` and `starci release scaffold-e2e`)",
15750
+ "starci test run": "starci test run is removed (the L1 to L4 spec ladder is gone with the runtime specs; `starci runtime verify` proves a change, `starci release cut` runs the release rows)",
15751
+ "starci gate runtime-coverage": "starci gate runtime-coverage is removed (the runtime measures no coverage of its own; the example apps keep their Codecov flags)",
15752
+ "starci release env-test": "starci release env-test is removed (the release rows are the package clean-test (`starci release clean-test`), the scaffold e2e (`starci release scaffold-e2e`) and the runtime check)",
15753
+ "starci runtime benchmark-snapshot": "starci runtime benchmark-snapshot is removed (routing evidence is read live from the ledgers: `starci machine op-metrics --by op` and the ledger view v_model_scorecard (modules/models/registry.yaml costPolicy))"
15767
15754
  }
15768
15755
  };
@@ -0,0 +1,98 @@
1
+ import { createHash } from "node:crypto"
2
+ import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs"
3
+ import { dirname, join, relative, resolve } from "node:path"
4
+ import { fileURLToPath, pathToFileURL } from "node:url"
5
+
6
+ /**
7
+ * The build stamp ties a built `dist/` to the exact source it was built from.
8
+ *
9
+ * `npm run build` ends by writing `dist/.build-stamp.json`: the package version, the source digest
10
+ * (below), a digest of the built files, and the build time. The root check
11
+ * `scripts/checks/check-grammar-dist.mjs` recomputes the source digest and refuses a dist whose stamp is
12
+ * missing or names other source, so a stale build can no longer pass for the current one.
13
+ *
14
+ * The source digest covers everything that decides what `dist/` contains: every file under `src/`
15
+ * except stories, test helpers, specs and tests (they never ship), `tsconfig.build.json`,
16
+ * `packages/grammar/scripts/copy-css.mjs`, and the `exports` and `files` fields of `package.json`. Line endings are
17
+ * normalised so a CRLF checkout of the same commit has the same digest.
18
+ */
19
+
20
+ export const STAMP_FILE = ".build-stamp.json"
21
+ export const STAMP_SCHEMA = "starci/grammar-build-stamp@1"
22
+ export const DIGEST_ALGORITHM = "starci/grammar-source-digest@1"
23
+
24
+ const DEV_ONLY_DIRS = new Set(["stories", "__test__"])
25
+ const DEV_ONLY_FILE = /\.(?:stories|spec|test)\./
26
+
27
+ const slash = (value) => value.replaceAll("\\", "/")
28
+ const normalised = (buffer) => Buffer.from(buffer.toString("latin1").replaceAll("\r\n", "\n"), "latin1")
29
+
30
+ function filesUnder(dir, keep = () => true) {
31
+ if (!existsSync(dir)) return []
32
+ return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
33
+ const full = join(dir, entry.name)
34
+ if (entry.isDirectory()) return keep(entry, true) ? filesUnder(full, keep) : []
35
+ return entry.isFile() && keep(entry, false) ? [full] : []
36
+ })
37
+ }
38
+
39
+ /** The order `.sort()` gives without a compare function (UTF-16 code units): the stamp digest depends on it. */
40
+ const byCodeUnit = (a, b) => (a < b ? -1 : a > b ? 1 : 0)
41
+
42
+ function hashEntries(entries) {
43
+ const hash = createHash("sha256")
44
+ for (const [name, bytes] of entries.sort(([a], [b]) => byCodeUnit(a, b))) {
45
+ hash.update(name)
46
+ hash.update("\0")
47
+ hash.update(bytes === null ? "<absent>" : bytes)
48
+ hash.update("\0")
49
+ }
50
+ return `sha256:${hash.digest("hex")}`
51
+ }
52
+
53
+ /** The files the source digest reads, relative to the package root, in digest order. */
54
+ export function sourceInputs(packageRoot) {
55
+ const src = filesUnder(join(packageRoot, "src"), (entry, isDir) =>
56
+ isDir ? !DEV_ONLY_DIRS.has(entry.name) : !DEV_ONLY_FILE.test(entry.name))
57
+ return [...src.map((file) => slash(relative(packageRoot, file))), "tsconfig.build.json", "scripts/copy-css.mjs"].sort(byCodeUnit)
58
+ }
59
+
60
+ /** The digest of everything that decides the content of `dist/`. */
61
+ export function sourceDigest(packageRoot) {
62
+ const entries = sourceInputs(packageRoot).map((name) => {
63
+ const file = join(packageRoot, name)
64
+ return [name, existsSync(file) ? normalised(readFileSync(file)) : null]
65
+ })
66
+ const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"))
67
+ entries.push(["package.json#exports+files", Buffer.from(JSON.stringify({ exports: manifest.exports ?? null, files: manifest.files ?? null }))])
68
+ return hashEntries(entries)
69
+ }
70
+
71
+ /** The digest of the built files themselves (everything in `dist/` except the stamp). */
72
+ export function distDigest(packageRoot) {
73
+ const dist = join(packageRoot, "dist")
74
+ const files = filesUnder(dist).map((file) => slash(relative(dist, file))).filter((name) => name !== STAMP_FILE)
75
+ return hashEntries(files.map((name) => [name, normalised(readFileSync(join(dist, name)))]))
76
+ }
77
+
78
+ export function writeStamp(packageRoot, { now = new Date() } = {}) {
79
+ const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"))
80
+ if (!existsSync(join(packageRoot, "dist"))) throw new Error("Cannot stamp a build that has no dist/ directory.")
81
+ const stamp = {
82
+ schema: STAMP_SCHEMA,
83
+ package: manifest.name,
84
+ version: manifest.version,
85
+ algorithm: DIGEST_ALGORITHM,
86
+ sourceDigest: sourceDigest(packageRoot),
87
+ distDigest: distDigest(packageRoot),
88
+ builtAt: now.toISOString(),
89
+ }
90
+ writeFileSync(join(packageRoot, "dist", STAMP_FILE), `${JSON.stringify(stamp, null, 2)}\n`)
91
+ return stamp
92
+ }
93
+
94
+ if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
95
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..")
96
+ const stamp = writeStamp(packageRoot)
97
+ console.log(`dist/${STAMP_FILE}: ${stamp.package}@${stamp.version} ${stamp.sourceDigest.slice(0, 19)}`)
98
+ }
@@ -0,0 +1,79 @@
1
+ // scripts/agent/codex-app-server.mjs — the runtime's `codex app-server` client (kept out of trust.mjs, which is over
2
+ // its size budget).
3
+ //
4
+ // Codex computes the hash it trusts a hook by; launch trust asks it through the app-server protocol the way Orca
5
+ // trusts its own hooks (scripts/agent/trust.mjs trustCodexToolGuard). The client is a node one-shot: it spawns
6
+ // `codex app-server`, sends initialize then each request, and prints one stdout line — the results array, or
7
+ // {failed} when codex ended (or never started) before answering. Without that line an early exit only drained the
8
+ // client's event loop: exit 0, nothing printed, and codex's stderr discarded — so "answered nothing (exit 0)" was
9
+ // the client's exit, never codex's. The failure names codex's exit/signal, the request it left unanswered, its
10
+ // stderr tail, `codex --version` and the CODEX_HOME it ran with; its text starts with APP_SERVER_FAILURE, which
11
+ // scripts/agent/provider-outage.mjs reads as a worker-start strike of the codex circuit.
12
+ //
13
+ // The probe is a runtime-owned child: it gets the caller's env without the seat identity or the seat's guard-shim
14
+ // PATH (scripts/lib/seat-env.mjs). A launch-trust call made under a Kernel seat otherwise inherits both — and
15
+ // `codex`'s own launcher resolves `node` through PATH, so the seat's tool wrapper bound the seat's role to it and
16
+ // refused the probe as a raw tool call (RIGHTS_RAW_TOOL, exit 2; `codex --version` printed the same refusal).
17
+ import { runNode } from '../api/node/run-node.mjs';
18
+ import { parseJson } from '../lib/json.mjs';
19
+ import { withoutSeatEnv, withoutSeatShim } from '../lib/seat-env.mjs';
20
+
21
+ // Every launch-trust app-server failure starts with this text; provider-outage.mjs classifies it.
22
+ export const APP_SERVER_FAILURE = 'codex app-server answered nothing';
23
+
24
+ const APP_SERVER_CLIENT = String.raw`
25
+ const { spawn, spawnSync } = require('node:child_process');
26
+ const reqs = JSON.parse(process.argv[1]);
27
+ const p = spawn('codex app-server', { shell: true, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
28
+ const out = []; let buf = ''; let next = 0; let ready = false; let err = '';
29
+ const send = (o) => p.stdin.write(JSON.stringify(o) + '\n');
30
+ const ask = () => { if (next >= reqs.length) { console.log(JSON.stringify(out)); p.kill(); process.exit(0); } send({ id: 100 + next, ...reqs[next] }); };
31
+ const fail = (exit, signal, spawnError) => {
32
+ const v = spawnSync('codex --version', { shell: true, encoding: 'utf8', timeout: 15000, windowsHide: true });
33
+ const version = String(v.stdout || v.stderr || '').trim() || null;
34
+ console.log(JSON.stringify({ failed: { exit, signal, spawnError, stage: ready ? reqs[next].method : 'initialize', stderr: err.trim(), version } }));
35
+ process.exit(3);
36
+ };
37
+ p.stdin.on('error', () => {});
38
+ p.stderr.on('data', (d) => { err = (err + d).slice(-4000); });
39
+ p.stdout.on('data', (d) => { buf += d; let i; while ((i = buf.indexOf('\n')) >= 0) { const line = buf.slice(0, i); buf = buf.slice(i + 1); let m; try { m = JSON.parse(line); } catch { continue; }
40
+ if (m.id === 1) { ready = true; send({ method: 'initialized' }); ask(); }
41
+ else if (m.id === 100 + next) { out.push(m.error ? { error: m.error } : m.result); next += 1; ask(); } } });
42
+ p.on('error', (e) => fail(null, null, e.message));
43
+ p.on('close', (code, signal) => fail(code, signal, null));
44
+ send({ id: 1, method: 'initialize', params: { clientInfo: { name: 'starci-launch-trust', version: '1' } } });
45
+ `;
46
+
47
+ const tail = (text, n) => { const t = String(text ?? '').replace(/\s+/g, ' ').trim(); return t.length > n ? '...' + t.slice(-n) : t; };
48
+
49
+ // The error of an app-server call that returned no results: what ended it (codex's exit/signal or the client's own),
50
+ // codex's stderr tail and version, and the CODEX_HOME it ran with.
51
+ function appServerFailure({ home, timeoutMs, r, failed }) {
52
+ const parts = [];
53
+ if (failed) {
54
+ parts.push(
55
+ failed.spawnError ? 'did not start: ' + failed.spawnError
56
+ : 'exited ' + (failed.exit ?? 'on ' + failed.signal) + ' before answering ' + failed.stage,
57
+ failed.stderr ? 'stderr: ' + tail(failed.stderr, 400) : 'no stderr',
58
+ failed.version ? 'codex --version: ' + tail(failed.version, 120) : 'codex --version printed nothing');
59
+ } else {
60
+ parts.push('client exit ' + r.status + (r.error ? ': ' + r.error.message : ''));
61
+ if (r.error?.code === 'ETIMEDOUT') parts.push('no answer within ' + timeoutMs + 'ms');
62
+ const stderr = tail(r.stderr, 400);
63
+ if (stderr) parts.push('client stderr: ' + stderr);
64
+ }
65
+ parts.push('CODEX_HOME ' + home);
66
+ return APP_SERVER_FAILURE + ' (' + parts.join('; ') + ')';
67
+ }
68
+
69
+ /**
70
+ * The app-server calls of one Codex home, in order: `requests` [{method, params}] -> results[] (an error result is
71
+ * {error}). No results throws the precise failure (appServerFailure).
72
+ */
73
+ export function codexAppServer({ home, requests, timeoutMs = 60_000, env = process.env }) {
74
+ const r = runNode(['-e', APP_SERVER_CLIENT, JSON.stringify(requests)], { timeout: timeoutMs,
75
+ env: { ...withoutSeatShim(withoutSeatEnv(env)), CODEX_HOME: home } });
76
+ const last = parseJson(String(r.stdout ?? '').trim().split(/\r?\n/).pop() ?? '', null);
77
+ if (Array.isArray(last)) return last;
78
+ throw new Error(appServerFailure({ home, timeoutMs, r, failed: last?.failed ?? null }));
79
+ }
@@ -0,0 +1,34 @@
1
+ // scripts/agent/codex-mirror-source.mjs — the system Codex home a launch also trusts, beside Orca's managed Codex home.
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+
6
+ /**
7
+ * The system Codex home (<home>/.codex). Orca starts a Codex worker in one of two homes and the launch cannot know
8
+ * which until Orca spawns it: the managed home (<userData>/codex-runtime-home/home), whose config.toml Orca rebuilds
9
+ * from this home's at every launch keeping only its own `[projects.*]` and `[hooks.state.*]` tables (a
10
+ * `[[hooks.PreToolUse]]` block written to the managed file alone is gone seconds after `worker-start`, observed
11
+ * 2026-10-07 18:32), or this home itself, once Codex has approved Orca's status hook in it (Orca 1.4.221 on Windows,
12
+ * as on macOS and Linux). Launch trust therefore records the project, the notices and the guard in both.
13
+ *
14
+ * Null when the launch's Codex home is no Orca-chosen one (an explicit CODEX_HOME): Orca neither mirrors from nor
15
+ * starts the worker in the system home then. A trust home (specs) re-roots the source under `<root>/system`, a
16
+ * directory of its own beside the managed `<root>/.codex`.
17
+ */
18
+ function codexMirrorSource({ env = process.env } = {}) {
19
+ const root = env.STARCI_AGENT_TRUST_HOME || null;
20
+ if (root) return path.join(root, 'system', '.codex');
21
+ return env.CODEX_HOME ? null : path.join(os.homedir(), '.codex');
22
+ }
23
+
24
+ /**
25
+ * The Codex homes one launch records trust in: the active home(s) plus the system home when it has a config.toml.
26
+ * A system home without one stays untouched: Orca refuses a blank mirror source, and a file created for the launch
27
+ * alone would replace the owner's settings in the mirror and mask them in the home Orca starts the worker in.
28
+ */
29
+ export function codexLaunchHomes({ homes, env = process.env }) {
30
+ const source = codexMirrorSource({ env });
31
+ const key = (dir) => path.resolve(dir).toLowerCase();
32
+ const present = source && fs.existsSync(path.join(source, 'config.toml')) && !homes.some((h) => key(h.dir) === key(source));
33
+ return present ? [...homes, { kind: 'system-codex-home', dir: path.resolve(source) }] : homes;
34
+ }
@@ -0,0 +1,80 @@
1
+ // The host-agent preflight of one launch (contract change host-agent-preflight): before anything is trusted or started,
2
+ // the agent the route names must be usable on THIS host. Three refusals, each typed:
3
+ // agent-disabled-on-host Orca's own settings (orca-data.json of the active profile, settings.disabledTuiAgents) disable it;
4
+ // agent-binary-missing its CLI binary (the card's start.cli, or Orca's agentCmdOverrides command) is not on PATH;
5
+ // agent-bypass-missing Orca's settings.agentDefaultArgs for the agent lack the card's bypassFlag (an approval prompt no one answers);
6
+ // model-not-listed the model is no model the runtime declares for that provider (a provider that declares none, like Cursor whose
7
+ // models Orca lists dynamically, is not judged) (registry.yaml models + the pools' model pins);
8
+ // a card with no model flag (Devin) takes no model.
9
+ // No agent list is hard-coded: the card, Orca's settings and PATH decide. A test process reads none of them unless a spec passes
10
+ // its own `settingsFile` / `pathDirs` (the host's real settings must not decide a spec's verdict).
11
+ import fs from 'node:fs';
12
+ import os from 'node:os';
13
+ import path from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+ import { parseYaml } from '../../engine/yaml.mjs';
16
+ import { isSpecRun } from '../lib/env.mjs';
17
+ import { appDataBase } from '../lib/app-data.mjs';
18
+
19
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
20
+ const readYaml = (rel) => { try { return parseYaml(fs.readFileSync(path.join(root, rel), 'utf8')); } catch { return null; } };
21
+ const readJson = (file) => { try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; } };
22
+
23
+ /** Orca's userData folder (STARCI_ORCA_USER_DATA re-roots it, as for Orca's CODEX_HOME in agent/trust.mjs). */
24
+ export function orcaUserData({ env = process.env, platform = process.platform, home = os.homedir() } = {}) {
25
+ if (env.STARCI_ORCA_USER_DATA) return env.STARCI_ORCA_USER_DATA;
26
+ return path.join(appDataBase({ env, platform, home }), 'orca');
27
+ }
28
+
29
+ /** The settings file of Orca's active profile: <userData>/profiles/<activeProfileId>/orca-data.json. */
30
+ function orcaSettingsFile(opts = {}) {
31
+ const data = orcaUserData(opts);
32
+ const profile = readJson(path.join(data, 'orca-profile-index.json'))?.activeProfileId ?? 'local-default';
33
+ return path.join(data, 'profiles', profile, 'orca-data.json');
34
+ }
35
+
36
+ /** The models the runtime declares for `provider`: the registry `models` entries plus every pool's pins. */
37
+ function modelsOfProvider(provider) {
38
+ const found = new Set();
39
+ const registry = readYaml('modules/models/registry.yaml');
40
+ for (const [id, row] of Object.entries(registry?.models ?? {})) if (row?.provider === provider) found.add(id);
41
+ for (const pool of Object.values(registry?.pools ?? {})) {
42
+ if (pool?.provider !== provider) continue;
43
+ if (typeof pool.defaultModel === 'string') found.add(pool.defaultModel);
44
+ for (const v of Object.values(pool.models ?? {})) if (typeof v === 'string') found.add(v);
45
+ }
46
+ return found;
47
+ }
48
+
49
+ const onPath = (binary, { pathDirs, platform, env = process.env }) => {
50
+ const exts = platform === 'win32' ? ['', ...(env.PATHEXT || '.EXE;.CMD;.BAT').split(';').map((e) => e.toLowerCase())] : [''];
51
+ return pathDirs.some((dir) => exts.some((ext) => { try { return fs.statSync(path.join(dir, binary + ext)).isFile(); } catch { return false; } }));
52
+ };
53
+
54
+ /**
55
+ * {ok:true} or {ok:false, code, error}. `card` is the agent card (loadAdapter). Injectable for specs: settingsFile, pathDirs,
56
+ * platform, env, models (a Set replacing the declared models).
57
+ */
58
+ export function hostAgentVerdict({ provider, model = null, card, env = process.env, platform = process.platform, settingsFile = null, pathDirs = null, models = null }) {
59
+ if (!settingsFile && !pathDirs && isSpecRun(env)) return { ok: true, skipped: 'a test process does not read the host agents' };
60
+ const agent = card?.start?.agentArgument ?? provider;
61
+ const settings = readJson(settingsFile ?? orcaSettingsFile({ env, platform }))?.settings ?? {};
62
+ if ((settings.disabledTuiAgents ?? []).includes(agent)) {
63
+ return { ok: false, code: 'agent-disabled-on-host', error: `agent '${agent}' is disabled in Orca's settings (disabledTuiAgents): enable it in Orca or route the role to another agent` };
64
+ }
65
+ const flag = card?.start?.bypassFlag;
66
+ if (flag && !String(settings.agentDefaultArgs?.[agent] ?? '').includes(flag)) {
67
+ return { ok: false, code: 'agent-bypass-missing', error: `agent '${agent}' has no '${flag}' in Orca's agentDefaultArgs: a worker would stop at an approval prompt no one answers; add it in Orca's settings` };
68
+ }
69
+ const override = settings.agentCmdOverrides?.[agent];
70
+ const binary = (typeof override === 'string' && override.trim() ? override.trim().split(/\s+/)[0] : null) ?? card?.start?.cli ?? agent;
71
+ const dirs = pathDirs ?? String(env.PATH || env.Path || '').split(path.delimiter).filter(Boolean);
72
+ if (!path.isAbsolute(binary) && !onPath(binary, { pathDirs: dirs, platform, env })) {
73
+ return { ok: false, code: 'agent-binary-missing', error: `agent '${agent}' needs the CLI binary '${binary}', which is not on PATH: install it or route the role to another agent` };
74
+ }
75
+ if (card?.start?.modelArgument !== false && model) {
76
+ const listed = models ?? modelsOfProvider(provider);
77
+ if (listed.size && !listed.has(model)) return { ok: false, code: 'model-not-listed', error: `model '${model}' is not a model the runtime declares for provider '${provider}' (modules/models/registry.yaml: models, pools)` };
78
+ }
79
+ return { ok: true };
80
+ }
@@ -0,0 +1,53 @@
1
+ // Current launch-root identity and owner-profile authorization. This module
2
+ // resolves authority only; the trust writer keeps all provider file effects.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { revParseQuery } from '../api/git/rev-parse-query.mjs';
6
+ import { launchTrustSettings } from '../../engine/config.mjs';
7
+
8
+ /** The launch cwd as a directory, or null for an Orca selector ('active', 'id:…'). */
9
+ function launchDirectory(worktree) {
10
+ if (typeof worktree !== 'string' || !worktree.trim()) return null;
11
+ const p = worktree.startsWith('path:') ? worktree.slice(5) : worktree;
12
+ try { return fs.statSync(p).isDirectory() ? path.resolve(p) : null; } catch { return null; }
13
+ }
14
+
15
+ /** Paths Codex keys trust by: the cwd, its git toplevel and the main worktree root. */
16
+ export function codexTrustPaths(cwd) {
17
+ const out = [path.resolve(cwd)];
18
+ const git = (...args) => {
19
+ try {
20
+ const r = revParseQuery(args, { dir: cwd, timeout: 10000 });
21
+ return r.status === 0 ? r.stdout.trim() : null;
22
+ } catch { return null; }
23
+ };
24
+ const top = git('--show-toplevel');
25
+ if (top) out.push(path.resolve(top));
26
+ const common = git('--path-format=absolute', '--git-common-dir');
27
+ if (common && path.basename(common) === '.git') out.push(path.resolve(path.dirname(common)));
28
+ const seen = new Set();
29
+ return out.filter((p) => {
30
+ const k = process.platform === 'win32' ? p.toLowerCase() : p;
31
+ if (seen.has(k)) return false;
32
+ seen.add(k);
33
+ return true;
34
+ });
35
+ }
36
+
37
+ /** Resolve an existing checkout to exact current owner roots; never authorize by path prefix. */
38
+ export function launchTrustVerdict({cwd,config,platform=process.platform,roots=codexTrustPaths}={}){
39
+ const dir=launchDirectory(cwd);
40
+ if(!dir)return {ok:false,status:'declined',reason:'automatic trust requires a resolved existing launch directory'};
41
+ let policy;try{policy=config===undefined?launchTrustSettings():launchTrustSettings(config);}catch(error){return {ok:false,status:'declined',reason:String(error.message)};}
42
+ if(policy?.profile!=='automatic')return {ok:false,status:'declined',reason:policy?.profile==='declined'?'owner declined automatic launch trust':'current owner launchTrust profile is not adopted'};
43
+ const key=p=>{const real=fs.realpathSync(p);return platform==='win32'?real.toLowerCase():real;};
44
+ try{
45
+ const paths=roots(dir);
46
+ const approved=new Map(policy.roots.map(root=>[key(root),root]));
47
+ // A worktree is authorized by its exact Git main root. A non-Git directory
48
+ // needs its own exact root entry; a child of an approved directory is insufficient.
49
+ const root=paths.at(-1);
50
+ if(!root||!approved.has(key(root)))return {ok:false,status:'declined',reason:'launch repository is outside the exact owner-approved roots'};
51
+ return {ok:true,dir,paths,approval:{approvedBy:policy.approvedBy,approvalRef:policy.approvalRef,root:approved.get(key(root))}};
52
+ }catch(error){return {ok:false,status:'declined',reason:`cannot verify launch roots: ${error.message}`};}
53
+ }