@enterpriseai/cli 3.19.0 → 3.19.2

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 (364) hide show
  1. package/package.json +3 -3
  2. package/resources/deploy/eai-app-template/producer-pin.json +5 -5
  3. package/resources/deploy/eai-app-template/tests/source-unknown-deployment-evidence.test.mjs +2141 -1
  4. package/resources/gofer/.gofer-version +4 -357
  5. package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
  6. package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
  7. package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
  8. package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
  9. package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
  10. package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
  11. package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
  12. package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
  13. package/resources/gofer/claude-commands/eai-update.md +46 -0
  14. package/resources/gofer/claude-commands/eai.md +355 -0
  15. package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
  16. package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
  17. package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
  18. package/resources/gofer/commands/0_gofer_start.md +440 -99
  19. package/resources/gofer/commands/0a_problem_validation.md +187 -27
  20. package/resources/gofer/commands/10_gofer_cloud.md +183 -23
  21. package/resources/gofer/commands/1_gofer_research.md +239 -30
  22. package/resources/gofer/commands/2_gofer_specify.md +239 -35
  23. package/resources/gofer/commands/3_gofer_plan.md +259 -43
  24. package/resources/gofer/commands/4_gofer_tasks.md +401 -81
  25. package/resources/gofer/commands/5_gofer_implement.md +375 -84
  26. package/resources/gofer/commands/6_gofer_validate.md +284 -53
  27. package/resources/gofer/commands/7_gofer_save.md +187 -26
  28. package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
  29. package/resources/gofer/commands/8_gofer_branding.md +183 -23
  30. package/resources/gofer/commands/9_gofer_tests.md +212 -23
  31. package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
  32. package/resources/gofer/commands/gofer_check_workspace.md +123 -8
  33. package/resources/gofer/commands/gofer_constitution.md +183 -23
  34. package/resources/gofer/commands/gofer_diagnose.md +183 -23
  35. package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
  36. package/resources/gofer/commands/gofer_hydrate.md +183 -23
  37. package/resources/gofer/commands/gofer_personality.md +117 -6
  38. package/resources/gofer/commands/gofer_plan.md +117 -6
  39. package/resources/gofer/commands/gofer_side.md +117 -6
  40. package/resources/gofer/commands/gofer_spec_summary.md +183 -23
  41. package/resources/gofer/commands/gofer_tdd.md +183 -23
  42. package/resources/gofer/commands/gofer_vocabulary.md +185 -25
  43. package/resources/gofer/commands/gofer_zoom_out.md +183 -23
  44. package/resources/gofer/config/typesafe-learning-review.json +16 -0
  45. package/resources/gofer/config/typesafe-semantic-review.json +9 -0
  46. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
  47. package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
  48. package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
  49. package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
  50. package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
  51. package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
  52. package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
  53. package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
  54. package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
  55. package/resources/gofer/gemini/extension.json +4 -4
  56. package/resources/gofer/github-agents/eai.agent.md +83 -0
  57. package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
  58. package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
  59. package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
  60. package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
  61. package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
  62. package/resources/gofer/github-skills/eai/SKILL.md +365 -0
  63. package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
  64. package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
  65. package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
  66. package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
  67. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
  68. package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
  69. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
  70. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
  71. package/resources/gofer/memory/constitution.md +9 -7
  72. package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
  73. package/resources/gofer/memory/lessons.md +0 -31
  74. package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
  75. package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
  76. package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
  77. package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
  78. package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
  79. package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
  80. package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
  81. package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
  82. package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
  83. package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
  84. package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
  85. package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
  86. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
  87. package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
  88. package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
  89. package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
  90. package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
  91. package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
  92. package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
  93. package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
  94. package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
  95. package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
  96. package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
  97. package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
  98. package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
  99. package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
  100. package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
  101. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
  102. package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
  103. package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
  104. package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
  105. package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
  106. package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
  107. package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
  108. package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
  109. package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
  110. package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
  111. package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
  112. package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
  113. package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
  114. package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
  115. package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
  116. package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
  117. package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
  118. package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
  119. package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
  120. package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
  121. package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
  122. package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
  123. package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
  124. package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
  125. package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
  126. package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
  127. package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
  128. package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
  129. package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
  130. package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
  131. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
  132. package/resources/gofer/references/agent-catalog.json +126 -0
  133. package/resources/gofer/references/blocker-mediation.md +156 -0
  134. package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
  135. package/resources/gofer/references/delivery-lineage.md +48 -0
  136. package/resources/gofer/references/mvp-capability-validation.md +102 -0
  137. package/resources/gofer/references/platform/README.md +1 -1
  138. package/resources/gofer/references/platform/eai-app-template.md +15 -13
  139. package/resources/gofer/references/platform/eai-auth-access.md +104 -0
  140. package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
  141. package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
  142. package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
  143. package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
  144. package/resources/gofer/references/platform/eai.md +44 -8
  145. package/resources/gofer/references/platform/vertical-template.md +10 -9
  146. package/resources/gofer/references/priority-outcome-protection.md +152 -0
  147. package/resources/gofer/references/verified-agent-execution.md +179 -0
  148. package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
  149. package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
  150. package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
  151. package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
  152. package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
  153. package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
  154. package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
  155. package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
  156. package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
  157. package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
  158. package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
  159. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
  160. package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
  161. package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
  162. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
  163. package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
  164. package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
  165. package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
  166. package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
  167. package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
  168. package/resources/gofer/specify-commands/gofer_personality.md +117 -6
  169. package/resources/gofer/specify-commands/gofer_plan.md +117 -6
  170. package/resources/gofer/specify-commands/gofer_side.md +117 -6
  171. package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
  172. package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
  173. package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
  174. package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
  175. package/resources/gofer/specify-config/object-type-routing.json +24 -0
  176. package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
  177. package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
  178. package/resources/gofer/system-skills/eai/SKILL.md +365 -0
  179. package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
  180. package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
  181. package/resources/gofer/templates/build-map-template.md +64 -0
  182. package/resources/gofer/templates/business-scenarios-template.json +14 -0
  183. package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
  184. package/resources/gofer/templates/context-bundle-template.md +4 -3
  185. package/resources/gofer/templates/contract-pack-template.md +8 -8
  186. package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
  187. package/resources/gofer/templates/delivery-lineage-template.json +8 -0
  188. package/resources/gofer/templates/eai-preflight-template.md +109 -68
  189. package/resources/gofer/templates/goal-ledger-template.json +1 -1
  190. package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
  191. package/resources/gofer/templates/loop-contract-template.json +3 -1
  192. package/resources/gofer/templates/plan-template.md +8 -7
  193. package/resources/gofer/templates/priority-plan-template.json +29 -0
  194. package/resources/gofer/templates/proposal-review-template.md +6 -3
  195. package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
  196. package/resources/gofer/templates/research-template.md +7 -6
  197. package/resources/gofer/templates/spec-summary-template.md +1 -1
  198. package/resources/gofer/templates/spec-template.md +45 -6
  199. package/resources/gofer/templates/tasks-template.md +12 -3
  200. package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
  201. package/resources/gofer/templates/ui-review-log-template.md +21 -3
  202. package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
  203. package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
  204. package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
  205. package/resources/linked-sources.json +4 -4
  206. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
  207. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
  208. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
  209. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
  210. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
  211. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
  212. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
  213. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
  214. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
  215. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
  216. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
  217. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
  218. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
  219. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  220. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
  221. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
  222. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
  223. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
  224. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
  225. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
  226. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
  227. package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
  228. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
  229. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
  230. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
  231. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
  232. package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
  233. package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
  234. package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
  235. package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
  236. package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
  237. package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
  238. package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
  239. package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
  240. package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
  241. package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
  242. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
  243. package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
  244. package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
  245. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
  246. package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
  247. package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
  248. package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
  249. package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
  250. package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
  251. package/resources/gofer/claude-commands/gofer_personality.md +0 -39
  252. package/resources/gofer/claude-commands/gofer_plan.md +0 -35
  253. package/resources/gofer/claude-commands/gofer_side.md +0 -40
  254. package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
  255. package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
  256. package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
  257. package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
  258. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
  259. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
  260. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
  261. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
  262. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
  263. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
  264. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
  265. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
  266. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
  267. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
  268. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
  269. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
  270. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
  271. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
  272. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
  273. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
  274. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
  275. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
  276. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
  277. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
  278. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
  279. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
  280. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
  281. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
  282. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
  283. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
  284. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
  285. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
  286. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
  287. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
  288. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
  289. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
  290. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
  291. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
  292. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
  293. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
  294. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
  295. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
  296. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
  297. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
  298. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
  299. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
  300. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
  301. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
  302. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
  303. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
  304. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
  305. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
  306. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
  307. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
  308. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
  309. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
  310. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
  311. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
  312. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
  313. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
  314. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
  315. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
  316. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
  317. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
  318. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
  319. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
  320. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
  321. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
  322. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
  323. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
  324. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
  325. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
  326. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
  327. package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
  328. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
  329. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
  330. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
  331. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
  332. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
  333. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
  334. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
  335. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
  336. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
  337. package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
  338. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
  339. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
  340. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
  341. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
  342. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
  343. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
  344. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
  345. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
  346. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
  347. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
  348. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
  349. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
  350. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
  351. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  352. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
  353. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
  354. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
  355. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
  356. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
  357. package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
  358. package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
  359. package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
  360. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
  361. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
  362. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
  363. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
  364. package/resources/gofer/templates/ui-approval-template.md +0 -32
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Production entrypoint for the verified native runtime. Composes the real
4
+ * capability issuer, the real append-only ledger, and `createVerifiedNativeRuntime`
5
+ * to run one bounded, ledger-authorized native task in an isolated worktree.
6
+ *
7
+ * This is deliberately the only command that calls `createVerifiedNativeRuntime`
8
+ * outside of a test. It fails closed with TRUSTED_EVALUATOR_REQUIRED when no
9
+ * local trust identity is registered — that is expected until the account
10
+ * trust store is provisioned; it is not a sign the wiring is missing.
11
+ */
12
+ import { execFileSync } from 'node:child_process';
13
+ import { createHash } from 'node:crypto';
14
+ import { constants } from 'node:fs';
15
+ import { promises as fs } from 'node:fs';
16
+ import { fileURLToPath } from 'node:url';
17
+ import path from 'node:path';
18
+ import process from 'process';
19
+ import { createVerifiedNativeRuntime } from './gofer-native-runtime.mjs';
20
+ import { createVerifiedWorktree, disposeVerifiedWorktree } from './gofer-native-adapter.mjs';
21
+ import { createRuntimeLedger } from './gofer-runtime-ledger.mjs';
22
+ import { issueLocalCapabilityReceipt } from './gofer-local-capability-issuer.mjs';
23
+ import { inspectEaiLocalIsolation } from './gofer-local-isolation.mjs';
24
+
25
+ const SMOKE_TASK_ID = 'T001';
26
+ const SMOKE_CHECK_NAME = 'smoke-file-check';
27
+ const SMOKE_FILE_NAME = 'NATIVE_SMOKE_PROOF.md';
28
+ const SMOKE_FILE_CONTENT = 'native wiring smoke test passed.\n';
29
+ const noFollowFlag = process.platform === 'win32' ? 0 : constants.O_NOFOLLOW;
30
+
31
+ function parseArgs(argv) {
32
+ const args = { workspace: '', featureDir: '', capabilityReceipt: '', benchmark: '' };
33
+ for (let index = 0; index < argv.length; index += 1) {
34
+ const arg = argv[index];
35
+ if (arg === '--workspace') args.workspace = argv[++index] || '';
36
+ else if (arg === '--feature-dir') args.featureDir = argv[++index] || '';
37
+ else if (arg === '--capability-receipt') args.capabilityReceipt = argv[++index] || '';
38
+ else if (arg === '--benchmark') args.benchmark = argv[++index] || '';
39
+ else throw new Error(`Unknown argument: ${arg}`);
40
+ }
41
+ if (!path.isAbsolute(args.workspace)) throw new Error('--workspace <absolute-path> is required');
42
+ // A receipt and a signed benchmark only make sense together.
43
+ if (Boolean(args.capabilityReceipt) !== Boolean(args.benchmark) ||
44
+ [args.capabilityReceipt, args.benchmark].some(value => value && !path.isAbsolute(value))) {
45
+ throw new Error('--capability-receipt and --benchmark need absolute paths and must be given together');
46
+ }
47
+ return args;
48
+ }
49
+
50
+ async function readJsonFile(filename) {
51
+ const file = await fs.open(filename, constants.O_RDONLY | constants.O_NOFOLLOW);
52
+ try {
53
+ const info = await file.stat();
54
+ if (!info.isFile() || info.size > 1024 * 1024) throw new Error('JSON input must be a regular file under 1 MiB');
55
+ return JSON.parse(await file.readFile('utf8'));
56
+ } finally { await file.close(); }
57
+ }
58
+
59
+ export function gitHead(workspaceRoot) {
60
+ return execFileSync('git', ['-C', workspaceRoot, 'rev-parse', 'HEAD'], { encoding: 'utf8' }).trim();
61
+ }
62
+
63
+ async function confinedFeatureDirectory(workspace, requested) {
64
+ const root = await fs.realpath(workspace);
65
+ const target = path.resolve(requested || path.join(root, '.specify', 'specs', 'native-runtime-smoke'));
66
+ const relative = path.relative(root, target);
67
+ if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
68
+ throw new Error('FEATURE_DIRECTORY_OUTSIDE_WORKSPACE');
69
+ }
70
+ let current = root;
71
+ for (const component of relative.split(path.sep).filter(Boolean)) {
72
+ current = path.join(current, component);
73
+ const info = await fs.lstat(current).catch((error) => {
74
+ if (error?.code === 'ENOENT') return null;
75
+ throw error;
76
+ });
77
+ if (!info) break;
78
+ if (info.isSymbolicLink()) throw new Error('FEATURE_DIRECTORY_SYMLINK');
79
+ }
80
+ return target;
81
+ }
82
+
83
+ /** Build the minimal set of controller documents `reviewPriority` requires,
84
+ * describing exactly one bounded, inert smoke task. Kept in the controller's
85
+ * source-side feature directory, never the isolated task worktree (D029). */
86
+ export async function prepareSmokeFeature(featureDir, revision) {
87
+ await fs.mkdir(featureDir, { recursive: true, mode: 0o700 });
88
+ await fs.writeFile(path.join(featureDir, 'spec.md'),
89
+ '# Native Runtime Smoke Task\n\n' +
90
+ '- FR-001: Create one fixed-content proof file and change nothing else.\n', { mode: 0o600 });
91
+ await fs.writeFile(path.join(featureDir, 'decisions.md'),
92
+ '## D001 - Run one bounded native smoke task\n\n' +
93
+ 'The user approved wiring the verified native runtime into a real command ' +
94
+ 'and running one bounded, inert smoke task to prove the dispatch path.\n', { mode: 0o600 });
95
+ await fs.writeFile(path.join(featureDir, 'plan.md'),
96
+ '# Plan\n\nRun one bounded native task in a verified local worktree.\n', { mode: 0o600 });
97
+ await fs.writeFile(path.join(featureDir, 'loop-contract.json'), `${JSON.stringify({
98
+ schemaVersion: 1, requirePriorityPlan: true, loopId: 'native-runtime-smoke',
99
+ profile: 'standard', objective: 'Prove the verified native runtime dispatches one real task end to end.',
100
+ entryStage: '0_gofer_start', maxIterations: 2, budget: {}, evalCommands: [],
101
+ successCriteria: [], stopConditions: [],
102
+ humanEscalation: { maxFailedIterations: 1, owner: 'Gofer maintainers', escalateWhen: ['native host authority is unavailable'] },
103
+ }, null, 2)}\n`, { mode: 0o600 });
104
+ await fs.writeFile(path.join(featureDir, 'tasks.md'),
105
+ `- [ ] **${SMOKE_TASK_ID}** Create ${SMOKE_FILE_NAME} with fixed content.\n`, { mode: 0o600 });
106
+ await fs.writeFile(path.join(featureDir, 'traceability.md'),
107
+ '| Requirement | Task |\n| --- | --- |\n' +
108
+ `| FR-001 | ${SMOKE_TASK_ID} |\n`, { mode: 0o600 });
109
+ const plan = {
110
+ schemaVersion: 2,
111
+ revision,
112
+ objective: 'Prove the verified native runtime dispatches one real task end to end.',
113
+ lastInstruction: { id: 'D001', text: 'The user approved wiring the verified native runtime into a real command and running one bounded, inert smoke task to prove the dispatch path.' },
114
+ decisionPolicy: { mode: 'goal-led', askOnlyFor: ['goal-change', 'irreversible-action', 'missing-authority'] },
115
+ criticalPath: [SMOKE_TASK_ID],
116
+ tasks: { [SMOKE_TASK_ID]: { dependsOn: [], allowedEditScope: [SMOKE_FILE_NAME] } },
117
+ outcome: {
118
+ id: 'OUTCOME-SMOKE-001',
119
+ statement: 'A native host performs one scoped, ledger-governed smoke task in verified isolation.',
120
+ requirements: ['FR-001'],
121
+ target: { environment: 'local-native-host', revision },
122
+ receipt: 'evidence/outcome.json',
123
+ },
124
+ };
125
+ await fs.writeFile(path.join(featureDir, 'priority-plan.json'), `${JSON.stringify(plan, null, 2)}\n`, { mode: 0o600 });
126
+ }
127
+
128
+ /** The worker-facing adapter. `reserve`/`lease` delegate straight to the same
129
+ * ledger the graph engine authorizes and commits against; `check`/`verified`
130
+ * inspect the isolated worktree directly rather than trusting worker claims. */
131
+ export function createSmokeAdapter({ ledger }) {
132
+ return {
133
+ bindWorkspace({ workspaceRoot }) {
134
+ return {
135
+ workspaceRoot,
136
+ reserve: request => ledger.reserve(request),
137
+ lease: request => ledger.lease(request),
138
+ async inputRevision() { return gitHead(workspaceRoot); },
139
+ async check({ taskId, revision, inputRevision, check }) {
140
+ const target = path.join(workspaceRoot, SMOKE_FILE_NAME);
141
+ const actual = await fs.readFile(target, 'utf8').catch(() => null);
142
+ const executed = true;
143
+ const exitCode = actual === SMOKE_FILE_CONTENT ? 0 : 1;
144
+ return { taskId, revision, inputRevision, check, exitCode, executed,
145
+ receipt: createHash('sha256').update(`${taskId}:${inputRevision}:${actual ?? ''}`).digest('hex') };
146
+ },
147
+ async verified({ taskId, revision, inputRevision }) {
148
+ const target = path.join(workspaceRoot, SMOKE_FILE_NAME);
149
+ const actual = await fs.readFile(target, 'utf8').catch(() => null);
150
+ if (actual !== SMOKE_FILE_CONTENT) throw new Error('SMOKE_TASK_OUTPUT_MISMATCH');
151
+ return { committed: true, taskId, revision, inputRevision,
152
+ receipt: createHash('sha256').update(`verified:${taskId}:${inputRevision}`).digest('hex') };
153
+ },
154
+ };
155
+ },
156
+ };
157
+ }
158
+
159
+ /** Capability issuance needs an already-isolated worktree to probe, but the
160
+ * receipt itself attests host/model capability, not a specific worktree's
161
+ * identity. Issue it against a disposable probe worktree, exactly like the
162
+ * live capability diagnostic already recorded for this feature, then reuse
163
+ * the receipt for the separate, real task worktree below. */
164
+ async function issueDisposableCapabilityReceipt(workspace, host) {
165
+ const probe = await createVerifiedWorktree({ workspaceRoot: workspace, host,
166
+ localIsolation: inspectEaiLocalIsolation });
167
+ try {
168
+ return await issueLocalCapabilityReceipt({ workspaceRoot: probe.isolatedWorkspace });
169
+ } finally {
170
+ await disposeVerifiedWorktree({ workspaceRoot: probe.workspace,
171
+ isolatedWorkspace: probe.isolatedWorkspace, revision: probe.revision,
172
+ receipt: probe.receipt }).catch(() => {});
173
+ }
174
+ }
175
+
176
+ /** `capabilityReceipt` and `benchmark` ({ evidence, attestation }) may be supplied
177
+ * together to route by a signed independent benchmark. Without them the runner
178
+ * issues its own receipt and the routing gate correctly refuses to route. */
179
+ export async function runVerifiedSmokeTask({ workspace, featureDir, host = 'codex',
180
+ capabilityReceipt: suppliedReceipt, benchmark }) {
181
+ const revision = gitHead(workspace);
182
+ const resolvedFeatureDir = await confinedFeatureDirectory(workspace, featureDir);
183
+ // Complete every path-based controller write before any native worker can
184
+ // start. The worker receives only its isolated worktree and cannot reach the
185
+ // controller feature directory.
186
+ await prepareSmokeFeature(resolvedFeatureDir, revision);
187
+ // Bind every controller-side read and write to the same canonical directory.
188
+ // This prevents a caller-controlled symlink from redirecting evidence after
189
+ // the runtime has validated its feature root.
190
+ const controllerFeatureDir = await fs.realpath(resolvedFeatureDir);
191
+ const capabilityReceipt = suppliedReceipt ?? await issueDisposableCapabilityReceipt(workspace, host);
192
+ const ledger = await createRuntimeLedger({ ledgerPath: path.join(controllerFeatureDir, 'runtime-ledger.jsonl') });
193
+ const runtime = await createVerifiedNativeRuntime({
194
+ workspaceRoot: workspace,
195
+ host,
196
+ localIsolation: inspectEaiLocalIsolation,
197
+ capabilityReceipt,
198
+ requiredCapabilities: { isolationClass: 'git-worktree+local-os-sandbox' },
199
+ ledger,
200
+ promptForRequest: async () => `Create a file named ${SMOKE_FILE_NAME} in the repository root ` +
201
+ `containing exactly this one line: "${SMOKE_FILE_CONTENT.trim()}". Make no other change.`,
202
+ adapter: createSmokeAdapter({ ledger }),
203
+ });
204
+ // Create and retain the final evidence file descriptor before dispatch.
205
+ // Retirement writes through this descriptor and never resolves a path that
206
+ // a concurrent process could replace after the worker starts.
207
+ const evidenceSink = await openEvidenceSink(controllerFeatureDir);
208
+ let result;
209
+ try {
210
+ result = await runtime.run({
211
+ featureDir: controllerFeatureDir,
212
+ checks: { [SMOKE_TASK_ID]: [SMOKE_CHECK_NAME] },
213
+ approvalReceipt: 'local-smoke-approval',
214
+ benchmarkEvidence: benchmark?.evidence,
215
+ benchmarkAttestation: benchmark?.attestation,
216
+ maxCalls: 12,
217
+ maxConcurrent: 1,
218
+ deadlineMs: Date.now() + 300_000,
219
+ });
220
+ } catch (error) {
221
+ await evidenceSink.close().catch(() => {});
222
+ // A failed run keeps its worktree for recovery; say where it is instead of hiding it.
223
+ await runtime.dispose().catch(disposeError => process.stderr.write(
224
+ `Worktree kept at ${runtime.isolation.isolatedWorkspace}: ${disposeError.message}\n`));
225
+ throw error;
226
+ }
227
+ // A verified run must not leave a worktree behind, so disposal errors surface.
228
+ if (result.status !== 'verified' || result.adapterCallsSettled !== true) {
229
+ await evidenceSink.close().catch(() => {});
230
+ const location = runtime.isolation.isolatedWorkspace;
231
+ process.stderr.write(`Worktree kept at ${location}: native task requires recovery\n`);
232
+ throw new Error(`NATIVE_RUNTIME_REQUIRES_RECOVERY:${location}`);
233
+ }
234
+ try {
235
+ await retireVerifiedOutput({ isolatedWorkspace: runtime.isolation.isolatedWorkspace,
236
+ evidenceSink });
237
+ await evidenceSink.close();
238
+ await runtime.dispose();
239
+ } catch (error) {
240
+ await evidenceSink.close().catch(() => {});
241
+ process.stderr.write(
242
+ `Worktree kept at ${runtime.isolation.isolatedWorkspace}: ${error.message}\n`);
243
+ throw error;
244
+ }
245
+ return result;
246
+ }
247
+
248
+ function sameIdentity(left, right) {
249
+ if (left.dev === undefined || left.ino === undefined ||
250
+ right.dev === undefined || right.ino === undefined) return true;
251
+ return left.dev === right.dev && left.ino === right.ino;
252
+ }
253
+
254
+ async function openEvidenceSink(featureDirectory) {
255
+ const evidenceDirectory = path.join(featureDirectory, 'evidence');
256
+ const featureHandle = await fs.open(featureDirectory,
257
+ constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | noFollowFlag);
258
+ let evidenceHandle;
259
+ try {
260
+ const featureIdentity = await featureHandle.stat();
261
+ const featureAfterOpen = await fs.lstat(featureDirectory);
262
+ if (!featureIdentity.isDirectory() || featureAfterOpen.isSymbolicLink() ||
263
+ !sameIdentity(featureIdentity, featureAfterOpen)) {
264
+ throw new Error('CONTROLLER_FEATURE_DIRECTORY_CHANGED');
265
+ }
266
+ // Exclusive creation rejects every pre-existing path, including a symlink.
267
+ await fs.mkdir(evidenceDirectory, { mode: 0o700 });
268
+ evidenceHandle = await fs.open(evidenceDirectory,
269
+ constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | noFollowFlag);
270
+ const evidenceIdentity = await evidenceHandle.stat();
271
+ const [featureAfterCreate, evidenceAfterOpen] = await Promise.all([
272
+ fs.lstat(featureDirectory), fs.lstat(evidenceDirectory),
273
+ ]);
274
+ if (!evidenceIdentity.isDirectory() || evidenceAfterOpen.isSymbolicLink() ||
275
+ !sameIdentity(evidenceIdentity, evidenceAfterOpen) ||
276
+ !sameIdentity(featureIdentity, featureAfterCreate)) {
277
+ throw new Error('CONTROLLER_EVIDENCE_DIRECTORY_CHANGED');
278
+ }
279
+ const evidencePath = path.join(evidenceDirectory, SMOKE_FILE_NAME);
280
+ const sink = await fs.open(evidencePath,
281
+ constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollowFlag, 0o600);
282
+ const [featureAfterSinkOpen, evidenceAfterSinkOpen] = await Promise.all([
283
+ fs.lstat(featureDirectory), fs.lstat(evidenceDirectory),
284
+ ]);
285
+ if (!sameIdentity(featureIdentity, featureAfterSinkOpen) ||
286
+ !sameIdentity(evidenceIdentity, evidenceAfterSinkOpen)) {
287
+ await sink.close();
288
+ throw new Error('CONTROLLER_EVIDENCE_DIRECTORY_CHANGED');
289
+ }
290
+ return sink;
291
+ } finally {
292
+ await evidenceHandle?.close();
293
+ await featureHandle.close();
294
+ }
295
+ }
296
+
297
+ /** Keep the verified proof file as controller evidence, then remove it from the task
298
+ * worktree so the strict clean-state disposal check stays unchanged. */
299
+ async function retireVerifiedOutput({ isolatedWorkspace, evidenceSink }) {
300
+ const source = path.join(isolatedWorkspace, SMOKE_FILE_NAME);
301
+ const sourceHandle = await fs.open(source, constants.O_RDONLY | noFollowFlag);
302
+ let actual;
303
+ try {
304
+ const sourceInfo = await sourceHandle.stat();
305
+ if (!sourceInfo.isFile()) throw new Error('SMOKE_TASK_OUTPUT_INVALID');
306
+ actual = await sourceHandle.readFile('utf8');
307
+ } finally { await sourceHandle.close(); }
308
+ if (actual !== SMOKE_FILE_CONTENT) throw new Error('SMOKE_TASK_OUTPUT_MISMATCH');
309
+ const sinkInfo = await evidenceSink.stat();
310
+ if (!sinkInfo.isFile()) throw new Error('CONTROLLER_EVIDENCE_FILE_INVALID');
311
+ await evidenceSink.writeFile(actual);
312
+ await evidenceSink.sync();
313
+ await fs.rm(source);
314
+ }
315
+
316
+ async function main(argv) {
317
+ const args = parseArgs(argv);
318
+ const capabilityReceipt = args.capabilityReceipt ? await readJsonFile(args.capabilityReceipt) : undefined;
319
+ const benchmark = args.benchmark ? await readJsonFile(args.benchmark) : undefined;
320
+ const result = await runVerifiedSmokeTask({ workspace: args.workspace,
321
+ featureDir: args.featureDir || undefined, capabilityReceipt, benchmark });
322
+ process.stdout.write(`${JSON.stringify(result)}\n`);
323
+ }
324
+
325
+ if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
326
+ main(process.argv.slice(2)).catch(error => {
327
+ process.stderr.write(`${error.message}\n`);
328
+ process.exitCode = 1;
329
+ });
330
+ }
@@ -0,0 +1,289 @@
1
+ /** Durable, append-only authority ledger for a single verified runtime. */
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { chmod, link, lstat, mkdir, open, readFile, unlink } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { DatabaseSync } from 'node:sqlite';
6
+
7
+ const text = value => typeof value === 'string' && value.trim().length > 0;
8
+ const digest = value => createHash('sha256').update(JSON.stringify(value)).digest('hex');
9
+ const sameList = (left, right) => Array.isArray(left) && Array.isArray(right) &&
10
+ left.length === right.length && left.every((value, index) => value === right[index]);
11
+
12
+ export async function acquireLedgerLock(lockPath) {
13
+ let metadata = await lstat(lockPath).catch(error => {
14
+ if (error.code === 'ENOENT') return null;
15
+ throw error;
16
+ });
17
+ if (!metadata) {
18
+ const temporary = `${lockPath}.${randomUUID()}.init`;
19
+ try {
20
+ const initial = new DatabaseSync(temporary, { timeout: 0 });
21
+ try { initial.exec('CREATE TABLE lock_identity (id INTEGER PRIMARY KEY)'); }
22
+ finally { initial.close(); }
23
+ await chmod(temporary, 0o600);
24
+ try { await link(temporary, lockPath); }
25
+ catch (error) { if (error.code !== 'EEXIST') throw error; }
26
+ } finally { await unlink(temporary).catch(() => {}); }
27
+ metadata = await lstat(lockPath);
28
+ }
29
+ // A legacy, empty .lock file may still belong to an older live controller.
30
+ // Do not reinterpret it as an unlocked database during an upgrade.
31
+ if (!metadata.isFile() || metadata.size === 0 ||
32
+ (process.platform !== 'win32' && (metadata.mode & 0o077) !== 0)) {
33
+ throw new Error('LEDGER_LOCK_MIGRATION_REQUIRED');
34
+ }
35
+ let database;
36
+ try {
37
+ database = new DatabaseSync(lockPath, { timeout: 0 });
38
+ database.exec('BEGIN IMMEDIATE');
39
+ return database;
40
+ } catch (error) {
41
+ database?.close();
42
+ throw new Error(/database is locked|SQLITE_BUSY/i.test(error.message) ? 'LEDGER_BUSY' : 'LEDGER_LOCK_UNAVAILABLE');
43
+ }
44
+ }
45
+
46
+ export async function createRuntimeLedger({ ledgerPath, now = () => new Date(), verifyCancellation,
47
+ verifyBenchmarkCapture } = {}) {
48
+ if (!path.isAbsolute(ledgerPath)) throw new Error('LEDGER_PATH_REQUIRED');
49
+ await mkdir(path.dirname(ledgerPath), { recursive: true, mode: 0o700 });
50
+ const lockPath = `${ledgerPath}.lock`;
51
+ const events = async () => (await readFile(ledgerPath, 'utf8').catch(error => {
52
+ if (error.code === 'ENOENT') return '';
53
+ throw error;
54
+ })).split('\n')
55
+ .filter(Boolean).map(line => JSON.parse(line));
56
+ const transact = async (event, evaluate) => {
57
+ const lock = await acquireLedgerLock(lockPath);
58
+ try {
59
+ const history = await events();
60
+ const result = await evaluate(history);
61
+ if (result?.allowed !== true) return result;
62
+ const record = { schemaVersion: 1, eventId: randomUUID(), at: now().toISOString(), ...event, ...result };
63
+ const append = await open(ledgerPath, 'a', 0o600);
64
+ try { await append.writeFile(`${JSON.stringify(record)}\n`); await append.sync(); } finally { await append.close(); }
65
+ return result;
66
+ } finally {
67
+ try { lock.exec('ROLLBACK'); } finally { lock.close(); }
68
+ }
69
+ };
70
+ const reservation = request => ({ taskId: request?.taskId, revision: request?.revision, attempt: request?.attempt,
71
+ budgetReservation: `reservation:${digest(request).slice(0, 24)}` });
72
+ return Object.freeze({
73
+ reserve: request => transact({ type: 'reserve', request }, async history => text(request?.taskId) && text(request?.revision) &&
74
+ Number.isSafeInteger(request?.attempt) && request.attempt > 0 &&
75
+ !history.some(item => item.type === 'reserve' && item.taskId === request.taskId &&
76
+ item.revision === request.revision && item.attempt >= request.attempt) &&
77
+ !history.some(item => item.type === 'lease' && item.taskId === request.taskId &&
78
+ !history.some(closed => closed.type === 'cancel-reconciled' && closed.leaseId === item.leaseId))
79
+ ? { allowed: true, ...reservation(request) } : { allowed: false }),
80
+ lease: request => transact({ type: 'lease', request }, async history => {
81
+ const reserved = reservation(request);
82
+ if (!history.some(item => item.type === 'reserve' && item.budgetReservation === reserved.budgetReservation) ||
83
+ history.some(item => item.type === 'lease' && item.budgetReservation === reserved.budgetReservation)) return { allowed: false };
84
+ if (history.some(item => item.type === 'lease' && item.taskId === request.taskId &&
85
+ !history.some(closed => closed.type === 'cancel-reconciled' && closed.leaseId === item.leaseId))) return { allowed: false };
86
+ return { allowed: true, taskId: request.taskId, revision: request.revision, attempt: request.attempt,
87
+ budgetReservation: reserved.budgetReservation,
88
+ leaseId: `lease:${randomUUID()}`, expiresAt: new Date(now().getTime() + 300000).toISOString() };
89
+ }),
90
+ authorize: request => transact({ type: 'authorize', request }, async history => {
91
+ if (!text(request?.leaseId) || !text(request?.budgetReservation) || !text(request?.approvalReceipt) ||
92
+ !Array.isArray(request?.dependencies)) return { allowed: false };
93
+ const lease = history.find(item => item.type === 'lease' && item.leaseId === request.leaseId);
94
+ const reserved = history.find(item => item.type === 'reserve' &&
95
+ item.budgetReservation === request.budgetReservation);
96
+ const replacement = history.filter(item => item.type === 'cancel-reconciled' &&
97
+ item.taskId === request.taskId && item.revision === request.revision).at(-1);
98
+ if (!lease || !reserved || lease.taskId !== request.taskId || lease.revision !== request.revision ||
99
+ lease.attempt !== request.attempt || lease.budgetReservation !== request.budgetReservation ||
100
+ reserved.taskId !== request.taskId || reserved.revision !== request.revision ||
101
+ reserved.attempt !== request.attempt ||
102
+ digest(reserved.request?.dependencies) !== digest(request.dependencies) ||
103
+ reserved.request?.worktreeReceipt !== request.worktreeReceipt ||
104
+ !sameList(reserved.request?.allowedEditScope, request.allowedEditScope) ||
105
+ !sameList(reserved.request?.requiredChecks, request.requiredChecks) ||
106
+ reserved.request?.capabilityReceiptHash !== request.capabilityReceiptHash ||
107
+ reserved.request?.approvalReceipt !== request.approvalReceipt ||
108
+ reserved.request?.selectedModel !== request.selectedModel ||
109
+ reserved.request?.benchmarkReceipt !== request.benchmarkReceipt ||
110
+ Date.parse(lease.expiresAt) <= now().getTime() ||
111
+ (replacement && request.worktreeReceipt !== replacement.replacementWorktreeReceipt) ||
112
+ history.some(item => item.leaseId === request.leaseId &&
113
+ ['authorize', 'cancel-reconciled'].includes(item.type))) return { allowed: false };
114
+ return { allowed: true, ...request, receipt: `authority:${digest(request).slice(0, 32)}` };
115
+ }),
116
+ authorizeNative: request => transact({ type: 'native-authorize', request }, async history => {
117
+ const authority = history.find(item => item.type === 'authorize' && item.leaseId === request?.leaseId && item.receipt === request?.ledgerAuthorityReceipt);
118
+ const lease = history.find(item => item.type === 'lease' && item.leaseId === request?.leaseId);
119
+ if (!authority || !lease || Date.parse(lease.expiresAt) <= now().getTime() ||
120
+ history.some(item => item.leaseId === request?.leaseId &&
121
+ ['native-authorize', 'commit-authorize', 'cancel-reconciled'].includes(item.type)) ||
122
+ authority.taskId !== request.taskId || authority.revision !== request.objectiveRevision ||
123
+ authority.attempt !== request.attempt ||
124
+ authority.budgetReservation !== request.budgetReservation || authority.approvalReceipt !== request.approvalReceipt ||
125
+ authority.worktreeReceipt !== request.worktreeReceipt ||
126
+ authority.capabilityReceiptHash !== request.capabilityReceiptHash || digest(authority.dependencies) !== digest(request.dependencies) ||
127
+ authority.selectedModel !== request.selectedModel ||
128
+ !sameList(authority.allowedEditScope, request.allowedWriteScope)) return { allowed: false };
129
+ return { allowed: true, ...request, isolation: 'git-worktree+local-os-sandbox', receipt: authority.receipt };
130
+ }),
131
+ authorizeCommit: request => transact({ type: 'commit-authorize', request }, async history => {
132
+ const authority = history.find(item => item.type === 'authorize' && item.leaseId === request?.leaseId);
133
+ const lease = history.find(item => item.type === 'lease' && item.leaseId === request?.leaseId);
134
+ const native = history.find(item => item.type === 'native-authorize' && item.leaseId === request?.leaseId);
135
+ const requiredChecks = authority?.requiredChecks;
136
+ const validation = request?.validation;
137
+ if (!authority || !lease || !native || Date.parse(lease.expiresAt) <= now().getTime() ||
138
+ history.some(item => item.leaseId === request?.leaseId &&
139
+ ['commit-authorize', 'cancel-reconciled'].includes(item.type)) ||
140
+ authority.taskId !== request.taskId || authority.revision !== request.revision ||
141
+ authority.attempt !== request.attempt || authority.budgetReservation !== request.budgetReservation ||
142
+ authority.approvalReceipt !== request.approvalReceipt || authority.capabilityReceiptHash !== request.capabilityReceiptHash ||
143
+ authority.worktreeReceipt !== request.worktreeReceipt ||
144
+ digest(authority.dependencies) !== digest(request.dependencies) || !text(request.inputRevision) ||
145
+ !Array.isArray(requiredChecks) || !requiredChecks.length ||
146
+ !Array.isArray(validation) || validation.length !== requiredChecks.length ||
147
+ new Set(validation.map(item => item?.check)).size !== requiredChecks.length ||
148
+ validation.some(item => !requiredChecks.includes(item?.check) || item?.passed !== true ||
149
+ item?.inputRevision !== request.inputRevision || !text(item?.receipt))) return { allowed: false };
150
+ return { allowed: true, taskId: request.taskId, revision: request.revision, inputRevision: request.inputRevision,
151
+ leaseId: request.leaseId, capabilityReceiptHash: request.capabilityReceiptHash, receipt: `commit:${digest(request).slice(0, 32)}` };
152
+ }),
153
+ authorizeBenchmarkCapture: request => transact({ type: 'benchmark-capture-authorize', request }, async history => {
154
+ const runs = request?.runs;
155
+ if (typeof verifyBenchmarkCapture !== 'function' || !text(request?.revision) ||
156
+ !text(request?.journalHash) || !text(request?.workerStopReceipt) ||
157
+ !/^[a-f0-9]{64}$/.test(request?.corpusHash ?? '') ||
158
+ !/^[a-f0-9]{64}$/.test(request?.reportSha256 ?? '') ||
159
+ !Array.isArray(runs) || runs.length < 12 || runs.length > 3000 ||
160
+ history.some(item => item.type === 'benchmark-capture-authorize' &&
161
+ item.corpusHash === request.corpusHash && item.reportSha256 === request.reportSha256)) return { allowed: false };
162
+ const cases = new Map();
163
+ const leases = new Set();
164
+ for (const run of runs) {
165
+ if (!text(run?.caseId) || ![1, 2, 3].includes(run?.run) ||
166
+ ![run.taskId, run.leaseId, run.worktreeReceipt, run.capabilityReceiptHash,
167
+ run.ledgerAuthorityReceipt, run.budgetReservation, run.approvalReceipt,
168
+ run.isolatedWorkspace].every(text) || leases.has(run.leaseId)) return { allowed: false };
169
+ leases.add(run.leaseId);
170
+ const repetitions = cases.get(run.caseId) ?? new Set();
171
+ if (repetitions.has(run.run)) return { allowed: false };
172
+ repetitions.add(run.run);
173
+ cases.set(run.caseId, repetitions);
174
+ const lease = history.find(item => item.type === 'lease' && item.leaseId === run.leaseId);
175
+ const authority = history.find(item => item.type === 'authorize' && item.leaseId === run.leaseId &&
176
+ item.receipt === run.ledgerAuthorityReceipt);
177
+ const native = history.find(item => item.type === 'native-authorize' && item.leaseId === run.leaseId &&
178
+ item.receipt === run.ledgerAuthorityReceipt);
179
+ if (!lease || !authority || !native || lease.taskId !== run.taskId ||
180
+ lease.revision !== request.revision || authority.taskId !== run.taskId ||
181
+ authority.revision !== request.revision || authority.worktreeReceipt !== run.worktreeReceipt ||
182
+ authority.capabilityReceiptHash !== run.capabilityReceiptHash ||
183
+ authority.budgetReservation !== run.budgetReservation ||
184
+ authority.approvalReceipt !== run.approvalReceipt ||
185
+ native.worktreeReceipt !== run.worktreeReceipt ||
186
+ native.capabilityReceiptHash !== run.capabilityReceiptHash ||
187
+ native.isolation !== 'git-worktree+local-os-sandbox' ||
188
+ history.some(item => item.type === 'cancel-reconciled' && item.leaseId === run.leaseId)) {
189
+ return { allowed: false };
190
+ }
191
+ }
192
+ if (cases.size < 4 || [...cases.values()].some(repetitions => repetitions.size !== 3)) return { allowed: false };
193
+ const proof = await verifyBenchmarkCapture(structuredClone(request));
194
+ if (proof?.allStopped !== true || proof.revision !== request.revision ||
195
+ proof.journalHash !== request.journalHash || proof.workerCount !== runs.length ||
196
+ proof.receipt !== request.workerStopReceipt ||
197
+ !Array.isArray(proof.cancelledLeases) || proof.cancelledLeases.length !== 0) return { allowed: false };
198
+ return { allowed: true, revision: request.revision, corpusHash: request.corpusHash,
199
+ reportSha256: request.reportSha256, workerStopReceipt: request.workerStopReceipt,
200
+ runs, receipt: `benchmark-capture:${digest(request).slice(0, 32)}` };
201
+ }),
202
+ inspectBenchmarkCapture: async request => {
203
+ if (!text(request?.receipt) || !text(request?.revision) ||
204
+ !/^[a-f0-9]{64}$/.test(request?.corpusHash ?? '') ||
205
+ !/^[a-f0-9]{64}$/.test(request?.reportSha256 ?? '') ||
206
+ !text(request?.workerStopReceipt)) return { valid: false };
207
+ const history = await events();
208
+ const record = history.find(item => item.type === 'benchmark-capture-authorize' &&
209
+ item.receipt === request.receipt && item.revision === request.revision &&
210
+ item.corpusHash === request.corpusHash && item.reportSha256 === request.reportSha256 &&
211
+ item.workerStopReceipt === request.workerStopReceipt);
212
+ return record ? { valid: true, receipt: record.receipt, runs: record.runs } : { valid: false };
213
+ },
214
+ recordBenchmarkSnapshot: request => transact({ type: 'benchmark-snapshot', request }, async history => {
215
+ if (!text(request?.captureReceipt) || !/^[a-f0-9]{64}$/.test(request?.corpusHash ?? '') ||
216
+ !/^[a-f0-9]{64}$/.test(request?.reportSha256 ?? '') ||
217
+ !/^[a-f0-9]{64}$/.test(request?.snapshotId ?? '')) return { allowed: false };
218
+ const capture = history.find(item => item.type === 'benchmark-capture-authorize' &&
219
+ item.receipt === request.captureReceipt && item.corpusHash === request.corpusHash &&
220
+ item.reportSha256 === request.reportSha256);
221
+ if (!capture || history.some(item => item.type === 'benchmark-snapshot' &&
222
+ item.captureReceipt === request.captureReceipt)) return { allowed: false };
223
+ return { allowed: true, ...request, receipt: `benchmark-snapshot:${digest(request).slice(0, 32)}` };
224
+ }),
225
+ reconcileCancelledLease: request => transact({ type: 'cancel-reconciled', request }, async history => {
226
+ if (typeof verifyCancellation !== 'function' || !text(request?.taskId) || !text(request?.revision) ||
227
+ !Number.isSafeInteger(request?.attempt) || !text(request?.leaseId) || !text(request?.journalHash) ||
228
+ !text(request?.workerStopReceipt) || !text(request?.abandonedWorktreeReceipt) ||
229
+ !text(request?.replacementWorktreeReceipt) ||
230
+ request.abandonedWorktreeReceipt === request.replacementWorktreeReceipt ||
231
+ !text(request?.inputRevision) || !text(request?.approvalReceipt) ||
232
+ !text(request?.capabilityReceiptHash) || !text(request?.budgetReservation)) return { allowed: false };
233
+ const lease = history.find(item => item.type === 'lease' && item.leaseId === request.leaseId);
234
+ const authority = history.find(item => item.type === 'authorize' && item.leaseId === request.leaseId);
235
+ const native = history.find(item => item.type === 'native-authorize' && item.leaseId === request.leaseId);
236
+ if (!lease || !authority || !native || lease.taskId !== request.taskId ||
237
+ lease.revision !== request.revision || lease.attempt !== request.attempt ||
238
+ authority.budgetReservation !== request.budgetReservation ||
239
+ authority.approvalReceipt !== request.approvalReceipt ||
240
+ authority.capabilityReceiptHash !== request.capabilityReceiptHash ||
241
+ authority.worktreeReceipt !== request.abandonedWorktreeReceipt ||
242
+ native.worktreeReceipt !== request.abandonedWorktreeReceipt ||
243
+ history.some(item => item.leaseId === request.leaseId &&
244
+ ['commit-authorize', 'cancel-reconciled'].includes(item.type))) return { allowed: false };
245
+ const proof = await verifyCancellation(structuredClone(request));
246
+ if (proof?.valid !== true || Object.entries(request).some(([key, value]) => proof[key] !== value)) return { allowed: false };
247
+ return { allowed: true, ...request, receipt: `cancellation:${digest(request).slice(0, 32)}` };
248
+ }),
249
+ inspectCancellation: async request => {
250
+ if (!text(request?.taskId) || !text(request?.revision) || !text(request?.leaseId) ||
251
+ !text(request?.receipt) || !text(request?.journalHash)) return { valid: false };
252
+ const history = await events();
253
+ const valid = history.some(item => item.type === 'cancel-reconciled' &&
254
+ item.taskId === request.taskId && item.revision === request.revision &&
255
+ item.leaseId === request.leaseId && item.receipt === request.receipt &&
256
+ item.journalHash === request.journalHash &&
257
+ Object.entries(request).every(([key, value]) => key === 'receipt' || item.request?.[key] === value));
258
+ return { valid, ...request };
259
+ },
260
+ readCancellation: async request => {
261
+ if (!text(request?.taskId) || !text(request?.revision) || !text(request?.leaseId) ||
262
+ !text(request?.journalHash)) return { found: false };
263
+ const history = await events();
264
+ const record = history.find(item => item.type === 'cancel-reconciled' &&
265
+ item.taskId === request.taskId && item.revision === request.revision &&
266
+ item.leaseId === request.leaseId && item.journalHash === request.journalHash);
267
+ return record ? { found: true, receipt: record.receipt, request: record.request } : { found: false };
268
+ },
269
+ // Recovery is read-only. It proves that journaled execution facts came from
270
+ // this ledger before a caller may consider any work reusable.
271
+ inspectRecovery: async request => {
272
+ if (!text(request?.revision) || !text(request?.journalHash) || !Array.isArray(request?.authorizations) ||
273
+ !Array.isArray(request?.commits)) return { allowed: false };
274
+ const history = await events();
275
+ const authorized = request.authorizations.every(proof => text(proof?.taskId) && text(proof?.leaseId) &&
276
+ text(proof?.receipt) && text(proof?.capabilityReceiptHash) && history.some(event =>
277
+ event.type === 'authorize' && event.taskId === proof.taskId && event.revision === request.revision &&
278
+ event.leaseId === proof.leaseId && event.receipt === proof.receipt &&
279
+ event.capabilityReceiptHash === proof.capabilityReceiptHash));
280
+ const committed = request.commits.every(proof => text(proof?.taskId) && text(proof?.leaseId) &&
281
+ text(proof?.receipt) && text(proof?.inputRevision) && text(proof?.capabilityReceiptHash) && history.some(event =>
282
+ event.type === 'commit-authorize' && event.taskId === proof.taskId && event.revision === request.revision &&
283
+ event.leaseId === proof.leaseId && event.receipt === proof.receipt &&
284
+ event.inputRevision === proof.inputRevision &&
285
+ event.capabilityReceiptHash === proof.capabilityReceiptHash));
286
+ return { allowed: authorized && committed, revision: request.revision, journalHash: request.journalHash };
287
+ },
288
+ });
289
+ }