@garygentry/feature-forge 0.2.13 → 0.3.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 +6 -3
- package/adapters/GENERATION-REPORT.md +20 -0
- package/adapters/claude/.feature-forge-bundle.json +1 -1
- package/adapters/claude/references/epic-manifest-schema.json +5 -0
- package/adapters/claude/references/forge-config-schema.json +2 -2
- package/adapters/claude/references/shared-conventions.md +12 -0
- package/adapters/claude/references/stacks/_generic.md +21 -0
- package/adapters/claude/references/stacks/go.md +19 -0
- package/adapters/claude/references/stacks/python.md +21 -0
- package/adapters/claude/references/stacks/rust.md +19 -0
- package/adapters/claude/references/stacks/typescript.md +23 -0
- package/adapters/claude/scripts/epic-manifest.py +75 -5
- package/adapters/claude/scripts/forge-root.sh +102 -14
- package/adapters/claude/scripts/forge-session.py +68 -9
- package/adapters/claude/skills/forge/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-0-epic/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-1-prd/SKILL.md +2 -0
- package/adapters/claude/skills/forge-1-prd/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-2-tech/SKILL.md +2 -0
- package/adapters/claude/skills/forge-2-tech/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-2-tech/references/stacks/_generic.md +21 -0
- package/adapters/claude/skills/forge-2-tech/references/stacks/go.md +19 -0
- package/adapters/claude/skills/forge-2-tech/references/stacks/python.md +21 -0
- package/adapters/claude/skills/forge-2-tech/references/stacks/rust.md +19 -0
- package/adapters/claude/skills/forge-2-tech/references/stacks/typescript.md +23 -0
- package/adapters/claude/skills/forge-3-specs/SKILL.md +2 -0
- package/adapters/claude/skills/forge-3-specs/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-3-specs/references/stacks/_generic.md +21 -0
- package/adapters/claude/skills/forge-3-specs/references/stacks/go.md +19 -0
- package/adapters/claude/skills/forge-3-specs/references/stacks/python.md +21 -0
- package/adapters/claude/skills/forge-3-specs/references/stacks/rust.md +19 -0
- package/adapters/claude/skills/forge-3-specs/references/stacks/typescript.md +23 -0
- package/adapters/claude/skills/forge-4-backlog/SKILL.md +5 -0
- package/adapters/claude/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/claude/skills/forge-4-backlog/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-5-loop/SKILL.md +7 -9
- package/adapters/claude/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/claude/skills/forge-5-loop/references/runner-contract.md +41 -0
- package/adapters/claude/skills/forge-5-loop/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-6-docs/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-fix/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/claude/skills/forge-guide/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-guide/references/stacks/_generic.md +21 -0
- package/adapters/claude/skills/forge-guide/references/stacks/go.md +19 -0
- package/adapters/claude/skills/forge-guide/references/stacks/python.md +21 -0
- package/adapters/claude/skills/forge-guide/references/stacks/rust.md +19 -0
- package/adapters/claude/skills/forge-guide/references/stacks/typescript.md +23 -0
- package/adapters/claude/skills/forge-verify/SKILL.md +3 -3
- package/adapters/claude/skills/forge-verify/references/shared-conventions.md +12 -0
- package/adapters/claude/skills/forge-verify/references/verification-checklists.md +82 -3
- package/adapters/codex/.feature-forge-bundle.json +1 -1
- package/adapters/codex/references/epic-manifest-schema.json +5 -0
- package/adapters/codex/references/forge-config-schema.json +2 -2
- package/adapters/codex/references/shared-conventions.md +12 -0
- package/adapters/codex/references/stacks/_generic.md +21 -0
- package/adapters/codex/references/stacks/go.md +19 -0
- package/adapters/codex/references/stacks/python.md +21 -0
- package/adapters/codex/references/stacks/rust.md +19 -0
- package/adapters/codex/references/stacks/typescript.md +23 -0
- package/adapters/codex/scripts/epic-manifest.py +75 -5
- package/adapters/codex/scripts/forge-root.sh +102 -14
- package/adapters/codex/scripts/forge-session.py +68 -9
- package/adapters/codex/skills/forge/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-0-epic/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-1-prd/SKILL.md +2 -0
- package/adapters/codex/skills/forge-1-prd/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-2-tech/SKILL.md +2 -0
- package/adapters/codex/skills/forge-2-tech/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-2-tech/references/stacks/_generic.md +21 -0
- package/adapters/codex/skills/forge-2-tech/references/stacks/go.md +19 -0
- package/adapters/codex/skills/forge-2-tech/references/stacks/python.md +21 -0
- package/adapters/codex/skills/forge-2-tech/references/stacks/rust.md +19 -0
- package/adapters/codex/skills/forge-2-tech/references/stacks/typescript.md +23 -0
- package/adapters/codex/skills/forge-3-specs/SKILL.md +2 -0
- package/adapters/codex/skills/forge-3-specs/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-3-specs/references/stacks/_generic.md +21 -0
- package/adapters/codex/skills/forge-3-specs/references/stacks/go.md +19 -0
- package/adapters/codex/skills/forge-3-specs/references/stacks/python.md +21 -0
- package/adapters/codex/skills/forge-3-specs/references/stacks/rust.md +19 -0
- package/adapters/codex/skills/forge-3-specs/references/stacks/typescript.md +23 -0
- package/adapters/codex/skills/forge-4-backlog/SKILL.md +5 -0
- package/adapters/codex/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/codex/skills/forge-4-backlog/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-5-loop/SKILL.md +7 -9
- package/adapters/codex/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/codex/skills/forge-5-loop/references/runner-contract.md +41 -0
- package/adapters/codex/skills/forge-5-loop/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-6-docs/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-fix/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/codex/skills/forge-guide/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-guide/references/stacks/_generic.md +21 -0
- package/adapters/codex/skills/forge-guide/references/stacks/go.md +19 -0
- package/adapters/codex/skills/forge-guide/references/stacks/python.md +21 -0
- package/adapters/codex/skills/forge-guide/references/stacks/rust.md +19 -0
- package/adapters/codex/skills/forge-guide/references/stacks/typescript.md +23 -0
- package/adapters/codex/skills/forge-verify/SKILL.md +3 -3
- package/adapters/codex/skills/forge-verify/references/shared-conventions.md +12 -0
- package/adapters/codex/skills/forge-verify/references/verification-checklists.md +82 -3
- package/adapters/copilot/.feature-forge-bundle.json +1 -1
- package/adapters/copilot/references/epic-manifest-schema.json +5 -0
- package/adapters/copilot/references/forge-config-schema.json +2 -2
- package/adapters/copilot/references/shared-conventions.md +12 -0
- package/adapters/copilot/references/stacks/_generic.md +21 -0
- package/adapters/copilot/references/stacks/go.md +19 -0
- package/adapters/copilot/references/stacks/python.md +21 -0
- package/adapters/copilot/references/stacks/rust.md +19 -0
- package/adapters/copilot/references/stacks/typescript.md +23 -0
- package/adapters/copilot/scripts/epic-manifest.py +75 -5
- package/adapters/copilot/scripts/forge-root.sh +102 -14
- package/adapters/copilot/scripts/forge-session.py +68 -9
- package/adapters/copilot/skills/forge/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-0-epic/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-1-prd/forge-1-prd.md +2 -0
- package/adapters/copilot/skills/forge-1-prd/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-2-tech/forge-2-tech.md +2 -0
- package/adapters/copilot/skills/forge-2-tech/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-2-tech/references/stacks/_generic.md +21 -0
- package/adapters/copilot/skills/forge-2-tech/references/stacks/go.md +19 -0
- package/adapters/copilot/skills/forge-2-tech/references/stacks/python.md +21 -0
- package/adapters/copilot/skills/forge-2-tech/references/stacks/rust.md +19 -0
- package/adapters/copilot/skills/forge-2-tech/references/stacks/typescript.md +23 -0
- package/adapters/copilot/skills/forge-3-specs/forge-3-specs.md +2 -0
- package/adapters/copilot/skills/forge-3-specs/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-3-specs/references/stacks/_generic.md +21 -0
- package/adapters/copilot/skills/forge-3-specs/references/stacks/go.md +19 -0
- package/adapters/copilot/skills/forge-3-specs/references/stacks/python.md +21 -0
- package/adapters/copilot/skills/forge-3-specs/references/stacks/rust.md +19 -0
- package/adapters/copilot/skills/forge-3-specs/references/stacks/typescript.md +23 -0
- package/adapters/copilot/skills/forge-4-backlog/forge-4-backlog.md +5 -0
- package/adapters/copilot/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/copilot/skills/forge-4-backlog/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-5-loop/forge-5-loop.md +7 -9
- package/adapters/copilot/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/copilot/skills/forge-5-loop/references/runner-contract.md +41 -0
- package/adapters/copilot/skills/forge-5-loop/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-6-docs/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-fix/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/copilot/skills/forge-guide/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-guide/references/stacks/_generic.md +21 -0
- package/adapters/copilot/skills/forge-guide/references/stacks/go.md +19 -0
- package/adapters/copilot/skills/forge-guide/references/stacks/python.md +21 -0
- package/adapters/copilot/skills/forge-guide/references/stacks/rust.md +19 -0
- package/adapters/copilot/skills/forge-guide/references/stacks/typescript.md +23 -0
- package/adapters/copilot/skills/forge-verify/forge-verify.md +3 -3
- package/adapters/copilot/skills/forge-verify/references/shared-conventions.md +12 -0
- package/adapters/copilot/skills/forge-verify/references/verification-checklists.md +82 -3
- package/adapters/cursor/.feature-forge-bundle.json +1 -1
- package/adapters/cursor/references/epic-manifest-schema.json +5 -0
- package/adapters/cursor/references/forge-config-schema.json +2 -2
- package/adapters/cursor/references/shared-conventions.md +12 -0
- package/adapters/cursor/references/stacks/_generic.md +21 -0
- package/adapters/cursor/references/stacks/go.md +19 -0
- package/adapters/cursor/references/stacks/python.md +21 -0
- package/adapters/cursor/references/stacks/rust.md +19 -0
- package/adapters/cursor/references/stacks/typescript.md +23 -0
- package/adapters/cursor/scripts/epic-manifest.py +75 -5
- package/adapters/cursor/scripts/forge-root.sh +102 -14
- package/adapters/cursor/scripts/forge-session.py +68 -9
- package/adapters/cursor/skills/forge/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-0-epic/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-1-prd/forge-1-prd.mdc +2 -0
- package/adapters/cursor/skills/forge-1-prd/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-2-tech/forge-2-tech.mdc +2 -0
- package/adapters/cursor/skills/forge-2-tech/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-2-tech/references/stacks/_generic.md +21 -0
- package/adapters/cursor/skills/forge-2-tech/references/stacks/go.md +19 -0
- package/adapters/cursor/skills/forge-2-tech/references/stacks/python.md +21 -0
- package/adapters/cursor/skills/forge-2-tech/references/stacks/rust.md +19 -0
- package/adapters/cursor/skills/forge-2-tech/references/stacks/typescript.md +23 -0
- package/adapters/cursor/skills/forge-3-specs/forge-3-specs.mdc +2 -0
- package/adapters/cursor/skills/forge-3-specs/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-3-specs/references/stacks/_generic.md +21 -0
- package/adapters/cursor/skills/forge-3-specs/references/stacks/go.md +19 -0
- package/adapters/cursor/skills/forge-3-specs/references/stacks/python.md +21 -0
- package/adapters/cursor/skills/forge-3-specs/references/stacks/rust.md +19 -0
- package/adapters/cursor/skills/forge-3-specs/references/stacks/typescript.md +23 -0
- package/adapters/cursor/skills/forge-4-backlog/forge-4-backlog.mdc +5 -0
- package/adapters/cursor/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/cursor/skills/forge-4-backlog/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-5-loop/forge-5-loop.mdc +7 -9
- package/adapters/cursor/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/cursor/skills/forge-5-loop/references/runner-contract.md +41 -0
- package/adapters/cursor/skills/forge-5-loop/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-6-docs/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-fix/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/cursor/skills/forge-guide/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-guide/references/stacks/_generic.md +21 -0
- package/adapters/cursor/skills/forge-guide/references/stacks/go.md +19 -0
- package/adapters/cursor/skills/forge-guide/references/stacks/python.md +21 -0
- package/adapters/cursor/skills/forge-guide/references/stacks/rust.md +19 -0
- package/adapters/cursor/skills/forge-guide/references/stacks/typescript.md +23 -0
- package/adapters/cursor/skills/forge-verify/forge-verify.mdc +3 -3
- package/adapters/cursor/skills/forge-verify/references/shared-conventions.md +12 -0
- package/adapters/cursor/skills/forge-verify/references/verification-checklists.md +82 -3
- package/adapters/gemini/.feature-forge-bundle.json +1 -1
- package/adapters/gemini/gemini-extension.json +1 -1
- package/adapters/gemini/references/epic-manifest-schema.json +5 -0
- package/adapters/gemini/references/forge-config-schema.json +2 -2
- package/adapters/gemini/references/shared-conventions.md +12 -0
- package/adapters/gemini/references/stacks/_generic.md +21 -0
- package/adapters/gemini/references/stacks/go.md +19 -0
- package/adapters/gemini/references/stacks/python.md +21 -0
- package/adapters/gemini/references/stacks/rust.md +19 -0
- package/adapters/gemini/references/stacks/typescript.md +23 -0
- package/adapters/gemini/scripts/epic-manifest.py +75 -5
- package/adapters/gemini/scripts/forge-root.sh +102 -14
- package/adapters/gemini/scripts/forge-session.py +68 -9
- package/adapters/gemini/skills/forge/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-0-epic/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-1-prd/forge-1-prd.md +2 -0
- package/adapters/gemini/skills/forge-1-prd/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-2-tech/forge-2-tech.md +2 -0
- package/adapters/gemini/skills/forge-2-tech/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-2-tech/references/stacks/_generic.md +21 -0
- package/adapters/gemini/skills/forge-2-tech/references/stacks/go.md +19 -0
- package/adapters/gemini/skills/forge-2-tech/references/stacks/python.md +21 -0
- package/adapters/gemini/skills/forge-2-tech/references/stacks/rust.md +19 -0
- package/adapters/gemini/skills/forge-2-tech/references/stacks/typescript.md +23 -0
- package/adapters/gemini/skills/forge-3-specs/forge-3-specs.md +2 -0
- package/adapters/gemini/skills/forge-3-specs/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-3-specs/references/stacks/_generic.md +21 -0
- package/adapters/gemini/skills/forge-3-specs/references/stacks/go.md +19 -0
- package/adapters/gemini/skills/forge-3-specs/references/stacks/python.md +21 -0
- package/adapters/gemini/skills/forge-3-specs/references/stacks/rust.md +19 -0
- package/adapters/gemini/skills/forge-3-specs/references/stacks/typescript.md +23 -0
- package/adapters/gemini/skills/forge-4-backlog/forge-4-backlog.md +5 -0
- package/adapters/gemini/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/gemini/skills/forge-4-backlog/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-5-loop/forge-5-loop.md +7 -9
- package/adapters/gemini/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/gemini/skills/forge-5-loop/references/runner-contract.md +41 -0
- package/adapters/gemini/skills/forge-5-loop/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-6-docs/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-fix/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/gemini/skills/forge-guide/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-guide/references/stacks/_generic.md +21 -0
- package/adapters/gemini/skills/forge-guide/references/stacks/go.md +19 -0
- package/adapters/gemini/skills/forge-guide/references/stacks/python.md +21 -0
- package/adapters/gemini/skills/forge-guide/references/stacks/rust.md +19 -0
- package/adapters/gemini/skills/forge-guide/references/stacks/typescript.md +23 -0
- package/adapters/gemini/skills/forge-verify/forge-verify.md +3 -3
- package/adapters/gemini/skills/forge-verify/references/shared-conventions.md +12 -0
- package/adapters/gemini/skills/forge-verify/references/verification-checklists.md +82 -3
- package/adapters/pi/.feature-forge-bundle.json +6 -0
- package/adapters/pi/agents/forge-researcher.md +139 -0
- package/adapters/pi/agents/forge-spec-writer.md +116 -0
- package/adapters/pi/agents/forge-verifier.md +126 -0
- package/adapters/pi/extensions/ask-user-question/LICENSE +21 -0
- package/adapters/pi/extensions/ask-user-question/README.md +91 -0
- package/adapters/pi/extensions/ask-user-question/ask-user-question.ts +298 -0
- package/adapters/pi/extensions/ask-user-question/config.ts +78 -0
- package/adapters/pi/extensions/ask-user-question/events.ts +57 -0
- package/adapters/pi/extensions/ask-user-question/index.ts +61 -0
- package/adapters/pi/extensions/ask-user-question/locales/de.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/en.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/es.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/fr.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/pt-BR.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/pt.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/ru.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/uk.json +27 -0
- package/adapters/pi/extensions/ask-user-question/locales/zh.json +29 -0
- package/adapters/pi/extensions/ask-user-question/reconcile.ts +49 -0
- package/adapters/pi/extensions/ask-user-question/rpc-fallback.ts +168 -0
- package/adapters/pi/extensions/ask-user-question/state/build-questionnaire.ts +302 -0
- package/adapters/pi/extensions/ask-user-question/state/i18n-bridge.ts +53 -0
- package/adapters/pi/extensions/ask-user-question/state/key-router.ts +277 -0
- package/adapters/pi/extensions/ask-user-question/state/questionnaire-session.ts +234 -0
- package/adapters/pi/extensions/ask-user-question/state/row-intent.ts +145 -0
- package/adapters/pi/extensions/ask-user-question/state/selectors/contract.ts +26 -0
- package/adapters/pi/extensions/ask-user-question/state/selectors/derivations.ts +42 -0
- package/adapters/pi/extensions/ask-user-question/state/selectors/focus.ts +19 -0
- package/adapters/pi/extensions/ask-user-question/state/selectors/projections.ts +101 -0
- package/adapters/pi/extensions/ask-user-question/state/state-reducer.ts +292 -0
- package/adapters/pi/extensions/ask-user-question/state/state.ts +55 -0
- package/adapters/pi/extensions/ask-user-question/tool/format-answer.ts +31 -0
- package/adapters/pi/extensions/ask-user-question/tool/response-envelope.ts +49 -0
- package/adapters/pi/extensions/ask-user-question/tool/types.ts +147 -0
- package/adapters/pi/extensions/ask-user-question/tool/validate-questionnaire.ts +58 -0
- package/adapters/pi/extensions/ask-user-question/vendor-config-shim.ts +65 -0
- package/adapters/pi/extensions/ask-user-question/view/component-binding.ts +47 -0
- package/adapters/pi/extensions/ask-user-question/view/components/inline-input.ts +98 -0
- package/adapters/pi/extensions/ask-user-question/view/components/multi-select-view.ts +193 -0
- package/adapters/pi/extensions/ask-user-question/view/components/option-list-view.ts +70 -0
- package/adapters/pi/extensions/ask-user-question/view/components/preview/markdown-content-cache.ts +79 -0
- package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-block-renderer.ts +111 -0
- package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-box-renderer.ts +88 -0
- package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-layout-decider.ts +202 -0
- package/adapters/pi/extensions/ask-user-question/view/components/preview/preview-pane.ts +228 -0
- package/adapters/pi/extensions/ask-user-question/view/components/submit-picker.ts +67 -0
- package/adapters/pi/extensions/ask-user-question/view/components/tab-bar.ts +59 -0
- package/adapters/pi/extensions/ask-user-question/view/components/wrapping-select.ts +293 -0
- package/adapters/pi/extensions/ask-user-question/view/dialog-builder.ts +224 -0
- package/adapters/pi/extensions/ask-user-question/view/props-adapter.ts +125 -0
- package/adapters/pi/extensions/ask-user-question/view/stateful-view.ts +26 -0
- package/adapters/pi/extensions/ask-user-question/view/tab-components.ts +18 -0
- package/adapters/pi/extensions/ask-user-question/view/tab-content-strategy.ts +252 -0
- package/adapters/pi/package.json +26 -0
- package/adapters/pi/references/epic-manifest-schema.json +125 -0
- package/adapters/pi/references/forge-config-schema.json +236 -0
- package/adapters/pi/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/references/portable-root.md +71 -0
- package/adapters/pi/references/process-overview.md +143 -0
- package/adapters/pi/references/ralph-loop-contract.md +221 -0
- package/adapters/pi/references/shared-conventions.md +295 -0
- package/adapters/pi/references/skill-frontmatter.schema.json +17 -0
- package/adapters/pi/references/stack-resolution.md +54 -0
- package/adapters/pi/references/stacks/_generic.md +111 -0
- package/adapters/pi/references/stacks/go.md +157 -0
- package/adapters/pi/references/stacks/python.md +184 -0
- package/adapters/pi/references/stacks/rust.md +170 -0
- package/adapters/pi/references/stacks/typescript.md +134 -0
- package/adapters/pi/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/references/templates/specs-hygiene/AGENTS.md +32 -0
- package/adapters/pi/references/templates/specs-hygiene/CLAUDE.md +31 -0
- package/adapters/pi/references/vendor-construct-inventory.md +50 -0
- package/adapters/pi/scripts/epic-manifest.py +1694 -0
- package/adapters/pi/scripts/forge-bootstrap.py +1070 -0
- package/adapters/pi/scripts/forge-init.sh +58 -0
- package/adapters/pi/scripts/forge-root.sh +179 -0
- package/adapters/pi/scripts/forge-session.py +1888 -0
- package/adapters/pi/scripts/validate-traceability.py +150 -0
- package/adapters/pi/skills/forge/SKILL.md +243 -0
- package/adapters/pi/skills/forge/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge/references/process-overview.md +143 -0
- package/adapters/pi/skills/forge/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-0-epic/SKILL.md +308 -0
- package/adapters/pi/skills/forge-0-epic/references/edit-mode.md +266 -0
- package/adapters/pi/skills/forge-0-epic/references/epic-manifest-subcommands.md +75 -0
- package/adapters/pi/skills/forge-0-epic/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-0-epic/references/portable-root.md +71 -0
- package/adapters/pi/skills/forge-0-epic/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-0-epic/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-1-prd/SKILL.md +164 -0
- package/adapters/pi/skills/forge-1-prd/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-1-prd/references/prd-template.md +106 -0
- package/adapters/pi/skills/forge-1-prd/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-1-prd/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-2-tech/SKILL.md +225 -0
- package/adapters/pi/skills/forge-2-tech/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-2-tech/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-2-tech/references/stack-discovery-checklist.md +95 -0
- package/adapters/pi/skills/forge-2-tech/references/stack-resolution.md +54 -0
- package/adapters/pi/skills/forge-2-tech/references/stacks/_generic.md +111 -0
- package/adapters/pi/skills/forge-2-tech/references/stacks/go.md +157 -0
- package/adapters/pi/skills/forge-2-tech/references/stacks/python.md +184 -0
- package/adapters/pi/skills/forge-2-tech/references/stacks/rust.md +170 -0
- package/adapters/pi/skills/forge-2-tech/references/stacks/typescript.md +134 -0
- package/adapters/pi/skills/forge-2-tech/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-3-specs/SKILL.md +178 -0
- package/adapters/pi/skills/forge-3-specs/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-3-specs/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-3-specs/references/spec-archetypes.md +106 -0
- package/adapters/pi/skills/forge-3-specs/references/spec-examples.md +71 -0
- package/adapters/pi/skills/forge-3-specs/references/stacks/_generic.md +111 -0
- package/adapters/pi/skills/forge-3-specs/references/stacks/go.md +157 -0
- package/adapters/pi/skills/forge-3-specs/references/stacks/python.md +184 -0
- package/adapters/pi/skills/forge-3-specs/references/stacks/rust.md +170 -0
- package/adapters/pi/skills/forge-3-specs/references/stacks/typescript.md +134 -0
- package/adapters/pi/skills/forge-3-specs/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-4-backlog/SKILL.md +175 -0
- package/adapters/pi/skills/forge-4-backlog/references/forge-config-schema.json +236 -0
- package/adapters/pi/skills/forge-4-backlog/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-4-backlog/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-4-backlog/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-5-loop/SKILL.md +314 -0
- package/adapters/pi/skills/forge-5-loop/references/forge-config-schema.json +236 -0
- package/adapters/pi/skills/forge-5-loop/references/ralph-loop-contract.md +221 -0
- package/adapters/pi/skills/forge-5-loop/references/result-reporting.md +85 -0
- package/adapters/pi/skills/forge-5-loop/references/runner-contract.md +341 -0
- package/adapters/pi/skills/forge-5-loop/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-5-loop/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-6-docs/SKILL.md +202 -0
- package/adapters/pi/skills/forge-6-docs/references/doc-conventions.md +126 -0
- package/adapters/pi/skills/forge-6-docs/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-6-docs/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-bootstrap/SKILL.md +250 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/ci/github-actions.yml +12 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/generic/run.sh +3 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/generic/test.sh +13 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/go/go.mod +3 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/go/main.go +12 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/go/main_test.go +11 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/AGENTS.md +35 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/CLAUDE.md +36 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/hygiene/README.md +11 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/Apache-2.0/LICENSE +198 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/licenses/MIT/LICENSE +21 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/python/pyproject.toml +24 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/__init__.py +5 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/python/src/{{PKG}}/main.py +13 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/python/tests/test_smoke.py +8 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/rust/Cargo.toml +15 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/lib.rs +7 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/rust/src/main.rs +5 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/rust/tests/smoke.rs +6 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/package.json +15 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/src/index.ts +4 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/test/smoke.test.ts +6 -0
- package/adapters/pi/skills/forge-bootstrap/references/templates/typescript/tsconfig.json +14 -0
- package/adapters/pi/skills/forge-fix/SKILL.md +98 -0
- package/adapters/pi/skills/forge-fix/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-fix/references/stage-exit-protocol.md +258 -0
- package/adapters/pi/skills/forge-guide/SKILL.md +192 -0
- package/adapters/pi/skills/forge-guide/references/forge-config-schema.json +236 -0
- package/adapters/pi/skills/forge-guide/references/process-overview.md +143 -0
- package/adapters/pi/skills/forge-guide/references/ralph-loop-contract.md +221 -0
- package/adapters/pi/skills/forge-guide/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-guide/references/stack-resolution.md +54 -0
- package/adapters/pi/skills/forge-guide/references/stacks/_generic.md +111 -0
- package/adapters/pi/skills/forge-guide/references/stacks/go.md +157 -0
- package/adapters/pi/skills/forge-guide/references/stacks/python.md +184 -0
- package/adapters/pi/skills/forge-guide/references/stacks/rust.md +170 -0
- package/adapters/pi/skills/forge-guide/references/stacks/typescript.md +134 -0
- package/adapters/pi/skills/forge-init/SKILL.md +72 -0
- package/adapters/pi/skills/forge-verify/SKILL.md +273 -0
- package/adapters/pi/skills/forge-verify/references/pipeline-state-schema.json +191 -0
- package/adapters/pi/skills/forge-verify/references/shared-conventions.md +295 -0
- package/adapters/pi/skills/forge-verify/references/verification-checklists.md +477 -0
- package/dist/agent-targets.d.ts +1 -1
- package/dist/agent-targets.js +23 -3
- package/dist/detect.d.ts +1 -1
- package/dist/detect.js +2 -1
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.js +2 -2
- package/dist/placements.js +5 -1
- package/dist/rauf.d.ts +4 -4
- package/dist/rauf.js +3 -3
- package/dist/types.d.ts +31 -6
- package/dist/types.js +6 -3
- package/package.json +14 -3
|
@@ -117,8 +117,20 @@ VERIFY_TOKEN_BY_STAGE: Final[dict[str, str]] = {
|
|
|
117
117
|
|
|
118
118
|
#: A production stage status that counts as "done" for next-stage selection.
|
|
119
119
|
_DONE_STATUS: Final = "complete"
|
|
120
|
-
#:
|
|
120
|
+
#: The authoritative forge-verify status vocabulary. SOURCE OF TRUTH:
|
|
121
|
+
#: references/pipeline-state-schema.json (definitions.verifyEntry.properties.status.enum).
|
|
122
|
+
#: A status outside this set is unrecognized and must not be silently interpreted (#148).
|
|
123
|
+
#: NOTE: epic-manifest.py keeps a byte-identical copy — flat, self-contained scripts have
|
|
124
|
+
#: no shared import module (each is copied verbatim into per-agent adapter bundles).
|
|
125
|
+
KNOWN_VERIFY_STATUSES: Final = frozenset(
|
|
126
|
+
{"pending", "passed", "findings-reported", "findings-applied", "skipped"}
|
|
127
|
+
)
|
|
128
|
+
#: Verify statuses that count as "resolved" (no outstanding verify needed). A STRICT
|
|
129
|
+
#: subset of KNOWN_VERIFY_STATUSES — not collapsible into it (different meaning).
|
|
121
130
|
_VERIFY_RESOLVED: Final = frozenset({"passed", "findings-applied", "skipped"})
|
|
131
|
+
#: Per-process dedupe for the unknown-verify-status diagnostic (#148) so a single
|
|
132
|
+
#: bogus status is flagged once, not once per verify_state() call in a command.
|
|
133
|
+
_UNKNOWN_VERIFY_WARNED: set[str] = set()
|
|
122
134
|
|
|
123
135
|
#: Default context window when the model can't be inferred and config is silent.
|
|
124
136
|
_DEFAULT_WINDOW: Final = 200_000
|
|
@@ -257,6 +269,25 @@ def _verify_entry(state: dict, verify_key: str) -> dict:
|
|
|
257
269
|
return entry if isinstance(entry, dict) else {}
|
|
258
270
|
|
|
259
271
|
|
|
272
|
+
def _warn_unknown_verify_status(stage_name: str, status: object) -> None:
|
|
273
|
+
"""Emit a one-time stderr diagnostic for an out-of-vocabulary verify status (#148).
|
|
274
|
+
|
|
275
|
+
The freshness classifier maps an unrecognized status to "never verified" — correct,
|
|
276
|
+
but silent, so a typo poisons the downstream gate (e.g. forge-5-loop's dependency
|
|
277
|
+
check) with no clue. Flagging it here makes the bad value visible where it is read.
|
|
278
|
+
"""
|
|
279
|
+
key = f"{stage_name}={status!r}"
|
|
280
|
+
if key in _UNKNOWN_VERIFY_WARNED:
|
|
281
|
+
return
|
|
282
|
+
_UNKNOWN_VERIFY_WARNED.add(key)
|
|
283
|
+
known = ", ".join(sorted(KNOWN_VERIFY_STATUSES))
|
|
284
|
+
print(
|
|
285
|
+
f"feature-forge: unknown {stage_name} status {status!r} "
|
|
286
|
+
f"(treated as unverified; expected one of {known})",
|
|
287
|
+
file=sys.stderr,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
260
291
|
def verify_state(state: dict) -> tuple[str | None, str]:
|
|
261
292
|
"""Classify verify freshness for the most-recently-completed stage.
|
|
262
293
|
|
|
@@ -299,6 +330,12 @@ def verify_state(state: dict) -> tuple[str | None, str]:
|
|
|
299
330
|
if status not in _VERIFY_RESOLVED:
|
|
300
331
|
if status == "findings-reported":
|
|
301
332
|
return stage, "failing"
|
|
333
|
+
# An unrecognized status (outside KNOWN_VERIFY_STATUSES) is treated as
|
|
334
|
+
# "never verified" — defensible, but flag it once so a typo (e.g. the
|
|
335
|
+
# eye-slip 'findings-resolved') doesn't silently poison the gate that
|
|
336
|
+
# reads this label (#148). ``pending``/``None`` are known/absent → quiet.
|
|
337
|
+
if status is not None and status not in KNOWN_VERIFY_STATUSES:
|
|
338
|
+
_warn_unknown_verify_status(f"forge-verify-{token}", status)
|
|
302
339
|
return stage, "never"
|
|
303
340
|
verified_version = entry.get("verifiedStageVersion")
|
|
304
341
|
stage_version = _stage_version(state, stage)
|
|
@@ -1397,6 +1434,17 @@ def _resolve_feature_dir(specs_dir: Path, feature: str, epic: str | None) -> Pat
|
|
|
1397
1434
|
return flat
|
|
1398
1435
|
|
|
1399
1436
|
|
|
1437
|
+
def _host_command(command: str, host: str) -> str:
|
|
1438
|
+
"""Rewrite a `/feature-forge:` slash command to the host's surface.
|
|
1439
|
+
|
|
1440
|
+
Pi's slash-command surface is `/skill:` (matching the adapter body's
|
|
1441
|
+
`/feature-forge:` -> `/skill:` translation). The scripted stage-exit output bypasses
|
|
1442
|
+
that body translation, so it rewrites the commands it emits here. No-op for
|
|
1443
|
+
claude/generic, which keep the canonical `/feature-forge:` form.
|
|
1444
|
+
"""
|
|
1445
|
+
return command.replace("/feature-forge:", "/skill:") if host == "pi" else command
|
|
1446
|
+
|
|
1447
|
+
|
|
1400
1448
|
def _next_steps_block(
|
|
1401
1449
|
next_command: str, host: str, reconcile: dict | None = None
|
|
1402
1450
|
) -> str:
|
|
@@ -1426,6 +1474,18 @@ def _next_steps_block(
|
|
|
1426
1474
|
"2. Then start a fresh session and run the next stage below — or "
|
|
1427
1475
|
"re-run `/feature-forge:forge` to let the navigator resume from disk."
|
|
1428
1476
|
)
|
|
1477
|
+
elif host == "pi":
|
|
1478
|
+
# Pi's fresh-session command is `/new` (not `/clear`); its slash-command
|
|
1479
|
+
# surface is `/skill:` (the fenced command below is rewritten to match).
|
|
1480
|
+
clear_line = (
|
|
1481
|
+
"1. `/new` — recommended unconditionally at this stage boundary; every "
|
|
1482
|
+
"artifact is on disk, so the work survives starting a fresh session. "
|
|
1483
|
+
"I can't run `/new` for you — you have to run it yourself."
|
|
1484
|
+
)
|
|
1485
|
+
next_line = (
|
|
1486
|
+
"2. Then, in the new session, run the next stage below — or re-run "
|
|
1487
|
+
"`/skill:forge` to let the navigator resume from disk."
|
|
1488
|
+
)
|
|
1429
1489
|
else:
|
|
1430
1490
|
clear_line = (
|
|
1431
1491
|
"1. Clear your session / start a fresh session — recommended "
|
|
@@ -1442,7 +1502,7 @@ def _next_steps_block(
|
|
|
1442
1502
|
# epic-change request the primary is the reconcile command; otherwise it is the
|
|
1443
1503
|
# normal next-stage command. The fence sits before the sentinel, so the
|
|
1444
1504
|
# sentinel remains the absolute last line.
|
|
1445
|
-
fenced_command = reconcile["command"] if blocking else next_command
|
|
1505
|
+
fenced_command = _host_command(reconcile["command"] if blocking else next_command, host)
|
|
1446
1506
|
lines = ["**Next steps**", clear_line]
|
|
1447
1507
|
if blocking:
|
|
1448
1508
|
count = reconcile["count"]
|
|
@@ -1458,15 +1518,14 @@ def _next_steps_block(
|
|
|
1458
1518
|
lines.append("")
|
|
1459
1519
|
lines.append(f"```\n{fenced_command}\n```")
|
|
1460
1520
|
if blocking and reconcile.get("deferred"):
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
)
|
|
1521
|
+
deferred_cmd = _host_command(reconcile["deferred"], host)
|
|
1522
|
+
lines.append(f"After reconciling, continue the pipeline with: `{deferred_cmd}`")
|
|
1464
1523
|
elif reconcile and reconcile.get("reminder"):
|
|
1465
1524
|
count = reconcile["count"]
|
|
1466
1525
|
plural = "s" if count != 1 else ""
|
|
1467
1526
|
lines.append(
|
|
1468
1527
|
f"You also flagged {count} epic change{plural} to reconcile when "
|
|
1469
|
-
f"convenient: `{reconcile['command']}`"
|
|
1528
|
+
f"convenient: `{_host_command(reconcile['command'], host)}`"
|
|
1470
1529
|
)
|
|
1471
1530
|
lines.append(NEXT_STEPS_SENTINEL)
|
|
1472
1531
|
return "\n".join(lines)
|
|
@@ -1593,10 +1652,10 @@ def stage_exit(
|
|
|
1593
1652
|
"verifyGate": verify_gate,
|
|
1594
1653
|
"autoFixEligible": auto_fix_eligible,
|
|
1595
1654
|
"verifyState": verify_label,
|
|
1596
|
-
"verifyCommand": f"/feature-forge:forge-verify {feature}",
|
|
1655
|
+
"verifyCommand": _host_command(f"/feature-forge:forge-verify {feature}", host),
|
|
1597
1656
|
"autoVerifyEffective": effective_auto_verify,
|
|
1598
1657
|
"nextStage": next_stage_id,
|
|
1599
|
-
"nextCommand": next_command,
|
|
1658
|
+
"nextCommand": _host_command(next_command, host) if next_command else next_command,
|
|
1600
1659
|
"invalidAutoVerifyKeys": invalid_auto_verify_keys(config),
|
|
1601
1660
|
"gitRepo": git_repo,
|
|
1602
1661
|
"cleanTree": clean_tree,
|
|
@@ -1722,7 +1781,7 @@ def main() -> int:
|
|
|
1722
1781
|
p_exit.add_argument("--epic", default=None, help="Epic name for a nested member")
|
|
1723
1782
|
p_exit.add_argument("--next-feature", default=None, dest="next_feature",
|
|
1724
1783
|
help="First actionable feature (epic handoff next-command arg)")
|
|
1725
|
-
p_exit.add_argument("--host", default="claude", choices=("claude", "generic"),
|
|
1784
|
+
p_exit.add_argument("--host", default="claude", choices=("claude", "generic", "pi"),
|
|
1726
1785
|
help="Host wording for the NEXT-STEPS block")
|
|
1727
1786
|
p_exit.add_argument("--json", action="store_true", dest="json_output")
|
|
1728
1787
|
|
|
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
|
|
|
274
274
|
|
|
275
275
|
**Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
|
|
276
276
|
|
|
277
|
+
## Stage-Completion Re-check
|
|
278
|
+
|
|
279
|
+
Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
|
|
280
|
+
|
|
281
|
+
**Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
|
|
282
|
+
|
|
283
|
+
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
284
|
+
|
|
285
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
286
|
+
|
|
287
|
+
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
288
|
+
|
|
277
289
|
## Force Mode
|
|
278
290
|
|
|
279
291
|
If the user passes `--force` as an argument, skip prerequisite validation with a warning:
|
|
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
|
|
|
274
274
|
|
|
275
275
|
**Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
|
|
276
276
|
|
|
277
|
+
## Stage-Completion Re-check
|
|
278
|
+
|
|
279
|
+
Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
|
|
280
|
+
|
|
281
|
+
**Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
|
|
282
|
+
|
|
283
|
+
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
284
|
+
|
|
285
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
286
|
+
|
|
287
|
+
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
288
|
+
|
|
277
289
|
## Force Mode
|
|
278
290
|
|
|
279
291
|
If the user passes `--force` as an argument, skip prerequisite validation with a warning:
|
|
@@ -122,6 +122,8 @@ Iterate until the user confirms the PRD is complete.
|
|
|
122
122
|
|
|
123
123
|
## Step 6: Update Pipeline State and Commit
|
|
124
124
|
|
|
125
|
+
Before writing state or running the stage exit, invoke the **Stage-Completion Re-check** block in `references/shared-conventions.md` with `{stage}` = `forge-1-prd` — a resumed mid-stage continuation must not overwrite a committed `PRD.md` or re-fire a finished exit.
|
|
126
|
+
|
|
125
127
|
Write pipeline state conforming to `references/pipeline-state-schema.json`.
|
|
126
128
|
|
|
127
129
|
1. Create or update `{resolvedFeatureDir}/.pipeline-state.json`:
|
|
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
|
|
|
274
274
|
|
|
275
275
|
**Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
|
|
276
276
|
|
|
277
|
+
## Stage-Completion Re-check
|
|
278
|
+
|
|
279
|
+
Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
|
|
280
|
+
|
|
281
|
+
**Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
|
|
282
|
+
|
|
283
|
+
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
284
|
+
|
|
285
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
286
|
+
|
|
287
|
+
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
288
|
+
|
|
277
289
|
## Force Mode
|
|
278
290
|
|
|
279
291
|
If the user passes `--force` as an argument, skip prerequisite validation with a warning:
|
|
@@ -184,6 +184,8 @@ Use `AskUserQuestion` to collect this feedback.
|
|
|
184
184
|
|
|
185
185
|
## Step 7: Update Pipeline State and Commit
|
|
186
186
|
|
|
187
|
+
Before writing state or running the stage exit, invoke the **Stage-Completion Re-check** block in `references/shared-conventions.md` with `{stage}` = `forge-2-tech` — a resumed mid-stage continuation must not overwrite a committed `tech-spec.md` or re-fire a finished exit.
|
|
188
|
+
|
|
187
189
|
Write pipeline state conforming to `references/pipeline-state-schema.json`.
|
|
188
190
|
|
|
189
191
|
1. Update `{resolvedFeatureDir}/.pipeline-state.json`:
|
|
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
|
|
|
274
274
|
|
|
275
275
|
**Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
|
|
276
276
|
|
|
277
|
+
## Stage-Completion Re-check
|
|
278
|
+
|
|
279
|
+
Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
|
|
280
|
+
|
|
281
|
+
**Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
|
|
282
|
+
|
|
283
|
+
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
284
|
+
|
|
285
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
286
|
+
|
|
287
|
+
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
288
|
+
|
|
277
289
|
## Force Mode
|
|
278
290
|
|
|
279
291
|
If the user passes `--force` as an argument, skip prerequisite validation with a warning:
|
|
@@ -79,6 +79,27 @@ Replace stack-specific checks with these generic equivalents:
|
|
|
79
79
|
| "JSDoc on every field" | "Documentation comments on every field" |
|
|
80
80
|
| "tsconfig.json extends root" | "Build configuration follows project conventions" |
|
|
81
81
|
|
|
82
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
83
|
+
|
|
84
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
85
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
86
|
+
Since no dedicated profile applies, identify these by role rather than exact filename:
|
|
87
|
+
|
|
88
|
+
- **Runtime entrypoints (a legitimate non-test call site):** the process/main entry the build's
|
|
89
|
+
run command actually launches (from the CI/`Makefile`/manifest "start" target), an HTTP/RPC handler
|
|
90
|
+
or route, a scheduled/worker task, or a CLI subcommand — **not** a file in the project's test
|
|
91
|
+
directory or matching its test-file convention.
|
|
92
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** any
|
|
93
|
+
module/hook the framework runs **once per process before serving** — a startup/lifecycle hook, an
|
|
94
|
+
import-time initializer, a global preload, or a shared test-setup module that bootstraps production
|
|
95
|
+
graphs. Side effects here run on every process start (and, under a dev/watch runtime, on every
|
|
96
|
+
reload).
|
|
97
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** database/ORM
|
|
98
|
+
clients and connection pools, message/queue clients, telemetry/observability SDKs, or a broad
|
|
99
|
+
whole-service-layer import. An init pulling any of these into a universal bootstrap entry is the
|
|
100
|
+
CHECK-I23 pattern — recommend lazy initialization at the first handler/worker that needs the graph,
|
|
101
|
+
not eagerly at process start.
|
|
102
|
+
|
|
82
103
|
## Acceptance Criteria Patterns
|
|
83
104
|
|
|
84
105
|
Use these placeholder patterns in backlog items. Replace `{typeCheckCommand}`, `{testCommand}`, and `{module}` with values from `forge.config.json` and the project structure:
|
|
@@ -84,6 +84,25 @@ When examining a Go project, check for:
|
|
|
84
84
|
- **Formatting**: `gofmt -l .` or `goimports -l .` (should produce no output)
|
|
85
85
|
- **Module tidiness**: `go mod tidy` (ensures `go.mod` and `go.sum` are consistent)
|
|
86
86
|
|
|
87
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
88
|
+
|
|
89
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
90
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
91
|
+
|
|
92
|
+
- **Runtime entrypoints (a legitimate non-test call site):** `func main()` in a `package main` under
|
|
93
|
+
`cmd/…` or the module root, an HTTP handler registered on a `*http.ServeMux` / router, a gRPC service
|
|
94
|
+
registration, or a worker/consumer goroutine started from `main` — not a `*_test.go` file.
|
|
95
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package-level
|
|
96
|
+
`func init()` that constructs heavy clients, package-level `var` initializers that dial/connect at
|
|
97
|
+
import time, or a single `bootstrap`/`wire` module `main` calls before serving. `init()` and
|
|
98
|
+
package-var side effects run on **every** binary start, before `main` gets control.
|
|
99
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB drivers/pools
|
|
100
|
+
(`database/sql` + a driver, `pgx`, `gorm`, `mongo-driver`), message/queue clients (`sarama`/Kafka,
|
|
101
|
+
`amqp`, `go-redis`), telemetry SDKs (`go.opentelemetry.io/*`, `sentry-go`), or a broad internal
|
|
102
|
+
service package. An `init()` or package-var that dials any of these is the CHECK-I23 pattern —
|
|
103
|
+
recommend a `sync.Once` lazy constructor invoked from the first handler that needs it, not an
|
|
104
|
+
eager package-level connect.
|
|
105
|
+
|
|
87
106
|
## Testing
|
|
88
107
|
|
|
89
108
|
- **Framework**: `testing` stdlib package
|
|
@@ -111,6 +111,27 @@ async def refresh_session_token(
|
|
|
111
111
|
- **Import validation**: `mypy` with `--strict` or `--disallow-untyped-defs` catches missing type annotations
|
|
112
112
|
- **Module export validation**: `__all__` lists in `__init__.py` match spec's public API
|
|
113
113
|
|
|
114
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
115
|
+
|
|
116
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
117
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
118
|
+
|
|
119
|
+
- **Runtime entrypoints (a legitimate non-test call site):** a `if __name__ == "__main__":` block, a
|
|
120
|
+
`[project.scripts]` console-script target in `pyproject.toml`, an ASGI/WSGI app object
|
|
121
|
+
(`app = FastAPI()` / Django `wsgi.py` / `asgi.py`), a route/view/handler, a Celery/RQ task module, or
|
|
122
|
+
a management command — not a `test_*.py` / `conftest.py`.
|
|
123
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package
|
|
124
|
+
`__init__.py` that eagerly instantiates heavy clients at import time, a framework startup hook
|
|
125
|
+
(FastAPI `lifespan` / `@app.on_event("startup")`, Django `AppConfig.ready()`, a Gunicorn/uvicorn
|
|
126
|
+
`--preload` module), or a `conftest.py` that bootstraps production graphs. Import-time side effects
|
|
127
|
+
here run on every process start.
|
|
128
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM engines
|
|
129
|
+
(`sqlalchemy.create_engine`, `psycopg`, Django ORM, `pymongo`, `redis`), task queues (`celery`,
|
|
130
|
+
`rq`, `kafka`), telemetry SDKs (`opentelemetry`, `sentry_sdk`), or a whole-service-layer package
|
|
131
|
+
import. An init pulling any of these at a universal entry is the CHECK-I23 pattern — recommend lazy
|
|
132
|
+
init (module-level `@lru_cache` factory, `Depends()` provider, or first-use lazy import) at the
|
|
133
|
+
handler that needs it.
|
|
134
|
+
|
|
114
135
|
## Testing
|
|
115
136
|
|
|
116
137
|
- **Framework**: pytest (with `conftest.py` for fixtures)
|
|
@@ -90,6 +90,25 @@ When examining a Rust project, check for:
|
|
|
90
90
|
- **Formatting**: `cargo fmt --check` (ensures code matches `rustfmt` style)
|
|
91
91
|
- **Unsafe audit**: `cargo geiger` (if security-sensitive — counts unsafe blocks)
|
|
92
92
|
|
|
93
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
94
|
+
|
|
95
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
96
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
97
|
+
|
|
98
|
+
- **Runtime entrypoints (a legitimate non-test call site):** `fn main()` in `main.rs` or a `[[bin]]`
|
|
99
|
+
target, an async runtime entry (`#[tokio::main]`), an HTTP handler registered on an axum/actix/warp
|
|
100
|
+
router, or a worker task spawned from `main` — not a `#[cfg(test)]` module or a `tests/` integration
|
|
101
|
+
file.
|
|
102
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a `lazy_static!`
|
|
103
|
+
/ `once_cell::sync::Lazy` static that eagerly constructs heavy clients, a single `bootstrap`/`setup`
|
|
104
|
+
fn `main` calls before serving, or a `#[ctor]`-style pre-`main` initializer. A `Lazy` static is only
|
|
105
|
+
a risk when it is *forced* at startup rather than on first use.
|
|
106
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB pools
|
|
107
|
+
(`sqlx::Pool`, `diesel`, `deadpool`, `mongodb`), message/queue clients (`rdkafka`, `lapin`,
|
|
108
|
+
`redis`), telemetry SDKs (`opentelemetry`, `sentry`), or a broad internal service crate. Constructing
|
|
109
|
+
any of these eagerly at a universal entry is the CHECK-I23 pattern — recommend a `OnceCell`/`Lazy`
|
|
110
|
+
forced on **first use** by the handler that needs it, not at process start.
|
|
111
|
+
|
|
93
112
|
## Testing
|
|
94
113
|
|
|
95
114
|
- **Framework**: Built-in test harness (`#[test]`, `#[cfg(test)]`)
|
|
@@ -64,6 +64,29 @@ When examining a TypeScript project, check for:
|
|
|
64
64
|
- **Cross-package type checks**: `bun run typecheck` (or equivalent) passes for both the feature package AND packages that depend on it
|
|
65
65
|
- **Import path validation**: All import paths resolve correctly per the `exports` map in `package.json`
|
|
66
66
|
|
|
67
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
68
|
+
|
|
69
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
70
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
71
|
+
|
|
72
|
+
- **Runtime entrypoints (a legitimate non-test call site):** a `package.json` `bin` / CLI `main`; a
|
|
73
|
+
server entry that actually starts listening (`src/server.ts`, `src/index.ts` invoking `listen`); a
|
|
74
|
+
worker/consumer file; and for Next.js — `middleware.ts`, `app/**/route.ts` route handlers,
|
|
75
|
+
`app/**/{page,layout,template}.tsx`, server actions, and `instrumentation.ts`. Express/Hono/Fastify:
|
|
76
|
+
the file that constructs the app and calls `.listen()`.
|
|
77
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** Next.js
|
|
78
|
+
`instrumentation.ts` / `instrumentation.js` (its `register()` runs once per server process before
|
|
79
|
+
any request), an app-server preload/`register`/`--import` hook, a root `app/layout.tsx` that
|
|
80
|
+
eagerly imports server singletons, and global test setup (`vitest.setup.ts`, `jest.setup.ts`) if it
|
|
81
|
+
bootstraps production graphs. Wiring a heavy init here loads it on **every** cold start (and, under
|
|
82
|
+
the dev server, on every module re-evaluation).
|
|
83
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM clients
|
|
84
|
+
(`drizzle-orm`, `@prisma/client`, `pg`, `mongoose`, `kysely`), queue/worker libs (`bullmq`, `bull`,
|
|
85
|
+
`kafkajs`, `ioredis`), telemetry/observability SDKs (`@opentelemetry/*`, `@sentry/node`), and a
|
|
86
|
+
whole-service-layer barrel (`import * as services from "@repo/services"`). An init that pulls any of
|
|
87
|
+
these into a universal bootstrap entry is the CHECK-I23 pattern — recommend lazy init at the first
|
|
88
|
+
route/handler/worker that needs it.
|
|
89
|
+
|
|
67
90
|
## Testing
|
|
68
91
|
|
|
69
92
|
- **Framework**: Vitest (most common in modern TS), Jest, or testing-library
|
|
@@ -117,6 +117,8 @@ do not reload everything. This keeps quality up under context pressure.
|
|
|
117
117
|
|
|
118
118
|
## Step 5: Cross-Reference Validation
|
|
119
119
|
|
|
120
|
+
Before writing `TRACEABILITY.md` or running the stage exit, invoke the **Stage-Completion Re-check** block in `references/shared-conventions.md` with `{stage}` = `forge-3-specs` — a resumed mid-stage continuation must not overwrite a committed `TRACEABILITY.md` or re-fire a finished exit.
|
|
121
|
+
|
|
120
122
|
After writing all documents, verify:
|
|
121
123
|
|
|
122
124
|
1. Every PRD requirement has coverage in at least one spec document
|
|
@@ -274,6 +274,18 @@ This write is **left uncommitted**: it is staged and committed as part of this s
|
|
|
274
274
|
|
|
275
275
|
**Incremental artifact tracking:** When a stage writes multiple files (e.g. forge-3-specs writing a suite of spec documents), update the `stages.{stage}.artifacts` array in `.pipeline-state.json` after writing each file — not just at stage completion. This is what makes the Interrupted inventory above precise about which files were successfully written.
|
|
276
276
|
|
|
277
|
+
## Stage-Completion Re-check
|
|
278
|
+
|
|
279
|
+
Invoke this block **at the head of any post-entry step that writes a stage artifact or runs the Scripted Stage Exit** — the Stage-Entry Guard runs only once, at the top of the skill. A **resumed or pasted mid-stage instruction** (e.g. "continue {stage}: write TRACEABILITY.md, run the stage exit") enters *below* the entry guard, so nothing re-checks completion before it overwrites a committed artifact and re-fires a finished exit — data-destructive if followed literally. This re-check is the idempotency backstop for that path. `{stage}` is the invoking skill's id.
|
|
280
|
+
|
|
281
|
+
**Re-read** `stages.{stage}` in `{resolvedFeatureDir}/.pipeline-state.json`, then classify by **provenance** — a legitimate completion runs in the same session that applied this stage's Entry Stamp; a replayed continuation finds a finished stage it did not produce:
|
|
282
|
+
|
|
283
|
+
1. **Proceed** when `stages.{stage}.status` is `"in-progress"` (this session's Entry Stamp — you are finishing the run you started) or absent/`pending`. Run the write / exit normally.
|
|
284
|
+
|
|
285
|
+
2. **Detect-and-refuse** when ALL of these hold: `stages.{stage}.status ∈ {"complete", "stale"}` **AND** the stage's artifacts (incl. `TRACEABILITY.md` for forge-3-specs) exist on disk **AND** a `commitHash` is recorded for the stage **AND** you did **not** author this stage earlier in the current session. This is a stale/replayed continuation of an already-finished, committed stage. Do **not** overwrite the artifact or re-run the exit. Route instead to the **Stage-Entry Guard**'s *Re-authoring* path: surface the same `AskUserQuestion` warning ("A completed {stage} artifact already exists for '{feature}' (v{n}{, marked stale}). Continuing will create a new version. Proceed?"). Only on explicit confirmation re-enter from the Entry Stamp (the version bumps at exit); otherwise **stop** and report that the stage is already complete — cite the recorded `commitHash` and offer `/feature-forge:forge {feature}` to see true state.
|
|
286
|
+
|
|
287
|
+
When you cannot confirm you authored the current run, treat it as a replay and refuse: a false refuse costs one confirmation click; a false proceed overwrites a committed artifact and re-churns a stage version. `--force` follows Force Mode (skip the gate, treat as a deliberate re-author).
|
|
288
|
+
|
|
277
289
|
## Force Mode
|
|
278
290
|
|
|
279
291
|
If the user passes `--force` as an argument, skip prerequisite validation with a warning:
|
|
@@ -79,6 +79,27 @@ Replace stack-specific checks with these generic equivalents:
|
|
|
79
79
|
| "JSDoc on every field" | "Documentation comments on every field" |
|
|
80
80
|
| "tsconfig.json extends root" | "Build configuration follows project conventions" |
|
|
81
81
|
|
|
82
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
83
|
+
|
|
84
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
85
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
86
|
+
Since no dedicated profile applies, identify these by role rather than exact filename:
|
|
87
|
+
|
|
88
|
+
- **Runtime entrypoints (a legitimate non-test call site):** the process/main entry the build's
|
|
89
|
+
run command actually launches (from the CI/`Makefile`/manifest "start" target), an HTTP/RPC handler
|
|
90
|
+
or route, a scheduled/worker task, or a CLI subcommand — **not** a file in the project's test
|
|
91
|
+
directory or matching its test-file convention.
|
|
92
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** any
|
|
93
|
+
module/hook the framework runs **once per process before serving** — a startup/lifecycle hook, an
|
|
94
|
+
import-time initializer, a global preload, or a shared test-setup module that bootstraps production
|
|
95
|
+
graphs. Side effects here run on every process start (and, under a dev/watch runtime, on every
|
|
96
|
+
reload).
|
|
97
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** database/ORM
|
|
98
|
+
clients and connection pools, message/queue clients, telemetry/observability SDKs, or a broad
|
|
99
|
+
whole-service-layer import. An init pulling any of these into a universal bootstrap entry is the
|
|
100
|
+
CHECK-I23 pattern — recommend lazy initialization at the first handler/worker that needs the graph,
|
|
101
|
+
not eagerly at process start.
|
|
102
|
+
|
|
82
103
|
## Acceptance Criteria Patterns
|
|
83
104
|
|
|
84
105
|
Use these placeholder patterns in backlog items. Replace `{typeCheckCommand}`, `{testCommand}`, and `{module}` with values from `forge.config.json` and the project structure:
|
|
@@ -84,6 +84,25 @@ When examining a Go project, check for:
|
|
|
84
84
|
- **Formatting**: `gofmt -l .` or `goimports -l .` (should produce no output)
|
|
85
85
|
- **Module tidiness**: `go mod tidy` (ensures `go.mod` and `go.sum` are consistent)
|
|
86
86
|
|
|
87
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
88
|
+
|
|
89
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
90
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
91
|
+
|
|
92
|
+
- **Runtime entrypoints (a legitimate non-test call site):** `func main()` in a `package main` under
|
|
93
|
+
`cmd/…` or the module root, an HTTP handler registered on a `*http.ServeMux` / router, a gRPC service
|
|
94
|
+
registration, or a worker/consumer goroutine started from `main` — not a `*_test.go` file.
|
|
95
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package-level
|
|
96
|
+
`func init()` that constructs heavy clients, package-level `var` initializers that dial/connect at
|
|
97
|
+
import time, or a single `bootstrap`/`wire` module `main` calls before serving. `init()` and
|
|
98
|
+
package-var side effects run on **every** binary start, before `main` gets control.
|
|
99
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB drivers/pools
|
|
100
|
+
(`database/sql` + a driver, `pgx`, `gorm`, `mongo-driver`), message/queue clients (`sarama`/Kafka,
|
|
101
|
+
`amqp`, `go-redis`), telemetry SDKs (`go.opentelemetry.io/*`, `sentry-go`), or a broad internal
|
|
102
|
+
service package. An `init()` or package-var that dials any of these is the CHECK-I23 pattern —
|
|
103
|
+
recommend a `sync.Once` lazy constructor invoked from the first handler that needs it, not an
|
|
104
|
+
eager package-level connect.
|
|
105
|
+
|
|
87
106
|
## Testing
|
|
88
107
|
|
|
89
108
|
- **Framework**: `testing` stdlib package
|
|
@@ -111,6 +111,27 @@ async def refresh_session_token(
|
|
|
111
111
|
- **Import validation**: `mypy` with `--strict` or `--disallow-untyped-defs` catches missing type annotations
|
|
112
112
|
- **Module export validation**: `__all__` lists in `__init__.py` match spec's public API
|
|
113
113
|
|
|
114
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
115
|
+
|
|
116
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
117
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
118
|
+
|
|
119
|
+
- **Runtime entrypoints (a legitimate non-test call site):** a `if __name__ == "__main__":` block, a
|
|
120
|
+
`[project.scripts]` console-script target in `pyproject.toml`, an ASGI/WSGI app object
|
|
121
|
+
(`app = FastAPI()` / Django `wsgi.py` / `asgi.py`), a route/view/handler, a Celery/RQ task module, or
|
|
122
|
+
a management command — not a `test_*.py` / `conftest.py`.
|
|
123
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a package
|
|
124
|
+
`__init__.py` that eagerly instantiates heavy clients at import time, a framework startup hook
|
|
125
|
+
(FastAPI `lifespan` / `@app.on_event("startup")`, Django `AppConfig.ready()`, a Gunicorn/uvicorn
|
|
126
|
+
`--preload` module), or a `conftest.py` that bootstraps production graphs. Import-time side effects
|
|
127
|
+
here run on every process start.
|
|
128
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM engines
|
|
129
|
+
(`sqlalchemy.create_engine`, `psycopg`, Django ORM, `pymongo`, `redis`), task queues (`celery`,
|
|
130
|
+
`rq`, `kafka`), telemetry SDKs (`opentelemetry`, `sentry_sdk`), or a whole-service-layer package
|
|
131
|
+
import. An init pulling any of these at a universal entry is the CHECK-I23 pattern — recommend lazy
|
|
132
|
+
init (module-level `@lru_cache` factory, `Depends()` provider, or first-use lazy import) at the
|
|
133
|
+
handler that needs it.
|
|
134
|
+
|
|
114
135
|
## Testing
|
|
115
136
|
|
|
116
137
|
- **Framework**: pytest (with `conftest.py` for fixtures)
|
|
@@ -90,6 +90,25 @@ When examining a Rust project, check for:
|
|
|
90
90
|
- **Formatting**: `cargo fmt --check` (ensures code matches `rustfmt` style)
|
|
91
91
|
- **Unsafe audit**: `cargo geiger` (if security-sensitive — counts unsafe blocks)
|
|
92
92
|
|
|
93
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
94
|
+
|
|
95
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
96
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
97
|
+
|
|
98
|
+
- **Runtime entrypoints (a legitimate non-test call site):** `fn main()` in `main.rs` or a `[[bin]]`
|
|
99
|
+
target, an async runtime entry (`#[tokio::main]`), an HTTP handler registered on an axum/actix/warp
|
|
100
|
+
router, or a worker task spawned from `main` — not a `#[cfg(test)]` module or a `tests/` integration
|
|
101
|
+
file.
|
|
102
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** a `lazy_static!`
|
|
103
|
+
/ `once_cell::sync::Lazy` static that eagerly constructs heavy clients, a single `bootstrap`/`setup`
|
|
104
|
+
fn `main` calls before serving, or a `#[ctor]`-style pre-`main` initializer. A `Lazy` static is only
|
|
105
|
+
a risk when it is *forced* at startup rather than on first use.
|
|
106
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB pools
|
|
107
|
+
(`sqlx::Pool`, `diesel`, `deadpool`, `mongodb`), message/queue clients (`rdkafka`, `lapin`,
|
|
108
|
+
`redis`), telemetry SDKs (`opentelemetry`, `sentry`), or a broad internal service crate. Constructing
|
|
109
|
+
any of these eagerly at a universal entry is the CHECK-I23 pattern — recommend a `OnceCell`/`Lazy`
|
|
110
|
+
forced on **first use** by the handler that needs it, not at process start.
|
|
111
|
+
|
|
93
112
|
## Testing
|
|
94
113
|
|
|
95
114
|
- **Framework**: Built-in test harness (`#[test]`, `#[cfg(test)]`)
|
|
@@ -64,6 +64,29 @@ When examining a TypeScript project, check for:
|
|
|
64
64
|
- **Cross-package type checks**: `bun run typecheck` (or equivalent) passes for both the feature package AND packages that depend on it
|
|
65
65
|
- **Import path validation**: All import paths resolve correctly per the `exports` map in `package.json`
|
|
66
66
|
|
|
67
|
+
### Runtime Entrypoints & Bootstrap-Wiring Sites
|
|
68
|
+
|
|
69
|
+
Used by `CHECK-I22` (a runtime-required bootstrap needs a **non-test** caller on one of these) and
|
|
70
|
+
`CHECK-I23` (a heavy init wired into a **universal** bootstrap entry should move to a lazier site).
|
|
71
|
+
|
|
72
|
+
- **Runtime entrypoints (a legitimate non-test call site):** a `package.json` `bin` / CLI `main`; a
|
|
73
|
+
server entry that actually starts listening (`src/server.ts`, `src/index.ts` invoking `listen`); a
|
|
74
|
+
worker/consumer file; and for Next.js — `middleware.ts`, `app/**/route.ts` route handlers,
|
|
75
|
+
`app/**/{page,layout,template}.tsx`, server actions, and `instrumentation.ts`. Express/Hono/Fastify:
|
|
76
|
+
the file that constructs the app and calls `.listen()`.
|
|
77
|
+
- **Universal bootstrap entries (run on every startup — the `CHECK-I23` risk site):** Next.js
|
|
78
|
+
`instrumentation.ts` / `instrumentation.js` (its `register()` runs once per server process before
|
|
79
|
+
any request), an app-server preload/`register`/`--import` hook, a root `app/layout.tsx` that
|
|
80
|
+
eagerly imports server singletons, and global test setup (`vitest.setup.ts`, `jest.setup.ts`) if it
|
|
81
|
+
bootstraps production graphs. Wiring a heavy init here loads it on **every** cold start (and, under
|
|
82
|
+
the dev server, on every module re-evaluation).
|
|
83
|
+
- **Heavy server-only import markers (what makes an init "heavy" for `CHECK-I23`):** DB/ORM clients
|
|
84
|
+
(`drizzle-orm`, `@prisma/client`, `pg`, `mongoose`, `kysely`), queue/worker libs (`bullmq`, `bull`,
|
|
85
|
+
`kafkajs`, `ioredis`), telemetry/observability SDKs (`@opentelemetry/*`, `@sentry/node`), and a
|
|
86
|
+
whole-service-layer barrel (`import * as services from "@repo/services"`). An init that pulls any of
|
|
87
|
+
these into a universal bootstrap entry is the CHECK-I23 pattern — recommend lazy init at the first
|
|
88
|
+
route/handler/worker that needs it.
|
|
89
|
+
|
|
67
90
|
## Testing
|
|
68
91
|
|
|
69
92
|
- **Framework**: Vitest (most common in modern TS), Jest, or testing-library
|
|
@@ -94,6 +94,9 @@ After presenting the plan as text, use `AskUserQuestion` following the **Decisio
|
|
|
94
94
|
|
|
95
95
|
**Forge-specific item requirements** layered on top of `author-backlog`'s output:
|
|
96
96
|
- `specReferences` must be paths **relative to the project root** (e.g. `specs/auth/00-core-definitions.md`), NOT relative to the backlog file. The validator resolves them from the project root (not from `--specs-dir`, which only gates the check).
|
|
97
|
+
- **Epic members — cross-member shared-state coupling (#144).** When authoring the backlog for an epic member, check whether this feature writes or migrates a file that a *sibling* member's already-shipped tests pin (its `mutatesShared[]` hint in `epic-manifest.json`, or a shared data corpus / generated fixture its specs say it mutates). If so, schedule a **reconciliation item up front** — before the first mutating item — that regenerates or re-pins the sibling's fixture (or updates the sibling test to the new shape), so the sibling suite stays green instead of red-gating every commit mid-loop. This is the authoring counterpart to forge-verify's CHECK-E10.
|
|
98
|
+
- **Generated-artifact freshness vs. `testCommand` `--check` gates (#145).** If the project's `testCommand` gates on staleness of generated artifacts (`<generator> --check`-style sub-commands that fail when a checked-in generated file is out of date), then any item that regenerates **one** such artifact must regenerate **and commit all** the sibling artifacts those `--check` gates depend on — enumerate the whole gated set, not just the artifact the item is "about", or the item passes locally yet red-gates on the stale-generated check. Pass this to `author-backlog` alongside `testCommand` so the full regeneration sequence lands in each affected item; forge-verify's CHECK-B26 flags a partial set or an ungated regenerator after the fact.
|
|
99
|
+
- **Lifecycle-gated artifacts — no test item forcing a forbidden transition (#150).** A test/e2e item whose acceptance asserts a *published / released / approved / human-reviewed* artifact state must either (a) `dependsOn` an explicit, human-gated publish/review item that legitimately produces that state, or (b) assert the state via a **dev-build / fixture path**. A test item must **never** be the only thing forcing a lifecycle transition another item pins the other way (e.g. one item keeps artifact `X` *draft* while a test demands it *published*, with nothing between to publish it) — the loop, unable to publish or obtain a human sign-off, will **fabricate** the provenance. `author-backlog` owns the general rule; forge-verify's CHECK-B27 flags a contradictory pair with no publisher in the dependency closure after the fact.
|
|
97
100
|
|
|
98
101
|
> **Backlog schema & rauf contract are unchanged (REQ-COMPAT-03).** Epic membership adds **no** fields to backlog items — dependency edges live in the epic manifest, never in any backlog item. The JSON written here is byte-for-byte the same shape as a pre-epic standalone feature's backlog, and rauf is still launched against a single per-feature backlog path. Only the *path composition* changes (the `{feature}` segment in the backlog-directory rule above), not the schema or rauf's CLI surface.
|
|
99
102
|
|
|
@@ -131,6 +134,8 @@ State that the backlog is ready and invite adjustments before committing — a s
|
|
|
131
134
|
|
|
132
135
|
## Step 7: Update Pipeline State and Commit
|
|
133
136
|
|
|
137
|
+
Before writing state or running the stage exit, invoke the **Stage-Completion Re-check** block in `references/shared-conventions.md` with `{stage}` = `forge-4-backlog` — a resumed mid-stage continuation must not overwrite a committed `backlog.json` or re-fire a finished exit.
|
|
138
|
+
|
|
134
139
|
Write pipeline state conforming to `references/pipeline-state-schema.json`. Follow the Git Commit Protocol in `references/shared-conventions.md`.
|
|
135
140
|
|
|
136
141
|
1. Update `{resolvedFeatureDir}/.pipeline-state.json`:
|
|
@@ -217,8 +217,8 @@
|
|
|
217
217
|
},
|
|
218
218
|
"installHint": {
|
|
219
219
|
"type": "string",
|
|
220
|
-
"default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.
|
|
221
|
-
"description": "Shown when the runner BINARY is missing or too old (version gate fails, minRunnerVersion floor) — how to obtain/upgrade the CLI itself. Names two distinct binary-provisioning paths: (1) the cross-agent installer (`npx @garygentry/feature-forge install`, the multi-agent provisioning path that pins @garygentry/rauf@0.
|
|
220
|
+
"default": "Provision rauf for a multi-agent setup with the cross-agent installer: `npx @garygentry/feature-forge install` (records the pinned @garygentry/rauf@0.13.0 default). Or install/upgrade just the rauf CLI: `npx @garygentry/rauf@0.13.0 --version`, or `curl -fsSL https://raw.githubusercontent.com/garygentry/rauf/main/scripts/install-binary.sh | bash`.",
|
|
221
|
+
"description": "Shown when the runner BINARY is missing or too old (version gate fails, minRunnerVersion floor) — how to obtain/upgrade the CLI itself. Names two distinct binary-provisioning paths: (1) the cross-agent installer (`npx @garygentry/feature-forge install`, the multi-agent provisioning path that pins @garygentry/rauf@0.13.0), and (2) the direct rauf-CLI install/upgrade one-liner. Distinct from setupHint (which installs per-project artifacts); a version-gate failure is ALWAYS this hint, never setupHint."
|
|
222
222
|
},
|
|
223
223
|
"schemaVersion": {
|
|
224
224
|
"type": "string",
|