@enterpriseai/cli 3.19.0 → 3.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. package/package.json +3 -3
  2. package/resources/deploy/eai-app-template/producer-pin.json +5 -5
  3. package/resources/deploy/eai-app-template/tests/source-unknown-deployment-evidence.test.mjs +2141 -1
  4. package/resources/gofer/.gofer-version +4 -357
  5. package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
  6. package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
  7. package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
  8. package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
  9. package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
  10. package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
  11. package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
  12. package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
  13. package/resources/gofer/claude-commands/eai-update.md +46 -0
  14. package/resources/gofer/claude-commands/eai.md +355 -0
  15. package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
  16. package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
  17. package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
  18. package/resources/gofer/commands/0_gofer_start.md +440 -99
  19. package/resources/gofer/commands/0a_problem_validation.md +187 -27
  20. package/resources/gofer/commands/10_gofer_cloud.md +183 -23
  21. package/resources/gofer/commands/1_gofer_research.md +239 -30
  22. package/resources/gofer/commands/2_gofer_specify.md +239 -35
  23. package/resources/gofer/commands/3_gofer_plan.md +259 -43
  24. package/resources/gofer/commands/4_gofer_tasks.md +401 -81
  25. package/resources/gofer/commands/5_gofer_implement.md +375 -84
  26. package/resources/gofer/commands/6_gofer_validate.md +284 -53
  27. package/resources/gofer/commands/7_gofer_save.md +187 -26
  28. package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
  29. package/resources/gofer/commands/8_gofer_branding.md +183 -23
  30. package/resources/gofer/commands/9_gofer_tests.md +212 -23
  31. package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
  32. package/resources/gofer/commands/gofer_check_workspace.md +123 -8
  33. package/resources/gofer/commands/gofer_constitution.md +183 -23
  34. package/resources/gofer/commands/gofer_diagnose.md +183 -23
  35. package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
  36. package/resources/gofer/commands/gofer_hydrate.md +183 -23
  37. package/resources/gofer/commands/gofer_personality.md +117 -6
  38. package/resources/gofer/commands/gofer_plan.md +117 -6
  39. package/resources/gofer/commands/gofer_side.md +117 -6
  40. package/resources/gofer/commands/gofer_spec_summary.md +183 -23
  41. package/resources/gofer/commands/gofer_tdd.md +183 -23
  42. package/resources/gofer/commands/gofer_vocabulary.md +185 -25
  43. package/resources/gofer/commands/gofer_zoom_out.md +183 -23
  44. package/resources/gofer/config/typesafe-learning-review.json +16 -0
  45. package/resources/gofer/config/typesafe-semantic-review.json +9 -0
  46. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
  47. package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
  48. package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
  49. package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
  50. package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
  51. package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
  52. package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
  53. package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
  54. package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
  55. package/resources/gofer/gemini/extension.json +4 -4
  56. package/resources/gofer/github-agents/eai.agent.md +83 -0
  57. package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
  58. package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
  59. package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
  60. package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
  61. package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
  62. package/resources/gofer/github-skills/eai/SKILL.md +365 -0
  63. package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
  64. package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
  65. package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
  66. package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
  67. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
  68. package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
  69. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
  70. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
  71. package/resources/gofer/memory/constitution.md +9 -7
  72. package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
  73. package/resources/gofer/memory/lessons.md +0 -31
  74. package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
  75. package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
  76. package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
  77. package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
  78. package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
  79. package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
  80. package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
  81. package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
  82. package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
  83. package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
  84. package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
  85. package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
  86. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
  87. package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
  88. package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
  89. package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
  90. package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
  91. package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
  92. package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
  93. package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
  94. package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
  95. package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
  96. package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
  97. package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
  98. package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
  99. package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
  100. package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
  101. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
  102. package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
  103. package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
  104. package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
  105. package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
  106. package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
  107. package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
  108. package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
  109. package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
  110. package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
  111. package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
  112. package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
  113. package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
  114. package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
  115. package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
  116. package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
  117. package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
  118. package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
  119. package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
  120. package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
  121. package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
  122. package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
  123. package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
  124. package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
  125. package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
  126. package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
  127. package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
  128. package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
  129. package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
  130. package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
  131. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
  132. package/resources/gofer/references/agent-catalog.json +126 -0
  133. package/resources/gofer/references/blocker-mediation.md +156 -0
  134. package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
  135. package/resources/gofer/references/delivery-lineage.md +48 -0
  136. package/resources/gofer/references/mvp-capability-validation.md +102 -0
  137. package/resources/gofer/references/platform/README.md +1 -1
  138. package/resources/gofer/references/platform/eai-app-template.md +15 -13
  139. package/resources/gofer/references/platform/eai-auth-access.md +104 -0
  140. package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
  141. package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
  142. package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
  143. package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
  144. package/resources/gofer/references/platform/eai.md +44 -8
  145. package/resources/gofer/references/platform/vertical-template.md +10 -9
  146. package/resources/gofer/references/priority-outcome-protection.md +152 -0
  147. package/resources/gofer/references/verified-agent-execution.md +179 -0
  148. package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
  149. package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
  150. package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
  151. package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
  152. package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
  153. package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
  154. package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
  155. package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
  156. package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
  157. package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
  158. package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
  159. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
  160. package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
  161. package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
  162. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
  163. package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
  164. package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
  165. package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
  166. package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
  167. package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
  168. package/resources/gofer/specify-commands/gofer_personality.md +117 -6
  169. package/resources/gofer/specify-commands/gofer_plan.md +117 -6
  170. package/resources/gofer/specify-commands/gofer_side.md +117 -6
  171. package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
  172. package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
  173. package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
  174. package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
  175. package/resources/gofer/specify-config/object-type-routing.json +24 -0
  176. package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
  177. package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
  178. package/resources/gofer/system-skills/eai/SKILL.md +365 -0
  179. package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
  180. package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
  181. package/resources/gofer/templates/build-map-template.md +64 -0
  182. package/resources/gofer/templates/business-scenarios-template.json +14 -0
  183. package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
  184. package/resources/gofer/templates/context-bundle-template.md +4 -3
  185. package/resources/gofer/templates/contract-pack-template.md +8 -8
  186. package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
  187. package/resources/gofer/templates/delivery-lineage-template.json +8 -0
  188. package/resources/gofer/templates/eai-preflight-template.md +109 -68
  189. package/resources/gofer/templates/goal-ledger-template.json +1 -1
  190. package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
  191. package/resources/gofer/templates/loop-contract-template.json +3 -1
  192. package/resources/gofer/templates/plan-template.md +8 -7
  193. package/resources/gofer/templates/priority-plan-template.json +29 -0
  194. package/resources/gofer/templates/proposal-review-template.md +6 -3
  195. package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
  196. package/resources/gofer/templates/research-template.md +7 -6
  197. package/resources/gofer/templates/spec-summary-template.md +1 -1
  198. package/resources/gofer/templates/spec-template.md +45 -6
  199. package/resources/gofer/templates/tasks-template.md +12 -3
  200. package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
  201. package/resources/gofer/templates/ui-review-log-template.md +21 -3
  202. package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
  203. package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
  204. package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
  205. package/resources/linked-sources.json +4 -4
  206. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
  207. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
  208. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
  209. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
  210. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
  211. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
  212. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
  213. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
  214. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
  215. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
  216. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
  217. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
  218. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
  219. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  220. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
  221. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
  222. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
  223. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
  224. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
  225. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
  226. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
  227. package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
  228. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
  229. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
  230. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
  231. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
  232. package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
  233. package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
  234. package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
  235. package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
  236. package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
  237. package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
  238. package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
  239. package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
  240. package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
  241. package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
  242. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
  243. package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
  244. package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
  245. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
  246. package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
  247. package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
  248. package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
  249. package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
  250. package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
  251. package/resources/gofer/claude-commands/gofer_personality.md +0 -39
  252. package/resources/gofer/claude-commands/gofer_plan.md +0 -35
  253. package/resources/gofer/claude-commands/gofer_side.md +0 -40
  254. package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
  255. package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
  256. package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
  257. package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
  258. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
  259. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
  260. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
  261. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
  262. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
  263. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
  264. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
  265. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
  266. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
  267. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
  268. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
  269. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
  270. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
  271. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
  272. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
  273. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
  274. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
  275. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
  276. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
  277. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
  278. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
  279. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
  280. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
  281. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
  282. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
  283. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
  284. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
  285. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
  286. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
  287. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
  288. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
  289. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
  290. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
  291. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
  292. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
  293. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
  294. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
  295. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
  296. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
  297. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
  298. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
  299. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
  300. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
  301. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
  302. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
  303. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
  304. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
  305. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
  306. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
  307. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
  308. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
  309. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
  310. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
  311. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
  312. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
  313. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
  314. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
  315. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
  316. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
  317. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
  318. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
  319. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
  320. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
  321. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
  322. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
  323. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
  324. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
  325. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
  326. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
  327. package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
  328. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
  329. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
  330. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
  331. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
  332. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
  333. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
  334. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
  335. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
  336. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
  337. package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
  338. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
  339. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
  340. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
  341. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
  342. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
  343. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
  344. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
  345. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
  346. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
  347. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
  348. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
  349. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
  350. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
  351. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  352. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
  353. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
  354. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
  355. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
  356. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
  357. package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
  358. package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
  359. package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
  360. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
  361. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
  362. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
  363. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
  364. package/resources/gofer/templates/ui-approval-template.md +0 -32
@@ -8,13 +8,14 @@
8
8
  *
9
9
  * Surfaces: claude, claude-mirror, copilot, github-prompts, github-agents,
10
10
  * github-skills, claude-skills, agents-skills, system-skills,
11
- * gemini, agents-md, codex-config
11
+ * grok-skills, gemini, agents-md, codex-config
12
12
  */
13
13
 
14
14
  import { promises as fs } from 'fs';
15
15
  import path from 'path';
16
16
  import { createHash } from 'crypto';
17
17
  import { validateDescriptions } from './canonical-descriptions.mjs';
18
+ import { SUPPORTED_HOSTS } from './gofer-surface-update.mjs';
18
19
  import { parseStageCommand } from './parse-stage-command.mjs';
19
20
 
20
21
  // ---------------------------------------------------------------------------
@@ -37,6 +38,7 @@ const ALL_SURFACES = [
37
38
  'github-skills',
38
39
  'agents-skills',
39
40
  'system-skills',
41
+ 'grok-skills',
40
42
  'gemini',
41
43
  'agents-md',
42
44
  'codex-config',
@@ -45,6 +47,20 @@ const ALL_SURFACES = [
45
47
  const PUBLIC_SITE_URL = 'https://eai-support.github.io/eai-gofer';
46
48
  const PUBLIC_RELEASES_URL = `${PUBLIC_SITE_URL}/releases`;
47
49
  const PUBLIC_PLUGIN_URL = `${PUBLIC_RELEASES_URL}/plugins/eai-gofer`;
50
+ const PUBLIC_ENTRYPOINTS = [
51
+ {
52
+ stem: 'eai',
53
+ name: 'eai',
54
+ title: 'Eai',
55
+ description: 'Start or continue the EAI delivery pipeline.',
56
+ },
57
+ {
58
+ stem: 'eai-update',
59
+ name: 'eai-update',
60
+ title: 'Eai Update',
61
+ description: 'Install or update EAI Gofer for this AI coding app.',
62
+ },
63
+ ];
48
64
  const SURFACE_WORKSPACE_HOSTS = {
49
65
  'claude': 'claude',
50
66
  'claude-mirror': 'claude',
@@ -53,8 +69,9 @@ const SURFACE_WORKSPACE_HOSTS = {
53
69
  'github-prompts': 'copilot',
54
70
  'github-agents': 'copilot',
55
71
  'github-skills': 'copilot',
56
- 'agents-skills': 'codex',
72
+ 'agents-skills': 'codex-or-antigravity',
57
73
  'system-skills': 'codex',
74
+ 'grok-skills': 'grok',
58
75
  'gemini': 'gemini',
59
76
  };
60
77
  const WORKSPACE_PREFLIGHT_EXCLUDED_COMMANDS = new Set([
@@ -65,6 +82,15 @@ const WORKSPACE_PREFLIGHT_EXCLUDED_COMMANDS = new Set([
65
82
  'gofer:bootstrap-workspace',
66
83
  'gofer:eai-first-run',
67
84
  ]);
85
+
86
+ const LEGACY_HELPER_COMMAND_FILES = new Set([
87
+ 'gofer_bootstrap_workspace.md',
88
+ 'gofer_check_workspace.md',
89
+ 'gofer_eai_first_run.md',
90
+ 'gofer_personality.md',
91
+ 'gofer_plan.md',
92
+ 'gofer_side.md',
93
+ ]);
68
94
  const LEGACY_STAGE_STEMS = new Map([
69
95
  ['0_gofer_start', ['0_business_scenario']],
70
96
  ]);
@@ -77,7 +103,8 @@ const LEGACY_STAGE_STEMS = new Map([
77
103
  * Returns true if the given stage should be excluded from the given surface.
78
104
  * Gofer keeps this function for older tests/imports, but no stages are
79
105
  * excluded by name anymore. Surface availability is controlled by stage
80
- * frontmatter so Claude, Copilot, Codex, and Gemini stay in parity.
106
+ * frontmatter so all current semantic hosts and the legacy Gemini file format
107
+ * stay in parity.
81
108
  *
82
109
  * @param {string} stageName
83
110
  * @param {string} surface
@@ -127,7 +154,7 @@ function buildGeminiExtensionManifest(version) {
127
154
  return {
128
155
  name: 'eai-gofer',
129
156
  version,
130
- description: 'Gofer core pipeline and helper commands as a Gemini CLI extension',
157
+ description: 'Legacy Gemini CLI file-format compatibility for EAI Gofer',
131
158
  license: 'Apache-2.0',
132
159
  commands: '.gemini/commands/gofer/',
133
160
  gofer: {
@@ -202,6 +229,32 @@ async function removeLegacyGeneratedPaths(outPath, legacyPaths) {
202
229
  }
203
230
  }
204
231
 
232
+ async function clearDirectoryEntries(dirPath, predicate, dryRun, label) {
233
+ let entries;
234
+ try {
235
+ entries = await fs.readdir(dirPath, { withFileTypes: true });
236
+ } catch (error) {
237
+ if (error?.code === 'ENOENT') {
238
+ return;
239
+ }
240
+ throw error;
241
+ }
242
+
243
+ for (const entry of entries) {
244
+ if (!predicate(entry)) {
245
+ continue;
246
+ }
247
+
248
+ const target = path.join(dirPath, entry.name);
249
+ if (dryRun) {
250
+ console.log(`[dry-run] ${label}: would remove ${target}`);
251
+ } else {
252
+ await fs.rm(target, { recursive: true, force: true });
253
+ console.log(`${label}: removed ${target}`);
254
+ }
255
+ }
256
+ }
257
+
205
258
  function getCodexLegacySkillDirs(root, surfaceRoot, stageStem, stageName) {
206
259
  return [
207
260
  path.join(root, surfaceRoot, stageName),
@@ -210,6 +263,411 @@ function getCodexLegacySkillDirs(root, surfaceRoot, stageStem, stageName) {
210
263
  ];
211
264
  }
212
265
 
266
+ function buildInternalStageList(stages) {
267
+ return stages
268
+ .map((stage) => `- \`${getStageOutputStem(stage)}\` - ${stage.frontmatter.description}`)
269
+ .join('\n');
270
+ }
271
+
272
+ function buildAlwaysEaiSection() {
273
+ return `## Always-On EAI Contract
274
+ <!-- gofer:always-on-eai:start -->
275
+
276
+ Apply this contract to every request after Gofer is installed for this repo or AI coding app. The user does not need to type \`/eai\` or \`$eai\`.
277
+
278
+ 1. Preserve the user's request. Do not rewrite it or add a visible command prefix.
279
+ 2. Treat an explicit \`/eai\` (Claude, Copilot, Antigravity, Grok, or VS Code) or \`$eai\` (Codex) prefix as an idempotent request for the same contract.
280
+ 3. Apply the Controlled English Contract to every Gofer-authored message and artifact.
281
+ 4. Keep the reply short unless the user asks for detail.
282
+ 5. Explain the business effect first.
283
+ 6. Put technical evidence in durable artifacts.
284
+ 7. Do not make the user choose pipeline stages. Select the next internal stage yourself.
285
+ 8. Do not repeat workspace setup on every message. Check it before meaningful repo work, tool use, or a pipeline stage.
286
+ 9. Keep the update and installation path separate. When the user explicitly asks to update Gofer, run only its maintenance contract.
287
+ 10. When a new app conversation starts with \`Get started with EAI\`, send the Required First-Run Response before workspace preflight, EAI readiness, setup, tool calls, or stage routing.
288
+ <!-- gofer:always-on-eai:end -->`;
289
+ }
290
+
291
+ function buildUserFacingResponseGateSection() {
292
+ return `## User-Facing Response Gate
293
+
294
+ Before each user-facing reply, check the draft against these rules:
295
+
296
+ 1. Lead with the business outcome, effect, risk, or decision.
297
+ 2. Use concise, simple language.
298
+ 3. Include technical detail only when it supports a decision or the user asks for it.
299
+ 4. If any check fails, rewrite the reply before sending it.
300
+
301
+ ${buildDeliveryDisciplineContract()}`;
302
+ }
303
+
304
+ export function buildDeliveryDisciplineContract() {
305
+ return `**Business Updates And Goal Checks**
306
+
307
+ For every material code or contract change, keep \`spec.md\`, \`plan.md\`, \`tasks.md\`, \`test-spec.md\`, \`change-manifest.json\`, \`blast-radius-report.md\`, and \`traceability.md\` current before more implementation work. Keep executable feature tests in the owning repository. Add an \`eai-testing-dev\` contract only for a deployed canary, route/config contract, authentication smoke, workspace smoke, or release-evidence surface.
308
+
309
+ Use \`.specify/references/business-updates-and-goal-checks.md\`. Before each reply, explain the result, business effect, and next action in plain language. For progress, use two or three short sentences. Run \`node .specify/scripts/node/gofer-response-check.mjs --input <private-draft-file>\` before sending a drafted progress update; rewrite failed drafts. Use \`--kind answer\` for answers and \`--technical\` only when technical detail was requested. Do not repeat unchanged progress. This helper cannot intercept messages that the host sends directly.
310
+
311
+ Before each work batch, read the current goal, specification, tasks, and latest findings. Make ordinary design, sequencing, diagnosis, repair, and verification decisions that advance the goal. Record material decisions and update affected feature documents when new evidence changes the path. Never weaken acceptance criteria to match failing code. Do not invent approval where approval is required. Mark a task complete only after its linked checks pass; reopen affected tasks when evidence is stale. For app and non-app features with a spec and tasks, enable \`requireDeliveryCheckpoint\` in \`loop-contract.json\` and run \`node .specify/scripts/node/gofer-delivery-check.mjs --feature-dir <feature-dir>\` before advancing or claiming completion. Follow the reference to capture a reviewed checkpoint, not merely to clear a failure. Keep existing MVP exemptions, reviews, loops, and release gates. Conversation-only requests need no feature files.
312
+
313
+ For status, blocker, low-confidence, and decision replies, use the Recommendation, Why, Next step, Owner, and User action labels in .specify/references/blocker-mediation.md, then add the --business-update option to the response checker. State only evidence-backed causes; probabilities show the closest alternative, not why Jev chose its answer.
314
+
315
+ **Priority And Outcome Protection**
316
+
317
+ Jev must judge goal alignment, specification currency, executable test coverage, and blast-radius completeness at every configured checkpoint. Missing evidence, a conflict, partial alignment, low confidence, or an unavailable verdict blocks the affected task. Update the records and rerun the checkpoint. Never ignore the result, edit the receipt, or complete work with an unresolved verdict.
318
+
319
+ Follow \`.specify/references/priority-outcome-protection.md\`. Treat the stated goal as authority for ordinary delivery decisions. Record material user direction and Gofer decisions in decisions.md. Maintain priority-plan.json with ordered tasks, dependencies, allowedEditScope and the current outcome. Enable requirePriorityPlan for new feature contracts. Run \`node .specify/scripts/node/gofer-priority-check.mjs --feature-dir <feature-dir> --task T001\` before the action, and include --workspace <repo-root> plus --changed-file for each proposed or actual changed repo-relative path. Follow its nextTask; recorded independent work may run in parallel. Do not switch to unrelated work when blocked. Ask only when a decision changes the goal, needs missing authority or access, causes irreversible loss, creates external cost or commitment, changes production or public exposure, or conflicts with an explicit user constraint. On resume, state the agreed outcome and next task in plain language after reading the last recorded direction. Keep routine conversation free of feature paperwork.
320
+
321
+ **Pre-Edit Chat Readiness**
322
+
323
+ Before each source or test edit batch for a feature, run \`node .specify/scripts/node/gofer-pre-edit-check.mjs --workspace <repo-root> --feature-dir <feature-dir> --task Tnnn --changed-file <repo-relative-path>\`, repeating \`--changed-file\` for every intended path. This confirms that the goal ledger, specification, plan, and tasks are usable, and that the selected task and edit scope are current. Start no edit until it returns \`ready\`. If it blocks, create or update the missing feature records, resolve the finding, then rerun the gate. Reuse existing feature records; conversation-only work needs no feature files.
324
+
325
+ Offer an optional Jev chat-readiness review when context could affect whether the work is set up for success. Run it only when the user explicitly selects it, for example: “Check whether this chat is set up for success with Jev.” Summarize only relevant chat context in a short feature-local \`chat-readiness-context.md\`; do not send the transcript, secrets, or unrelated personal information. Then add \`--jev-chat-readiness --chat-context-file chat-readiness-context.md\` to the pre-edit check. Jev assesses the selected goal, specification, plan, tasks, decisions, context, and proposed scope. No Jev request occurs by default. A blocked, low-confidence, unavailable, or non-ready result blocks the selected task until reconciled. Jev cannot approve scope changes or replace deterministic checks.
326
+
327
+ Before technical escalation, attach fresh diagnosis through the blocker helper's ask event verification field. Check the exact command, route, environment, own mistake and existing authority. Do not invent a workspace, ask for login without checking it, require an unsafe alternative, or equate administrator access with permission. Business decisions need no failing command. At completion, run the priority checker with --finish; a missing or stale outcome receipt means unverified, regardless of test scores. Use --completion for the final gofer-closed-loop-audit.mjs run; a routine drift audit alone does not prove completion. When TypeSafe semantic review is enabled for the feature, run \`node .specify/scripts/node/gofer-semantic-drift.mjs --workspace <repo-root> --feature-dir <feature-dir> --event <resume|before_task_batch|after_material_finding|before_validation>\` at resume, before a material task batch, after a material finding, and before validation. A TypeSafe conflict or uncertain result requires Gofer reconciliation; it cannot edit artefacts, bypass scope controls, or complete work. Preserve detailed test results, early local MVP scope, non-app work, independent approved tasks and all release/security checks.`;
328
+ }
329
+
330
+ function buildJourneyStateSection() {
331
+ return `## Journey State
332
+
333
+ Before routing work, decide where the user is now.
334
+
335
+ 1. Read current feature state from \`.specify/specs/\`, \`goal-ledger.json\`, \`eai-preflight.md\`, \`research.md\`, \`spec.md\`, \`plan.md\`, \`tasks.md\`, validation reports, loop evidence, and handoff notes when they exist.
336
+ 2. Classify the request as conversation, research/docs/audit, EAI app delivery, or ambiguous.
337
+ 3. For conversation or research/docs/audit, continue the non-app Gofer path after the one required non-app confirmation.
338
+ 4. For EAI app delivery or ambiguous app work, continue directly into EAI readiness.
339
+ 5. Find the earliest missing pipeline artifact or blocked EAI gate.
340
+ 6. Run that internal stage next, then continue forward.
341
+ 7. Keep the user-facing explanation at the business level.`;
342
+ }
343
+
344
+ function buildMvpCapabilityValidationSection() {
345
+ return `## MVP Capability-Based Validation
346
+
347
+ Use \`.specify/references/mvp-capability-validation.md\` as the source of
348
+ truth. Validate the work that the active feature specification requires now.
349
+ Do not apply later delivery requirements to an early MVP.
350
+
351
+ 1. Create \`.specify/specs/{feature}/\` before app or operator-tool source work.
352
+ 2. Keep \`spec.md\`, \`plan.md\`, \`tasks.md\`, \`traceability.md\`, and the validation scope aligned.
353
+ 3. Mark each relevant capability as \`not_applicable\`, \`planned\`, \`implemented\`, \`verified\`, or \`blocked\`.
354
+ 4. Require evidence only for an implemented capability or a capability required by the current delivery decision.
355
+ 5. Treat \`run.sh\`, \`run.bat\`, and \`run.ps1\` as launch evidence only. They do not prove authentication, sessions, EAI access, or deployment readiness.
356
+ 6. For a user-facing change, store the local HTTP check, screenshot, and review outcome in the feature validation report.
357
+ 7. If browser validation is blocked, mark that user journey \`unverified\`. Do not call it complete.
358
+ 8. If the user changes scope, update the feature artifacts before continuing. Explain what changed, what remains valid, and what now needs evidence.
359
+ 9. Use truthful completion language. For example: \`The server runs. Authentication is not in the current MVP scope.\`
360
+ 10. When the feature claims a release or deployed outcome, create \`release-capability-ledger.md\` from \`.specify/templates/release-capability-ledger-template.md\`.
361
+ 11. Do not report a release complete or score 100% when a required capability is missing from traceability, remains on an open PR, is absent from the release branch, or lacks required deployed evidence.`;
362
+ }
363
+
364
+ function buildVerifiedEaiCliCommandContract() {
365
+ return `## Verified EAI CLI Command Contract
366
+
367
+ Do not invent, guess, or complete EAI CLI commands from memory.
368
+
369
+ 1. Before you suggest or run an \`eai ...\` command, verify the exact command from the installed CLI.
370
+ 2. Start with \`eai --describe\` and use its command map as the source of truth.
371
+ 3. For a specific command, run \`eai <command> --help\` or the CLI-described equivalent before using flags, subcommands, or examples.
372
+ 4. Use \`eai agent guide --format json\` when the CLI advertises it.
373
+ 5. Use \`eai errors explain <code-or-reason> --format json\` after errors when the CLI advertises it.
374
+ 6. If the command is not listed or help fails, do not run it. Say the installed EAI CLI does not expose that command, then choose a safe listed command or ask the user to update EAI CLI.
375
+ 7. Record the verified command and source in \`eai-preflight.md\`, \`service-fit-matrix.md\`, or the active feature notes before the command changes files or external systems.
376
+ 8. For commands that create, deploy, publish, change workspaces, change Entra, or spend money, confirm with the user after verification and before execution.
377
+
378
+ ${buildEaiHostingAndDeploymentContract()}`;
379
+ }
380
+
381
+ export function buildEaiHostingAndDeploymentContract() {
382
+ return `## EAI Hosting And Deployment Contract
383
+
384
+ When an app reaches a deployment decision, ask once: **"Where should this app run: EAI-managed Azure, your Azure, or local only?"**
385
+
386
+ Explain the choices before the user decides:
387
+
388
+ - **EAI-managed Azure**: use the current local app as source, choose who maintains its GitHub repository, and deploy its verified commit through TenantInfra.
389
+ - **Your Azure**: keep the existing customer-owned Azure deployment path and credentials.
390
+ - **Local only**: stop after local validation. Do not create cloud resources.
391
+
392
+ For EAI-managed Azure:
393
+
394
+ 1. Verify \`eai deploy app --help\` and \`eai deploy doctor --help\` from the installed CLI. The doctor command must advertise \`--operation-id\`, \`--app-key\`, \`--tenant-id\`, \`--target-tenant-id\`, and \`--evidence-out\`. If it does not, stop and ask the user to update the CLI. Do not reproduce its API, GitHub, workflow, or TenantInfra logic in Gofer.
395
+ 2. Verify EAI login, the selected tenant, and app access. The CLI must verify a GitHub identity linked to that same EAI actor through its browser handoff. Guide the user to link an existing GitHub account or create one if needed. Matching email text or a local \`gh\` login does not prove this association.
396
+ 3. Ask **"Who should maintain the app source: EAI-maintained or My GitHub?"** after identity verification. Keep this choice separate from EAI Azure hosting. EAI-maintained means a server-owned bot repository; My GitHub means the customer's repository.
397
+ 4. For **EAI-maintained**, use \`eai deploy app <app-key> --target eai --tenant-id <app-scope-tenant> --source eai-managed --target-tenant-id <runtime-tenant> [--environment preview] [--wait] --format json\`. The CLI packages the exact bounded local source. EAI derives the repository, creates and validates the bot PR, merges it, and dispatches the exact merged commit. Do not require an origin remote, a customer push, customer write access to the EAI repository, or customer PR merging. Never treat an accepted bundle or \`pending_review\` receipt as deployment success.
398
+ 5. For **My GitHub**, use \`eai deploy app <app-key> --target eai --tenant-id <app-scope-tenant> --source customer-owned --repo <owner/name> --installation-id <positive-id> --target-tenant-id <runtime-tenant> [--branch main] [--environment preview] [--workflow .github/workflows/eai-app.yml] [--wait] --format json\`. The customer commits, pushes, reviews, and merges under that repository's rules. If the CLI installs or updates its workflow, stop at its commit-and-push instruction and continue only after that exact commit is available remotely.
399
+ 6. Use the app-scope tenant for \`--tenant-id\`. Record the approved runtime tenant from \`targetTenantId\`; initial deployment, resume, and retry must always pass it explicitly with \`--target-tenant-id\`, including same-tenant deployments. Persist the selected source mode and returned operation ID in the active feature notes. Read, resume, and retry only that exact operation using the CLI's returned next action.
400
+ 7. For the customer-owned source operation, resume with \`eai deploy app <app-key> --target eai --tenant-id <app-scope-tenant> --target-tenant-id <runtime-tenant> --resume <operation-id> [--wait] --format json\`. Retry with the same tenant flags and \`--retry <operation-id>\`. Never omit the target tenant or substitute the latest operation. For EAI-maintained publication, follow only its own CLI-returned exact-operation \`nextAction\`; do not substitute the customer-owned dispatch path. Before running any returned action that re-invokes \`eai deploy app\`, verify it names the same \`<app-key>\`, uses \`--target eai\`, passes the same \`--tenant-id <app-scope-tenant>\` and \`--target-tenant-id <runtime-tenant>\`, addresses \`<operation-id>\` explicitly, and uses \`--format json\`. If any binding is missing or different, stop and report the inconsistent CLI action instead of running it or repairing it from memory.
401
+ 8. Treat the CLI JSON as the deployment authority. Record its target tenant, source mode, source binding, bundle digest when present, bot PR and merged commit when present, deployment ID, runtime identity, active URL, pointer versions, status, and next action without copying tokens or secrets.
402
+ 9. Claim deployment complete only when the CLI reports \`classification: succeeded\`, \`status: active\`, \`requiresTenantInfra: true\`, an HTTPS \`activeUrl\`, a deployment ID, and runtime identity. Run \`eai deploy doctor --operation-id <operation-id> --app-key <app-key> --tenant-id <app-scope-tenant> --target-tenant-id <runtime-tenant> --evidence-out .eai/deploy-doctor.json --format json\`. The CLI must derive the active URL from the exact PublicAPI operation, verify the deployment, runtime, source, and configuration bindings, run authenticated readiness, and atomically write the receipt. Require the saved receipt to bind the operation, app, both tenants, source and configuration digests, deployment, runtime identity, readiness checks, and timestamp. Every recorded check must pass before the shared readiness gate can pass. When a Gofer deployment task is present, replace every command placeholder with the returned values and retain the selected initial command plus that complete inline doctor command on the task's checkbox line before completion. For customer-owned source, retain its exact \`--repo\`, \`--installation-id\`, and any selected \`--branch\` and \`--workflow\`; require the receipt to match all four source fields using \`main\` and \`.github/workflows/eai-app.yml\` when the optional flags are omitted. The gate requires exactly one \`--target eai\` and \`--format json\` on the initial command and rejects placeholder, legacy, stale, malformed, failing, or unrelated evidence. Do not replace \`--evidence-out\` with shell-specific directory creation or output redirection.
403
+
404
+ If deployment stops, use the CLI reason and \`nextAction\`. Then run \`eai errors explain <code-or-reason> --format json\` when advertised. Explain what happened, why it matters, and the exact safe resume action. Keep these causes separate:
405
+
406
+ - EAI login, selected account, tenant membership, or app access;
407
+ - missing or incorrectly linked GitHub identity for the signed-in EAI actor;
408
+ - customer-repository GitHub login or wrong GitHub account;
409
+ - missing tenant repository connection for customer-owned source;
410
+ - missing or incorrect GitHub App installation or repository grant;
411
+ - protected repository or workflow update that needs a commit and push;
412
+ - rejected local source, unapproved template pin, pending bot PR checks, or publication failure;
413
+ - OpenID Connect (OIDC), workflow permission, evidence, or run failure;
414
+ - TenantInfra acceptance, progress, or deployment failure.
415
+
416
+ Never ask the user for a GitHub App private key, personal access token, Azure credential, or platform service token. Keep customer Azure and local deployment behavior unchanged.`;
417
+ }
418
+
419
+
420
+ function buildEaiPlatformDecisionSection() {
421
+ return `## EAI Platform Decision Contract
422
+
423
+ For app delivery, make EAI Platform choices for the business user.
424
+
425
+ 1. Read \`.specify/references/platform/eai-service-patterns.md\`, \`.specify/references/platform/eai-repo-contract.md\`, and \`.specify/references/platform/eai.md\` before architecture or storage decisions.
426
+ 2. Run \`eai --describe\` before assuming current CLI syntax.
427
+ 3. Run \`eai agent guide --format json\` when the CLI advertises it.
428
+ 4. Run \`eai resources schema --format json\` and \`eai workflow readiness --format json\` when advertised and relevant.
429
+ 5. Create or update \`.specify/specs/{feature}/service-fit-matrix.md\`.
430
+ 6. Prefer the EAI app template, PublicAPI, ResourceAPI, object types, workflows, goals, targets, platform AI services, and workspace identity.
431
+ 7. Prefer PostgreSQL for relational, transactional, reporting, and workflow state.
432
+ 8. Prefer DocumentDB for flexible JSON documents, nested records, and high-change document models.
433
+ 9. Prefer Blob Storage for large files and binary content behind API-mediated access.
434
+ 10. Prefer AI Search as a derived search projection, not as the source of record.
435
+ 11. Prefer EAI content understanding and document services for classification, extraction, summarization, and Retrieval-Augmented Generation.
436
+ 12. Prefer EAI workflows, goals, and targets for approvals, long-running work, service goals, operating targets, and auditable process state.
437
+ 13. Use Azure second when the EAI Platform does not yet expose the needed capability.
438
+ 14. Use any other platform only as an explicit exception with rationale, owner, expiry, and validation evidence.
439
+ 15. Ask the user only for material business, security, cost, deployment, destructive, or external-system decisions.`;
440
+ }
441
+
442
+ function buildPublicEntrypointMarkdown(entry, stages, host) {
443
+ if (entry.name === 'eai-update') {
444
+ return buildEaiUpdateEntrypointMarkdown(host);
445
+ }
446
+
447
+ const legacyCompatibilityNotice =
448
+ host === 'gemini'
449
+ ? '> Legacy compatibility: this generated Gemini file remains for existing repositories only. Gemini is not a current Gofer host. Use Google Antigravity and `agy` for the current Google surface.\n\n'
450
+ : '';
451
+ const sharedAgentsHost = host === 'codex-or-antigravity';
452
+ const workspaceHost =
453
+ sharedAgentsHost ? '<current-host>' : host === 'gemini' ? 'antigravity' : host;
454
+ const workspaceHostSelection = sharedAgentsHost
455
+ ? 'This skill is shared by Codex and Google Antigravity. Replace `<current-host>` with `codex` in Codex or `antigravity` in Antigravity.'
456
+ : '';
457
+
458
+ return `# ${entry.title}
459
+
460
+ ${legacyCompatibilityNotice}Use this as the single user-facing Gofer command. Apply its contract to every request after Gofer is installed. Use \`/${entry.name}\` on Claude, Copilot, Antigravity, Grok, or VS Code, and \`$${entry.name}\` on Codex. The prefix is optional. Do not ask users to run numbered stage commands unless they explicitly request low-level internals.
461
+
462
+ ## User-Facing Contract
463
+
464
+ - Keep the command window simple: expose \`eai\` only.
465
+ - Treat \`.specify/commands/*.md\` as internal stage contracts, not user-facing commands.
466
+ - Keep all Gofer functions available by routing internally to the right stage contract.
467
+ - Explain progress in business language first; provide technical details when the user asks.
468
+
469
+ ## Controlled English Contract
470
+
471
+ Use ASD-STE100 Simplified Technical English as the target writing standard for all Gofer-authored chat, documents, commands, summaries, PR notes, error guidance, and validation artifacts. ASD-STE100 is copyright and a trademark of ASD; do not bundle the protected ASD dictionary and do not claim ASD certification.
472
+
473
+ Apply these rules before any user-facing output:
474
+
475
+ 1. Use short sentences. Keep instructions to 20 words or fewer where possible.
476
+ 2. Use one action per instruction.
477
+ 3. Use active voice. Use passive voice only when the actor is unknown or not important.
478
+ 4. Use simple present, simple past, simple future, infinitive, or imperative verb forms.
479
+ 5. Use approved project terms and necessary technical nouns only. Define acronyms on first use.
480
+ 6. Use direct words. Avoid idioms, marketing adjectives, vague praise, and hedging.
481
+ 7. Use vertical lists for complex information.
482
+ 8. Put one topic in each paragraph.
483
+ 9. For errors, write: what happened, why it matters, what to do next, and the exact safe command when one exists.
484
+ 10. Keep raw logs, stack traces, IDs, and secrets out of chat unless the user asks for technical detail.
485
+
486
+ ${buildUserFacingResponseGateSection()}
487
+
488
+ ${buildAlwaysEaiSection()}
489
+
490
+ ## Workspace Preflight
491
+
492
+ ${workspaceHostSelection}
493
+
494
+ 1. Resolve the repository root.
495
+ 2. Run \`node .specify/scripts/node/gofer-workspace-check.mjs --host ${workspaceHost} --json\` when available.
496
+ 3. If the repo is missing or stale, ask exactly: **"This repo is missing or stale for Gofer. Initialize/update it now?"**
497
+ 4. If the user says yes, run \`node .specify/scripts/node/gofer-workspace-bootstrap.mjs --host ${workspaceHost} --include-mirrors\`, then resume this command.
498
+ 5. If the user says no, stop and explain that Gofer needs the repo scaffold before it can safely continue.
499
+
500
+ ${buildLocalSettingsCleanupContractSection()}
501
+
502
+ ${buildAppPreviewRunnerContractSection()}
503
+
504
+ ${buildJourneyStateSection()}
505
+
506
+ ${buildMvpCapabilityValidationSection()}
507
+
508
+ ${buildAuthAccessDecisionContract()}
509
+
510
+ ## App vs Non-App Routing
511
+
512
+ 1. Classify the request before EAI readiness: EAI app delivery, non-application work, or ambiguous.
513
+ 2. If the request is EAI app delivery or ambiguous, continue directly into the EAI app delivery path; do not ask for confirmation just because app delivery is inferred.
514
+ 3. If the request is clearly non-app work, confirm once: **"This looks like non-app work, so I will skip EAI workspace/app setup and continue the Gofer research/docs path. Is that right?"**
515
+ 4. When the user confirms non-app, do not run \`eai whoami\`, workspace selection, \`eai init\`, or first-run setup. Record the decision and continue the appropriate Gofer research, documentation, audit, migration, or planning path.
516
+ 5. If the user says it is app work, switch to EAI app delivery and run EAI readiness.
517
+
518
+ ## EAI Platform Readiness
519
+
520
+ 1. Run \`eai whoami\` only when the current feature uses EAI Platform services, the user asks for EAI setup, or EAI CLI recovery is needed.
521
+ 2. Require \`eai-app-template-readiness\`, \`eai verify\`, and \`eai template check --format json\` only when the feature creates, changes, or validates an EAI Platform app integration.
522
+ 3. Require the authentication journey only when the specification includes sign-in, protected content, user roles, or a deployment target that requires identity.
523
+ 4. For a local MVP with no EAI or authentication capability, record those states as \`not_applicable\` or \`planned\` and continue with local feature validation.
524
+ 5. When an EAI capability becomes required, run the first-run/setup path from \`.specify/commands/gofer_eai_first_run.md\`, then require canonical template evidence before that capability can complete.
525
+ 6. Do not accept copied marker files, a partial scaffold, or a custom template as proof that \`eai init\` completed.
526
+ 7. After any \`eai\` error, run \`eai errors explain <code-or-reason> --format json\` when available before guessing remediation.
527
+ 8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local \`.env\` values into artifacts.
528
+
529
+ ${buildVerifiedEaiCliCommandContract()}
530
+
531
+ ${buildEaiPlatformDecisionSection()}
532
+
533
+ ## First Conversation
534
+
535
+ When this is the first EAI conversation for a new app:
536
+
537
+ 1. Treat \`Get started with EAI\` as the first-run trigger. Ignore capitalization, punctuation, and decorative emoji around the phrase.
538
+ 2. Show the following compact orientation once. Do not repeat it after onboarding starts or when existing feature state means the work should resume.
539
+
540
+ ### Required First-Run Response
541
+
542
+ \`\`\`markdown
543
+ ## Welcome to Enterprise AI 👋
544
+
545
+ I’ll help you improve a process and turn it into a secure enterprise application:
546
+
547
+ 1. **Improve** — understand the opportunity and design the solution.
548
+ 2. **Build** — prepare data, add AI, and connect systems.
549
+ 3. **Test and deploy** — validate, launch, and share securely.
550
+ 4. **Run and measure** — monitor results, costs, activity, and value.
551
+
552
+ The EAI Platform supports every step with secure data, identity, multi-tenancy, and AI models.
553
+
554
+ I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
555
+
556
+ **First question:** What process would you like to improve, or what would you like the application to help people do?
557
+ \`\`\`
558
+
559
+ 3. After the first answer, ask one short question at a time about the users, current process, desired value, success measures, and material constraints.
560
+ 4. Treat \`Show me the admin screen\` as a request for the relevant manual path. Use a verified link from repository or platform context when available. Never invent an admin URL.
561
+ 5. Explain EAI capabilities only when they help the next decision. Do not begin with platform architecture or a list of tools.
562
+ 6. Use the repository and EAI CLI as sources of truth. Run \`eai --describe\` before assuming command syntax and explain known errors before recovery.
563
+ 7. Keep numbered Gofer stages internal. Say what is being learned, designed, built, or checked in business language.
564
+ 8. Explain why specification-led delivery improves AI quality: it creates a shared, testable statement of the outcome before code changes multiply.
565
+ 9. Pause once for approval of the business specification. After approval, continue automatically unless a material business, security, cost, deployment, or destructive decision needs approval.
566
+ 10. Do not create a GitHub repository, deploy, publish, spend money, or change external systems without the relevant user approval.
567
+
568
+ ## Route The Pipeline
569
+
570
+ 1. Read existing feature state from \`.specify/specs/\`, pipeline state files, checkpoints, validation artifacts, and loop evidence.
571
+ 2. Decide the next internal stage contract needed to move the feature toward completion.
572
+ 3. If no feature state exists yet, start from \`.specify/commands/0_gofer_start.md\`.
573
+ 4. Execute the selected stage by following the matching file in \`.specify/commands/\`.
574
+ 5. Continue through research, specify, plan, tasks, implement, and validate unless a real business, security, release, or user-approval decision blocks progress.
575
+ 6. When app UI is involved, show the user the working UI as early and as often as practical.
576
+ 7. Keep stakeholder summaries, build maps, diagrams, loop evidence, tests, and validation artifacts current.
577
+
578
+ ${buildContinuationContractSection()}
579
+
580
+ ## Internal Function Contracts
581
+
582
+ ${buildInternalStageList(stages)}
583
+ `;
584
+ }
585
+
586
+ function buildEaiUpdateEntrypointMarkdown(host) {
587
+ if (host === 'gemini') {
588
+ return `## Legacy Gemini File-Format Compatibility
589
+
590
+ This file remains only so existing Gemini CLI repositories can read the generated Gofer command format. Gemini is not a current Gofer host. Google Antigravity and its \`agy\` CLI are the current Google surface.
591
+
592
+ ## What To Do
593
+
594
+ 1. Install or update EAI Gofer from Google Antigravity with \`agy plugin install https://github.com/eai-support/eai-gofer\`.
595
+ 2. Use \`--host antigravity\` with \`gofer-surface-update.mjs\`.
596
+ 3. Start a new Antigravity session after installation.
597
+
598
+ Existing automation that passes \`--host gemini\` is mapped to \`antigravity\` as a hidden compatibility alias. New commands and documentation must use \`antigravity\`. The updater reports exactly these current hosts: ${SUPPORTED_HOSTS.join(', ')}.
599
+ ${buildBlockerMediationContract()}
600
+ `;
601
+ }
602
+
603
+ const sharedAgentsHost = host === 'codex-or-antigravity';
604
+ const selectedHost = sharedAgentsHost ? '<current-host>' : host;
605
+ const hostSelection = sharedAgentsHost
606
+ ? '2. This skill is shared by Codex and Google Antigravity. Set `<current-host>` to `codex` in Codex or `antigravity` in the `agy` CLI.'
607
+ : `2. Use \`${host}\` as the current semantic host.`;
608
+
609
+ return `## Update EAI Gofer
610
+
611
+ Use this command to install or update EAI Gofer for the current AI coding app. This command works without an EAI project, a Gofer scaffold, or EAI sign-in.
612
+
613
+ ## Update Contract
614
+
615
+ 1. Do not run workspace checks, \`eai init\`, \`eai whoami\`, or pipeline stages.
616
+ ${hostSelection}
617
+ 3. Check the current host first:
618
+ \`node <plugin-root>/.specify/scripts/node/gofer-surface-update.mjs --action inspect --host ${selectedHost} --json\`
619
+ 4. If the plugin root is not known, identify the installed plugin bundle before you run the helper.
620
+ 5. State whether EAI Gofer is installed and whether the host command is available.
621
+ 6. Explain the planned user-level change and ask for approval before any install or update command.
622
+ 7. After approval, run one of these commands from the bundled helper:
623
+ - Install: \`node <plugin-root>/.specify/scripts/node/gofer-surface-update.mjs --action install --host ${selectedHost} --execute --json\`
624
+ - Update: \`node <plugin-root>/.specify/scripts/node/gofer-surface-update.mjs --action update --host ${selectedHost} --execute --json\`
625
+ 8. After an actual install or update, the helper archives stale Gofer command and skill entries. It adds a small managed always-on instruction for Claude, Codex, Copilot, Antigravity, and VS Code. For Grok, it verifies the installed plugin's \`skills/eai/SKILL.md\` always-on contract instead of inventing a separate global instruction file. It keeps the current \`eai\` and \`eai-update\` entries. For Codex, a clean official local marketplace on \`main\` fast-forwards safely. A dirty, non-main, or unrecognised local marketplace remains unchanged and reports that its plugin update is incomplete while it still refreshes the always-on instruction. If the Codex marketplace source is unknown, it stops without changes.
626
+ 9. Run only the selected host by default. Use \`--host all\` only when the user explicitly asks to install or update every detected host.
627
+ 10. Show the required reload step from the helper output. Do not claim the command is ready until the host reloads.
628
+
629
+ ## Supported Hosts
630
+
631
+ - Claude Code: refresh the marketplace and plugin, then run \`/reload-plugins\`.
632
+ - Codex: refresh a confirmed Git marketplace and apply the plugin, then start a new task or restart Codex. A clean official local \`main\` checkout fast-forwards and applies the plugin. Other local checkouts keep their work unchanged, refresh the always-on instruction, and report what needs attention. An unknown source stops the update to protect local work.
633
+ - GitHub Copilot: refresh the marketplace and plugin, then restart the CLI session or start a new app chat.
634
+ - Google Antigravity: install or reinstall the repository plugin with \`agy\`, then start a new Antigravity session.
635
+ - Grok Build: install or update the repository plugin with \`grok\`, then start a new Grok Build session.
636
+ - VS Code: install or update \`EnterpriseAI.gofer\`, then run **Developer: Reload Window**.
637
+
638
+ ## Limits
639
+
640
+ - This command updates user-level plugins and extensions. It archives known stale Gofer entries and replaces only Gofer's managed instruction section. It does not remove unrelated user files or host-managed plugin caches. It does not add the repo-owned \`.specify/\` scaffold.
641
+ - For a repository scaffold, use \`/eai add or refresh the Gofer scaffold for this repo\` after the host update.
642
+ - Gemini files remain only for legacy file-format compatibility. Gemini is not a current updater host.
643
+ - Keep the full Gofer delivery pipeline unchanged. This command only manages its host installation.
644
+ ${buildBlockerMediationContract()}
645
+ `;
646
+ }
647
+
648
+ export function buildPublicEntrypointPrompt(entry, stages, host) {
649
+ return [
650
+ '---',
651
+ `name: ${entry.name}`,
652
+ `description: ${entry.description}`,
653
+ 'agent: agent',
654
+ // Inherit enabled host tools rather than restricting Copilot to foreign aliases.
655
+ 'argument-hint: goal-or-feature-description',
656
+ 'gofer:',
657
+ ' workflowProfile: standard',
658
+ ' publicEntrypoint: true',
659
+ ' canonicalSource: .specify/commands/0_gofer_start.md',
660
+ ' metadataSource: scripts/generate-commands.ts',
661
+ '---',
662
+ '',
663
+ buildPublicEntrypointMarkdown(entry, stages, host),
664
+ ].join('\n');
665
+ }
666
+
667
+ function buildPublicEntrypointSkill(entry, version, stages, hostLabel, host) {
668
+ return `---\nname: ${entry.name}\ndescription: "${entry.description}"\n---\n\n# ${entry.title}\n\nVersion: ${version}\nHost: ${hostLabel}\n\n${buildPublicEntrypointMarkdown(entry, stages, host)}`;
669
+ }
670
+
213
671
  // ---------------------------------------------------------------------------
214
672
  // Surface emitters
215
673
  // ---------------------------------------------------------------------------
@@ -225,29 +683,14 @@ function getCodexLegacySkillDirs(root, surfaceRoot, stageStem, stageName) {
225
683
  async function emitClaude(stages, root, dryRun) {
226
684
  const outDir = path.join(root, '.claude', 'commands');
227
685
  let count = 0;
228
- for (const stage of stages) {
229
- const { name, surfaces } = stage.frontmatter;
230
- if (!surfaces.includes('claude')) continue;
231
- if (shouldExclude(String(name), 'claude')) continue;
232
-
233
- const stageStem = getStageOutputStem(stage);
234
- const outPath = path.join(outDir, `${stageStem}.md`);
235
- const legacyPaths = [
236
- path.join(outDir, `${name}.md`),
237
- ...getLegacyStageStems(stage).map((legacyStem) => path.join(outDir, `${legacyStem}.md`)),
238
- ];
686
+ await clearDirectoryEntries(outDir, (entry) => entry.name.endsWith('.md'), dryRun, 'claude');
687
+ for (const entry of PUBLIC_ENTRYPOINTS) {
688
+ const outPath = path.join(outDir, `${entry.stem}.md`);
239
689
  if (dryRun) {
240
690
  console.log(`[dry-run] claude: would write ${outPath}`);
241
691
  } else {
242
692
  await ensureDir(outDir);
243
- await fs.writeFile(
244
- outPath,
245
- injectTokenCostPolicy(
246
- injectWorkspacePreflight(stage.body, String(name), SURFACE_WORKSPACE_HOSTS['claude'])
247
- ),
248
- 'utf8'
249
- );
250
- await removeLegacyGeneratedPaths(outPath, legacyPaths);
693
+ await fs.writeFile(outPath, buildPublicEntrypointMarkdown(entry, stages, 'claude'), 'utf8');
251
694
  console.log(`claude: wrote ${outPath}`);
252
695
  }
253
696
  count++;
@@ -267,33 +710,23 @@ async function emitClaude(stages, root, dryRun) {
267
710
  async function emitClaudeMirror(stages, root, dryRun) {
268
711
  const outDir = path.join(root, 'extension', 'resources', 'claude-commands');
269
712
  let count = 0;
270
- for (const stage of stages) {
271
- const { name, surfaces } = stage.frontmatter;
272
- if (!surfaces.includes('claude-mirror')) continue;
273
- if (shouldExclude(String(name), 'claude-mirror')) continue;
274
-
275
- const stageStem = getStageOutputStem(stage);
276
- const outPath = path.join(outDir, `${stageStem}.md`);
277
- const legacyPaths = [
278
- path.join(outDir, `${name}.md`),
279
- ...getLegacyStageStems(stage).map((legacyStem) => path.join(outDir, `${legacyStem}.md`)),
280
- ];
713
+ await clearDirectoryEntries(
714
+ outDir,
715
+ (entry) => entry.name.endsWith('.md'),
716
+ dryRun,
717
+ 'claude-mirror'
718
+ );
719
+ for (const entry of PUBLIC_ENTRYPOINTS) {
720
+ const outPath = path.join(outDir, `${entry.stem}.md`);
281
721
  if (dryRun) {
282
722
  console.log(`[dry-run] claude-mirror: would write ${outPath}`);
283
723
  } else {
284
724
  await ensureDir(outDir);
285
725
  await fs.writeFile(
286
726
  outPath,
287
- injectTokenCostPolicy(
288
- injectWorkspacePreflight(
289
- stage.body,
290
- String(name),
291
- SURFACE_WORKSPACE_HOSTS['claude-mirror']
292
- )
293
- ),
727
+ buildPublicEntrypointMarkdown(entry, stages, 'claude'),
294
728
  'utf8'
295
729
  );
296
- await removeLegacyGeneratedPaths(outPath, legacyPaths);
297
730
  console.log(`claude-mirror: wrote ${outPath}`);
298
731
  }
299
732
  count++;
@@ -314,29 +747,14 @@ async function emitClaudeMirror(stages, root, dryRun) {
314
747
  async function emitCopilot(stages, root, dryRun) {
315
748
  const outDir = path.join(root, 'extension', 'resources', 'copilot-prompts');
316
749
  let count = 0;
317
- for (const stage of stages) {
318
- const { name, surfaces } = stage.frontmatter;
319
- if (shouldExclude(String(name), 'copilot')) continue;
320
- if (!surfaces.includes('copilot')) continue;
321
-
322
- const stageStem = getStageOutputStem(stage);
323
- const outPath = path.join(outDir, `${stageStem}.prompt.md`);
324
- const legacyPaths = [
325
- path.join(outDir, `${name}.prompt.md`),
326
- ...getLegacyStageStems(stage).map((legacyStem) =>
327
- path.join(outDir, `${legacyStem}.prompt.md`)
328
- ),
329
- ];
750
+ await clearDirectoryEntries(outDir, (entry) => entry.name.endsWith('.prompt.md'), dryRun, 'copilot');
751
+ for (const entry of PUBLIC_ENTRYPOINTS) {
752
+ const outPath = path.join(outDir, `${entry.stem}.prompt.md`);
330
753
  if (dryRun) {
331
754
  console.log(`[dry-run] copilot: would write ${outPath}`);
332
755
  } else {
333
756
  await ensureDir(outDir);
334
- await fs.writeFile(
335
- outPath,
336
- buildCopilotPromptContent(stage, SURFACE_WORKSPACE_HOSTS['copilot']),
337
- 'utf8'
338
- );
339
- await removeLegacyGeneratedPaths(outPath, legacyPaths);
757
+ await fs.writeFile(outPath, buildPublicEntrypointPrompt(entry, stages, 'copilot'), 'utf8');
340
758
  console.log(`copilot: wrote ${outPath}`);
341
759
  }
342
760
  count++;
@@ -357,29 +775,19 @@ async function emitCopilot(stages, root, dryRun) {
357
775
  async function emitGithubPrompts(stages, root, dryRun) {
358
776
  const outDir = path.join(root, '.github', 'prompts');
359
777
  let count = 0;
360
- for (const stage of stages) {
361
- const { name, surfaces } = stage.frontmatter;
362
- if (shouldExclude(String(name), 'github-prompts')) continue;
363
- if (!surfaces.includes('github-prompts')) continue;
364
-
365
- const stageStem = getStageOutputStem(stage);
366
- const outPath = path.join(outDir, `${stageStem}.prompt.md`);
367
- const legacyPaths = [
368
- path.join(outDir, `${name}.prompt.md`),
369
- ...getLegacyStageStems(stage).map((legacyStem) =>
370
- path.join(outDir, `${legacyStem}.prompt.md`)
371
- ),
372
- ];
778
+ await clearDirectoryEntries(
779
+ outDir,
780
+ (entry) => entry.name.endsWith('.prompt.md'),
781
+ dryRun,
782
+ 'github-prompts'
783
+ );
784
+ for (const entry of PUBLIC_ENTRYPOINTS) {
785
+ const outPath = path.join(outDir, `${entry.stem}.prompt.md`);
373
786
  if (dryRun) {
374
787
  console.log(`[dry-run] github-prompts: would write ${outPath}`);
375
788
  } else {
376
789
  await ensureDir(outDir);
377
- await fs.writeFile(
378
- outPath,
379
- buildCopilotPromptContent(stage, SURFACE_WORKSPACE_HOSTS['github-prompts']),
380
- 'utf8'
381
- );
382
- await removeLegacyGeneratedPaths(outPath, legacyPaths);
790
+ await fs.writeFile(outPath, buildPublicEntrypointPrompt(entry, stages, 'copilot'), 'utf8');
383
791
  console.log(`github-prompts: wrote ${outPath}`);
384
792
  }
385
793
  count++;
@@ -414,13 +822,7 @@ function buildCopilotPromptContent(stage, host = SURFACE_WORKSPACE_HOSTS['copilo
414
822
  '---',
415
823
  `name: ${stageName}`,
416
824
  `description: ${description}`,
417
- 'agent: copilot-workspace',
418
- 'tools:',
419
- ' - Read',
420
- ' - Grep',
421
- ' - Glob',
422
- ' - Bash',
423
- ' - WebSearch',
825
+ 'agent: agent',
424
826
  'argument-hint: feature-name-or-description',
425
827
  'gofer:',
426
828
  ' workflowProfile: standard',
@@ -460,8 +862,8 @@ function splitMarkdownFrontmatter(content) {
460
862
  */
461
863
  function transformClaudeContent(content, toPlatform) {
462
864
  let transformed = content;
463
- const stageCommandPattern = /\/(\d+[a-z]?_[a-z0-9_]+)/g;
464
- const helperCommandPattern = /\/(gofer_[a-z0-9_]+)/g;
865
+ const stageCommandPattern = /(?<![A-Za-z0-9_.])\/(\d+[a-z]?_[a-z0-9_]+)/g;
866
+ const helperCommandPattern = /(?<![A-Za-z0-9_.])\/(gofer_[a-z0-9_]+)/g;
465
867
 
466
868
  transformed = transformed.replace(/\*\*AUTO-CHAIN[^]*?(?=\n##|\n---|\n\*\*|$)/g, '');
467
869
  transformed = transformed.replace(
@@ -485,12 +887,13 @@ function transformClaudeContent(content, toPlatform) {
485
887
  * @param {string} commandName
486
888
  * @returns {string}
487
889
  */
488
- function injectPipelineContinuation(content, platform, commandName) {
890
+ export function injectPipelineContinuation(content, platform, commandName) {
489
891
  void platform;
490
892
  const nextCommand = getNextCommand(commandName);
491
893
  if (!nextCommand) return content;
492
894
 
493
- const autoChainSection = `\n\n## Pipeline Continuation\n\nThis completes the ${commandName} stage. To continue the Gofer pipeline:\n\n**Next Command:** \`#${nextCommand}\`\n\nThe next stage will read the artifacts from this stage and continue the workflow automatically.\n\n**Note:** Copilot Chat supports context preservation. Your conversation history will be maintained as you progress through pipeline stages.\n`;
895
+ if (content.includes('<!-- gofer:next-contract:start -->')) return content;
896
+ const autoChainSection = `\n\n## Pipeline Continuation\n<!-- gofer:next-contract:start -->\n\nNext internal contract: \`.specify/commands/${nextCommand}.md\`. Read and follow it in the same conversation after the current stage's required evidence and approval checks pass. Apply the shared continuation contract; do not ask the user to invoke a numbered command. Honor research-only requests, explicit pauses and material/user approval gates. If blocked, report Progress, Stop reason and Next action.\n<!-- gofer:next-contract:end -->\n`;
494
897
 
495
898
  if (content.includes('## Key Rules')) {
496
899
  return content.replace('## Key Rules', `${autoChainSection}\n## Key Rules`);
@@ -499,38 +902,73 @@ function injectPipelineContinuation(content, platform, commandName) {
499
902
  return content + autoChainSection;
500
903
  }
501
904
 
502
- function buildEaiPlatformSessionPreflightSection() {
503
- return `
504
- ## EAI Platform Session Preflight
905
+ export function buildAuthAccessDecisionContract() {
906
+ return `**Authentication Access Decision**
505
907
 
506
- Before any Gofer stage/helper command does pipeline work:
908
+ When adding or changing authentication, read \`.specify/references/platform/eai-auth-access.md\`. Ask: **"Who should be able to use this app: only members of its EAI workspace (recommended), or any authenticated EAI user?"** Default to \`workspace-only\`. Wait for the answer before changing auth code. An unanswered question must not widen access. Preserve stricter existing rules. Record the answer in the feature spec; do not repeat a confirmed question unless its scope changes.
507
909
 
508
- 1. Treat durable delivery as EAI Platform delivery by default, with Azure second and every other stack only by explicit exception.
509
- 2. Run \`eai whoami\` and confirm the EAI CLI is installed, the user is logged in, and an active workspace is visible.
510
- 3. If \`eai\` is missing, \`eai whoami\` fails, the token is expired, or no active workspace is available, stop and run \`/gofer:eai-first-run\` or ask the user to approve login/setup before continuing.
511
- 4. For EAI app delivery, do not continue into research, specification, planning, tasks, implementation, or validation until \`.specify/specs/{feature}/eai-preflight.md\` records login, workspace, template, app-readiness, and next-action evidence.
512
- 5. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local \`.env\` values into Gofer artifacts; record only product-safe readiness status and evidence.
910
+ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Verify platform support and CLI syntax; do not invent SSO commands. Enforce trusted server-side workspace membership and app permissions. A session, CIAM directory ID, or email domain alone is not workspace access. Platform-wide sign-in never grants access to another workspace's data. Test allowed and denied users, revoked membership, unavailable membership checks, and cross-workspace requests. These checks apply only when authentication is implemented or required, not to non-app work or an auth-free local MVP.`;
911
+ }
912
+
913
+ function buildEaiPlatformSessionPreflightSection() {
914
+ return `
915
+ ## Application Classification And EAI Preflight
916
+
917
+ Before any EAI CLI, login, workspace, template, or app-enrollment action:
918
+
919
+ 1. Classify the request as **EAI app delivery** or **non-application work** using the application signals in \`.specify/commands/0_gofer_start.md\`.
920
+ 2. Create \`.specify/specs/{feature}/\` and record the active delivery scope before app or operator-tool source work.
921
+ 3. If the request is clearly non-app work, confirm once: **"This looks like non-app work, so I will skip EAI workspace/app setup and continue the Gofer research/docs path. Is that right?"**
922
+ 4. If the user confirms non-app, record the decision and mark app-only capabilities \`not_applicable\`. Do not run \`eai whoami\`, \`eai workspace select\`, \`eai init\`, or \`/gofer:eai-first-run\`.
923
+ 5. For local MVP app work, validate the implemented user journey, repo runner, and preview evidence. Do not require EAI setup, authentication, or deployment when the active specification does not require them.
924
+ 6. When the feature uses EAI Platform services, requires a workspace, or prepares deployment, run \`eai whoami\` and record the EAI readiness evidence in \`eai-preflight.md\`.
925
+ 7. When the feature creates, changes, or validates an EAI Platform app integration, run \`node .specify/scripts/node/eai-app-template-readiness.mjs --root . --json\`. A missing checker or status other than \`ready\` blocks that EAI capability. It does not block unrelated local MVP work.
926
+ 8. When authentication is implemented or required, validate provider, callback, sign-in, session, first protected API call, and safe denied access.
927
+ 9. When deployment is requested or claimed, require the relevant EAI template, security, configuration, and deployment evidence before completion.
928
+ 10. For durable app delivery, use EAI Platform first, Azure second, and every other stack only by explicit exception.
929
+ 11. If the user changes scope, update \`spec.md\`, \`plan.md\`, \`tasks.md\`, \`traceability.md\`, and validation scope before continuing. Explain the business effect and evidence change.
930
+ 12. Do not accept copied marker files, partial scaffolds, or custom templates as readiness evidence for an EAI capability.
931
+ 13. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local \`.env\` values into Gofer artifacts; record only product-safe readiness status and evidence.
932
+
933
+ ${buildAuthAccessDecisionContract()}
513
934
  `.trim();
514
935
  }
515
936
 
516
937
  function injectEaiPlatformSessionPreflight(content) {
517
- if (content.includes('## EAI Platform Session Preflight')) {
518
- return content;
938
+ const section = `${buildMvpCapabilityValidationSection()}\n\n${buildEaiPlatformSessionPreflightSection()}`;
939
+ // Remove previous generated copies before replacing the bounded preflight.
940
+ // This makes a workspace refresh idempotent.
941
+ const withoutMvpCapabilitySection = content.replace(
942
+ /\n?## MVP Capability-Based Validation\n[\s\S]*?(?=\n## |\s*$)/g,
943
+ ''
944
+ );
945
+ const existingHeading = withoutMvpCapabilitySection.includes('## Application Classification And EAI Preflight')
946
+ ? '## Application Classification And EAI Preflight'
947
+ : withoutMvpCapabilitySection.includes('## EAI Platform Session Preflight')
948
+ ? '## EAI Platform Session Preflight'
949
+ : null;
950
+
951
+ if (existingHeading) {
952
+ const headingIndex = withoutMvpCapabilitySection.indexOf(existingHeading);
953
+ const nextHeadingIndex = withoutMvpCapabilitySection.indexOf('\n## ', headingIndex + existingHeading.length);
954
+ const suffix = nextHeadingIndex === -1 ? '' : withoutMvpCapabilitySection.slice(nextHeadingIndex).replace(/^\n+/, '');
955
+ return suffix
956
+ ? `${withoutMvpCapabilitySection.slice(0, headingIndex).trimEnd()}\n\n${section}\n\n${suffix}`
957
+ : `${withoutMvpCapabilitySection.slice(0, headingIndex).trimEnd()}\n\n${section}\n`;
519
958
  }
520
959
 
521
- const section = buildEaiPlatformSessionPreflightSection();
522
- const workspaceHeadingIndex = content.indexOf('## Workspace Preflight');
960
+ const workspaceHeadingIndex = withoutMvpCapabilitySection.indexOf('## Workspace Preflight');
523
961
  if (workspaceHeadingIndex !== -1) {
524
- const nextHeadingIndex = content.indexOf('\n## ', workspaceHeadingIndex + 1);
962
+ const nextHeadingIndex = withoutMvpCapabilitySection.indexOf('\n## ', workspaceHeadingIndex + 1);
525
963
  if (nextHeadingIndex !== -1) {
526
- return `${content.slice(0, nextHeadingIndex).trimEnd()}\n\n${section}\n\n${content
964
+ return `${withoutMvpCapabilitySection.slice(0, nextHeadingIndex).trimEnd()}\n\n${section}\n\n${withoutMvpCapabilitySection
527
965
  .slice(nextHeadingIndex)
528
966
  .replace(/^\n+/, '')}`;
529
967
  }
530
- return `${content.trimEnd()}\n\n${section}\n`;
968
+ return `${withoutMvpCapabilitySection.trimEnd()}\n\n${section}\n`;
531
969
  }
532
970
 
533
- return `${section}\n\n${content}`;
971
+ return `${section}\n\n${withoutMvpCapabilitySection}`;
534
972
  }
535
973
 
536
974
  function buildWorkspacePreflightSection(host = 'auto', includeEaiPreflight = true) {
@@ -548,6 +986,7 @@ Before doing stage/helper work:
548
986
  - \`.specify/.gofer-version\`
549
987
  - \`.specify/commands/0_gofer_start.md\`
550
988
  - \`.specify/templates/spec-template.md\`
989
+ - \`.specify/templates/build-map-template.md\`
551
990
  - \`.specify/templates/loop-contract-template.json\`
552
991
  - \`.specify/templates/working-backwards-prfaq-template.md\`
553
992
  - \`.specify/templates/business-owner-summary-template.md\`
@@ -561,19 +1000,32 @@ Before doing stage/helper work:
561
1000
  - \`.specify/scripts/powershell/install-optional-tools.ps1\`
562
1001
  - \`.specify/templates/gofer-model-policy.yaml\`
563
1002
  - \`.specify/memory/gofer-model-policy.yaml\`
1003
+ - \`.specify/scripts/node/gofer-local-settings-cleanup.mjs\`
1004
+ - \`.specify/scripts/node/gofer-ui-preview.mjs\`
564
1005
  - \`.specify/specs/\`
565
1006
  - \`.specify/memory/\`
566
1007
  3. Check host-specific repo-owned files when relevant:
567
1008
  - Claude: \`AGENTS.md\`, \`CLAUDE.md\`, \`.claude/settings.json\`
568
1009
  - Codex: \`AGENTS.md\`
569
1010
  - Copilot: \`.github/copilot-instructions.md\`
570
- - VS Code extension mirrors Claude/Copilot/Gemini resources itself and should still keep the core scaffold healthy
1011
+ - Google Antigravity: \`AGENTS.md\`, \`GEMINI.md\`
1012
+ - Grok Build: \`AGENTS.md\`; its installed plugin provides \`skills/eai/SKILL.md\`
1013
+ - VS Code: \`.github/copilot-instructions.md\`; the extension manages its packaged resource mirrors
571
1014
  4. If the repo already has the workspace checker script, prefer running:
572
1015
  - \`node .specify/scripts/node/gofer-workspace-check.mjs --host ${host} --json\`
573
1016
  5. If the workspace is missing or stale, ask exactly:
574
1017
  - **"This repo is missing or stale for Gofer. Initialize/update it now?"**
575
1018
  6. If the user says yes, run the Gofer workspace bootstrap helper and then resume this command from the top.
576
- 7. If the user says no, stop and explain that Gofer stage/helper work depends on the repo-owned scaffold.${eaiPreflight}
1019
+ 7. After a Gofer install, update, or bootstrap, remove stale local Gofer command entries with:
1020
+ - \`node .specify/scripts/node/gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1021
+ 8. If the cleanup helper is only available in the downloaded bundle, run:
1022
+ - macOS/Linux: \`node ~/plugins/eai-gofer/.specify/scripts/node/gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1023
+ - Windows: \`node %USERPROFILE%\\plugins\\eai-gofer\\.specify\\scripts\\node\\gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1024
+ 9. For EAI app delivery, use the repo runner for local previews:
1025
+ - macOS, Linux, and GitHub Codespaces: \`./run.sh dev 3001\`
1026
+ - Windows: \`run.bat dev 3001\`
1027
+ 10. Do not start app previews with direct \`npm run dev\` commands when the repo runner exists.
1028
+ 11. If the user says no, stop and explain that Gofer stage/helper work depends on the repo-owned scaffold.${eaiPreflight}
577
1029
  `.trim();
578
1030
  }
579
1031
 
@@ -592,7 +1044,8 @@ function injectWorkspacePreflight(content, commandName, host = 'auto') {
592
1044
 
593
1045
  const section = buildWorkspacePreflightSection(
594
1046
  host,
595
- !content.includes('## EAI Platform Session Preflight')
1047
+ !content.includes('## Application Classification And EAI Preflight') &&
1048
+ !content.includes('## EAI Platform Session Preflight')
596
1049
  );
597
1050
  const headingMatch = content.match(/^# [^\n]+\n+/);
598
1051
  if (!headingMatch) {
@@ -612,12 +1065,8 @@ function buildTokenCostPolicySection() {
612
1065
 
613
1066
  Before spawning agents, calling tools, or loading large files:
614
1067
 
615
- 1. Treat \`.specify/memory/gofer-model-policy.yaml\` as the repo-owned source of truth for simple, medium, hard, and arbiter model routing. If it is missing, run \`/gofer:bootstrap-workspace\` before continuing.
616
- 2. Use the cheapest capable model first.
617
- - Claude: Haiku for scouting/extraction; Sonnet for normal implementation, synthesis, validation, and security; Opus for high-risk arbitration or release-critical failures.
618
- - Codex/OpenAI: GPT mini for simple coding; GPT nano only for locate/classify/summarize/mechanical work; GPT-5.3-Codex or flagship GPT for tool-heavy coding, architecture, and release-critical validation.
619
- - Gemini: Flash-Lite for cheap large-context scan/summarize; Flash for default research synthesis; Pro for large-context architecture or high-risk arbitration.
620
- - Copilot: prefer Auto for simple and default work; ask the user before choosing a paid/high-tier picker model for hard security, architecture, or release gates.
1068
+ 1. Treat \`.specify/memory/gofer-model-policy.yaml\` as advisory capability, cost, and quality constraints. A fresh signed host receipt and independently verified benchmark evidence select the model. If it is missing, run \`/gofer:bootstrap-workspace\` before continuing.
1069
+ 2. Use the lowest-cost model that the live router qualifies for this task. Its signed host receipt and independent benchmark evidence must govern the exact model identity. Do not select a model from static provider examples, names, or price alone.
621
1070
  3. Keep raw tool output out of the main conversation context. Save stable findings to \`.specify/specs/{feature}/context-bundle.md\`, then work from summaries.
622
1071
  4. Use provider prompt/context caching only for stable, non-secret prefixes: Gofer scaffold, AGENTS/CLAUDE/Copilot instructions, constitution, repo map, stage contracts, and validation rubric.
623
1072
  5. Before continuing after large research, planning, implementation, or validation bursts, checkpoint the durable artifacts and compact/clear/resume context when the host supports it.
@@ -626,7 +1075,250 @@ Before spawning agents, calling tools, or loading large files:
626
1075
  `.trim();
627
1076
  }
628
1077
 
1078
+ function buildBusinessProgressContractSection() {
1079
+ return `
1080
+ ## Business-Friendly Progress Contract
1081
+ <!-- gofer:business-progress:start -->
1082
+
1083
+ Default user-facing updates must be concise, business-level, and easy to scan.
1084
+ Keep the technical work rigorous in artifacts, tests, logs, and code, but do
1085
+ not lead with implementation jargon unless the user asks for it.
1086
+
1087
+ Use ASD-STE100 Simplified Technical English as the target writing standard for
1088
+ all Gofer-authored chat, documents, commands, summaries, PR notes, error
1089
+ guidance, and validation artifacts. ASD-STE100 is copyright and a trademark of
1090
+ ASD; do not bundle the protected ASD dictionary and do not claim ASD
1091
+ certification.
1092
+
1093
+ 1. Explain progress as what is being connected, changed, checked, or fixed and
1094
+ why it matters to the business outcome.
1095
+ 2. Use the running build map: create or update
1096
+ \`.specify/specs/{feature}/build-map.md\` from
1097
+ \`.specify/templates/build-map-template.md\` for application delivery, and
1098
+ refer to its plain-language areas in progress updates.
1099
+ 3. When there is a problem, translate it into business impact, current status,
1100
+ next action, and what input or approval is needed. Keep raw stack traces,
1101
+ command logs, IDs, and acronyms out of chat unless asked.
1102
+ 4. If the user asks for technical depth, provide it on request and point to the
1103
+ durable artifact that contains the evidence.
1104
+ 5. Prefer a compact update shape:
1105
+ - \`Working on\`: the build-map area or stakeholder outcome
1106
+ - \`Why it matters\`: user/business impact
1107
+ - \`Status\`: done, checking, fixing, blocked, or needs decision
1108
+ 6. Use one action per instruction.
1109
+ 7. Keep instructions to 20 words or fewer where possible.
1110
+ 8. Use active voice unless the actor is unknown or not important.
1111
+ 9. Use simple verb forms: simple present, simple past, simple future,
1112
+ infinitive, or imperative.
1113
+ 10. Define acronyms on first use and use approved project terms.
1114
+ 11. Avoid idioms, marketing adjectives, vague praise, and hedging.
1115
+ 12. Use vertical lists for complex information and one topic per paragraph.
1116
+ 13. For errors, state what happened, why it matters, what to do next, and the
1117
+ exact safe command when one exists.
1118
+ 14. Do not remove technical validation, security checks, EAI preflights, tests,
1119
+ or loop evidence. This contract changes presentation, not engineering
1120
+ standards.
1121
+ 15. Before each user-facing reply, check that it leads with the business effect,
1122
+ uses concise simple language, and includes only useful technical detail.
1123
+ 16. If any check fails, rewrite the reply before sending it.
1124
+ ${buildDeliveryDisciplineContract()}
1125
+
1126
+ <!-- gofer:business-progress:end -->
1127
+ `.trim();
1128
+ }
1129
+
1130
+ function buildLocalSettingsCleanupContractSection() {
1131
+ return `
1132
+ ## Local Settings Cleanup Contract
1133
+ <!-- gofer:local-settings-cleanup:start -->
1134
+
1135
+ After any Gofer install, update, release refresh, or workspace bootstrap:
1136
+
1137
+ 1. Archive stale Gofer command and skill entries before continuing.
1138
+ 2. Prefer the repo helper:
1139
+ - \`node .specify/scripts/node/gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1140
+ 3. If the repo helper is missing, use the stable plugin bundle helper:
1141
+ - macOS/Linux: \`node ~/plugins/eai-gofer/.specify/scripts/node/gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1142
+ - Windows: \`node %USERPROFILE%\\plugins\\eai-gofer\\.specify\\scripts\\node\\gofer-local-settings-cleanup.mjs --workspace . --apply --json\`
1143
+ 4. This cleanup covers old Claude, Codex, Copilot, Gemini, Grok, VS Code, desktop, and CLI command surfaces.
1144
+ 5. Do not remove the current public \`eai\` entrypoint.
1145
+ 6. Ask the user to refresh or restart the host command picker only after cleanup completes.
1146
+ <!-- gofer:local-settings-cleanup:end -->
1147
+ `.trim();
1148
+ }
1149
+
1150
+ function injectLocalSettingsCleanupContract(content) {
1151
+ if (content.includes('<!-- gofer:local-settings-cleanup:start -->')) {
1152
+ return content;
1153
+ }
1154
+
1155
+ const workspaceHeadingIndex = content.indexOf('## Workspace Preflight');
1156
+ if (workspaceHeadingIndex !== -1) {
1157
+ const nextHeadingIndex = content.indexOf('\n## ', workspaceHeadingIndex + 1);
1158
+ if (nextHeadingIndex !== -1) {
1159
+ return `${content.slice(0, nextHeadingIndex).trimEnd()}\n\n${buildLocalSettingsCleanupContractSection()}\n\n${content
1160
+ .slice(nextHeadingIndex)
1161
+ .replace(/^\n+/, '')}`;
1162
+ }
1163
+ }
1164
+
1165
+ return `${content.trimEnd()}\n\n${buildLocalSettingsCleanupContractSection()}`;
1166
+ }
1167
+
1168
+ function buildAppPreviewRunnerContractSection() {
1169
+ return `
1170
+ ## App Preview Runner Contract
1171
+ <!-- gofer:app-preview-runner:start -->
1172
+
1173
+ For EAI app delivery, every UI preview must use the repo runner when it exists.
1174
+
1175
+ 1. Use \`./run.sh dev 3001\` on macOS, Linux, and GitHub Codespaces.
1176
+ 2. Use \`run.bat dev 3001\` on Windows.
1177
+ 3. Use a different port only when the feature notes record the reason.
1178
+ 4. Restart only this app. Before stopping a process, verify its exact checkout, process ID, start time and command, then recheck immediately before stopping it. Never stop another app, an unknown process, or every process on a port. If ownership is uncertain, leave it running and ask the user. Inspect older runners before use; do not run one that kills by port alone.
1179
+ 5. Do not use direct \`npm run dev\`, \`next dev\`, or package-manager preview commands when \`run.sh\`, \`run.bat\`, or \`run.ps1\` exists.
1180
+ 6. After every UI-facing change, run:
1181
+ - \`node .specify/scripts/node/gofer-ui-preview.mjs --feature-dir {FEATURE_DIR} --command "./run.sh dev 3001" --open auto --screenshot --change "<change summary>"\`
1182
+ 7. On Windows, use:
1183
+ - \`node .specify/scripts/node/gofer-ui-preview.mjs --feature-dir {FEATURE_DIR} --command "run.bat dev 3001" --open auto --screenshot --change "<change summary>"\`
1184
+ 8. If the runner is missing in an EAI app template repo, refresh the template before preview work continues.
1185
+ 9. Check the exact preview page and the current implemented user journey after each change. A running process, open browser, screenshot alone, error page or dry run is not proof that it works. Say ready to view only after those checks pass. Otherwise explain what is unchecked or failing; do not claim readiness. Record fresh browser and test evidence. Local MVP checks cover only implemented behaviour; do not add future auth or deployment gates. Keep showing clearly labelled drafts without adding approval stops.
1186
+ <!-- gofer:app-preview-runner:end -->
1187
+ `.trim();
1188
+ }
1189
+
1190
+ function injectAppPreviewRunnerContract(content) {
1191
+ if (content.includes('<!-- gofer:app-preview-runner:start -->')) {
1192
+ return content.replace(/## App Preview Runner Contract\n<!-- gofer:app-preview-runner:start -->[\s\S]*?<!-- gofer:app-preview-runner:end -->/, buildAppPreviewRunnerContractSection());
1193
+ }
1194
+
1195
+ const progressHeadingIndex = content.indexOf('## Business-Friendly Progress Contract');
1196
+ if (progressHeadingIndex !== -1) {
1197
+ const nextHeadingIndex = content.indexOf('\n## ', progressHeadingIndex + 1);
1198
+ if (nextHeadingIndex !== -1) {
1199
+ return `${content.slice(0, nextHeadingIndex).trimEnd()}\n\n${buildAppPreviewRunnerContractSection()}\n\n${content
1200
+ .slice(nextHeadingIndex)
1201
+ .replace(/^\n+/, '')}`;
1202
+ }
1203
+ }
1204
+
1205
+ return `${content.trimEnd()}\n\n${buildAppPreviewRunnerContractSection()}`;
1206
+ }
1207
+
1208
+ function insertSectionAfterTitle(content, section) {
1209
+ const frontmatterMatch = content.match(/^---\n[\s\S]*?\n---\n?/);
1210
+ const prefix = frontmatterMatch ? frontmatterMatch[0].trimEnd() : '';
1211
+ const body = frontmatterMatch
1212
+ ? content.slice(frontmatterMatch[0].length).replace(/^\n+/, '')
1213
+ : content;
1214
+
1215
+ const headingMatch = body.match(/^# [^\n]+\n+/);
1216
+ if (!headingMatch) {
1217
+ return prefix
1218
+ ? `${prefix}\n\n${section}\n\n${body}`
1219
+ : `${section}\n\n${body}`;
1220
+ }
1221
+
1222
+ const insertAt = headingMatch[0].length;
1223
+ const refreshedBody = `${body.slice(0, insertAt)}${section}\n\n${body
1224
+ .slice(insertAt)
1225
+ .replace(/^\n+/, '')}`;
1226
+ return prefix ? `${prefix}\n\n${refreshedBody}` : refreshedBody;
1227
+ }
1228
+
1229
+ function injectBusinessProgressContract(content) {
1230
+ const section = buildBusinessProgressContractSection();
1231
+ const startMarker = '<!-- gofer:business-progress:start -->';
1232
+ const endMarker = '<!-- gofer:business-progress:end -->';
1233
+
1234
+ if (content.includes(startMarker) && content.includes(endMarker)) {
1235
+ const headingIndex = content.indexOf('## Business-Friendly Progress Contract');
1236
+ const endIndex = content.indexOf(endMarker, headingIndex) + endMarker.length;
1237
+ const suffix = content.slice(endIndex).replace(/^\n+/, '');
1238
+ return suffix
1239
+ ? `${content.slice(0, headingIndex).trimEnd()}\n\n${section}\n\n${suffix}`
1240
+ : `${content.slice(0, headingIndex).trimEnd()}\n\n${section}\n`;
1241
+ }
1242
+
1243
+ for (const heading of [
1244
+ '## Token And Cost Policy',
1245
+ '## Application Classification And EAI Preflight',
1246
+ '## EAI Platform Session Preflight',
1247
+ ]) {
1248
+ const headingIndex = content.indexOf(heading);
1249
+ if (headingIndex === -1) continue;
1250
+ const nextHeading = content.indexOf('\n## ', headingIndex + 1);
1251
+ if (nextHeading !== -1) {
1252
+ return `${content.slice(0, nextHeading).trimEnd()}\n\n${section}\n\n${content
1253
+ .slice(nextHeading)
1254
+ .replace(/^\n+/, '')}`;
1255
+ }
1256
+ }
1257
+
1258
+ return insertSectionAfterTitle(content, section);
1259
+ }
1260
+
1261
+ export function buildContinuationContractSection() {
1262
+ return `## Continuation And Stop Contract
1263
+ <!-- gofer:continuation:start -->
1264
+
1265
+ 1. Preserve the requested scope and mode, including read-only, plan-only, research-only and MVP work. Keep the full applicable pipeline, stage functions, artifacts, reviews and validation; do not expand an MVP into an unapproved release.
1266
+ 2. After a stage's required evidence is complete, read and follow the next internal file in .specify/commands/ in the same conversation. Do not require a numbered command or a host-specific skill dispatcher. Optional helpers remain optional; maintenance and control commands do not start delivery work.
1267
+ 3. Treat the stated business goal as authority for ordinary planning, task ordering, design, diagnosis, repair, testing, and reversible repository changes within scope. Record material Gofer decisions with their reason and effect. Do not ask the user to choose implementation details that Gofer can safely decide.
1268
+ 4. Ask only when the goal is unclear or changes, the action is irreversible or destructive, it changes security or access, it creates external cost or commitment, it changes production or public exposure, it requires missing authority or credentials, or it conflicts with an explicit user constraint. Record the exact reason before asking. missing or ambiguous approval is not approval when an approval boundary applies. Rejected, revoked, changed or unclear authority requires a pause.
1269
+ 5. Pause for material scope, security, cost, deployment, destructive or protected files/boundary changes and any outstanding user gate. A business goal does not authorize publishing, spending, external changes, or bypassing host permissions. Complete safe authorized work without bypassing the blocked gate.
1270
+ 6. A tool proposal is not execution. If host consent is required, wait for it. After the tool result or approved proposal returns, inspect the result and resume the next authorized action within approved scope; do not end with only a plan or a proposed tool call. A denied tool or unavailable capability must not be bypassed through another host or CLI.
1271
+ 7. Use the current agent's available native tools. Optional Gofer/MCP tools are conveniences, not prerequisites. If the current agent lacks a required capability, report that limitation and the safe next action; do not pretend a handoff button transfers control automatically.
1272
+ 8. Stop after research only when research-only work was requested, the user paused, or a real gate blocks progress. Otherwise continue to specification. At validation, report completion only when the requested scope's required evidence passes; failures remain unfinished work.
1273
+ 9. Respect budget, context and retry limits from the existing loop contract. Repair safe within-scope failures only within those limits. Preserve a checkpoint before an orderly context stop; resume by reading its recorded stage and rechecking scope, approvals and evidence. Never claim an abrupt host termination was handled.
1274
+ 10. Report concise Progress during work. At every controlled stop, report Progress, Stop reason and Next action, including the exact missing input or approval and unfinished work. Reasons are requested scope complete, user pause, approval required, material change, missing capability/access, validation blocked, or budget/context/retry limit. Stage completion alone is not pipeline completion.
1275
+ ${buildBlockerMediationContract()}
1276
+ ${buildVerifiedSpecialistContract()}
1277
+ <!-- gofer:continuation:end -->`;
1278
+ }
1279
+
1280
+ export function buildBlockerMediationContract() {
1281
+ return `
1282
+ **Blocker Mediation**
1283
+
1284
+ - Before repeating a failed action or asking for missing input, read .specify/references/blocker-mediation.md and inspect the private blocker register with gofer-blocker-control.mjs. Reuse the same state directory and goal, subject and condition keys across stages, restarts and surfaces. Different wording, models or tools do not create a new blocker.
1285
+ - Classify the cause first. Missing user decisions, access, external dependencies and unavailable capabilities require a recorded wait. Reserve an ask event before asking; ask once, explain the business impact and required change, then stop affected work. An unanswered question is not new evidence. Do not poll or rephrase it to keep running.
1286
+ - Technical ask events require a fresh verification file under .specify/references/priority-outcome-protection.md: actual diagnosis, self-cause check and why no authorized repair is available. Business choices need no failed command. For feature tasks, use gofer-priority-check.mjs and the saved direction before switching work; this does not start delivery during maintenance or conversation.
1287
+ - For AI-solvable or unknown causes, reserve each attempt before execution. Allow one investigation and one different recovery within existing tighter budgets. Record its result even when interrupted or unsuccessful. An unfinished reservation must not launch again. Do not reset the register, change keys or switch surfaces to obtain more attempts.
1288
+ - Resume only after a real user answer or changed external evidence has been recorded and checked. The helper allows one evidence-backed resumption; exhausted limits need human review. Never invent approval or evidence. Successful model output and a running server do not resolve a blocker without the relevant check.
1289
+ - Save the blocker, unfinished tasks and next action before stopping. Continue only approved tasks that do not depend on it. Keep the original goal; update specs, plans, tasks and validation for accepted direction changes, and reopen stale checks. Do not quietly drop requirements to make progress.
1290
+ - Use node .specify/scripts/node/gofer-blocker-control.mjs --state-dir <private-state-directory> --event <private-event.json> before controlled actions; inspect with --state-dir alone, or add --task T001 for an independent task. A denied action, invalid record or missing helper means stop and explain the limitation, not bypass it. Use the installed plugin script path if no repo scaffold exists. Conversation-only work uses a private session state directory and does not require app setup or feature files.
1291
+ - Strict loop validation checks every recorded feature blocker. Shared instructions guide native chats; this helper cannot intercept calls that a host sends directly. Do not claim native enforcement from package tests alone.`;
1292
+ }
1293
+
1294
+ export function buildVerifiedSpecialistContract() {
1295
+ return `
1296
+
1297
+ ## Verified Specialist Execution
1298
+
1299
+ Use .specify/references/verified-agent-execution.md before specialist delegation in any app or non-app stage. The shared agent-catalog.json retains specialist responsibilities. Resolve roles with gofer-agent-catalog.mjs; obtain tools and models from the current host, never from another provider's examples. Keep internal roles out of the public command picker.
1300
+
1301
+ Preserve every required review. Provider-specific Task/model examples describe intent, not portable commands or proof of support. Run independent work together only when dependencies, permission boundaries, scope and budgets allow it. Otherwise serialize supported work. A required independent review remains unverified if separate execution is unavailable; never relabel self-review as independent.
1302
+
1303
+ The experimental gofer-verified-execution.mjs controller accepts trusted adapters, not worker-supplied commands. It checks current priority, bounds calls and attempts, records required checks, and rejects stale results. Its local process tests do not qualify native model execution. Do not activate an unqualified host adapter or bypass existing blocker, permission, outcome or release gates. Preserve normal safe Gofer work and explain the limitation.
1304
+ `;
1305
+ }
1306
+
1307
+ export function injectContinuationContract(content) {
1308
+ const section = buildContinuationContractSection();
1309
+ const pattern = /## Continuation And Stop Contract\n<!-- gofer:continuation:start -->[\s\S]*?<!-- gofer:continuation:end -->/;
1310
+ const cleaned = content.replace(/(<!-- gofer:continuation:end -->)\n+## Verified Specialist Execution\n[\s\S]*?(?=\n## |$)/g, '$1');
1311
+ if (pattern.test(cleaned)) return cleaned.replace(pattern, section);
1312
+ return insertSectionAfterTitle(cleaned, section);
1313
+ }
1314
+
629
1315
  function injectTokenCostPolicy(content) {
1316
+ return injectContinuationContract(injectAppPreviewRunnerContract(
1317
+ injectLocalSettingsCleanupContract(injectBusinessProgressContract(injectTokenCostPolicyOnly(content)))
1318
+ ));
1319
+ }
1320
+
1321
+ function injectTokenCostPolicyOnly(content) {
630
1322
  const section = buildTokenCostPolicySection();
631
1323
  const startMarker = '<!-- gofer:token-cost-policy:start -->';
632
1324
  const endMarker = '<!-- gofer:token-cost-policy:end -->';
@@ -671,15 +1363,57 @@ function injectTokenCostPolicy(content) {
671
1363
  }
672
1364
  }
673
1365
 
674
- const headingMatch = content.match(/^# [^\n]+\n+/);
675
- if (!headingMatch) {
676
- return `${section}\n\n${content}`;
1366
+ return insertSectionAfterTitle(content, section);
1367
+ }
1368
+
1369
+ async function refreshCanonicalCommandSources(root, dryRun) {
1370
+ const commandsDir = path.join(root, '.specify', 'commands');
1371
+ let entries;
1372
+ try {
1373
+ entries = await fs.readdir(commandsDir);
1374
+ } catch {
1375
+ throw new Error(`.specify/commands/ not found at ${commandsDir}`);
677
1376
  }
678
1377
 
679
- const insertAt = headingMatch[0].length;
680
- const prefix = content.slice(0, insertAt);
681
- const suffix = content.slice(insertAt).replace(/^\n+/, '');
682
- return `${prefix}${section}\n\n${suffix}`;
1378
+ let changed = 0;
1379
+ for (const entry of entries) {
1380
+ if (!entry.endsWith('.md') || entry === '.gitkeep') continue;
1381
+ const filePath = path.join(commandsDir, entry);
1382
+ const source = await fs.readFile(filePath, 'utf8');
1383
+ // Emitter tests use intentionally partial command fixtures. Only normalize
1384
+ // canonical command files that can be parsed and emitted as real stages.
1385
+ if (!source.startsWith('---')) continue;
1386
+ let refreshed = LEGACY_HELPER_COMMAND_FILES.has(entry)
1387
+ ? injectContinuationContract(source)
1388
+ : injectTokenCostPolicy(injectEaiPlatformSessionPreflight(source));
1389
+ if (refreshed.includes('<!-- gofer:app-preview-runner:start -->')) {
1390
+ refreshed = injectAppPreviewRunnerContract(refreshed);
1391
+ }
1392
+ if (entry === 'gofer_eai_first_run.md') {
1393
+ const withoutAuthScope = refreshed.replace(
1394
+ /\n?## Auth Scope Before Setup\n[\s\S]*?(?=\n## |\s*$)/g,
1395
+ ''
1396
+ );
1397
+ refreshed = insertSectionAfterTitle(
1398
+ withoutAuthScope,
1399
+ `## Auth Scope Before Setup\n\n${buildAuthAccessDecisionContract()}`
1400
+ );
1401
+ }
1402
+ if (refreshed === source) continue;
1403
+
1404
+ changed++;
1405
+ if (dryRun) {
1406
+ console.log(`[dry-run] canonical commands: would normalize ${path.relative(root, filePath)}`);
1407
+ continue;
1408
+ }
1409
+
1410
+ await fs.writeFile(filePath, refreshed, 'utf8');
1411
+ }
1412
+
1413
+ if (changed > 0) {
1414
+ const suffix = dryRun ? ' would change' : ' changed';
1415
+ console.log(`Canonical command contracts:${suffix} ${changed} file(s)`);
1416
+ }
683
1417
  }
684
1418
 
685
1419
  /**
@@ -687,6 +1421,7 @@ function injectTokenCostPolicy(content) {
687
1421
  * @returns {string | null}
688
1422
  */
689
1423
  function getNextCommand(currentCommand) {
1424
+ if (currentCommand === '0a_problem_validation') return '1_gofer_research';
690
1425
  const pipeline = [
691
1426
  '0_gofer_start',
692
1427
  '1_gofer_research',
@@ -724,15 +1459,36 @@ function buildSkillContent(stageName, description, body) {
724
1459
  return `---\nname: ${stageName}\ndescription: "${description}"\n---\n\n${body}`;
725
1460
  }
726
1461
 
1462
+ async function emitDocumentationSkill(root, baseDir, dryRun, label) {
1463
+ const sourcePath = path.join(
1464
+ root,
1465
+ '.specify',
1466
+ 'skills',
1467
+ 'gofer-documentation',
1468
+ 'SKILL.md'
1469
+ );
1470
+ const outPath = path.join(baseDir, 'gofer-documentation', 'SKILL.md');
1471
+ try {
1472
+ await fs.access(sourcePath);
1473
+ } catch {
1474
+ return;
1475
+ }
1476
+ if (dryRun) {
1477
+ console.log(`[dry-run] ${label}: would write ${outPath}`);
1478
+ } else {
1479
+ await ensureDir(path.dirname(outPath));
1480
+ await fs.copyFile(sourcePath, outPath);
1481
+ console.log(`${label}: wrote ${outPath}`);
1482
+ }
1483
+ }
1484
+
727
1485
  function buildUmbrellaSkillContent(version, stages, hostLabel) {
728
- const stageList = stages
729
- .map((stage) => `- \`/${getStageOutputStem(stage)}\` - ${stage.frontmatter.description}`)
730
- .join('\n');
1486
+ const stageList = buildInternalStageList(stages);
731
1487
 
732
- return `---\nname: eai-gofer\ndescription: "Use Gofer's repo-owned pipeline, scripts, and validation tools without duplicating every slash command in the picker."\n---\n\n# EAI Gofer\n\nVersion: ${version}\nHost: ${hostLabel}\n\nUse this skill when the user asks to install, update, diagnose, run, or understand Gofer from an AI coding app. Prefer this umbrella skill for app-level discovery. Use the plain slash commands for individual pipeline stages.\n\n## Clean Surface Contract\n\n- Stage work uses the plain repo slash commands, for example \`/0_gofer_start\`, \`/1_gofer_research\`, and \`/6_gofer_validate\`.\n- App-level setup, troubleshooting, and explanation should use this \`eai-gofer\` skill plus the repo-owned scripts in \`.specify/scripts/\`.\n- Do not expose a second full set of namespaced stage commands in the same picker when plain slash commands are available.\n- Check workspace health before stage work: \`node .specify/scripts/node/gofer-workspace-check.mjs --host auto --json\`.\n- If missing or stale, ask the user before running: \`node .specify/scripts/node/gofer-workspace-bootstrap.mjs --host auto --include-mirrors\`.\n\n## Light Plugin And Repo Scripts\n\nThe light plugin installs durable Gofer knowledge and app integration metadata. The repository remains the source of truth for executable scripts, commands, templates, specs, and memory. After bootstrap, agents should prefer repo-local scripts over bundled fallback copies because the repo can be updated by \`eai gofer refresh\` or the VS Code extension.\n\n## First EAI Platform App\n\nIf the user is starting a first EAI Platform app, run \`/gofer:eai-first-run\` before \`/0_gofer_start\`. It is intentionally allowed before \`.specify/\` exists.\n\n## Current Pipeline\n\n${stageList}\n`;
1488
+ return `---\nname: eai\ndescription: "Use Gofer's repo-owned pipeline, scripts, and validation tools through one clean command surface."\n---\n\n# Eai\n\nVersion: ${version}\nHost: ${hostLabel}\n\nUse this skill when the user asks to install, update, diagnose, run, or understand Gofer from an AI coding app.\n\n## Clean Surface Contract\n\n- User-facing pickers should expose only \`eai\`.\n- Do not ask users to run numbered/helper stage commands such as \`/0_gofer_start\`, \`/1_gofer_research\`, or \`/6_gofer_validate\` unless they explicitly request internal details.\n- Keep the full pipeline available by routing internally through \`.specify/commands/*.md\` stage contracts.\n- Check workspace health before stage work: \`node .specify/scripts/node/gofer-workspace-check.mjs --host auto --json\`.\n- If missing or stale, ask the user before running: \`node .specify/scripts/node/gofer-workspace-bootstrap.mjs --host auto --include-mirrors\`.\n\n## Controlled English Contract\n\nUse ASD-STE100 Simplified Technical English as the target writing standard for all Gofer-authored chat, documents, commands, summaries, PR notes, error guidance, and validation artifacts. ASD-STE100 is copyright and a trademark of ASD; do not bundle the protected ASD dictionary and do not claim ASD certification.\n\nApply these rules before any user-facing output:\n\n1. Use short sentences. Keep instructions to 20 words or fewer where possible.\n2. Use one action per instruction.\n3. Use active voice. Use passive voice only when the actor is unknown or not important.\n4. Use simple present, simple past, simple future, infinitive, or imperative verb forms.\n5. Use approved project terms and necessary technical nouns only. Define acronyms on first use.\n6. Use direct words. Avoid idioms, marketing adjectives, vague praise, and hedging.\n7. Use vertical lists for complex information.\n8. Put one topic in each paragraph.\n9. For errors, write: what happened, why it matters, what to do next, and the exact safe command when one exists.\n10. Keep raw logs, stack traces, IDs, and secrets out of chat unless the user asks for technical detail.\n\n## Light Plugin And Repo Scripts\n\nThe light plugin installs durable Gofer knowledge and app integration metadata. The repository remains the source of truth for executable scripts, commands, templates, specs, and memory. After bootstrap, agents should prefer repo-local scripts over bundled fallback copies because the repo can be updated by \`eai gofer refresh\` or the VS Code extension.\n\n## App vs Non-App Routing\n\n- Classify each request before EAI readiness as EAI app delivery, non-application work, or ambiguous.\n- If the request is EAI app delivery or ambiguous, continue directly into the EAI app delivery path and run EAI readiness.\n- If the request is clearly non-app work, confirm once: **"This looks like non-app work, so I will skip EAI workspace/app setup and continue the Gofer research/docs path. Is that right?"**\n- If the user confirms non-app, do not run \`eai whoami\`, workspace selection, \`eai init\`, or first-run setup. Record the decision and continue the appropriate non-app path.\n\n## First EAI Platform App\n\nIf the user is starting a first EAI Platform app, use this public entrypoint and then follow the first-run/setup contract in \`.specify/commands/gofer_eai_first_run.md\` when it is present. That setup path is intentionally allowed before \`.specify/\` exists.\n\n${buildVerifiedEaiCliCommandContract()}\n\n## Internal Pipeline Contracts\n\n${stageList}\n`;
733
1489
  }
734
1490
 
735
- function buildGithubAgentContent({ id, description, tools, handoffs, body }) {
1491
+ export function buildGithubAgentContent({ id, description, tools, handoffs, body }) {
736
1492
  const frontmatter = [
737
1493
  '---',
738
1494
  `description: ${JSON.stringify(description)}`,
@@ -751,49 +1507,57 @@ function buildGithubAgentContent({ id, description, tools, handoffs, body }) {
751
1507
 
752
1508
  frontmatter.push('---');
753
1509
 
754
- return `${frontmatter.join('\n')}\n\n# ${id}\n\n${body.trim()}\n`;
1510
+ return `${frontmatter.join('\n')}\n\n# ${id}\n\n${buildUserFacingResponseGateSection()}\n\n${buildContinuationContractSection()}\n\n${body.trim()}\n`;
755
1511
  }
756
1512
 
757
- function getGithubAgentSpecs() {
758
- const goferTools = [
759
- 'search/codebase',
760
- 'vscode/askQuestion',
761
- 'gofer_check_workspace',
762
- 'gofer_bootstrap_workspace',
763
- 'gofer_get_pipeline_state',
764
- 'gofer_start_stage',
765
- 'gofer_validate_branch',
766
- 'gofer_open_artifact',
767
- ];
1513
+ export function getGithubAgentSpecs() {
1514
+ // Every stage writes artifacts and runs local checks, including intake preflight.
1515
+ // Stage instructions constrain usage; tool lists are not permission grants.
1516
+ const stageTools = ['read', 'search', 'edit', 'execute'];
768
1517
 
769
1518
  return [
1519
+ {
1520
+ id: 'eai',
1521
+ description: 'Gofer public entrypoint. Use for EAI delivery, research, planning, implementation, validation, and workspace setup.',
1522
+ tools: stageTools,
1523
+ handoffs: [],
1524
+ body: `
1525
+ You are the public EAI entrypoint for Gofer.
1526
+
1527
+ Use \`.github/prompts/eai.prompt.md\` as the canonical user-facing contract and route work through the existing \`.specify/commands/*.md\` stage contracts. Do not create a second Copilot-specific pipeline or ask users to choose numbered stages.
1528
+
1529
+ Before routing work, run \`node .specify/scripts/node/gofer-workspace-check.mjs --host copilot --json\` when available. If the workspace is missing or stale, ask before running \`node .specify/scripts/node/gofer-workspace-bootstrap.mjs --host copilot --include-mirrors\`.
1530
+
1531
+ Keep the public surface to \`eai\`. Select the next internal stage from the current workspace state, preserve Gofer artifacts and traceability, and apply the same safety, approval, EAI readiness, and controlled-English rules defined by the canonical prompt.
1532
+ `,
1533
+ },
770
1534
  {
771
1535
  id: 'gofer-business',
772
1536
  description: 'Gofer start and setup agent. Use for first-run setup, workspace health, feature intake, and selecting the right pipeline entry point.',
773
- tools: goferTools,
1537
+ tools: stageTools,
774
1538
  handoffs: [
775
1539
  {
776
1540
  agent: 'gofer-research',
777
1541
  label: 'Continue to Research',
778
- prompt: 'Continue with Gofer research for the confirmed feature. Check workspace health first, then run /1_gofer_research or the equivalent repo-local stage instruction.',
1542
+ prompt: 'Continue with Gofer research for the confirmed feature. Check workspace health first, then route internally through the 1_gofer_research stage contract.',
779
1543
  send: false,
780
1544
  },
781
1545
  ],
782
1546
  body: `
783
1547
  You are the Gofer start agent.
784
1548
 
785
- Start by checking Gofer workspace health. If the repo is missing or stale, ask before bootstrapping. Keep the user-facing surface simple: use plain slash commands for pipeline stages and the eai-gofer skill/tools for app-level setup.
1549
+ Check Gofer workspace health with the available native tools and repo-owned checker. During intake, edit only intake artifacts and execute only authorized workspace checks or approved setup. Ask before bootstrapping. Keep the user-facing surface simple: users see only eai; numbered stages and helpers are internal contracts. Continue into the next authorized internal stage without requiring a custom-agent handoff.
786
1550
 
787
1551
  Primary outputs:
788
1552
 
789
- - A clear route into \`/0_gofer_start\`, \`/gofer:eai-first-run\`, or standalone research.
1553
+ - A clear route into the public \`eai\` entrypoint, first-run setup, or standalone research.
790
1554
  - A concise statement of whether the repo has the Gofer scaffold, plugin/app support, and EAI first-run prerequisites.
791
1555
  `,
792
1556
  },
793
1557
  {
794
1558
  id: 'gofer-research',
795
1559
  description: 'Gofer research agent. Use for codebase and documentation research before specification.',
796
- tools: goferTools,
1560
+ tools: stageTools,
797
1561
  handoffs: [
798
1562
  {
799
1563
  agent: 'gofer-plan',
@@ -805,13 +1569,14 @@ Primary outputs:
805
1569
  body: `
806
1570
  You are the Gofer research agent.
807
1571
 
808
- Use \`/1_gofer_research\` as the stage contract. Keep raw output out of chat when it is large; write durable findings to \`.specify/specs/{feature}/research.md\` and \`context-bundle.md\`.
1572
+ Use \`.specify/commands/1_gofer_research.md\` as the internal stage contract. Keep raw output out of chat when it is large; write durable findings to \`.specify/specs/{feature}/research.md\` and \`context-bundle.md\`.
1573
+ During research, use execute only for authorized diagnostics and edit only research artifacts. Do not modify application code before the implementation stage and its approval checks. Stop after requested research-only work; otherwise continue internally.
809
1574
  `,
810
1575
  },
811
1576
  {
812
1577
  id: 'gofer-plan',
813
1578
  description: 'Gofer specification and planning agent. Use after research to produce spec, plan, contracts, and ordered tasks.',
814
- tools: goferTools,
1579
+ tools: stageTools,
815
1580
  handoffs: [
816
1581
  {
817
1582
  agent: 'gofer-implement',
@@ -823,13 +1588,14 @@ Use \`/1_gofer_research\` as the stage contract. Keep raw output out of chat whe
823
1588
  body: `
824
1589
  You are the Gofer planning agent.
825
1590
 
826
- Use \`/2_gofer_specify\`, \`/3_gofer_plan\`, and \`/4_gofer_tasks\` as the stage contracts. Keep the plan grounded in existing repository scripts, current platform capabilities, and explicit validation obligations.
1591
+ Use \`.specify/commands/2_gofer_specify.md\`, \`.specify/commands/3_gofer_plan.md\`, and \`.specify/commands/4_gofer_tasks.md\` as the internal stage contracts. Keep the plan grounded in existing repository scripts, current platform capabilities, and explicit validation obligations.
1592
+ During planning, edit specifications and task artifacts and execute only authorized discovery/check scripts. Implementation requires the scope and approval checks in the next internal contract.
827
1593
  `,
828
1594
  },
829
1595
  {
830
1596
  id: 'gofer-implement',
831
1597
  description: 'Gofer implementation agent. Use for task execution, code edits, tests, and repo-script driven changes.',
832
- tools: goferTools,
1598
+ tools: stageTools,
833
1599
  handoffs: [
834
1600
  {
835
1601
  agent: 'gofer-validate',
@@ -841,18 +1607,19 @@ Use \`/2_gofer_specify\`, \`/3_gofer_plan\`, and \`/4_gofer_tasks\` as the stage
841
1607
  body: `
842
1608
  You are the Gofer implementation agent.
843
1609
 
844
- Use \`/5_gofer_implement\` as the stage contract. Work from \`tasks.md\`, keep changes minimal, run repo tests, and update traceability evidence as tasks complete.
1610
+ Use \`.specify/commands/5_gofer_implement.md\` as the internal stage contract. Work from \`tasks.md\`, keep changes minimal, run repo tests, and update traceability evidence as tasks complete.
845
1611
  `,
846
1612
  },
847
1613
  {
848
1614
  id: 'gofer-validate',
849
1615
  description: 'Gofer validation agent. Use for branch validation, security checks, test evidence, and release readiness.',
850
- tools: goferTools,
1616
+ tools: stageTools,
851
1617
  handoffs: [],
852
1618
  body: `
853
1619
  You are the Gofer validation agent.
854
1620
 
855
- Use \`/6_gofer_validate\` as the terminal quality gate. Validate functional correctness, integration, security, standards, tests, generated artifacts, and release/public readiness where relevant.
1621
+ Use \`.specify/commands/6_gofer_validate.md\` as the terminal quality gate. Validate functional correctness, integration, security, standards, tests, generated artifacts, and release/public readiness where relevant.
1622
+ Use edit for validation evidence and execute for authorized tests and checks. If repairs are needed, return internally to the implementation contract within approved scope and retry limits, then revalidate. Do not mark failed checks complete.
856
1623
  `,
857
1624
  },
858
1625
  ];
@@ -879,22 +1646,17 @@ function escapeTomlString(value) {
879
1646
  async function emitAgentsSkills(stages, root, dryRun) {
880
1647
  const baseDir = path.join(root, '.agents', 'skills');
881
1648
  let count = 0;
882
- for (const stage of stages) {
883
- const { name, description, surfaces } = stage.frontmatter;
884
- if (shouldExclude(String(name), 'agents-skills')) continue;
885
- if (!surfaces.includes('agents-skills')) continue;
886
-
887
- const stageStem = getStageOutputStem(stage);
888
- const legacyStageStems = getLegacyStageStems(stage);
889
- const skillDir = path.join(baseDir, stageStem);
1649
+ const version = await detectPackageVersion(root);
1650
+ await clearDirectoryEntries(baseDir, (entry) => entry.isDirectory(), dryRun, 'agents-skills');
1651
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1652
+ const skillDir = path.join(baseDir, entry.stem);
890
1653
  const outPath = path.join(skillDir, 'SKILL.md');
891
- const legacySkillDir = path.join(baseDir, String(name));
892
- const content = buildSkillContent(
893
- String(name),
894
- String(description),
895
- injectTokenCostPolicy(
896
- injectWorkspacePreflight(stage.body, String(name), SURFACE_WORKSPACE_HOSTS['agents-skills'])
897
- )
1654
+ const content = buildPublicEntrypointSkill(
1655
+ entry,
1656
+ version,
1657
+ stages,
1658
+ 'Codex and Google Antigravity',
1659
+ SURFACE_WORKSPACE_HOSTS['agents-skills']
898
1660
  );
899
1661
 
900
1662
  if (dryRun) {
@@ -902,15 +1664,12 @@ async function emitAgentsSkills(stages, root, dryRun) {
902
1664
  } else {
903
1665
  await ensureDir(skillDir);
904
1666
  await fs.writeFile(outPath, content, 'utf8');
905
- await removeLegacyGeneratedPaths(skillDir, [
906
- legacySkillDir,
907
- ...legacyStageStems.map((legacyStem) => path.join(baseDir, legacyStem)),
908
- ...getCodexLegacySkillDirs(root, '.agents/skills', stageStem, String(name)),
909
- ]);
910
1667
  console.log(`agents-skills: wrote ${outPath}`);
911
1668
  }
912
1669
  count++;
913
1670
  }
1671
+ await emitDocumentationSkill(root, baseDir, dryRun, 'agents-skills');
1672
+ count++;
914
1673
  console.log(`agents-skills: ${count} file(s) emitted`);
915
1674
  return true;
916
1675
  }
@@ -939,35 +1698,53 @@ async function emitGithubAgents(stages, root, dryRun) {
939
1698
 
940
1699
  async function emitGithubSkills(stages, root, dryRun) {
941
1700
  const version = await detectPackageVersion(root);
942
- const outPath = path.join(root, '.github', 'skills', 'eai-gofer', 'SKILL.md');
943
- const content = buildUmbrellaSkillContent(version, stages, 'VS Code and GitHub Copilot');
1701
+ const baseDir = path.join(root, '.github', 'skills');
1702
+ await clearDirectoryEntries(baseDir, (entry) => entry.isDirectory(), dryRun, 'github-skills');
1703
+ let count = 0;
944
1704
 
945
- if (dryRun) {
946
- console.log(`[dry-run] github-skills: would write ${outPath}`);
947
- } else {
948
- await ensureDir(path.dirname(outPath));
949
- await fs.writeFile(outPath, content, 'utf8');
950
- console.log(`github-skills: wrote ${outPath}`);
1705
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1706
+ const outPath = path.join(baseDir, entry.stem, 'SKILL.md');
1707
+ const content = buildPublicEntrypointSkill(entry, version, stages, 'VS Code and GitHub Copilot', 'copilot');
1708
+ if (dryRun) {
1709
+ console.log(`[dry-run] github-skills: would write ${outPath}`);
1710
+ } else {
1711
+ await ensureDir(path.dirname(outPath));
1712
+ await fs.writeFile(outPath, content, 'utf8');
1713
+ console.log(`github-skills: wrote ${outPath}`);
1714
+ }
1715
+ count++;
951
1716
  }
952
1717
 
953
- console.log('github-skills: 1 file(s) emitted');
1718
+ await emitDocumentationSkill(root, baseDir, dryRun, 'github-skills');
1719
+ count++;
1720
+
1721
+ console.log(`github-skills: ${count} file(s) emitted`);
954
1722
  return true;
955
1723
  }
956
1724
 
957
1725
  async function emitClaudeSkills(stages, root, dryRun) {
958
1726
  const version = await detectPackageVersion(root);
959
- const outPath = path.join(root, '.claude', 'skills', 'eai-gofer', 'SKILL.md');
960
- const content = buildUmbrellaSkillContent(version, stages, 'Claude Code');
1727
+ const baseDir = path.join(root, '.claude', 'skills');
1728
+ await clearDirectoryEntries(baseDir, (entry) => entry.isDirectory(), dryRun, 'claude-skills');
1729
+ let count = 0;
961
1730
 
962
- if (dryRun) {
963
- console.log(`[dry-run] claude-skills: would write ${outPath}`);
964
- } else {
965
- await ensureDir(path.dirname(outPath));
966
- await fs.writeFile(outPath, content, 'utf8');
967
- console.log(`claude-skills: wrote ${outPath}`);
1731
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1732
+ const outPath = path.join(baseDir, entry.stem, 'SKILL.md');
1733
+ const content = buildPublicEntrypointSkill(entry, version, stages, 'Claude Code', 'claude');
1734
+ if (dryRun) {
1735
+ console.log(`[dry-run] claude-skills: would write ${outPath}`);
1736
+ } else {
1737
+ await ensureDir(path.dirname(outPath));
1738
+ await fs.writeFile(outPath, content, 'utf8');
1739
+ console.log(`claude-skills: wrote ${outPath}`);
1740
+ }
1741
+ count++;
968
1742
  }
969
1743
 
970
- console.log('claude-skills: 1 file(s) emitted');
1744
+ await emitDocumentationSkill(root, baseDir, dryRun, 'claude-skills');
1745
+ count++;
1746
+
1747
+ console.log(`claude-skills: ${count} file(s) emitted`);
971
1748
  return true;
972
1749
  }
973
1750
 
@@ -983,22 +1760,17 @@ async function emitClaudeSkills(stages, root, dryRun) {
983
1760
  async function emitSystemSkills(stages, root, dryRun) {
984
1761
  const baseDir = path.join(root, '.system', 'skills');
985
1762
  let count = 0;
986
- for (const stage of stages) {
987
- const { name, description, surfaces } = stage.frontmatter;
988
- if (shouldExclude(String(name), 'system-skills')) continue;
989
- if (!surfaces.includes('system-skills')) continue;
990
-
991
- const stageStem = getStageOutputStem(stage);
992
- const legacyStageStems = getLegacyStageStems(stage);
993
- const skillDir = path.join(baseDir, stageStem);
1763
+ const version = await detectPackageVersion(root);
1764
+ await clearDirectoryEntries(baseDir, (entry) => entry.isDirectory(), dryRun, 'system-skills');
1765
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1766
+ const skillDir = path.join(baseDir, entry.stem);
994
1767
  const outPath = path.join(skillDir, 'SKILL.md');
995
- const legacySkillDir = path.join(baseDir, String(name));
996
- const content = buildSkillContent(
997
- String(name),
998
- String(description),
999
- injectTokenCostPolicy(
1000
- injectWorkspacePreflight(stage.body, String(name), SURFACE_WORKSPACE_HOSTS['system-skills'])
1001
- )
1768
+ const content = buildPublicEntrypointSkill(
1769
+ entry,
1770
+ version,
1771
+ stages,
1772
+ 'Codex',
1773
+ SURFACE_WORKSPACE_HOSTS['system-skills']
1002
1774
  );
1003
1775
 
1004
1776
  if (dryRun) {
@@ -1006,19 +1778,38 @@ async function emitSystemSkills(stages, root, dryRun) {
1006
1778
  } else {
1007
1779
  await ensureDir(skillDir);
1008
1780
  await fs.writeFile(outPath, content, 'utf8');
1009
- await removeLegacyGeneratedPaths(skillDir, [
1010
- legacySkillDir,
1011
- ...legacyStageStems.map((legacyStem) => path.join(baseDir, legacyStem)),
1012
- ...getCodexLegacySkillDirs(root, '.system/skills', stageStem, String(name)),
1013
- ]);
1014
1781
  console.log(`system-skills: wrote ${outPath}`);
1015
1782
  }
1016
1783
  count++;
1017
1784
  }
1785
+ await emitDocumentationSkill(root, baseDir, dryRun, 'system-skills');
1786
+ count++;
1018
1787
  console.log(`system-skills: ${count} file(s) emitted`);
1019
1788
  return true;
1020
1789
  }
1021
1790
 
1791
+ async function emitGrokSkills(stages, root, dryRun) {
1792
+ const baseDir = path.join(root, '.grok', 'skills');
1793
+ let count = 0;
1794
+ const version = await detectPackageVersion(root);
1795
+ await clearDirectoryEntries(baseDir, (entry) => entry.isDirectory(), dryRun, 'grok-skills');
1796
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1797
+ const skillDir = path.join(baseDir, entry.stem);
1798
+ const outPath = path.join(skillDir, 'SKILL.md');
1799
+ const content = buildPublicEntrypointSkill(entry, version, stages, 'Grok Build', 'grok');
1800
+ if (dryRun) {
1801
+ console.log(`[dry-run] grok-skills: would write ${outPath}`);
1802
+ } else {
1803
+ await ensureDir(skillDir);
1804
+ await fs.writeFile(outPath, content, 'utf8');
1805
+ console.log(`grok-skills: wrote ${outPath}`);
1806
+ }
1807
+ count++;
1808
+ }
1809
+ console.log(`grok-skills: ${count} file(s) emitted`);
1810
+ return true;
1811
+ }
1812
+
1022
1813
  /**
1023
1814
  * T065 — gemini emitter
1024
1815
  * Emits plain markdown body and TOML command wrappers to
@@ -1036,27 +1827,19 @@ async function emitGemini(stages, root, dryRun) {
1036
1827
  const emittedNames = [];
1037
1828
  let count = 0;
1038
1829
 
1039
- for (const stage of stages) {
1040
- const { name, description, surfaces } = stage.frontmatter;
1041
- if (shouldExclude(String(name), 'gemini')) continue;
1042
- if (!surfaces.includes('gemini')) continue;
1043
-
1044
- const stageStem = getStageOutputStem(stage);
1045
- const markdownPath = path.join(outDir, `${stageStem}.md`);
1046
- const tomlPath = path.join(outDir, `${stageStem}.toml`);
1047
- const legacyStageStems = getLegacyStageStems(stage);
1048
- const legacyMarkdownPaths = [
1049
- path.join(outDir, `${name}.md`),
1050
- ...legacyStageStems.map((legacyStem) => path.join(outDir, `${legacyStem}.md`)),
1051
- ];
1052
- const legacyTomlPaths = [
1053
- path.join(outDir, `${name}.toml`),
1054
- ...legacyStageStems.map((legacyStem) => path.join(outDir, `${legacyStem}.toml`)),
1055
- ];
1056
- const sourceFileName = path.basename(stage.filePath);
1830
+ await clearDirectoryEntries(
1831
+ outDir,
1832
+ (entry) => entry.name.endsWith('.md') || entry.name.endsWith('.toml'),
1833
+ dryRun,
1834
+ 'gemini'
1835
+ );
1836
+
1837
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1838
+ const markdownPath = path.join(outDir, `${entry.stem}.md`);
1839
+ const tomlPath = path.join(outDir, `${entry.stem}.toml`);
1057
1840
  const tomlContent = [
1058
- `description = "${escapeTomlString(String(description || name))}"`,
1059
- `prompt = "{{include: ../../../.specify/commands/${sourceFileName}}}"`,
1841
+ `description = "${escapeTomlString(entry.description)}"`,
1842
+ `prompt = "{{include: ./${entry.stem}.md}}"`,
1060
1843
  '',
1061
1844
  ].join('\n');
1062
1845
 
@@ -1065,20 +1848,12 @@ async function emitGemini(stages, root, dryRun) {
1065
1848
  console.log(`[dry-run] gemini: would write ${tomlPath}`);
1066
1849
  } else {
1067
1850
  await ensureDir(outDir);
1068
- await fs.writeFile(
1069
- markdownPath,
1070
- injectTokenCostPolicy(
1071
- injectWorkspacePreflight(stage.body, String(name), SURFACE_WORKSPACE_HOSTS['gemini'])
1072
- ),
1073
- 'utf8'
1074
- );
1851
+ await fs.writeFile(markdownPath, buildPublicEntrypointMarkdown(entry, stages, 'gemini'), 'utf8');
1075
1852
  await fs.writeFile(tomlPath, tomlContent, 'utf8');
1076
- await removeLegacyGeneratedPaths(markdownPath, legacyMarkdownPaths);
1077
- await removeLegacyGeneratedPaths(tomlPath, legacyTomlPaths);
1078
1853
  console.log(`gemini: wrote ${markdownPath}`);
1079
1854
  console.log(`gemini: wrote ${tomlPath}`);
1080
1855
  }
1081
- emittedNames.push(String(name));
1856
+ emittedNames.push(entry.name);
1082
1857
  count++;
1083
1858
  }
1084
1859
 
@@ -1112,7 +1887,7 @@ async function emitGemini(stages, root, dryRun) {
1112
1887
 
1113
1888
  /**
1114
1889
  * T067 — agents-md emitter
1115
- * Creates .agents/AGENTS.md — a consolidated AGENTS.md for Gemini/Codex.
1890
+ * Creates .agents/AGENTS.md — a consolidated AGENTS.md for Codex/Antigravity.
1116
1891
  * Includes all stages emitted to portable agent surfaces.
1117
1892
  *
1118
1893
  * @param {Array} stages
@@ -1122,37 +1897,41 @@ async function emitGemini(stages, root, dryRun) {
1122
1897
  async function emitAgentsMd(stages, root, dryRun) {
1123
1898
  const outPath = path.join(root, '.agents', 'AGENTS.md');
1124
1899
  const timestamp = new Date().toISOString();
1125
- const sections = [];
1126
-
1127
- for (const stage of stages) {
1128
- const { name, title, surfaces } = stage.frontmatter;
1129
- if (shouldExclude(String(name), 'agents-md')) continue;
1130
- if (!surfaces.includes('gemini') && !surfaces.includes('codex') && !surfaces.includes('agents-skills')) continue;
1131
-
1132
- const summary = stage.body.slice(0, 200).replace(/\n+$/, '');
1133
- const sectionTitle = title ? String(title) : String(name);
1134
- sections.push(`### ${sectionTitle}\n${summary}...`);
1135
- }
1900
+ const stageList = buildInternalStageList(stages);
1136
1901
 
1137
1902
  const content = `# Gofer Agent Commands
1138
1903
 
1139
- This file documents all Gofer pipeline commands available as agent skills.
1904
+ This file documents the public Gofer command surface and internal pipeline contracts.
1140
1905
 
1141
1906
  Generated: ${timestamp}
1142
1907
 
1908
+ ## Public Entrypoints
1909
+
1910
+ - \`eai\` - Start or continue Gofer from one user-facing command.
1911
+
1912
+ Do not expose numbered or helper stage commands in user-facing pickers. They remain available as internal contracts under \`.specify/commands/\`.
1913
+
1914
+ ${buildUserFacingResponseGateSection()}
1915
+
1916
+ ${buildAlwaysEaiSection()}
1917
+
1918
+ ${buildVerifiedEaiCliCommandContract()}
1919
+
1143
1920
  ## EAI CLI Discovery And Recovery
1144
1921
 
1922
+ - Classify work before EAI readiness: app delivery continues directly; clear non-app work asks once before skipping EAI workspace/app setup.
1145
1923
  - Run \`eai update --check\` before first EAI platform work when the CLI may be stale.
1146
1924
  - Run \`eai --describe\` before assuming command syntax.
1147
1925
  - If advertised, run \`eai agent guide --format json\` before planning or fixing EAI workflows.
1148
1926
  - After any \`eai\` error, run \`eai errors explain <code-or-reason> --format json\` before guessing remediation.
1149
1927
  - If \`eai errors explain\` is unavailable, match \`.specify/references/platform/eai-error-catalog.yaml\`, run read-only diagnostics before mutating fixes, and stop at the retry or escalation condition.
1150
1928
  - For \`eai user invite\` 5xx or \`EXTERNAL_SERVICE_ERROR\`, check existing members with \`eai user list --workspace <workspace-id> --search <email> --format json\`; use \`eai user role set --workspace <workspace-id> --member-id <member-id> --role tenant-admin --format json\` only after verification and user approval, then tell the app user to sign out and sign back in.
1929
+ - For \`MISSING_TENANT\`, \`app_token_tenant_context_required\`, or "Tenant context required for app tokens" on platform user lookup or membership prerequisites, run \`eai errors explain app_token_tenant_context_required --format json\`, confirm workspace context, and retry \`/v4/platform/tenants/<tenant-id>/...\` routes before changing workspace members, Entra, role definitions, databases, or cloud portals.
1151
1930
  - Use \`eai publicapi\` only for authorized PublicAPI \`/v4/...\` routes.
1152
1931
 
1153
1932
  ## Commands
1154
1933
 
1155
- ${sections.join('\n\n')}
1934
+ ${stageList}
1156
1935
  `;
1157
1936
 
1158
1937
  if (dryRun) {
@@ -1163,7 +1942,7 @@ ${sections.join('\n\n')}
1163
1942
  console.log(`agents-md: wrote ${outPath}`);
1164
1943
  }
1165
1944
 
1166
- console.log(`agents-md: ${sections.length} section(s) emitted`);
1945
+ console.log(`agents-md: ${PUBLIC_ENTRYPOINTS.length} public entrie(s) emitted`);
1167
1946
  return true;
1168
1947
  }
1169
1948
 
@@ -1178,6 +1957,7 @@ ${sections.join('\n\n')}
1178
1957
  * @param {boolean} dryRun
1179
1958
  */
1180
1959
  async function emitCodexConfig(stages, root, dryRun) {
1960
+ void stages;
1181
1961
  const outDir = path.join(root, '.specify', 'outputs');
1182
1962
  const outPath = path.join(outDir, 'codex-config-fragment.toml');
1183
1963
  const timestamp = new Date().toISOString();
@@ -1191,14 +1971,9 @@ async function emitCodexConfig(stages, root, dryRun) {
1191
1971
  ];
1192
1972
 
1193
1973
  let count = 0;
1194
- for (const stage of stages) {
1195
- const { name, surfaces } = stage.frontmatter;
1196
- if (shouldExclude(String(name), 'codex-config')) continue;
1197
- if (!surfaces.includes('codex') && !surfaces.includes('agents-skills')) continue;
1198
-
1199
- const stageStem = getStageOutputStem(stage);
1974
+ for (const entry of PUBLIC_ENTRYPOINTS) {
1200
1975
  lines.push(`[[skills.config]]`);
1201
- lines.push(`path = "/full/path/to/repo/.agents/skills/${escapeTomlString(stageStem)}"`);
1976
+ lines.push(`path = "/full/path/to/repo/.agents/skills/${escapeTomlString(entry.stem)}"`);
1202
1977
  lines.push(`enabled = true`);
1203
1978
  lines.push(``);
1204
1979
  count++;
@@ -1228,6 +2003,7 @@ const EMITTERS = {
1228
2003
  'github-skills': emitGithubSkills,
1229
2004
  'agents-skills': emitAgentsSkills,
1230
2005
  'system-skills': emitSystemSkills,
2006
+ 'grok-skills': emitGrokSkills,
1231
2007
  'gemini': emitGemini,
1232
2008
  'agents-md': emitAgentsMd,
1233
2009
  'codex-config': emitCodexConfig,
@@ -1239,6 +2015,7 @@ const EMITTERS = {
1239
2015
 
1240
2016
  function parseArgs(argv) {
1241
2017
  const args = {
2018
+ check: false,
1242
2019
  dryRun: false,
1243
2020
  surfaces: ALL_SURFACES,
1244
2021
  root: process.cwd(),
@@ -1248,6 +2025,8 @@ function parseArgs(argv) {
1248
2025
  const arg = argv[i];
1249
2026
  if (arg === '--dry-run') {
1250
2027
  args.dryRun = true;
2028
+ } else if (arg === '--check') {
2029
+ args.check = true;
1251
2030
  } else if (arg === '--surfaces' && argv[i + 1]) {
1252
2031
  args.surfaces = argv[i + 1].split(',').map((s) => s.trim()).filter(Boolean);
1253
2032
  i++;
@@ -1297,7 +2076,7 @@ function validateExclusions(stages, surfaces) {
1297
2076
 
1298
2077
  async function main() {
1299
2078
  const argv = process.argv.slice(2);
1300
- const { dryRun, surfaces, root } = parseArgs(argv);
2079
+ const { check, dryRun, surfaces, root } = parseArgs(argv);
1301
2080
 
1302
2081
  // Validate canonical descriptions first (budget check)
1303
2082
  try {
@@ -1308,6 +2087,34 @@ async function main() {
1308
2087
  process.exit(1);
1309
2088
  }
1310
2089
 
2090
+ // Minimal emitter fixtures do not include the full Gofer reference library.
2091
+ // Only a real Gofer workspace may receive automatic contract normalization.
2092
+ const commandsDir = path.join(root, '.specify', 'commands');
2093
+ try {
2094
+ await fs.access(commandsDir);
2095
+ } catch (err) {
2096
+ if (err?.code === 'ENOENT') {
2097
+ console.error('Canonical command normalization failed: .specify/commands/ not found');
2098
+ process.exit(1);
2099
+ }
2100
+ throw err;
2101
+ }
2102
+ const capabilityContractPath = path.join(
2103
+ root,
2104
+ '.specify',
2105
+ 'references',
2106
+ 'mvp-capability-validation.md'
2107
+ );
2108
+ try {
2109
+ await fs.access(capabilityContractPath);
2110
+ await refreshCanonicalCommandSources(root, dryRun || check);
2111
+ } catch (err) {
2112
+ if (err?.code !== 'ENOENT') {
2113
+ console.error(`Canonical command normalization failed: ${err instanceof Error ? err.message : String(err)}`);
2114
+ process.exit(1);
2115
+ }
2116
+ }
2117
+
1311
2118
  // Load all stage command files from .specify/commands/
1312
2119
  let stages;
1313
2120
  try {
@@ -1326,7 +2133,8 @@ async function main() {
1326
2133
  // T043: validate exclusions
1327
2134
  validateExclusions(stages, surfaces);
1328
2135
 
1329
- if (dryRun) {
2136
+ if (dryRun || check) {
2137
+ if (check) console.log('[check] Generation inputs are valid; no files were written.');
1330
2138
  console.log('[dry-run] Would emit to surfaces:', surfaces.join(', '));
1331
2139
  console.log('[dry-run] Stages:', stages.map((s) => s.frontmatter.name).join(', '));
1332
2140
  process.exit(0);