@garygentry/feature-forge 0.1.4 → 0.2.0
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/README.md +19 -1
- package/adapters/GENERATION-REPORT.md +17 -13
- package/adapters/claude/.feature-forge-bundle.json +6 -0
- package/adapters/claude/references/forge-config-schema.json +36 -10
- package/adapters/claude/references/pipeline-state-schema.json +4 -0
- package/adapters/claude/references/portable-root.md +8 -5
- package/adapters/claude/references/process-overview.md +15 -5
- package/adapters/claude/references/shared-conventions.md +69 -4
- package/adapters/claude/references/stack-resolution.md +4 -1
- package/adapters/claude/references/stacks/go.md +1 -1
- package/adapters/claude/references/stacks/python.md +1 -1
- package/adapters/claude/references/stacks/rust.md +1 -1
- package/adapters/claude/references/stacks/typescript.md +1 -1
- package/adapters/claude/references/templates/specs-hygiene/AGENTS.md +23 -0
- package/adapters/claude/references/templates/specs-hygiene/CLAUDE.md +22 -0
- package/adapters/claude/scripts/epic-manifest.py +1379 -0
- package/adapters/claude/scripts/forge-bootstrap.py +991 -0
- package/adapters/claude/scripts/forge-init.sh +44 -0
- package/adapters/claude/scripts/forge-root.sh +30 -8
- package/adapters/claude/scripts/validate-traceability.py +150 -0
- package/adapters/claude/skills/forge/SKILL.md +5 -5
- package/adapters/claude/skills/forge-0-epic/SKILL.md +13 -15
- package/adapters/claude/skills/forge-0-epic/references/edit-mode.md +2 -2
- package/adapters/claude/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
- package/adapters/claude/skills/forge-1-prd/SKILL.md +6 -4
- package/adapters/claude/skills/forge-2-tech/SKILL.md +8 -7
- package/adapters/claude/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
- package/adapters/claude/skills/forge-3-specs/SKILL.md +1 -1
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +2 -2
- package/adapters/claude/skills/forge-5-loop/SKILL.md +20 -18
- package/adapters/claude/skills/forge-5-loop/references/result-reporting.md +13 -0
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +40 -0
- package/adapters/claude/skills/forge-6-docs/SKILL.md +11 -1
- package/adapters/claude/skills/forge-bootstrap/SKILL.md +240 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/claude/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/claude/skills/forge-fix/SKILL.md +1 -1
- package/adapters/claude/skills/forge-init/SKILL.md +1 -1
- package/adapters/claude/skills/forge-verify/SKILL.md +7 -2
- package/adapters/claude/skills/forge-verify/references/verification-checklists.md +1 -1
- package/adapters/codex/.feature-forge-bundle.json +6 -0
- package/adapters/codex/agents/{forge-researcher.md → forge-researcher.toml} +4 -4
- package/adapters/codex/agents/{forge-spec-writer.md → forge-spec-writer.toml} +4 -4
- package/adapters/codex/agents/{forge-verifier.md → forge-verifier.toml} +4 -4
- package/adapters/codex/references/forge-config-schema.json +36 -10
- package/adapters/codex/references/pipeline-state-schema.json +4 -0
- package/adapters/codex/references/portable-root.md +8 -5
- package/adapters/codex/references/process-overview.md +15 -5
- package/adapters/codex/references/shared-conventions.md +69 -4
- package/adapters/codex/references/stack-resolution.md +4 -1
- package/adapters/codex/references/stacks/go.md +1 -1
- package/adapters/codex/references/stacks/python.md +1 -1
- package/adapters/codex/references/stacks/rust.md +1 -1
- package/adapters/codex/references/stacks/typescript.md +1 -1
- package/adapters/codex/references/templates/specs-hygiene/AGENTS.md +23 -0
- package/adapters/codex/references/templates/specs-hygiene/CLAUDE.md +22 -0
- package/adapters/codex/scripts/epic-manifest.py +1379 -0
- package/adapters/codex/scripts/forge-bootstrap.py +991 -0
- package/adapters/codex/scripts/forge-init.sh +44 -0
- package/adapters/codex/scripts/forge-root.sh +30 -8
- package/adapters/codex/scripts/validate-traceability.py +150 -0
- package/adapters/codex/skills/forge/{forge.md → SKILL.md} +16 -6
- package/adapters/codex/skills/forge-0-epic/{forge-0-epic.md → SKILL.md} +33 -25
- package/adapters/codex/skills/forge-0-epic/references/edit-mode.md +2 -2
- package/adapters/codex/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
- package/adapters/codex/skills/forge-1-prd/{forge-1-prd.md → SKILL.md} +22 -10
- package/adapters/codex/skills/forge-2-tech/{forge-2-tech.md → SKILL.md} +26 -15
- package/adapters/codex/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
- package/adapters/codex/skills/forge-3-specs/{forge-3-specs.md → SKILL.md} +16 -6
- package/adapters/codex/skills/forge-4-backlog/{forge-4-backlog.md → SKILL.md} +15 -5
- package/adapters/codex/skills/forge-5-loop/{forge-5-loop.md → SKILL.md} +40 -28
- package/adapters/codex/skills/forge-5-loop/references/result-reporting.md +13 -0
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +40 -0
- package/adapters/codex/skills/forge-6-docs/{forge-6-docs.md → SKILL.md} +26 -6
- package/adapters/codex/skills/forge-bootstrap/SKILL.md +249 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/codex/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/codex/skills/forge-fix/{forge-fix.md → SKILL.md} +12 -2
- package/adapters/codex/skills/forge-init/{forge-init.md → SKILL.md} +11 -1
- package/adapters/codex/skills/forge-verify/{forge-verify.md → SKILL.md} +24 -9
- package/adapters/codex/skills/forge-verify/references/verification-checklists.md +1 -1
- package/adapters/copilot/.feature-forge-bundle.json +6 -0
- package/adapters/copilot/references/forge-config-schema.json +36 -10
- package/adapters/copilot/references/pipeline-state-schema.json +4 -0
- package/adapters/copilot/references/portable-root.md +8 -5
- package/adapters/copilot/references/process-overview.md +15 -5
- package/adapters/copilot/references/shared-conventions.md +69 -4
- package/adapters/copilot/references/stack-resolution.md +4 -1
- package/adapters/copilot/references/stacks/go.md +1 -1
- package/adapters/copilot/references/stacks/python.md +1 -1
- package/adapters/copilot/references/stacks/rust.md +1 -1
- package/adapters/copilot/references/stacks/typescript.md +1 -1
- package/adapters/copilot/references/templates/specs-hygiene/AGENTS.md +23 -0
- package/adapters/copilot/references/templates/specs-hygiene/CLAUDE.md +22 -0
- package/adapters/copilot/scripts/epic-manifest.py +1379 -0
- package/adapters/copilot/scripts/forge-bootstrap.py +991 -0
- package/adapters/copilot/scripts/forge-init.sh +44 -0
- package/adapters/copilot/scripts/forge-root.sh +30 -8
- package/adapters/copilot/scripts/validate-traceability.py +150 -0
- package/adapters/copilot/skills/forge/forge.md +16 -6
- package/adapters/copilot/skills/forge-0-epic/forge-0-epic.md +33 -25
- package/adapters/copilot/skills/forge-0-epic/references/edit-mode.md +2 -2
- package/adapters/copilot/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +22 -10
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +26 -15
- package/adapters/copilot/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +16 -6
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +15 -5
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +40 -28
- package/adapters/copilot/skills/forge-5-loop/references/result-reporting.md +13 -0
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +40 -0
- package/adapters/copilot/skills/forge-6-docs/forge-6-docs.md +26 -6
- package/adapters/copilot/skills/forge-bootstrap/forge-bootstrap.md +249 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/copilot/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/copilot/skills/forge-fix/forge-fix.md +12 -2
- package/adapters/copilot/skills/forge-init/forge-init.md +11 -1
- package/adapters/copilot/skills/forge-verify/forge-verify.md +24 -9
- package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +1 -1
- package/adapters/cursor/.feature-forge-bundle.json +6 -0
- package/adapters/cursor/references/forge-config-schema.json +36 -10
- package/adapters/cursor/references/pipeline-state-schema.json +4 -0
- package/adapters/cursor/references/portable-root.md +8 -5
- package/adapters/cursor/references/process-overview.md +15 -5
- package/adapters/cursor/references/shared-conventions.md +69 -4
- package/adapters/cursor/references/stack-resolution.md +4 -1
- package/adapters/cursor/references/stacks/go.md +1 -1
- package/adapters/cursor/references/stacks/python.md +1 -1
- package/adapters/cursor/references/stacks/rust.md +1 -1
- package/adapters/cursor/references/stacks/typescript.md +1 -1
- package/adapters/cursor/references/templates/specs-hygiene/AGENTS.md +23 -0
- package/adapters/cursor/references/templates/specs-hygiene/CLAUDE.md +22 -0
- package/adapters/cursor/scripts/epic-manifest.py +1379 -0
- package/adapters/cursor/scripts/forge-bootstrap.py +991 -0
- package/adapters/cursor/scripts/forge-init.sh +44 -0
- package/adapters/cursor/scripts/forge-root.sh +30 -8
- package/adapters/cursor/scripts/validate-traceability.py +150 -0
- package/adapters/cursor/skills/forge/forge.mdc +16 -6
- package/adapters/cursor/skills/forge-0-epic/forge-0-epic.mdc +33 -25
- package/adapters/cursor/skills/forge-0-epic/references/edit-mode.md +2 -2
- package/adapters/cursor/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +22 -10
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +26 -15
- package/adapters/cursor/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +16 -6
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +15 -5
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +40 -28
- package/adapters/cursor/skills/forge-5-loop/references/result-reporting.md +13 -0
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +40 -0
- package/adapters/cursor/skills/forge-6-docs/forge-6-docs.mdc +26 -6
- package/adapters/cursor/skills/forge-bootstrap/forge-bootstrap.mdc +250 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/cursor/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/cursor/skills/forge-fix/forge-fix.mdc +12 -2
- package/adapters/cursor/skills/forge-init/forge-init.mdc +11 -1
- package/adapters/cursor/skills/forge-verify/forge-verify.mdc +24 -9
- package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +1 -1
- package/adapters/gemini/.feature-forge-bundle.json +6 -0
- package/adapters/gemini/gemini-extension.json +5 -1
- package/adapters/gemini/references/forge-config-schema.json +36 -10
- package/adapters/gemini/references/pipeline-state-schema.json +4 -0
- package/adapters/gemini/references/portable-root.md +8 -5
- package/adapters/gemini/references/process-overview.md +15 -5
- package/adapters/gemini/references/shared-conventions.md +69 -4
- package/adapters/gemini/references/stack-resolution.md +4 -1
- package/adapters/gemini/references/stacks/go.md +1 -1
- package/adapters/gemini/references/stacks/python.md +1 -1
- package/adapters/gemini/references/stacks/rust.md +1 -1
- package/adapters/gemini/references/stacks/typescript.md +1 -1
- package/adapters/gemini/references/templates/specs-hygiene/AGENTS.md +23 -0
- package/adapters/gemini/references/templates/specs-hygiene/CLAUDE.md +22 -0
- package/adapters/gemini/scripts/epic-manifest.py +1379 -0
- package/adapters/gemini/scripts/forge-bootstrap.py +991 -0
- package/adapters/gemini/scripts/forge-init.sh +44 -0
- package/adapters/gemini/scripts/forge-root.sh +30 -8
- package/adapters/gemini/scripts/validate-traceability.py +150 -0
- package/adapters/gemini/skills/forge/forge.md +16 -6
- package/adapters/gemini/skills/forge-0-epic/forge-0-epic.md +33 -25
- package/adapters/gemini/skills/forge-0-epic/references/edit-mode.md +2 -2
- package/adapters/gemini/skills/forge-0-epic/references/epic-manifest-subcommands.md +1 -1
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +22 -10
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +26 -15
- package/adapters/gemini/skills/forge-2-tech/references/stack-discovery-checklist.md +4 -4
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +16 -6
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +15 -5
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +40 -28
- package/adapters/gemini/skills/forge-5-loop/references/result-reporting.md +13 -0
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +40 -0
- package/adapters/gemini/skills/forge-6-docs/forge-6-docs.md +26 -6
- package/adapters/gemini/skills/forge-bootstrap/forge-bootstrap.md +249 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +24 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +25 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/gemini/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/gemini/skills/forge-fix/forge-fix.md +12 -2
- package/adapters/gemini/skills/forge-init/forge-init.md +11 -1
- package/adapters/gemini/skills/forge-verify/forge-verify.md +24 -9
- package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +1 -1
- package/dist/agent-targets.d.ts +20 -4
- package/dist/agent-targets.js +29 -4
- package/dist/apply.js +245 -18
- package/dist/cli.js +12 -6
- package/dist/hash.d.ts +5 -0
- package/dist/hash.js +7 -0
- package/dist/manifest.d.ts +4 -2
- package/dist/manifest.js +58 -2
- package/dist/placements.d.ts +69 -0
- package/dist/placements.js +116 -0
- package/dist/plan.d.ts +7 -0
- package/dist/plan.js +87 -1
- package/dist/rauf.d.ts +4 -4
- package/dist/rauf.js +3 -3
- package/dist/report.js +21 -0
- package/dist/source.d.ts +4 -3
- package/dist/source.js +4 -3
- package/dist/types.d.ts +163 -19
- package/dist/types.js +42 -11
- package/package.json +1 -1
- package/adapters/codex/agents/openai.yaml +0 -10
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Initialize feature-forge configuration in the current project.
|
|
3
|
+
# Creates forge.config.json with sensible defaults.
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
CONFIG_FILE="forge.config.json"
|
|
8
|
+
|
|
9
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
10
|
+
echo "⚠️ $CONFIG_FILE already exists. Skipping."
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
cat > "$CONFIG_FILE" << 'EOF'
|
|
15
|
+
{
|
|
16
|
+
"specsDir": "./specs",
|
|
17
|
+
"docsDir": "./docs/architecture",
|
|
18
|
+
"backlogDir": null,
|
|
19
|
+
"gitCommitAfterStage": true,
|
|
20
|
+
"commitPrefix": "forge",
|
|
21
|
+
"stack": null,
|
|
22
|
+
"typeCheckCommand": null,
|
|
23
|
+
"testCommand": null,
|
|
24
|
+
"loopIterationMultiplier": 1.5
|
|
25
|
+
}
|
|
26
|
+
EOF
|
|
27
|
+
|
|
28
|
+
echo "✅ Created $CONFIG_FILE with defaults."
|
|
29
|
+
echo ""
|
|
30
|
+
echo "Defaults:"
|
|
31
|
+
echo " specsDir: ./specs"
|
|
32
|
+
echo " docsDir: ./docs/architecture"
|
|
33
|
+
echo " backlogDir: null (defaults to {specsDir}/{feature}/backlog.json)"
|
|
34
|
+
echo " gitCommitAfterStage: true"
|
|
35
|
+
echo " commitPrefix: forge"
|
|
36
|
+
echo " stack: null (auto-detected during forge-2-tech)"
|
|
37
|
+
echo " typeCheckCommand: null (auto-detected during forge-2-tech)"
|
|
38
|
+
echo " testCommand: null (auto-detected during forge-2-tech)"
|
|
39
|
+
echo " loopIterationMultiplier: 1.5 (multiplier for loop iterations)"
|
|
40
|
+
echo ""
|
|
41
|
+
echo "The loop runner defaults to rauf. To target a different ralph-style runner,"
|
|
42
|
+
echo "add a \"loopRunner\" block (see references/forge-config-schema.json)."
|
|
43
|
+
echo ""
|
|
44
|
+
echo "Edit $CONFIG_FILE to customize paths and stack settings for your project."
|
|
@@ -13,13 +13,17 @@
|
|
|
13
13
|
set -euo pipefail
|
|
14
14
|
|
|
15
15
|
# Sentinel predicate (00-core-definitions.md §2 / SENTINEL_FILES). A directory is a valid
|
|
16
|
-
#
|
|
17
|
-
#
|
|
16
|
+
# feature-forge root iff it carries the neutral bundle sentinel `.feature-forge-bundle.json`
|
|
17
|
+
# (emitted into EVERY per-agent adapter bundle) OR the legacy Claude plugin manifest
|
|
18
|
+
# `.claude-plugin/plugin.json` (the canon repo root + the Claude bundle). Content-based, so it
|
|
19
|
+
# identifies a feature-forge install under ANY agent's directory layout — not just Claude's.
|
|
18
20
|
is_root() { # $1 = candidate dir
|
|
19
|
-
[ -f "$1
|
|
21
|
+
[ -f "$1/.feature-forge-bundle.json" ] || [ -f "$1/.claude-plugin/plugin.json" ]
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
# ── Step 1: self-location — parent of this script's dir is the
|
|
24
|
+
# ── Step 1: self-location — parent of this script's dir is the install root. ─────────────
|
|
25
|
+
# This is the PRIMARY path: a bundle ships its own scripts/forge-root.sh, so the parent of
|
|
26
|
+
# this script's dir is that bundle's root under any agent's layout.
|
|
23
27
|
self_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
24
28
|
root="$(cd -- "$self_dir/.." && pwd -P)"
|
|
25
29
|
if is_root "$root"; then
|
|
@@ -27,11 +31,23 @@ if is_root "$root"; then
|
|
|
27
31
|
exit 0
|
|
28
32
|
fi
|
|
29
33
|
|
|
30
|
-
# ── Step 2: candidate-root probe (authoritative multi-root list; extend here first).
|
|
31
|
-
# Globs that match nothing expand to themselves; the is_root test rejects such literals.
|
|
34
|
+
# ── Step 2: candidate-root probe (authoritative multi-agent root list; extend here first). ─
|
|
35
|
+
# Globs that match nothing expand to themselves; the is_root test rejects such literals. Covers
|
|
36
|
+
# every supported agent's install destination under BOTH global ($HOME) and project ($PWD) scope,
|
|
37
|
+
# matching the installer's per-agent layout: claude .claude/skills, codex .agents/skills, copilot
|
|
38
|
+
# .github/feature-forge, cursor .cursor/rules, gemini .gemini/extensions.
|
|
32
39
|
for candidate in \
|
|
33
40
|
"$HOME/.claude/skills/feature-forge" \
|
|
41
|
+
"$PWD/.claude/skills/feature-forge" \
|
|
34
42
|
"$HOME"/.claude/plugins/*/feature-forge \
|
|
43
|
+
"$HOME/.agents/skills/feature-forge" \
|
|
44
|
+
"$PWD/.agents/skills/feature-forge" \
|
|
45
|
+
"$HOME/.github/feature-forge" \
|
|
46
|
+
"$PWD/.github/feature-forge" \
|
|
47
|
+
"$HOME/.cursor/rules/feature-forge" \
|
|
48
|
+
"$PWD/.cursor/rules/feature-forge" \
|
|
49
|
+
"$HOME/.gemini/extensions/feature-forge" \
|
|
50
|
+
"$PWD/.gemini/extensions/feature-forge" \
|
|
35
51
|
; do
|
|
36
52
|
if is_root "$candidate"; then
|
|
37
53
|
printf '%s\n' "$candidate"
|
|
@@ -39,12 +55,18 @@ for candidate in \
|
|
|
39
55
|
fi
|
|
40
56
|
done
|
|
41
57
|
|
|
42
|
-
# ── Step 3: env fallback —
|
|
58
|
+
# ── Step 3: env fallback — neutral FEATURE_FORGE_ROOT, then the legacy CLAUDE_PLUGIN_ROOT. ─
|
|
59
|
+
# The neutral override works for every agent; CLAUDE_PLUGIN_ROOT is kept only for backwards
|
|
60
|
+
# compatibility with existing Claude installs (C-4).
|
|
61
|
+
if [ -n "${FEATURE_FORGE_ROOT:-}" ] && is_root "$FEATURE_FORGE_ROOT"; then
|
|
62
|
+
printf '%s\n' "$FEATURE_FORGE_ROOT"
|
|
63
|
+
exit 0
|
|
64
|
+
fi
|
|
43
65
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && is_root "$CLAUDE_PLUGIN_ROOT"; then
|
|
44
66
|
printf '%s\n' "$CLAUDE_PLUGIN_ROOT"
|
|
45
67
|
exit 0
|
|
46
68
|
fi
|
|
47
69
|
|
|
48
70
|
# ── Step 4: failure — actionable message to stderr, exit 1 (REQ-RES-04). ─────────────────
|
|
49
|
-
echo "feature-forge: cannot locate
|
|
71
|
+
echo "feature-forge: cannot locate install root. Set FEATURE_FORGE_ROOT to the bundle dir, or run from an installed skill dir." >&2
|
|
50
72
|
exit 1
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate requirement traceability between PRD and implementation specs.
|
|
3
|
+
|
|
4
|
+
Extracts REQ-XXX-NN identifiers from a PRD file and checks that every
|
|
5
|
+
requirement is referenced in at least one implementation spec document.
|
|
6
|
+
Also reports orphaned references (IDs found in specs but not in PRD).
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python validate-traceability.py <prd-path> <specs-dir> [--json]
|
|
10
|
+
|
|
11
|
+
Exit codes:
|
|
12
|
+
0 = all requirements covered, no orphans
|
|
13
|
+
1 = gaps or orphans found
|
|
14
|
+
2 = file not found or read error
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import json
|
|
19
|
+
import re
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
REQ_PATTERN = re.compile(r"REQ-[A-Z]+-\d+")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def extract_req_ids(text: str) -> set[str]:
|
|
27
|
+
"""Extract all unique REQ-XXX-NN identifiers from text."""
|
|
28
|
+
return set(REQ_PATTERN.findall(text))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main() -> int:
|
|
32
|
+
parser = argparse.ArgumentParser(
|
|
33
|
+
description="Validate requirement traceability between PRD and specs"
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument("prd_path", help="Path to PRD.md file")
|
|
36
|
+
parser.add_argument("specs_dir", help="Directory containing ##-*.md spec files")
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"--json", action="store_true", dest="json_output", help="Output as JSON"
|
|
39
|
+
)
|
|
40
|
+
args = parser.parse_args()
|
|
41
|
+
|
|
42
|
+
prd_path = Path(args.prd_path)
|
|
43
|
+
specs_dir = Path(args.specs_dir)
|
|
44
|
+
|
|
45
|
+
# Read PRD
|
|
46
|
+
if not prd_path.exists():
|
|
47
|
+
print(f"Error: PRD file not found: {prd_path}", file=sys.stderr)
|
|
48
|
+
return 2
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
prd_text = prd_path.read_text()
|
|
52
|
+
except OSError as e:
|
|
53
|
+
print(f"Error reading PRD: {e}", file=sys.stderr)
|
|
54
|
+
return 2
|
|
55
|
+
|
|
56
|
+
prd_reqs = extract_req_ids(prd_text)
|
|
57
|
+
|
|
58
|
+
if not prd_reqs:
|
|
59
|
+
print(f"Warning: No REQ-XXX-NN identifiers found in {prd_path}", file=sys.stderr)
|
|
60
|
+
|
|
61
|
+
# Read spec files (##-*.md pattern)
|
|
62
|
+
if not specs_dir.exists():
|
|
63
|
+
print(f"Error: Specs directory not found: {specs_dir}", file=sys.stderr)
|
|
64
|
+
return 2
|
|
65
|
+
|
|
66
|
+
spec_files = sorted(specs_dir.glob("[0-9][0-9]-*.md"))
|
|
67
|
+
if not spec_files:
|
|
68
|
+
print(f"Warning: No spec files matching ##-*.md found in {specs_dir}", file=sys.stderr)
|
|
69
|
+
|
|
70
|
+
# Track which specs cover which requirements
|
|
71
|
+
spec_reqs: dict[str, set[str]] = {}
|
|
72
|
+
all_spec_reqs: set[str] = set()
|
|
73
|
+
|
|
74
|
+
for spec_file in spec_files:
|
|
75
|
+
try:
|
|
76
|
+
text = spec_file.read_text()
|
|
77
|
+
reqs = extract_req_ids(text)
|
|
78
|
+
spec_reqs[spec_file.name] = reqs
|
|
79
|
+
all_spec_reqs |= reqs
|
|
80
|
+
except OSError as e:
|
|
81
|
+
print(f"Warning: Could not read {spec_file}: {e}", file=sys.stderr)
|
|
82
|
+
|
|
83
|
+
# Also check TRACEABILITY.md if it exists
|
|
84
|
+
traceability_file = specs_dir / "TRACEABILITY.md"
|
|
85
|
+
if traceability_file.exists():
|
|
86
|
+
try:
|
|
87
|
+
text = traceability_file.read_text()
|
|
88
|
+
trace_reqs = extract_req_ids(text)
|
|
89
|
+
spec_reqs["TRACEABILITY.md"] = trace_reqs
|
|
90
|
+
all_spec_reqs |= trace_reqs
|
|
91
|
+
except OSError:
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
# Analysis
|
|
95
|
+
uncovered = sorted(prd_reqs - all_spec_reqs)
|
|
96
|
+
orphaned = sorted(all_spec_reqs - prd_reqs)
|
|
97
|
+
|
|
98
|
+
# Per-requirement coverage map
|
|
99
|
+
coverage: dict[str, list[str]] = {}
|
|
100
|
+
for req_id in sorted(prd_reqs):
|
|
101
|
+
covering_specs = [
|
|
102
|
+
name for name, reqs in spec_reqs.items() if req_id in reqs
|
|
103
|
+
]
|
|
104
|
+
coverage[req_id] = covering_specs
|
|
105
|
+
|
|
106
|
+
has_issues = bool(uncovered or orphaned)
|
|
107
|
+
|
|
108
|
+
if args.json_output:
|
|
109
|
+
result = {
|
|
110
|
+
"prd_file": str(prd_path),
|
|
111
|
+
"specs_dir": str(specs_dir),
|
|
112
|
+
"total_requirements": len(prd_reqs),
|
|
113
|
+
"total_spec_files": len(spec_files),
|
|
114
|
+
"uncovered_requirements": uncovered,
|
|
115
|
+
"orphaned_references": orphaned,
|
|
116
|
+
"coverage": coverage,
|
|
117
|
+
"valid": not has_issues,
|
|
118
|
+
}
|
|
119
|
+
print(json.dumps(result, indent=2))
|
|
120
|
+
else:
|
|
121
|
+
print(f"PRD: {prd_path} ({len(prd_reqs)} requirements)")
|
|
122
|
+
print(f"Specs: {specs_dir} ({len(spec_files)} spec files)")
|
|
123
|
+
print()
|
|
124
|
+
|
|
125
|
+
if uncovered:
|
|
126
|
+
print(f"UNCOVERED REQUIREMENTS ({len(uncovered)}):")
|
|
127
|
+
for req_id in uncovered:
|
|
128
|
+
print(f" - {req_id}: not found in any spec file")
|
|
129
|
+
print()
|
|
130
|
+
|
|
131
|
+
if orphaned:
|
|
132
|
+
print(f"ORPHANED REFERENCES ({len(orphaned)}):")
|
|
133
|
+
for req_id in orphaned:
|
|
134
|
+
sources = [
|
|
135
|
+
name for name, reqs in spec_reqs.items() if req_id in reqs
|
|
136
|
+
]
|
|
137
|
+
print(f" - {req_id}: found in {', '.join(sources)} but not in PRD")
|
|
138
|
+
print()
|
|
139
|
+
|
|
140
|
+
if not has_issues:
|
|
141
|
+
print("All requirements covered. No orphaned references.")
|
|
142
|
+
else:
|
|
143
|
+
total_issues = len(uncovered) + len(orphaned)
|
|
144
|
+
print(f"Found {total_issues} issue(s).")
|
|
145
|
+
|
|
146
|
+
return 1 if has_issues else 0
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
sys.exit(main())
|
|
@@ -29,13 +29,13 @@ For pipeline architecture details, read `references/process-overview.md`.
|
|
|
29
29
|
|
|
30
30
|
1. **Epics first.** Identify epic directories as any `{specsDir}/*/` that directly contains an `epic-manifest.json` **and no `.pipeline-state.json` of its own** (an epic root is never itself a feature). For each epic, run:
|
|
31
31
|
```bash
|
|
32
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
32
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
33
33
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
34
34
|
python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
|
|
35
35
|
```
|
|
36
36
|
and show one rollup line: `{epic} — {complete}/{total} complete, next: {nextCommand}`.
|
|
37
37
|
2. **Standalone features below.** Scan the remaining `{specsDir}/*/` that directly contain a `.pipeline-state.json` **without** an `epic` back-pointer. A nested member's `.pipeline-state.json` is **attributed to its epic (Tier 1), never listed as a standalone feature**.
|
|
38
|
-
- Within this standalone tier the existing logic still applies: if exactly one active (non-complete) standalone pipeline exists, show its dashboard; if multiple exist, list them with a one-line summary each and use
|
|
38
|
+
- Within this standalone tier the existing logic still applies: if exactly one active (non-complete) standalone pipeline exists, show its dashboard; if multiple exist, list them with a one-line summary each and use the host's question mechanism to ask which to focus on.
|
|
39
39
|
|
|
40
40
|
If no epics and no standalone features exist, say: "No active feature pipelines found. Start one with `/feature-forge:forge-1-prd <feature-name>` or group several with `/feature-forge:forge-0-epic <epic-name>`."
|
|
41
41
|
|
|
@@ -83,7 +83,7 @@ Use these status indicators:
|
|
|
83
83
|
When the named argument is an epic (`{specsDir}/{name}/epic-manifest.json` exists), render the epic dashboard instead of a per-feature one. Run:
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
86
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
87
87
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
88
88
|
python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
|
|
89
89
|
```
|
|
@@ -142,18 +142,18 @@ Commands:
|
|
|
142
142
|
Support these sub-commands for pipeline lifecycle management:
|
|
143
143
|
- `/feature-forge:forge pause {feature}` — Set `pipelineStatus` to `"paused"`. Do NOT modify `currentStage` or any stage statuses. The pipeline freezes exactly as-is. Show a confirmation.
|
|
144
144
|
- `/feature-forge:forge resume {feature}` — Set `pipelineStatus` back to `"active"`. Calculate how long the feature was paused (from `updatedAt` to now). If paused for more than 24 hours, show a hint: "This feature was paused for {duration}. Session context may have been lost — consider re-running `/feature-forge:forge-{currentStage} {feature}` to rebuild context."
|
|
145
|
-
- `/feature-forge:forge abandon {feature}` — Set `pipelineStatus` to `"abandoned"`. Use
|
|
145
|
+
- `/feature-forge:forge abandon {feature}` — Set `pipelineStatus` to `"abandoned"`. Use the host's question mechanism to confirm first, and state what's reversible: abandoning does not delete artifacts and can be undone with `/feature-forge:forge resume {feature}`, so the cost is low — but if the user really means "stop and discard," point out that `pause` is the better choice when they're only setting it aside. Offer **Abandon** · **Pause instead** · **Cancel**.
|
|
146
146
|
|
|
147
147
|
**Epic lifecycle.** When the argument names an **epic** (`{specsDir}/{name}/epic-manifest.json` exists), `pause` / `resume` / `abandon` operate on the epic manifest, not a `.pipeline-state.json`:
|
|
148
148
|
|
|
149
149
|
- Set the manifest's top-level `status` (`paused` / `active` / `abandoned`) via the helper's `set-status` mutator — an atomic write that also bumps `updatedAt`:
|
|
150
150
|
```bash
|
|
151
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
151
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
152
152
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
153
153
|
python3 "$R/scripts/epic-manifest.py" set-status "{epic}" --status paused --specs-dir "{specsDir}"
|
|
154
154
|
```
|
|
155
155
|
For `complete`, do **not** set the status directly — completion is *derived* from member states (the rollup), so the manifest `status` is a lifecycle flag, never a completion signal.
|
|
156
|
-
- **Member feature states are NOT silently mutated.** Pausing/abandoning the epic changes only the manifest `status`. Before doing so, use
|
|
156
|
+
- **Member feature states are NOT silently mutated.** Pausing/abandoning the epic changes only the manifest `status`. Before doing so, use the host's question mechanism to make the relationship explicit and frame the trade-off: "Pausing the epic does not pause its in-flight member features. {N} members are active. Pause the epic only, or also pause each member?" Recommend **epic only** when members are mid-stage and the user just wants to stop *new* orchestration; recommend **also pause members** when the intent is a hard freeze of all in-flight work. If the user opts to pause members too, update each member's own `pipelineStatus` **individually and visibly** (one explicit action per member), never as a hidden side-effect.
|
|
157
157
|
- Commit the change via the Git Commit Protocol, staging `{specsDir}/{epic}/`.
|
|
158
158
|
|
|
159
159
|
When listing features, show active pipelines by default. Include a count of paused/abandoned: "3 active pipelines (1 paused, 1 abandoned — use `/feature-forge:forge list all` to see them)."
|
|
@@ -163,3 +163,13 @@ When listing features, show active pipelines by default. Include a count of paus
|
|
|
163
163
|
- Never modify any spec files, backlog files, or pipeline state beyond the `notes`, `updatedAt`, and `pipelineStatus` fields. The navigator is read-only except for notes and lifecycle commands.
|
|
164
164
|
- If a user asks to "continue" or "pick up where I left off" without naming a feature, check for active pipelines before asking. Only ask if ambiguous.
|
|
165
165
|
- The pipeline state file is the source of truth. Don't infer stage from the existence of files alone — a file might exist from a previous incomplete run.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Host execution notes
|
|
170
|
+
|
|
171
|
+
This skill was authored Claude-first; the body above refers to "the host's question mechanism", "the host's subagent mechanism", and "the host's background-execution mechanism". Use your runtime's equivalent for each — and if your runtime has no such tool:
|
|
172
|
+
|
|
173
|
+
- **User input:** ask the question directly and wait for the answer before proceeding. Do not skip a required question or assume an answer.
|
|
174
|
+
- **Subagents:** if your host cannot dispatch the named custom agent, run that step inline yourself.
|
|
175
|
+
- **Background / monitoring:** run long-lived commands in the foreground (or your host's background facility) and report progress as it arrives.
|
|
@@ -14,13 +14,13 @@ is delegated to `scripts/epic-manifest.py`.
|
|
|
14
14
|
|
|
15
15
|
This skill **composes** JSON and **issues** helper commands. It NEVER eyeballs a dependency
|
|
16
16
|
graph for cycles, NEVER hand-rolls a manifest write where a mutator exists, and NEVER asks a
|
|
17
|
-
question in inline prose — every question goes through
|
|
17
|
+
question in inline prose — every question goes through the host's question mechanism.
|
|
18
18
|
|
|
19
19
|
## Prerequisites
|
|
20
20
|
|
|
21
21
|
Read and follow `references/shared-conventions.md` for:
|
|
22
22
|
- the **Feature Name Requirement** (applied here to the *epic* name — see below),
|
|
23
|
-
- the **User Input Protocol** (the
|
|
23
|
+
- the **User Input Protocol** (the the host's question mechanism guardrail — all questions go through the tool),
|
|
24
24
|
- **Configuration Reading**, and
|
|
25
25
|
- the **Git Commit Protocol**.
|
|
26
26
|
|
|
@@ -39,7 +39,7 @@ checks but still load any on-disk artifacts.
|
|
|
39
39
|
plugin path and the configured specs dir:
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
42
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
43
43
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
44
44
|
python3 "$R/scripts/epic-manifest.py" <subcommand> ... --specs-dir "{specsDir}"
|
|
45
45
|
```
|
|
@@ -73,30 +73,32 @@ Resolve the epic subtree path `{specsDir}/{epic}/` and decide which branch to ru
|
|
|
73
73
|
epic, confirm the epic name itself does not collide with any existing feature or epic:
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
76
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
77
77
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
78
78
|
python3 "$R/scripts/epic-manifest.py" check-name "{epic}" --specs-dir "{specsDir}"
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
- Exit `0` → the name is free; proceed to C1.
|
|
82
82
|
- Exit `1` (`duplicate-name`) → STOP and surface the helper's finding **verbatim**; ask
|
|
83
|
-
(via
|
|
83
|
+
(via the host's question mechanism) for a different epic name, then re-run check-name.
|
|
84
84
|
- Exit `2` (unsafe name) → STOP and surface the finding; ask for a corrected name.
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
88
|
## Creation Branch
|
|
89
89
|
|
|
90
|
-
### Step 1 — Branch Setup
|
|
90
|
+
### Step 1 — Branch Setup
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
Invoke the **Branch Setup** block in `references/shared-conventions.md` with `{label}` = `{epic}` and
|
|
93
|
+
`{scope}` = `epic`. It self-gates (skips when not a git repo or when `branchPerFeature` is false),
|
|
94
|
+
detects whether you're on the default branch, and strongly recommends — still optionally — creating
|
|
95
|
+
`{branchPrefix}{epic}` when you are. Each member feature's `forge-1-prd` inherits this branch rather
|
|
96
|
+
than prompting again.
|
|
95
97
|
|
|
96
98
|
### Step C1 — Epic Framing Interview
|
|
97
99
|
|
|
98
100
|
Output context as text (what an epic is, that a decomposition interview will follow). Then
|
|
99
|
-
call
|
|
101
|
+
call the host's question mechanism to elicit:
|
|
100
102
|
|
|
101
103
|
1. **Epic goal / problem** — the overarching change being decomposed. Becomes the EPIC.md
|
|
102
104
|
"Overall Goal" narrative and seeds the manifest `description`.
|
|
@@ -109,29 +111,27 @@ The epic `name` is the validated CLI argument from Step 0 — do NOT prompt for
|
|
|
109
111
|
Drive a decomposition dialogue. Output your analysis as text first (how the goal might split,
|
|
110
112
|
right-sizing guidance: each feature should be a single pipeline-sized unit — a unit forge-1-prd
|
|
111
113
|
through forge-5-loop would carry end-to-end — not item-level interleaving). Then use
|
|
112
|
-
|
|
113
|
-
these two features really one?" and "Is any one of these really two?" Iterate until the user
|
|
114
|
-
confirms the set.
|
|
114
|
+
the host's question mechanism to elicit the candidate feature list. Per the **Decision Support** protocol in `references/shared-conventions.md`, lead with a **recommended decomposition** and a one-line rationale rather than asking the user to invent it unaided, then probe its seams ("Is any of these two really one? Is any one really two?"), naming the trade-off (more features = more parallelism but more edges). Iterate until the user confirms.
|
|
115
115
|
|
|
116
116
|
For **each** proposed feature name, before accepting it into the set, enforce global uniqueness
|
|
117
117
|
and name safety via the helper:
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
120
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
121
121
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
122
122
|
python3 "$R/scripts/epic-manifest.py" check-name "{feature}" --specs-dir "{specsDir}"
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
- Exit `0` → accept the name.
|
|
126
126
|
- Exit `1` (`duplicate-name`) → reject that name; surface the finding verbatim and re-prompt
|
|
127
|
-
(via
|
|
127
|
+
(via the host's question mechanism) for a different name.
|
|
128
128
|
- Exit `2` (`unsafe-name`) → reject; surface the finding and re-prompt.
|
|
129
129
|
|
|
130
130
|
Never accept a feature name that has not passed `check-name` exit 0.
|
|
131
131
|
|
|
132
132
|
### Step C3 — Per-Feature Charter + Structured Contracts
|
|
133
133
|
|
|
134
|
-
For each confirmed feature, run a focused
|
|
134
|
+
For each confirmed feature, run a focused the host's question mechanism batch (one feature at a time,
|
|
135
135
|
2–3 questions per call) eliciting:
|
|
136
136
|
|
|
137
137
|
- **Charter** — a single paragraph: scope statement + contract obligations. This is a
|
|
@@ -150,12 +150,10 @@ the structured arrays are the source of truth; EPIC.md renders them as prose lat
|
|
|
150
150
|
|
|
151
151
|
### Step C4 — Dependency-Edge Interview
|
|
152
152
|
|
|
153
|
-
For each feature, use
|
|
153
|
+
For each feature, use the host's question mechanism: "Which sibling features must be complete before this
|
|
154
154
|
one can build?" → populates `dependsOn: [names]`.
|
|
155
155
|
|
|
156
|
-
**Seed the suggestion from `consumes`:** a `consumes.from` X strongly implies `dependsOn` X.
|
|
157
|
-
Offer the union of each feature's `consumes.from` set as the default, but let the user confirm —
|
|
158
|
-
`dependsOn` is the authoritative edge set.
|
|
156
|
+
**Seed the suggestion from `consumes`:** a `consumes.from` X strongly implies `dependsOn` X. Per the **Decision Support** protocol, offer the union of each feature's `consumes.from` set as the **recommended default**, evidence-backed — but flag the cost (each edge serializes the loop and blocks dependents, so add only what contracts require). User confirms/overrides; `dependsOn` is authoritative.
|
|
159
157
|
|
|
160
158
|
The `features[]` array order is the user-declared sequence from C2 (order is a presentation
|
|
161
159
|
sequence, **not** a dependency ordering). Preserve the C2 order unless the user asks to reorder.
|
|
@@ -176,10 +174,10 @@ Compose the full `epic-manifest.json` per the 00 §2 schema, setting:
|
|
|
176
174
|
|
|
177
175
|
Write the composed JSON to `{specsDir}/{epic}/epic-manifest.json` (creating the epic dir first).
|
|
178
176
|
For the *initial* creation write the skill writes the file directly — atomic guarantees are only
|
|
179
|
-
required for in-place mutation, which is the helper mutators' job. Then validate:
|
|
177
|
+
required for in-place mutation, which is the helper mutators' job. Creating the epic dir first creates `{specsDir}/`, so after writing the manifest invoke the **Specs Directory Hygiene** block in `references/shared-conventions.md` (idempotent; stage anything it writes with this stage's commit). Then validate:
|
|
180
178
|
|
|
181
179
|
```bash
|
|
182
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
180
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
183
181
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
184
182
|
python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
|
|
185
183
|
```
|
|
@@ -240,7 +238,7 @@ now self-contained: manifest + EPIC.md + one subdirectory per member.
|
|
|
240
238
|
### Step C8 — Review, Pipeline State & Commit
|
|
241
239
|
|
|
242
240
|
1. **Review.** Present a summary (epic name, N features, dependency edges, contracts) as text,
|
|
243
|
-
then use
|
|
241
|
+
then use the host's question mechanism: "Does this epic decomposition look right? Any feature, dependency,
|
|
244
242
|
or contract to change before I commit?" If the user wants changes, loop back to the relevant
|
|
245
243
|
creation step, re-compose, and re-validate.
|
|
246
244
|
|
|
@@ -271,7 +269,7 @@ Entered from Step 0 when `{specsDir}/{epic}/epic-manifest.json` already exists (
|
|
|
271
269
|
branch). The edit branch mutates the manifest **only** through helper mutators — atomic
|
|
272
270
|
(temp file + `os.replace`) and internally re-validated, so a refused write leaves the manifest
|
|
273
271
|
**byte-identical**; the skill never hand-rolls an in-place write. Every question goes through
|
|
274
|
-
|
|
272
|
+
the host's question mechanism, and **every mutation is committed individually** so git history is the audit trail.
|
|
275
273
|
|
|
276
274
|
For the full E1–E6 mechanics — the E1 refuse-if-invalid protocol, E2 operation→mutator table, E3
|
|
277
275
|
contracts/remove-feature caveats (incl. the verbatim WARN block), E4 impact-warning rules, E5
|
|
@@ -300,4 +298,14 @@ section).
|
|
|
300
298
|
- A charter is one paragraph, not a PRD. Redirect requirement-level detail to `forge-1-prd`.
|
|
301
299
|
- Contracts have no mutator: edit `exposes`/`consumes` in the composed manifest entry, then
|
|
302
300
|
re-run `validate`.
|
|
303
|
-
- All questions go through
|
|
301
|
+
- All questions go through the host's question mechanism. Never put a question in your text output.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Host execution notes
|
|
306
|
+
|
|
307
|
+
This skill was authored Claude-first; the body above refers to "the host's question mechanism", "the host's subagent mechanism", and "the host's background-execution mechanism". Use your runtime's equivalent for each — and if your runtime has no such tool:
|
|
308
|
+
|
|
309
|
+
- **User input:** ask the question directly and wait for the answer before proceeding. Do not skip a required question or assume an answer.
|
|
310
|
+
- **Subagents:** if your host cannot dispatch the named custom agent, run that step inline yourself.
|
|
311
|
+
- **Background / monitoring:** run long-lived commands in the foreground (or your host's background facility) and report progress as it arrives.
|
|
@@ -16,7 +16,7 @@ question goes through `AskUserQuestion`.
|
|
|
16
16
|
Before offering any edit, validate the existing manifest:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
19
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
20
20
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
21
21
|
python3 "$R/scripts/epic-manifest.py" validate "{epic}" --specs-dir "{specsDir}" --json
|
|
22
22
|
```
|
|
@@ -77,7 +77,7 @@ status is **not** `not-started`, warn the user. Read the **live** status (never
|
|
|
77
77
|
completion in prose):
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
80
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
81
81
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
82
82
|
python3 "$R/scripts/epic-manifest.py" render-status "{epic}" --specs-dir "{specsDir}" --json
|
|
83
83
|
```
|
|
@@ -12,7 +12,7 @@ the write if it would introduce a cycle, dangling ref, duplicate, or schema viol
|
|
|
12
12
|
flag surface (owned by 02 §7):
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
15
|
+
R="$(for d in "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/*/feature-forge "$HOME"/.agents/skills/feature-forge ./.agents/skills/feature-forge; do [ -x "$d/scripts/forge-root.sh" ] && exec "$d/scripts/forge-root.sh"; done)"
|
|
16
16
|
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
17
17
|
# Add a feature — seeds EMPTY exposes/consumes; contracts are populated below.
|
|
18
18
|
python3 "$R/scripts/epic-manifest.py" add-feature "{epic}" "{feature}" \
|
|
@@ -16,11 +16,11 @@ Read and follow `references/shared-conventions.md` for feature name validation,
|
|
|
16
16
|
## Step 1: Read Configuration and Check State
|
|
17
17
|
|
|
18
18
|
### Branch Setup (if using git)
|
|
19
|
-
|
|
19
|
+
Invoke the **Branch Setup** block in `references/shared-conventions.md` with `{label}` = `{feature}` and `{scope}` = `feature`. It self-gates (skips when not a git repo, when `branchPerFeature` is false, or for an epic member that inherits the epic's branch), detects whether you're on the default branch, and strongly recommends — still optionally — creating `{branchPrefix}{feature}` when you are. Do this before directory resolution.
|
|
20
20
|
|
|
21
21
|
Set the working directory by invoking the **Feature Directory Resolution** block in `references/shared-conventions.md`, which yields `{resolvedFeatureDir}`. Note one PRD-specific caveat: at PRD time a brand-new standalone feature may have NO directory yet, so resolution is expected to fail `not-found` for a never-started standalone feature — in that case forge-1 creates `{specsDir}/{feature}/` as today. For an epic member the directory already exists (created empty by forge-0-epic with an `epic` back-pointer), so resolution succeeds and yields the nested path.
|
|
22
22
|
|
|
23
|
-
If `.pipeline-state.json` exists for this feature and `forge-1-prd` is already marked complete, use
|
|
23
|
+
If `.pipeline-state.json` exists for this feature and `forge-1-prd` is already marked complete, use the host's question mechanism to warn: "A PRD already exists for '{feature}'. Continuing will create a new version. Proceed?"
|
|
24
24
|
|
|
25
25
|
## Step 2: Examine Existing Context
|
|
26
26
|
|
|
@@ -61,23 +61,23 @@ A technology constraint is valid when it stems from organizational mandate, exis
|
|
|
61
61
|
|
|
62
62
|
### Interview Approach
|
|
63
63
|
|
|
64
|
-
**Turn structure:** Output your analysis or context as regular text, then use
|
|
64
|
+
**Turn structure:** Output your analysis or context as regular text, then use the host's question mechanism for the actual questions. NEVER put questions in your text output — they MUST go through the host's question mechanism.
|
|
65
65
|
|
|
66
|
-
**Pacing:** Cover one topic area at a time, asking 2-3 related questions per
|
|
66
|
+
**Pacing:** Cover one topic area at a time, asking 2-3 related questions per the host's question mechanism call. After receiving answers, probe deeper on anything incomplete before moving to the next topic. Signal progress in your text before the next question batch.
|
|
67
67
|
|
|
68
|
-
**Question strategies** (use these as content for
|
|
68
|
+
**Question strategies** (use these as content for the host's question mechanism, not as inline prose). The PRD stays at the requirements level (the *what*, not the *how* — that's forge-2-tech), so most questions are open elicitation. But whenever you offer the user a *choice* (scope boundary, MVP cut, a non-functional target), apply the **Decision Support** protocol in `references/shared-conventions.md`: propose a sensible default with its trade-off rather than an empty menu — e.g. "I'd scope V1 to X and defer Y; that ships sooner but means Y waits. Agree?":
|
|
69
69
|
- Probe deeper after each answer: failure modes, stakeholders, minimum viable version
|
|
70
70
|
- Challenge assumptions: which users specifically, what does "fast" mean quantitatively
|
|
71
71
|
- Identify edge cases: empty input, concurrent access, scale
|
|
72
72
|
- Capture non-functional requirements: performance, security, accessibility, observability
|
|
73
|
-
- Ask about what's OUT of scope — as important as what's in scope
|
|
73
|
+
- Ask about what's OUT of scope — as important as what's in scope; when proposing a scope line, recommend one and name what each side gives up
|
|
74
74
|
|
|
75
75
|
**Completion criteria:** The interview is complete when:
|
|
76
76
|
1. Every category in `references/prd-template.md` has been covered with at least one question
|
|
77
77
|
2. The user has confirmed there's nothing else to add
|
|
78
78
|
3. You can draft every PRD section without leaving TBD placeholders
|
|
79
79
|
|
|
80
|
-
Before moving to Step 4, summarize your coverage as text, then use
|
|
80
|
+
Before moving to Step 4, summarize your coverage as text, then use the host's question mechanism to ask: "Anything I'm missing?"
|
|
81
81
|
|
|
82
82
|
**Parking lot:** If the user raises a concern that belongs to a different pipeline stage, acknowledge it and note it in the pipeline state's `notes` field: "Good point — I've noted that for the [tech spec/implementation specs]. Let's continue with [current stage]."
|
|
83
83
|
|
|
@@ -87,6 +87,8 @@ Once the interview is thorough, write `{resolvedFeatureDir}/PRD.md` following th
|
|
|
87
87
|
|
|
88
88
|
Every requirement MUST have a unique ID (e.g., REQ-AUTH-01, REQ-PERF-01). These IDs are referenced by all downstream documents.
|
|
89
89
|
|
|
90
|
+
After writing the PRD (this is the point where `{specsDir}/{feature}/` is first created for a standalone feature), invoke the **Specs Directory Hygiene** block in `references/shared-conventions.md` to ensure `{specsDir}/AGENTS.md` (and `{specsDir}/CLAUDE.md` on the Claude host) exists. It is idempotent — it never overwrites an existing file.
|
|
91
|
+
|
|
90
92
|
## Step 5: Review with User
|
|
91
93
|
|
|
92
94
|
Present the complete PRD to the user. Ask:
|
|
@@ -94,7 +96,7 @@ Present the complete PRD to the user. Ask:
|
|
|
94
96
|
- "Are the priorities correct?"
|
|
95
97
|
- "Anything in here that should be out of scope?"
|
|
96
98
|
|
|
97
|
-
Use
|
|
99
|
+
Use the host's question mechanism to collect this feedback.
|
|
98
100
|
|
|
99
101
|
Iterate until the user confirms the PRD is complete.
|
|
100
102
|
|
|
@@ -108,9 +110,9 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
|
|
|
108
110
|
- Record `artifacts`, `completedAt`
|
|
109
111
|
- Set `stages.forge-1-prd.basedOnVersions` to `{}` (no upstream dependencies)
|
|
110
112
|
- Check downstream stages (`forge-2-tech`, `forge-3-specs`, `forge-4-backlog`, `forge-5-loop`, `forge-6-docs`). If any have `basedOnVersions` referencing an older version of `forge-1-prd`, set their status to `stale`.
|
|
111
|
-
2. Use
|
|
113
|
+
2. Use the host's question mechanism to ask: "Anything you want to note before we wrap? (preserved across sessions)"
|
|
112
114
|
- If yes, store in the `notes` field
|
|
113
|
-
3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files, attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"`, then set `stages.forge-1-prd.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
|
|
115
|
+
3. If `gitCommitAfterStage` is true, follow the Git Commit Protocol in `references/shared-conventions.md`: stage files (including `{specsDir}/AGENTS.md` / `{specsDir}/CLAUDE.md` if the Specs Directory Hygiene step just wrote them), attempt commit with message `"{commitPrefix}({feature}): complete PRD v{n}"`, then set `stages.forge-1-prd.status` to `complete` with commit hash only on success. If commit fails, leave status as `in-progress`.
|
|
114
116
|
5. Tell the user: "PRD complete. Next steps:\n - `/feature-forge:forge-verify {feature}` to verify the PRD\n - `/feature-forge:forge-2-tech {feature}` to start the tech spec\n - `/feature-forge:forge {feature}` to see full pipeline status"
|
|
115
117
|
|
|
116
118
|
## Gotchas
|
|
@@ -119,3 +121,13 @@ Write pipeline state conforming to `references/pipeline-state-schema.json`.
|
|
|
119
121
|
- If the user provides a very detailed initial description, don't skip the interview. Use their description as a starting point but probe for what's missing. Long descriptions often have big gaps in edge cases and non-functional requirements.
|
|
120
122
|
- Don't number requirements sequentially across categories (REQ-01, REQ-02...). Use category prefixes (REQ-AUTH-01, REQ-PERF-01) so inserting new requirements doesn't require renumbering.
|
|
121
123
|
- The PRD should be readable by a non-technical stakeholder. If a section requires deep technical knowledge to understand, it probably belongs in the tech spec, not the PRD.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Host execution notes
|
|
128
|
+
|
|
129
|
+
This skill was authored Claude-first; the body above refers to "the host's question mechanism", "the host's subagent mechanism", and "the host's background-execution mechanism". Use your runtime's equivalent for each — and if your runtime has no such tool:
|
|
130
|
+
|
|
131
|
+
- **User input:** ask the question directly and wait for the answer before proceeding. Do not skip a required question or assume an answer.
|
|
132
|
+
- **Subagents:** if your host cannot dispatch the named custom agent, run that step inline yourself.
|
|
133
|
+
- **Background / monitoring:** run long-lived commands in the foreground (or your host's background facility) and report progress as it arrives.
|