@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,484 @@
1
+ /**
2
+ * Host-neutral execution kernel. Adapters are trusted application code, never
3
+ * commands or capability declarations received from a worker or a document.
4
+ */
5
+ import { constants } from 'node:fs';
6
+ import { open, readFile, realpath, lstat, rename, writeFile } from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { createHash } from 'node:crypto';
9
+ import { reviewPriority } from './gofer-priority-check.mjs';
10
+ import { inspectBlockers } from './gofer-blocker-control.mjs';
11
+ import { capabilityReceiptHash, verifyCapabilityReceipt } from './gofer-host-capability.mjs';
12
+ import { selectCapabilityRoute } from './gofer-live-routing.mjs';
13
+ import { acquireLedgerLock } from './gofer-runtime-ledger.mjs';
14
+
15
+ const contractFiles = ['spec.md', 'plan.md', 'decisions.md', 'priority-plan.json', 'loop-contract.json'];
16
+ const MAX_CONTRACT_FILE_BYTES = 1024 * 1024;
17
+ const positive = value => Number.isSafeInteger(value) && value > 0;
18
+ const text = value => typeof value === 'string' && value.trim().length > 0;
19
+ function releaseResumeLock(lock) {
20
+ try { lock.exec('ROLLBACK'); } finally { lock.close(); }
21
+ }
22
+
23
+ export async function executionRevision(featureDir) {
24
+ return (await snapshot(featureDir)).revision;
25
+ }
26
+
27
+ async function snapshot(featureDir) {
28
+ const hash = createHash('sha256');
29
+ const files = {};
30
+ for (const file of contractFiles) {
31
+ files[file] = await readContractFile(featureDir, file);
32
+ hash.update(file).update(files[file]);
33
+ }
34
+ return { files, revision: hash.digest('hex') };
35
+ }
36
+
37
+ async function readContractFile(featureDir, name) {
38
+ const root = await realpath(featureDir);
39
+ const target = path.join(root, name);
40
+ // Resolve before opening. A different canonical path proves a supplied link.
41
+ const canonical = await realpath(target);
42
+ if (canonical !== target) throw new Error('UNSAFE_CONTRACT_FILE');
43
+ // Do not follow a link introduced after canonical-path validation on POSIX.
44
+ const flags = constants.O_RDONLY | (process.platform === 'win32' ? 0 : constants.O_NOFOLLOW);
45
+ const file = await open(canonical, flags);
46
+ try {
47
+ const stat = await file.stat();
48
+ if (!stat.isFile() || stat.size > MAX_CONTRACT_FILE_BYTES) throw new Error('UNSAFE_CONTRACT_FILE');
49
+ return await file.readFile({ encoding: 'utf8' });
50
+ } finally {
51
+ await file.close();
52
+ }
53
+ }
54
+
55
+ function freeze(value) {
56
+ if (value && typeof value === 'object') { Object.values(value).forEach(freeze); Object.freeze(value); }
57
+ return value;
58
+ }
59
+
60
+ async function canonicalScopes(workspace, scopes) {
61
+ const root = await realpath(workspace);
62
+ return Promise.all(scopes.map(async scope => {
63
+ const segments = scope.replace(/\/$/, '').split('/');
64
+ let current = root;
65
+ for (const segment of segments) {
66
+ current = path.join(current, segment);
67
+ try { if ((await lstat(current)).isSymbolicLink()) throw new Error('SYMLINK_SCOPE_UNQUALIFIED'); }
68
+ catch (error) { if (error.code !== 'ENOENT') throw error; }
69
+ }
70
+ return path.relative(root, current).split(path.sep).join('/');
71
+ }));
72
+ }
73
+
74
+ export function validateWorkGraph(plan, checks) {
75
+ if (![1, 2].includes(plan?.schemaVersion) || !text(plan.revision) || !plan.tasks ||
76
+ !Array.isArray(plan.criticalPath) || !plan.criticalPath.length) throw new Error('INVALID_GRAPH');
77
+ const ids = Object.keys(plan.tasks);
78
+ if (!ids.length || ids.length > 1000 || new Set(plan.criticalPath).size !== plan.criticalPath.length ||
79
+ plan.criticalPath.some(id => !ids.includes(id))) throw new Error('INVALID_GRAPH');
80
+ let edgeCount = 0;
81
+ let scopeCount = 0;
82
+ for (const id of ids) {
83
+ const task = plan.tasks[id];
84
+ if (!/^T\d+$/.test(id) || !task || !Array.isArray(task.dependsOn) ||
85
+ task.dependsOn.length > 256 || task.dependsOn.some(dep => !ids.includes(dep)) || !Array.isArray(task.allowedEditScope) ||
86
+ task.allowedEditScope.length > 256 ||
87
+ task.allowedEditScope.some(scope => !text(scope) || /(^\/|\/\/|\\|:|\0|[*?\[\]]|(^|\/)\.\.?($|\/))/.test(scope)) ||
88
+ !Array.isArray(checks[id]) || !checks[id].length || checks[id].length > 256 || checks[id].some(c => !text(c) || c.length > 1024) ||
89
+ new Set(checks[id]).size !== checks[id].length) throw new Error('INVALID_WORK_ORDER');
90
+ edgeCount += task.dependsOn.length;
91
+ scopeCount += task.allowedEditScope.length;
92
+ if (edgeCount > 10000 || scopeCount > 10000) throw new Error('INVALID_WORK_ORDER');
93
+ }
94
+ const states = new Map(ids.map(id => [id, 0]));
95
+ const visit = id => {
96
+ const state = states.get(id);
97
+ if (state === 1) throw new Error('CYCLIC_GRAPH');
98
+ if (state === 2) return;
99
+ states.set(id, 1);
100
+ for (const dependency of plan.tasks[id].dependsOn) visit(dependency);
101
+ states.set(id, 2);
102
+ };
103
+ ids.forEach(visit);
104
+ return ids;
105
+ }
106
+
107
+ function overlaps(a, b) {
108
+ // Conservative on case-insensitive hosts and on parent/child directory edits.
109
+ return a.some(left => b.some(right => {
110
+ const x = left.toLowerCase().replace(/\/$/, '');
111
+ const y = right.toLowerCase().replace(/\/$/, '');
112
+ return x === y || x.startsWith(`${y}/`) || y.startsWith(`${x}/`);
113
+ }));
114
+ }
115
+
116
+ /**
117
+ * Run a trusted adapter against the existing priority plan. Each required check
118
+ * runs separately from worker output. This library does not provide a sandbox.
119
+ * An existing journal is a reconciliation gate, not permission to replay work.
120
+ */
121
+ export async function runVerifiedGraph({ featureDir, workspaceRoot, checks, adapter,
122
+ ledger, capabilityReceipt, capabilityPublicKey, requiredCapabilities, benchmarkEvidence, verifyBenchmark,
123
+ advisoryConstraints, approvalReceipt, maxCalls, maxConcurrent = 1, deadlineMs, signal, recovery,
124
+ adapterDrainMs = 5000 }) {
125
+ // Copy before any await: a caller or worker must not remove required checks.
126
+ checks = freeze(structuredClone(checks));
127
+ const journalName = 'verified-execution.jsonl';
128
+ if (!positive(maxCalls) || !positive(maxConcurrent) || maxConcurrent > 8 ||
129
+ !positive(adapterDrainMs) || adapterDrainMs > 10000 ||
130
+ !Number.isFinite(deadlineMs) || deadlineMs <= Date.now()) throw new Error('FINITE_LIMITS_REQUIRED');
131
+ if (!text(approvalReceipt)) throw new Error('APPROVAL_RECEIPT_REQUIRED');
132
+ for (const method of ['execute', 'check', 'inputRevision', 'reserve', 'lease', 'verified']) {
133
+ if (typeof adapter?.[method] !== 'function') throw new Error(`TRUSTED_ADAPTER_REQUIRED:${method}`);
134
+ }
135
+ if (capabilityReceipt?.isolationClass !== 'git-worktree+local-os-sandbox' ||
136
+ typeof ledger?.authorize !== 'function' || typeof ledger?.authorizeCommit !== 'function' || !verifyCapabilityReceipt(capabilityReceipt, {
137
+ publicKey: capabilityPublicKey, requiredCapabilities,
138
+ })) throw new Error('LEDGER_CAPABILITY_AUTHORITY_REQUIRED');
139
+ const route = await selectCapabilityRoute({ receipt: capabilityReceipt, publicKey: capabilityPublicKey,
140
+ host: capabilityReceipt.host, requiredCapabilities, benchmarkEvidence, verifyBenchmark, advisoryConstraints });
141
+ const root = await realpath(featureDir);
142
+ const captured = await snapshot(root);
143
+ const plan = freeze(JSON.parse(captured.files['priority-plan.json']));
144
+ const loop = freeze(JSON.parse(captured.files['loop-contract.json']));
145
+ if (!positive(loop.maxIterations)) throw new Error('FINITE_ATTEMPTS_REQUIRED');
146
+ if (loop.budget?.maxModelSpendUsd != null) throw new Error('SPEND_RESERVATION_NOT_IMPLEMENTED');
147
+ if (loop.budget?.maxWallClockMinutes != null) {
148
+ if (!(loop.budget.maxWallClockMinutes > 0)) throw new Error('INVALID_DEADLINE');
149
+ deadlineMs = Math.min(deadlineMs, Date.now() + loop.budget.maxWallClockMinutes * 60000);
150
+ }
151
+ const ids = validateWorkGraph(plan, checks);
152
+ const initial = await reviewPriority(root);
153
+ if (initial.status !== 'pass') throw new Error(`PRIORITY_BLOCKED:${initial.findings.join(',')}`);
154
+ const revision = captured.revision;
155
+ const receiptHash = capabilityReceiptHash(capabilityReceipt);
156
+ if (await executionRevision(root) !== revision) throw new Error('STALE_DIRECTION');
157
+ const tasksText = await readFile(path.join(root, 'tasks.md'), 'utf8');
158
+ const previouslyComplete = new Set([...tasksText.matchAll(/^\s*-\s+\[[xX]\]\s+(?:\*\*)?(T\d+)\b/gm)].map(m => m[1]));
159
+ const scopes = {};
160
+ for (const id of ids) scopes[id] = await canonicalScopes(workspaceRoot, plan.tasks[id].allowedEditScope);
161
+ let resumeReport;
162
+ let resumeLock;
163
+ const lockPath = path.join(root, 'verified-execution.resume.lock');
164
+ if (recovery) {
165
+ // The transaction excludes other controllers and the operating system
166
+ // releases it if this controller exits before reconciliation finishes.
167
+ resumeLock = await acquireLedgerLock(lockPath).catch(() => { throw new Error('RESUME_LOCKED'); });
168
+ try {
169
+ const { inspectExecutionRecovery } = await import('./gofer-execution-recovery.mjs');
170
+ resumeReport = await inspectExecutionRecovery({ ...recovery, featureDir: root });
171
+ const run = resumeReport.run;
172
+ if (resumeReport.status !== 'reconciled' || !resumeReport.resumeAllowed ||
173
+ resumeReport.uncertainTasks.length || !run ||
174
+ run.revision !== revision || run.maxCalls !== maxCalls || run.maxConcurrent !== maxConcurrent ||
175
+ run.maxIterations !== loop.maxIterations || deadlineMs !== run.deadlineMs ||
176
+ run.capabilityReceiptHash !== receiptHash || run.selectedModel !== route.model.id ||
177
+ run.benchmarkReceipt !== route.benchmarkReceipt || run.approvalReceipt !== approvalReceipt ||
178
+ JSON.stringify(run.requiredChecks) !== JSON.stringify(checks) ||
179
+ (resumeReport.restartableTasks.length > 0 &&
180
+ (resumeReport.restartableTasks.length !== 1 ||
181
+ resumeReport.replacementWorktreeReceipt !== adapter.worktreeReceipt)) ||
182
+ previouslyComplete.size !== resumeReport.reusableTasks.length ||
183
+ [...previouslyComplete].some(id => !resumeReport.reusableTasks.includes(id)) ||
184
+ resumeReport.reusableTasks.length === ids.length) throw new Error('RESUME_RECONCILIATION_REQUIRED');
185
+ for (const taskId of resumeReport.reusableTasks) {
186
+ const input = await adapter.inputRevision({ taskId, revision,
187
+ allowedEditScope: plan.tasks[taskId].allowedEditScope, requiredChecks: checks[taskId] });
188
+ if (input !== resumeReport.verifiedInputs[taskId]) throw new Error('STALE_PREREQUISITE_EVIDENCE');
189
+ }
190
+ } catch (error) {
191
+ releaseResumeLock(resumeLock);
192
+ throw error;
193
+ }
194
+ } else if (previouslyComplete.size) throw new Error('BASELINE_EVIDENCE_RECONCILIATION_REQUIRED');
195
+ const states = Object.fromEntries(ids.map(id => [id, resumeReport?.reusableTasks.includes(id) ? 'verified' : 'pending']));
196
+ const attempts = Object.fromEntries(ids.map(id => [id, resumeReport?.attemptsConsumed[id] || 0]));
197
+ const verifiedInputs = new Map(Object.entries(resumeReport?.verifiedInputs || {}));
198
+ const controller = new AbortController();
199
+ const cancel = () => controller.abort(new Error('CANCELLED'));
200
+ if (signal?.aborted) cancel();
201
+ signal?.addEventListener('abort', cancel, { once: true });
202
+ const timer = setTimeout(() => controller.abort(new Error('DEADLINE')), Math.min(deadlineMs - Date.now(), 2147483647));
203
+ const file = await open(path.join(root, journalName), recovery ? constants.O_RDWR | constants.O_APPEND | constants.O_NOFOLLOW : 'wx', 0o600).catch(async error => {
204
+ clearTimeout(timer); signal?.removeEventListener('abort', cancel);
205
+ if (resumeLock) releaseResumeLock(resumeLock);
206
+ throw new Error(error.code === 'EEXIST' ? 'RECONCILIATION_REQUIRED' : 'JOURNAL_UNAVAILABLE');
207
+ });
208
+ let calls = resumeReport?.callsConsumed || 0;
209
+ let write = Promise.resolve();
210
+ let checkpointWrite = Promise.resolve();
211
+ let checkpointSequence = 0;
212
+ const pendingAdapterCalls = new Set();
213
+ let drainAttempted = false;
214
+ async function drainAdapterCalls() {
215
+ drainAttempted = true;
216
+ if (!pendingAdapterCalls.size) return true;
217
+ let drainTimer;
218
+ const settled = await Promise.race([
219
+ Promise.allSettled([...pendingAdapterCalls]).then(() => true),
220
+ new Promise(resolve => { drainTimer = setTimeout(() => resolve(false), adapterDrainMs); }),
221
+ ]);
222
+ clearTimeout(drainTimer);
223
+ return settled;
224
+ }
225
+ const record = event => {
226
+ write = write.then(async () => { await file.writeFile(`${JSON.stringify({ schemaVersion: 1, revision, time: new Date().toISOString(), ...event })}\n`); await file.sync(); })
227
+ .catch(() => { controller.abort(new Error('JOURNAL_FAILURE')); throw new Error('JOURNAL_FAILURE'); });
228
+ return write;
229
+ };
230
+ const abortCheck = () => {
231
+ if (Date.now() >= deadlineMs && !controller.signal.aborted) controller.abort(new Error('DEADLINE'));
232
+ if (controller.signal.aborted) throw controller.signal.reason;
233
+ };
234
+ // The checkpoint contains only current graph state plus the latest delta.
235
+ // It avoids replaying the entire append-only ledger during operator recovery.
236
+ async function checkpoint(event, taskId = null) {
237
+ // Serialize snapshots so concurrent tasks cannot race the replacement file.
238
+ checkpointWrite = checkpointWrite.then(async () => {
239
+ const payload = JSON.stringify({ schemaVersion: 1, revision, updatedAt: new Date().toISOString(),
240
+ delta: { event, taskId }, states, attempts, calls,
241
+ verifiedInputs: Object.fromEntries(verifiedInputs) });
242
+ const target = path.join(root, 'verified-execution.checkpoint.json');
243
+ const temporary = `${target}.${process.pid}.${++checkpointSequence}.tmp`;
244
+ try {
245
+ await writeFile(temporary, payload, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
246
+ await rename(temporary, target);
247
+ } catch {
248
+ controller.abort(new Error('CHECKPOINT_UNAVAILABLE'));
249
+ throw controller.signal.reason;
250
+ }
251
+ });
252
+ return checkpointWrite;
253
+ }
254
+ async function current() {
255
+ abortCheck();
256
+ if (await executionRevision(root) !== revision) {
257
+ controller.abort(new Error('STALE_DIRECTION'));
258
+ throw controller.signal.reason;
259
+ }
260
+ abortCheck();
261
+ }
262
+ async function invoke(method, request) {
263
+ await current();
264
+ const blockers = await inspectBlockers(root, { taskId: request.taskId });
265
+ if (blockers.blockers.some(b => b.state !== 'ready')) throw new Error('RECORDED_BLOCKER_WAIT');
266
+ if (calls >= maxCalls) throw new Error('CALL_LIMIT');
267
+ // Reserve globally before yielding, so parallel calls cannot overdraw.
268
+ calls++;
269
+ await record({ event: 'call_reserved', task: request.taskId, method, call: calls });
270
+ let listener;
271
+ try {
272
+ await current();
273
+ const operation = Promise.resolve().then(() => { abortCheck(); return adapter[method]({ ...request, signal: controller.signal }); });
274
+ const settled = operation.then(() => {}, () => {}).finally(() => pendingAdapterCalls.delete(settled));
275
+ pendingAdapterCalls.add(settled);
276
+ return await Promise.race([
277
+ operation,
278
+ new Promise((_, reject) => {
279
+ listener = () => reject(controller.signal.reason);
280
+ controller.signal.addEventListener('abort', listener, { once: true });
281
+ if (controller.signal.aborted) listener();
282
+ }),
283
+ ]);
284
+ } finally {
285
+ if (listener) controller.signal.removeEventListener('abort', listener);
286
+ }
287
+ }
288
+ async function runTask(taskId) {
289
+ const task = plan.tasks[taskId];
290
+ const dependencies = task.dependsOn.map(dependency => ({ taskId: dependency,
291
+ inputRevision: verifiedInputs.get(dependency) ?? null }));
292
+ if (dependencies.some(dependency => !text(dependency.inputRevision))) throw new Error('DEPENDENCY_INPUT_REQUIRED');
293
+ const request = { taskId, revision, dependencies, allowedEditScope: task.allowedEditScope, requiredChecks: checks[taskId], approvalReceipt,
294
+ ...(text(adapter.worktreeReceipt) ? { worktreeReceipt: adapter.worktreeReceipt } : {}),
295
+ capabilityReceiptHash: receiptHash, selectedModel: route.model.id, benchmarkReceipt: route.benchmarkReceipt };
296
+ let previousChecks = [];
297
+ try {
298
+ while (attempts[taskId] < loop.maxIterations) {
299
+ await current();
300
+ const blockers = await inspectBlockers(root, { taskId });
301
+ if (blockers.blockers.some(b => b.state !== 'ready')) throw new Error('RECORDED_BLOCKER_WAIT');
302
+ const priority = await reviewPriority(root, { task: taskId });
303
+ if (priority.status !== 'pass') throw new Error('PRIORITY_BLOCKED');
304
+ await canonicalScopes(workspaceRoot, task.allowedEditScope);
305
+ const attempt = ++attempts[taskId];
306
+ await record({ event: 'attempt_reserved', task: taskId, attempt });
307
+ const reservation = await invoke('reserve', { ...request, attempt });
308
+ if (reservation?.allowed !== true || !text(reservation.budgetReservation)) throw new Error('BLOCKER_OR_BUDGET_DENIED');
309
+ const lease = await invoke('lease', { ...request, attempt });
310
+ const leaseExpiry = Date.parse(lease?.expiresAt);
311
+ if (!text(lease?.leaseId) || !Number.isFinite(leaseExpiry) || leaseExpiry <= Date.now()) {
312
+ throw new Error('TASK_LEASE_REQUIRED');
313
+ }
314
+ await record({ event: 'lease_granted', task: taskId, attempt, leaseId: lease.leaseId, expiresAt: lease.expiresAt });
315
+ const leasedRequest = { ...request, attempt, budgetReservation: reservation.budgetReservation,
316
+ leaseId: lease.leaseId, leaseExpiresAt: lease.expiresAt };
317
+ const authority = await ledger.authorize(leasedRequest);
318
+ if (authority?.allowed !== true || authority.taskId !== taskId || authority.revision !== revision ||
319
+ authority.attempt !== attempt || authority.capabilityReceiptHash !== receiptHash ||
320
+ authority.budgetReservation !== reservation.budgetReservation || authority.leaseId !== lease.leaseId ||
321
+ authority.worktreeReceipt !== request.worktreeReceipt ||
322
+ authority.leaseExpiresAt !== lease.expiresAt || authority.allowedEditScope?.join('\0') !== request.allowedEditScope.join('\0') ||
323
+ authority.requiredChecks?.join('\0') !== request.requiredChecks.join('\0') || authority.approvalReceipt !== approvalReceipt ||
324
+ !text(authority.receipt)) throw new Error('LEDGER_AUTHORITY_REQUIRED');
325
+ await record({ event: 'ledger_authorized', task: taskId, attempt, leaseId: lease.leaseId,
326
+ budgetReservation: reservation.budgetReservation, receipt: authority.receipt, capabilityReceiptHash: receiptHash,
327
+ worktreeReceipt: request.worktreeReceipt ?? null });
328
+ states[taskId] = 'running';
329
+ await checkpoint('running', taskId);
330
+ // Repair sees measured failures, never just "try again" or prior reasoning.
331
+ const result = await invoke('execute', { ...leasedRequest, ledgerAuthorityReceipt: authority.receipt,
332
+ previousChecks: freeze(structuredClone(previousChecks)) });
333
+ await current();
334
+ if (!result || !Array.isArray(result.changedFiles) || result.changedFiles.some(f => !text(f))) throw new Error('INVALID_WORKER_RESULT');
335
+ const scope = await reviewPriority(root, { task: taskId, changedFiles: result.changedFiles, workspaceRoot });
336
+ if (scope.status !== 'pass') throw new Error('SCOPE_VIOLATION');
337
+ const inputRevision = await invoke('inputRevision', request);
338
+ if (!text(inputRevision)) throw new Error('INPUT_REVISION_REQUIRED');
339
+ states[taskId] = 'awaiting-check';
340
+ let passed = true;
341
+ previousChecks = [];
342
+ for (const check of checks[taskId]) {
343
+ let evidence;
344
+ try {
345
+ evidence = await invoke('check', { ...leasedRequest, check, inputRevision });
346
+ } catch {
347
+ // A failed check can leave local or remote work in an unknown state.
348
+ controller.abort(new Error('CHECK_RECONCILIATION_REQUIRED'));
349
+ throw controller.signal.reason;
350
+ }
351
+ await current();
352
+ const valid = evidence?.taskId === taskId && evidence.revision === revision &&
353
+ evidence.inputRevision === inputRevision && evidence.check === check &&
354
+ evidence.exitCode === 0 && evidence.executed === true && text(evidence.receipt);
355
+ await record({ event: 'check', task: taskId, attempt, check, inputRevision,
356
+ passed: valid, receipt: text(evidence?.receipt) ? evidence.receipt : null });
357
+ if (evidence?.cleanupVerified === false) {
358
+ controller.abort(new Error('CLEANUP_RECONCILIATION_REQUIRED'));
359
+ throw controller.signal.reason;
360
+ }
361
+ previousChecks.push({ check, passed: valid, inputRevision,
362
+ receipt: text(evidence?.receipt) ? evidence.receipt : null });
363
+ passed &&= valid;
364
+ }
365
+ if (await invoke('inputRevision', request) !== inputRevision) throw new Error('STALE_INPUT');
366
+ if (passed) {
367
+ await current();
368
+ const assertCurrent = async () => {
369
+ await current();
370
+ const blockers = await inspectBlockers(root, { taskId });
371
+ if (blockers.blockers.some(b => b.state !== 'ready')) throw new Error('RECORDED_BLOCKER_WAIT');
372
+ if (await invoke('inputRevision', request) !== inputRevision) throw new Error('STALE_INPUT');
373
+ await current();
374
+ };
375
+ await assertCurrent();
376
+ const commitAuthority = await ledger.authorizeCommit({ ...leasedRequest, inputRevision,
377
+ validation: freeze(structuredClone(previousChecks)) });
378
+ if (commitAuthority?.allowed !== true || commitAuthority.taskId !== taskId ||
379
+ commitAuthority.revision !== revision || commitAuthority.inputRevision !== inputRevision ||
380
+ commitAuthority.leaseId !== lease.leaseId || commitAuthority.capabilityReceiptHash !== receiptHash ||
381
+ !text(commitAuthority.receipt)) throw new Error('LEDGER_COMMIT_AUTHORITY_REQUIRED');
382
+ await record({ event: 'commit_authorized', task: taskId, attempt, leaseId: lease.leaseId,
383
+ inputRevision, receipt: commitAuthority.receipt, capabilityReceiptHash: receiptHash });
384
+ // The trusted adapter must compare-and-set, not unconditionally tick tasks.
385
+ const commit = await invoke('verified', { ...leasedRequest, inputRevision,
386
+ commitAuthorityReceipt: commitAuthority.receipt, assertCurrent });
387
+ if (commit?.committed !== true || commit.taskId !== taskId || commit.revision !== revision ||
388
+ commit.inputRevision !== inputRevision || !text(commit.receipt)) throw new Error('COMMIT_RECONCILIATION_REQUIRED');
389
+ await assertCurrent();
390
+ await current();
391
+ states[taskId] = 'verified';
392
+ verifiedInputs.set(taskId, inputRevision);
393
+ await record({ event: 'verified', task: taskId, inputRevision, receipt: commit.receipt });
394
+ await checkpoint('verified', taskId);
395
+ return;
396
+ }
397
+ await record({ event: 'repair_required', task: taskId, attempt });
398
+ }
399
+ throw new Error('ATTEMPT_LIMIT');
400
+ } catch (error) {
401
+ const reason = controller.signal.aborted ? controller.signal.reason.message : error.message;
402
+ states[taskId] = reason.startsWith('STALE') ? 'stale' : reason === 'CLEANUP_RECONCILIATION_REQUIRED' ? 'blocked' : controller.signal.aborted ? 'cancelled' : 'blocked';
403
+ await record({ event: states[taskId], task: taskId, reason, reconciliationRequired: true }).catch(() => {});
404
+ await checkpoint(states[taskId], taskId).catch(() => {});
405
+ }
406
+ }
407
+ try {
408
+ if (resumeReport) {
409
+ const contents = await file.readFile('utf8');
410
+ if (createHash('sha256').update(contents).digest('hex') !== resumeReport.journalHash) throw new Error('RECOVERY_INPUT_CHANGED');
411
+ await record({ event: 'resumed', previousJournalHash: resumeReport.journalHash,
412
+ callsConsumed: calls, attemptsConsumed: resumeReport.attemptsConsumed });
413
+ await checkpoint('resumed');
414
+ } else {
415
+ await record({ event: 'started', maxCalls, maxConcurrent, maxIterations: loop.maxIterations, capabilityReceiptHash: receiptHash,
416
+ selectedModel: route.model.id, benchmarkReceipt: route.benchmarkReceipt, approvalReceipt,
417
+ requiredChecks: checks, deadlineMs, baselineTasks: [...previouslyComplete],
418
+ worktreeReceipt: adapter.worktreeReceipt ?? null });
419
+ await checkpoint('started');
420
+ }
421
+ const active = new Map();
422
+ while (!controller.signal.aborted) {
423
+ let scheduled = false;
424
+ for (const id of ids) {
425
+ if (active.size === maxConcurrent || states[id] !== 'pending') continue;
426
+ if (!plan.tasks[id].dependsOn.every(dep => states[dep] === 'verified')) continue;
427
+ if ([...active.keys()].some(other => overlaps(scopes[id], scopes[other]))) continue;
428
+ for (const dependency of plan.tasks[id].dependsOn) {
429
+ const expected = verifiedInputs.get(dependency);
430
+ const currentInput = await invoke('inputRevision', {
431
+ taskId: dependency,
432
+ revision,
433
+ allowedEditScope: plan.tasks[dependency].allowedEditScope,
434
+ requiredChecks: checks[dependency],
435
+ });
436
+ if (currentInput !== expected) {
437
+ controller.abort(new Error('STALE_PREREQUISITE_EVIDENCE'));
438
+ break;
439
+ }
440
+ }
441
+ if (controller.signal.aborted) break;
442
+ if ((await reviewPriority(root, { task: id })).status !== 'pass') continue;
443
+ active.set(id, runTask(id).then(() => id));
444
+ scheduled = true;
445
+ }
446
+ if (active.size) {
447
+ const completed = await Promise.race(active.values());
448
+ active.delete(completed);
449
+ continue;
450
+ }
451
+ if (!scheduled) break;
452
+ }
453
+ // Cancellation stops new scheduling, but active work may still be draining
454
+ // its journal and checkpoint operations. Do not close the runtime ledger
455
+ // or return while a sibling can still write into the feature directory.
456
+ if (active.size) await Promise.allSettled([...active.values()]);
457
+ // The abort race stops scheduling promptly, but a trusted adapter may
458
+ // still be delivering cancellation. Give it a bounded drain window and
459
+ // report when it has not settled; recovery must then inspect the worker.
460
+ const adapterCallsSettled = await drainAdapterCalls();
461
+ const verified = ids.filter(id => states[id] === 'verified');
462
+ const status = !controller.signal.aborted && ids.every(id => states[id] === 'verified') ? 'verified' : 'incomplete';
463
+ // Task verification is not the feature/release outcome gate.
464
+ const result = { status, states, verified, calls, attempts, revision, cost: null, adapterCallsSettled,
465
+ nativeQualification: 'not-established', featureComplete: false };
466
+ await record({ event: 'finished', ...result });
467
+ await checkpoint('finished');
468
+ return result;
469
+ } finally {
470
+ controller.abort(new Error('RUN_CLOSED'));
471
+ if (!drainAttempted) await drainAdapterCalls();
472
+ clearTimeout(timer);
473
+ signal?.removeEventListener('abort', cancel);
474
+ // A journal failure must still drain checkpoint writes before callers or
475
+ // tests can remove the feature directory. Preserve the journal failure
476
+ // while ensuring no asynchronous checkpoint writer survives teardown.
477
+ try { await write; } finally {
478
+ try { await checkpointWrite; } finally {
479
+ await file.close();
480
+ if (resumeLock) releaseResumeLock(resumeLock);
481
+ }
482
+ }
483
+ }
484
+ }
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Human-run ceremony that creates the benchmark verifier's signing key.
4
+ *
5
+ * It generates a fresh Ed25519 key, encrypts it with a passphrase you type,
6
+ * and stores only the encrypted envelope. It never registers the key: trust
7
+ * comes from a root-owned registry file that only an administrator can write,
8
+ * so this tool prints the exact commands and changes nothing outside your
9
+ * trust folder. Run it in a terminal yourself. Do not run it through an agent.
10
+ */
11
+ import { createHash, generateKeyPairSync, randomUUID } from 'node:crypto';
12
+ import { constants } from 'node:fs';
13
+ import { lstat, mkdir, open } from 'node:fs/promises';
14
+ import path from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { assertStrongPassphrase, encryptSigningKey } from './gofer-encrypted-key.mjs';
17
+ import { VERIFIER_EVALUATOR, accountTrustRoot, protectedVerifierRegistryPath } from './gofer-trusted-evaluator.mjs';
18
+ import { promptHidden } from './gofer-tty-prompt.mjs';
19
+
20
+ const denied = () => new Error('VERIFIER_KEY_CEREMONY_REQUIRES_REVIEW');
21
+ const shellQuote = value => `'${value.replaceAll("'", "'\"'\"'")}'`;
22
+
23
+ async function writeExclusive(filename, value) {
24
+ const file = await open(filename, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL |
25
+ constants.O_NOFOLLOW, 0o600);
26
+ try { await file.writeFile(value, 'utf8'); await file.sync(); } finally { await file.close(); }
27
+ }
28
+
29
+ async function requireUninitializedRegistry(registryPath) {
30
+ try {
31
+ await lstat(registryPath);
32
+ } catch (error) {
33
+ if (error?.code === 'ENOENT') return;
34
+ throw denied();
35
+ }
36
+ throw denied();
37
+ }
38
+
39
+ /** First-key setup only: an installed registry requires reviewed rotation. */
40
+ export async function runVerifierKeyCeremony({ trustRoot, getPassphrase, existingEntries,
41
+ keyId = `heldout-verifier-${randomUUID()}`, registryPath = protectedVerifierRegistryPath() } = {}) {
42
+ if (!path.isAbsolute(trustRoot ?? '') || typeof getPassphrase !== 'function' ||
43
+ !path.isAbsolute(registryPath) || !/^[a-zA-Z0-9._-]{8,80}$/.test(keyId) ||
44
+ existingEntries !== undefined) throw denied();
45
+ await requireUninitializedRegistry(registryPath);
46
+ const rootInfo = await lstat(trustRoot);
47
+ if (!rootInfo.isDirectory() || rootInfo.uid !== process.getuid() || (rootInfo.mode & 0o077) !== 0) throw denied();
48
+ const active = path.join(trustRoot, 'active-keys');
49
+ await mkdir(active, { mode: 0o700, recursive: true });
50
+ const activeInfo = await lstat(active);
51
+ if (!activeInfo.isDirectory() || activeInfo.uid !== process.getuid() || (activeInfo.mode & 0o077) !== 0) throw denied();
52
+
53
+ const passphrase = await getPassphrase('New verifier passphrase (12+ characters): ');
54
+ assertStrongPassphrase(passphrase);
55
+ if (passphrase !== await getPassphrase('Repeat the passphrase: ')) throw denied();
56
+ await requireUninitializedRegistry(registryPath);
57
+
58
+ const pair = generateKeyPairSync('ed25519');
59
+ const publicKeyPem = pair.publicKey.export({ type: 'spki', format: 'pem' }).toString();
60
+ const envelope = await encryptSigningKey(pair.privateKey, passphrase);
61
+ // O_EXCL: an existing verifier identity is never replaced.
62
+ await writeExclusive(path.join(active, 'heldout-verifier.private.enc.json'), `${JSON.stringify(envelope)}\n`);
63
+ await writeExclusive(path.join(active, 'heldout-verifier.json'), `${JSON.stringify({ schemaVersion: 1,
64
+ host: 'codex', evaluator: VERIFIER_EVALUATOR, keyId })}\n`);
65
+ const pendingPath = path.join(trustRoot, 'verifier-registry.pending.json');
66
+ const pendingBytes = `${JSON.stringify({ schemaVersion: 1, evaluators: [
67
+ { keyId, host: 'codex', evaluator: VERIFIER_EVALUATOR, publicKeyPem }] }, null, 2)}\n`;
68
+ await writeExclusive(pendingPath, pendingBytes);
69
+ const pendingSha256 = createHash('sha256').update(pendingBytes, 'utf8').digest('hex');
70
+ const directory = path.dirname(registryPath);
71
+ const stageTemplate = path.join(directory, `${path.basename(registryPath)}.${keyId}.XXXXXX`);
72
+ const installScript = [
73
+ 'set -eu',
74
+ 'PATH=/usr/bin:/bin; export PATH',
75
+ `stage=$(mktemp ${shellQuote(stageTemplate)})`,
76
+ `trap 'rm -f -- "$stage"' EXIT`,
77
+ `install -o root -m 0600 ${shellQuote(pendingPath)} "$stage"`,
78
+ // SECURITY: Check the root-owned copy against ceremony bytes, not the mutable pending file.
79
+ 'if command -v sha256sum >/dev/null 2>&1; then staged_hash=$(sha256sum < "$stage"); elif command -v shasum >/dev/null 2>&1; then staged_hash=$(shasum -a 256 < "$stage"); else exit 1; fi',
80
+ `[ "\${staged_hash%% *}" = ${shellQuote(pendingSha256)} ]`,
81
+ 'chmod 0644 "$stage"',
82
+ `link "$stage" ${shellQuote(registryPath)}`,
83
+ ].join('; ');
84
+ return Object.freeze({ keyId, publicKeyPem, pendingPath, installCommands: Object.freeze([
85
+ `sudo /bin/mkdir -p ${shellQuote(directory)}`,
86
+ `sudo /bin/sh -c ${shellQuote(installScript)}`,
87
+ ]) });
88
+ }
89
+
90
+ if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
91
+ if (process.argv.length !== 2) throw denied();
92
+ runVerifierKeyCeremony({ trustRoot: accountTrustRoot(), getPassphrase: promptHidden })
93
+ .then(result => {
94
+ process.stdout.write(`\nVerifier key created (encrypted). Key id: ${result.keyId}\n\n` +
95
+ 'It is NOT trusted yet. An administrator must install the registry:\n\n' +
96
+ `${result.installCommands.map(command => ` ${command}`).join('\n')}\n\n` +
97
+ 'Then delete the old plaintext verifier key, which a worker can read:\n\n' +
98
+ ' rm ~/.eai-gofer-trust/staged-keys/heldout-verifier.private.pem\n');
99
+ })
100
+ .catch(error => { process.stderr.write(`${error.message}\n`); process.exitCode = 1; });
101
+ }
@@ -0,0 +1,32 @@
1
+ /** Shared checks about where a task worktree and its Git store live. */
2
+ import { spawnSync } from 'node:child_process';
3
+ import { realpathSync } from 'node:fs';
4
+ import path from 'node:path';
5
+
6
+ const text = value => typeof value === 'string' && value.trim().length > 0;
7
+ const gitEnvironment = Object.fromEntries(Object.entries(process.env)
8
+ .filter(([key]) => !key.startsWith('GIT_')));
9
+
10
+ export const insideDirectory = (parent, child) => {
11
+ const relative = path.relative(parent, child);
12
+ return relative === '' || (relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
13
+ };
14
+
15
+ /** The shared Git store of a linked worktree, or null. A plain repository is
16
+ * refused: its Git store lies inside the workspace, so it cannot be protected. */
17
+ export function sharedGitDirectory(workspaceRoot) {
18
+ if (!text(workspaceRoot)) return null;
19
+ const result = spawnSync('/usr/bin/git', ['-C', workspaceRoot, 'rev-parse', '--path-format=absolute',
20
+ '--show-toplevel', '--git-dir', '--git-common-dir'],
21
+ { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 5000, env: gitEnvironment });
22
+ if (result.status !== 0 || !result.stdout?.trim()) return null;
23
+ const [topLevel, gitDirectory, commonDirectory] = result.stdout.trim().split('\n');
24
+ if (!topLevel || !gitDirectory || !commonDirectory) return null;
25
+ try {
26
+ const workspace = realpathSync(workspaceRoot);
27
+ const common = realpathSync(commonDirectory);
28
+ if (realpathSync(topLevel) !== workspace || realpathSync(gitDirectory) === common ||
29
+ insideDirectory(workspace, common)) return null;
30
+ return common;
31
+ } catch { return null; }
32
+ }