@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.
- package/package.json +3 -3
- package/resources/deploy/eai-app-template/producer-pin.json +5 -5
- package/resources/deploy/eai-app-template/tests/source-unknown-deployment-evidence.test.mjs +2141 -1
- package/resources/gofer/.gofer-version +4 -357
- package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
- package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
- package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
- package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
- package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
- package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
- package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
- package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
- package/resources/gofer/claude-commands/eai-update.md +46 -0
- package/resources/gofer/claude-commands/eai.md +355 -0
- package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
- package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
- package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
- package/resources/gofer/commands/0_gofer_start.md +440 -99
- package/resources/gofer/commands/0a_problem_validation.md +187 -27
- package/resources/gofer/commands/10_gofer_cloud.md +183 -23
- package/resources/gofer/commands/1_gofer_research.md +239 -30
- package/resources/gofer/commands/2_gofer_specify.md +239 -35
- package/resources/gofer/commands/3_gofer_plan.md +259 -43
- package/resources/gofer/commands/4_gofer_tasks.md +401 -81
- package/resources/gofer/commands/5_gofer_implement.md +375 -84
- package/resources/gofer/commands/6_gofer_validate.md +284 -53
- package/resources/gofer/commands/7_gofer_save.md +187 -26
- package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
- package/resources/gofer/commands/8_gofer_branding.md +183 -23
- package/resources/gofer/commands/9_gofer_tests.md +212 -23
- package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
- package/resources/gofer/commands/gofer_check_workspace.md +123 -8
- package/resources/gofer/commands/gofer_constitution.md +183 -23
- package/resources/gofer/commands/gofer_diagnose.md +183 -23
- package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
- package/resources/gofer/commands/gofer_hydrate.md +183 -23
- package/resources/gofer/commands/gofer_personality.md +117 -6
- package/resources/gofer/commands/gofer_plan.md +117 -6
- package/resources/gofer/commands/gofer_side.md +117 -6
- package/resources/gofer/commands/gofer_spec_summary.md +183 -23
- package/resources/gofer/commands/gofer_tdd.md +183 -23
- package/resources/gofer/commands/gofer_vocabulary.md +185 -25
- package/resources/gofer/commands/gofer_zoom_out.md +183 -23
- package/resources/gofer/config/typesafe-learning-review.json +16 -0
- package/resources/gofer/config/typesafe-semantic-review.json +9 -0
- package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
- package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
- package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
- package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
- package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
- package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
- package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
- package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
- package/resources/gofer/gemini/extension.json +4 -4
- package/resources/gofer/github-agents/eai.agent.md +83 -0
- package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
- package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
- package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
- package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
- package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
- package/resources/gofer/github-skills/eai/SKILL.md +365 -0
- package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
- package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
- package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
- package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
- package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
- package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
- package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
- package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
- package/resources/gofer/memory/constitution.md +9 -7
- package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
- package/resources/gofer/memory/lessons.md +0 -31
- package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
- package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
- package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
- package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
- package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
- package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
- package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
- package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
- package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
- package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
- package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
- package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
- package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
- package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
- package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
- package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
- package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
- package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
- package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
- package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
- package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
- package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
- package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
- package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
- package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
- package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
- package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
- package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
- package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
- package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
- package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
- package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
- package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
- package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
- package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
- package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
- package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
- package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
- package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
- package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
- package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
- package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
- package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
- package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
- package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
- package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
- package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
- package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
- package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
- package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
- package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
- package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
- package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
- package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
- package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
- package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
- package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
- package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
- package/resources/gofer/references/agent-catalog.json +126 -0
- package/resources/gofer/references/blocker-mediation.md +156 -0
- package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
- package/resources/gofer/references/delivery-lineage.md +48 -0
- package/resources/gofer/references/mvp-capability-validation.md +102 -0
- package/resources/gofer/references/platform/README.md +1 -1
- package/resources/gofer/references/platform/eai-app-template.md +15 -13
- package/resources/gofer/references/platform/eai-auth-access.md +104 -0
- package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
- package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
- package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
- package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
- package/resources/gofer/references/platform/eai.md +44 -8
- package/resources/gofer/references/platform/vertical-template.md +10 -9
- package/resources/gofer/references/priority-outcome-protection.md +152 -0
- package/resources/gofer/references/verified-agent-execution.md +179 -0
- package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
- package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
- package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
- package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
- package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
- package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
- package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
- package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
- package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
- package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
- package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
- package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
- package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
- package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
- package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
- package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
- package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
- package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
- package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
- package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
- package/resources/gofer/specify-commands/gofer_personality.md +117 -6
- package/resources/gofer/specify-commands/gofer_plan.md +117 -6
- package/resources/gofer/specify-commands/gofer_side.md +117 -6
- package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
- package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
- package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
- package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
- package/resources/gofer/specify-config/object-type-routing.json +24 -0
- package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
- package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
- package/resources/gofer/system-skills/eai/SKILL.md +365 -0
- package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
- package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
- package/resources/gofer/templates/build-map-template.md +64 -0
- package/resources/gofer/templates/business-scenarios-template.json +14 -0
- package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
- package/resources/gofer/templates/context-bundle-template.md +4 -3
- package/resources/gofer/templates/contract-pack-template.md +8 -8
- package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
- package/resources/gofer/templates/delivery-lineage-template.json +8 -0
- package/resources/gofer/templates/eai-preflight-template.md +109 -68
- package/resources/gofer/templates/goal-ledger-template.json +1 -1
- package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
- package/resources/gofer/templates/loop-contract-template.json +3 -1
- package/resources/gofer/templates/plan-template.md +8 -7
- package/resources/gofer/templates/priority-plan-template.json +29 -0
- package/resources/gofer/templates/proposal-review-template.md +6 -3
- package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
- package/resources/gofer/templates/research-template.md +7 -6
- package/resources/gofer/templates/spec-summary-template.md +1 -1
- package/resources/gofer/templates/spec-template.md +45 -6
- package/resources/gofer/templates/tasks-template.md +12 -3
- package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
- package/resources/gofer/templates/ui-review-log-template.md +21 -3
- package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
- package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
- package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
- package/resources/linked-sources.json +4 -4
- package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
- package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
- package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
- package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
- package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
- package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
- package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
- package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
- package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
- package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
- package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
- package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
- package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
- package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
- package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
- package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
- package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
- package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
- package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
- package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
- package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
- package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
- package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
- package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
- package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
- package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
- package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
- package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
- package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
- package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
- package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
- package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
- package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
- package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
- package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
- package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
- package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
- package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
- package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
- package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
- package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
- package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
- package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
- package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
- package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
- package/resources/gofer/claude-commands/gofer_personality.md +0 -39
- package/resources/gofer/claude-commands/gofer_plan.md +0 -35
- package/resources/gofer/claude-commands/gofer_side.md +0 -40
- package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
- package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
- package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
- package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
- package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
- package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
- package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
- package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
- package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
- package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
- package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
- package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
- package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
- package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
- package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
- package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
- package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
- package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
- package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
- package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
- package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
- package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
- package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
- package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
- package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
- package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
- package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
- package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
- package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
- package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
- package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
- package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
- package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
- package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
- package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
- package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
- package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
- package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
- package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
- package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
- package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
- package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
- package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
- package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
- package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
- package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
- package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
- package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
- package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
- package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
- package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
- package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
- package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
- package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
- package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
- package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
- package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
- package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
- package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
- package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
- package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
- package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
- package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
- package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
- package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
- package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
- package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
- package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
- package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
- package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
- package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
- package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
- package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
- package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
- package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
- package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
- package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
- package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
- package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
- package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
- package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
- package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
- package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
- package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
- package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
- package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
- 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
|
|
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: '
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const
|
|
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:
|
|
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 =
|
|
464
|
-
const helperCommandPattern =
|
|
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
|
-
|
|
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
|
|
503
|
-
return
|
|
504
|
-
## EAI Platform Session Preflight
|
|
905
|
+
export function buildAuthAccessDecisionContract() {
|
|
906
|
+
return `**Authentication Access Decision**
|
|
505
907
|
|
|
506
|
-
|
|
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
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
-
|
|
518
|
-
|
|
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
|
|
522
|
-
const workspaceHeadingIndex = content.indexOf('## Workspace Preflight');
|
|
960
|
+
const workspaceHeadingIndex = withoutMvpCapabilitySection.indexOf('## Workspace Preflight');
|
|
523
961
|
if (workspaceHeadingIndex !== -1) {
|
|
524
|
-
const nextHeadingIndex =
|
|
962
|
+
const nextHeadingIndex = withoutMvpCapabilitySection.indexOf('\n## ', workspaceHeadingIndex + 1);
|
|
525
963
|
if (nextHeadingIndex !== -1) {
|
|
526
|
-
return `${
|
|
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 `${
|
|
968
|
+
return `${withoutMvpCapabilitySection.trimEnd()}\n\n${section}\n`;
|
|
531
969
|
}
|
|
532
970
|
|
|
533
|
-
return `${section}\n\n${
|
|
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
|
-
-
|
|
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.
|
|
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('##
|
|
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
|
|
616
|
-
2. Use the
|
|
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
|
-
|
|
675
|
-
|
|
676
|
-
|
|
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
|
-
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
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
|
|
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
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
1616
|
+
tools: stageTools,
|
|
851
1617
|
handoffs: [],
|
|
852
1618
|
body: `
|
|
853
1619
|
You are the Gofer validation agent.
|
|
854
1620
|
|
|
855
|
-
Use
|
|
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
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
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
|
|
943
|
-
|
|
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
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
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
|
-
|
|
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
|
|
960
|
-
|
|
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
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
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
|
-
|
|
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
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
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
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
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
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
const
|
|
1048
|
-
const
|
|
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(
|
|
1059
|
-
`prompt = "{{include:
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
-
${
|
|
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: ${
|
|
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
|
|
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(
|
|
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);
|