@enterpriseai/cli 3.19.0 → 3.19.1

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 (362) hide show
  1. package/package.json +1 -1
  2. package/resources/gofer/.gofer-version +4 -357
  3. package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
  4. package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
  5. package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
  6. package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
  7. package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
  8. package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
  9. package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
  10. package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
  11. package/resources/gofer/claude-commands/eai-update.md +46 -0
  12. package/resources/gofer/claude-commands/eai.md +355 -0
  13. package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
  14. package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
  15. package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
  16. package/resources/gofer/commands/0_gofer_start.md +440 -99
  17. package/resources/gofer/commands/0a_problem_validation.md +187 -27
  18. package/resources/gofer/commands/10_gofer_cloud.md +183 -23
  19. package/resources/gofer/commands/1_gofer_research.md +239 -30
  20. package/resources/gofer/commands/2_gofer_specify.md +239 -35
  21. package/resources/gofer/commands/3_gofer_plan.md +259 -43
  22. package/resources/gofer/commands/4_gofer_tasks.md +401 -81
  23. package/resources/gofer/commands/5_gofer_implement.md +375 -84
  24. package/resources/gofer/commands/6_gofer_validate.md +284 -53
  25. package/resources/gofer/commands/7_gofer_save.md +187 -26
  26. package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
  27. package/resources/gofer/commands/8_gofer_branding.md +183 -23
  28. package/resources/gofer/commands/9_gofer_tests.md +212 -23
  29. package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
  30. package/resources/gofer/commands/gofer_check_workspace.md +123 -8
  31. package/resources/gofer/commands/gofer_constitution.md +183 -23
  32. package/resources/gofer/commands/gofer_diagnose.md +183 -23
  33. package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
  34. package/resources/gofer/commands/gofer_hydrate.md +183 -23
  35. package/resources/gofer/commands/gofer_personality.md +117 -6
  36. package/resources/gofer/commands/gofer_plan.md +117 -6
  37. package/resources/gofer/commands/gofer_side.md +117 -6
  38. package/resources/gofer/commands/gofer_spec_summary.md +183 -23
  39. package/resources/gofer/commands/gofer_tdd.md +183 -23
  40. package/resources/gofer/commands/gofer_vocabulary.md +185 -25
  41. package/resources/gofer/commands/gofer_zoom_out.md +183 -23
  42. package/resources/gofer/config/typesafe-learning-review.json +16 -0
  43. package/resources/gofer/config/typesafe-semantic-review.json +9 -0
  44. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
  45. package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
  46. package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
  47. package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
  48. package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
  49. package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
  50. package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
  51. package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
  52. package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
  53. package/resources/gofer/gemini/extension.json +4 -4
  54. package/resources/gofer/github-agents/eai.agent.md +83 -0
  55. package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
  56. package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
  57. package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
  58. package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
  59. package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
  60. package/resources/gofer/github-skills/eai/SKILL.md +365 -0
  61. package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
  62. package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
  63. package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
  64. package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
  65. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
  66. package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
  67. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
  68. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
  69. package/resources/gofer/memory/constitution.md +9 -7
  70. package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
  71. package/resources/gofer/memory/lessons.md +0 -31
  72. package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
  73. package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
  74. package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
  75. package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
  76. package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
  77. package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
  78. package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
  79. package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
  80. package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
  81. package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
  82. package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
  83. package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
  84. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
  85. package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
  86. package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
  87. package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
  88. package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
  89. package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
  90. package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
  91. package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
  92. package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
  93. package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
  94. package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
  95. package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
  96. package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
  97. package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
  98. package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
  99. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
  100. package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
  101. package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
  102. package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
  103. package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
  104. package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
  105. package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
  106. package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
  107. package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
  108. package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
  109. package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
  110. package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
  111. package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
  112. package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
  113. package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
  114. package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
  115. package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
  116. package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
  117. package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
  118. package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
  119. package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
  120. package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
  121. package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
  122. package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
  123. package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
  124. package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
  125. package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
  126. package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
  127. package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
  128. package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
  129. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
  130. package/resources/gofer/references/agent-catalog.json +126 -0
  131. package/resources/gofer/references/blocker-mediation.md +156 -0
  132. package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
  133. package/resources/gofer/references/delivery-lineage.md +48 -0
  134. package/resources/gofer/references/mvp-capability-validation.md +102 -0
  135. package/resources/gofer/references/platform/README.md +1 -1
  136. package/resources/gofer/references/platform/eai-app-template.md +15 -13
  137. package/resources/gofer/references/platform/eai-auth-access.md +104 -0
  138. package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
  139. package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
  140. package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
  141. package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
  142. package/resources/gofer/references/platform/eai.md +44 -8
  143. package/resources/gofer/references/platform/vertical-template.md +10 -9
  144. package/resources/gofer/references/priority-outcome-protection.md +152 -0
  145. package/resources/gofer/references/verified-agent-execution.md +179 -0
  146. package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
  147. package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
  148. package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
  149. package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
  150. package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
  151. package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
  152. package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
  153. package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
  154. package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
  155. package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
  156. package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
  157. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
  158. package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
  159. package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
  160. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
  161. package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
  162. package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
  163. package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
  164. package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
  165. package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
  166. package/resources/gofer/specify-commands/gofer_personality.md +117 -6
  167. package/resources/gofer/specify-commands/gofer_plan.md +117 -6
  168. package/resources/gofer/specify-commands/gofer_side.md +117 -6
  169. package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
  170. package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
  171. package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
  172. package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
  173. package/resources/gofer/specify-config/object-type-routing.json +24 -0
  174. package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
  175. package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
  176. package/resources/gofer/system-skills/eai/SKILL.md +365 -0
  177. package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
  178. package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
  179. package/resources/gofer/templates/build-map-template.md +64 -0
  180. package/resources/gofer/templates/business-scenarios-template.json +14 -0
  181. package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
  182. package/resources/gofer/templates/context-bundle-template.md +4 -3
  183. package/resources/gofer/templates/contract-pack-template.md +8 -8
  184. package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
  185. package/resources/gofer/templates/delivery-lineage-template.json +8 -0
  186. package/resources/gofer/templates/eai-preflight-template.md +109 -68
  187. package/resources/gofer/templates/goal-ledger-template.json +1 -1
  188. package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
  189. package/resources/gofer/templates/loop-contract-template.json +3 -1
  190. package/resources/gofer/templates/plan-template.md +8 -7
  191. package/resources/gofer/templates/priority-plan-template.json +29 -0
  192. package/resources/gofer/templates/proposal-review-template.md +6 -3
  193. package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
  194. package/resources/gofer/templates/research-template.md +7 -6
  195. package/resources/gofer/templates/spec-summary-template.md +1 -1
  196. package/resources/gofer/templates/spec-template.md +45 -6
  197. package/resources/gofer/templates/tasks-template.md +12 -3
  198. package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
  199. package/resources/gofer/templates/ui-review-log-template.md +21 -3
  200. package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
  201. package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
  202. package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
  203. package/resources/linked-sources.json +2 -2
  204. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
  205. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
  206. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
  207. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
  208. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
  209. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
  210. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
  211. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
  212. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
  213. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
  214. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
  215. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
  216. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
  217. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  218. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
  219. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
  220. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
  221. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
  222. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
  223. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
  224. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
  225. package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
  226. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
  227. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
  228. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
  229. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
  230. package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
  231. package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
  232. package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
  233. package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
  234. package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
  235. package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
  236. package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
  237. package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
  238. package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
  239. package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
  240. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
  241. package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
  242. package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
  243. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
  244. package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
  245. package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
  246. package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
  247. package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
  248. package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
  249. package/resources/gofer/claude-commands/gofer_personality.md +0 -39
  250. package/resources/gofer/claude-commands/gofer_plan.md +0 -35
  251. package/resources/gofer/claude-commands/gofer_side.md +0 -40
  252. package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
  253. package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
  254. package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
  255. package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
  256. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
  257. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
  258. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
  259. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
  260. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
  261. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
  262. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
  263. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
  264. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
  265. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
  266. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
  267. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
  268. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
  269. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
  270. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
  271. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
  272. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
  273. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
  274. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
  275. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
  276. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
  277. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
  278. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
  279. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
  280. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
  281. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
  282. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
  283. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
  284. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
  285. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
  286. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
  287. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
  288. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
  289. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
  290. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
  291. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
  292. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
  293. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
  294. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
  295. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
  296. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
  297. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
  298. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
  299. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
  300. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
  301. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
  302. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
  303. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
  304. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
  305. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
  306. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
  307. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
  308. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
  309. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
  310. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
  311. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
  312. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
  313. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
  314. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
  315. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
  316. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
  317. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
  318. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
  319. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
  320. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
  321. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
  322. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
  323. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
  324. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
  325. package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
  326. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
  327. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
  328. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
  329. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
  330. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
  331. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
  332. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
  333. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
  334. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
  335. package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
  336. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
  337. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
  338. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
  339. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
  340. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
  341. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
  342. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
  343. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
  344. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
  345. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
  346. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
  347. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
  348. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
  349. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  350. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
  351. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
  352. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
  353. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
  354. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
  355. package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
  356. package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
  357. package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
  358. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
  359. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
  360. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
  361. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
  362. 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
+ }