@garygentry/feature-forge 0.2.14 → 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/forge-config-schema.json +2 -2
- package/adapters/claude/scripts/forge-root.sh +47 -3
- package/adapters/claude/scripts/forge-session.py +30 -8
- package/adapters/claude/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/claude/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/claude/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/codex/.feature-forge-bundle.json +1 -1
- package/adapters/codex/references/forge-config-schema.json +2 -2
- package/adapters/codex/scripts/forge-root.sh +47 -3
- package/adapters/codex/scripts/forge-session.py +30 -8
- package/adapters/codex/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/codex/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/codex/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/copilot/.feature-forge-bundle.json +1 -1
- package/adapters/copilot/references/forge-config-schema.json +2 -2
- package/adapters/copilot/scripts/forge-root.sh +47 -3
- package/adapters/copilot/scripts/forge-session.py +30 -8
- package/adapters/copilot/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/copilot/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/copilot/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/cursor/.feature-forge-bundle.json +1 -1
- package/adapters/cursor/references/forge-config-schema.json +2 -2
- package/adapters/cursor/scripts/forge-root.sh +47 -3
- package/adapters/cursor/scripts/forge-session.py +30 -8
- package/adapters/cursor/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/cursor/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/cursor/skills/forge-guide/references/forge-config-schema.json +2 -2
- package/adapters/gemini/.feature-forge-bundle.json +1 -1
- package/adapters/gemini/gemini-extension.json +1 -1
- package/adapters/gemini/references/forge-config-schema.json +2 -2
- package/adapters/gemini/scripts/forge-root.sh +47 -3
- package/adapters/gemini/scripts/forge-session.py +30 -8
- package/adapters/gemini/skills/forge-4-backlog/references/forge-config-schema.json +2 -2
- package/adapters/gemini/skills/forge-5-loop/references/forge-config-schema.json +2 -2
- package/adapters/gemini/skills/forge-guide/references/forge-config-schema.json +2 -2
- 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
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
# GENERATED — DO NOT EDIT. Source: skills/forge-1-prd/SKILL.md. Regenerate: python3 scripts/build-adapters.py
|
|
3
|
+
name: forge-1-prd
|
|
4
|
+
description: Create a requirements PRD for a feature through structured interview. Use when user runs /skill:forge-1-prd or explicitly asks to start the forge pipeline for a new feature. Do NOT trigger for general requirements discussions, project scoping outside forge, or PRD questions unrelated to the forge pipeline.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# forge-1-prd — Requirements Interviewer
|
|
8
|
+
|
|
9
|
+
Create a thorough, requirements-only PRD through relentless structured interviewing. The PRD captures WHAT the feature must do, not HOW it will be built.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
Read and follow `references/shared-conventions.md` for feature name validation, configuration reading, and force mode handling before proceeding.
|
|
14
|
+
|
|
15
|
+
**`--force-standalone` (forge-1-prd only).** A distinct flag from `--force`: it bypasses only the **Mint Guard** in Step 1 (letting you intentionally fork a name that is a known epic member into a detached standalone feature). It does **not** imply `--force` — prerequisite checks and the Stage-Entry Guard still run. Use it only when you genuinely mean to create a standalone feature that shares a name with an epic member on another branch.
|
|
16
|
+
|
|
17
|
+
## Step 1: Read Configuration and Check State
|
|
18
|
+
|
|
19
|
+
### Branch Setup (if using git)
|
|
20
|
+
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.
|
|
21
|
+
|
|
22
|
+
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 for a never-started standalone feature — as `not-found` (exit 1) when `{specsDir}/` already exists (other features present), or as `specs dir not found` (exit 2) when `{specsDir}/` itself does not exist yet (the very first feature, or a branch that never had a specs tree). In **both** of those "about to create a brand-new standalone" cases forge-1 creates `{specsDir}/{feature}/` as today. (The *other* exit-2 errors — `unsafe-name`, a path-containment escape — are genuine STOPs, never a mint.) 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.
|
|
23
|
+
|
|
24
|
+
### Mint Guard: refuse to fork a known epic member into a detached standalone (Issue #125)
|
|
25
|
+
|
|
26
|
+
Run this sub-step **whenever forge-1 is about to mint a brand-new flat standalone `{specsDir}/{feature}/`** — that is, when Feature Directory Resolution returned either `not-found` (exit 1) **or** `specs dir not found` (the exit-2 missing-specs-dir flavor, e.g. a clean default branch that has never had a specs tree). The exit-2 case is the *cleanest* split-brain trigger: on a branch that predates the epic, `{specsDir}/` may not exist at all, yet cross-branch discovery still sees the member on the epic branch. It prevents the split-brain-epic failure where a member of an epic (whose manifest lives on a *different, unmerged* branch) is silently forged as a disjoint standalone feature carrying no `epic` back-pointer. Skip it entirely when resolution succeeded (an epic member's directory already exists — resolution yields the nested path, so this never fires), on the other exit-2 errors (`unsafe-name` / path-containment — those STOP, they never mint), and when `--force-standalone` was passed (see below).
|
|
27
|
+
|
|
28
|
+
1. Run cross-branch discovery for this exact name (branch-agnostic — it scans all refs regardless of current HEAD):
|
|
29
|
+
```bash
|
|
30
|
+
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/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')"
|
|
31
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
32
|
+
python3 "$R/scripts/forge-session.py" discover-feature "{feature}" --specs-dir "{specsDir}" --json
|
|
33
|
+
```
|
|
34
|
+
2. **If any candidate has `isEpicMember: true` → HARD STOP.** This is not the soft switch/fetch/treat-as-new menu from the Feature Directory Resolution block — do **not** create any directory and do **not** fall through to the interview. Emit verbatim (filling `{epic}` and `{stateBranch}` from that candidate's `epic` and `stateBranch`):
|
|
35
|
+
> `{feature}` is a member of epic `{epic}` (recorded on branch `{stateBranch}`). You appear to be on a branch that does not contain that epic. Switch to `{stateBranch}` and run `/skill:forge-1-prd {feature}` there, or pass `--force-standalone` to intentionally fork a detached standalone feature.
|
|
36
|
+
3. **If candidates exist but none are epic members** → keep today's soft behavior: this is the ordinary cross-branch-discovery case already handled by the Feature Directory Resolution block's **Candidates found** menu (switch / fetch+switch / treat-as-new / stop). Defer to it.
|
|
37
|
+
4. **If nothing was found** (no candidates) → proceed to mint the flat standalone feature as today.
|
|
38
|
+
5. **If `--force-standalone` was passed** → skip this guard entirely, log a one-line warning ("Forking `{feature}` as a detached standalone despite epic membership on `{stateBranch}`"), and proceed to create the flat feature. `--force-standalone` is distinct from `--force` and does **not** imply it (see the Force Mode note below).
|
|
39
|
+
|
|
40
|
+
After resolution, invoke the **Stage-Entry Guard** block in `references/shared-conventions.md` with `{stage}` = `forge-1-prd`. It classifies re-entry (fresh / interrupted / re-authoring), runs the resume-vs-restart gate and the "create a new version?" warning as applicable, and applies the entry stamp on the authoring paths. For a brand-new standalone feature there is no state file yet, so the guard's **fresh** arm applies with nothing to prompt; the entry stamp lands when the state file is first created in Step 6.
|
|
41
|
+
|
|
42
|
+
## Step 2: Examine Existing Context
|
|
43
|
+
|
|
44
|
+
Before starting the interview, invoke the **Epic Context Injection** block in `references/shared-conventions.md`. This block self-gates: it skips entirely if the feature has no `epic` back-pointer, so standalone behavior is unchanged. If this feature is an epic member, the injected charter's `exposes`/`consumes` are requirement inputs — every contract obligation must appear as a REQ in the PRD.
|
|
45
|
+
|
|
46
|
+
1. **Check the project structure**: Read the project's build configuration and dependency manifests to understand what modules/packages exist. Look for `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `pom.xml`, workspace configs, or equivalent.
|
|
47
|
+
2. **Check existing specs**: Look at `{specsDir}/` for other features' PRDs to understand conventions and the overall system
|
|
48
|
+
3. **Check existing docs**: Look at the docs directory for architecture documentation
|
|
49
|
+
4. **Note integration surfaces**: Identify which existing packages might be relevant to this feature
|
|
50
|
+
|
|
51
|
+
This context helps you ask informed questions and spot gaps the user might not think of.
|
|
52
|
+
|
|
53
|
+
## Step 3: Conduct the Interview
|
|
54
|
+
|
|
55
|
+
Interview the user relentlessly. Your goal is to extract complete, unambiguous requirements.
|
|
56
|
+
|
|
57
|
+
Read `references/prd-template.md` for the interview structure and question categories. Cover every category. Don't rush — missing a requirement now costs 10x to fix later.
|
|
58
|
+
|
|
59
|
+
### CRITICAL GUARDRAIL: No Technology Decisions
|
|
60
|
+
|
|
61
|
+
The PRD is EXCLUSIVELY about requirements. You MUST enforce this boundary:
|
|
62
|
+
|
|
63
|
+
**When the user says something like:**
|
|
64
|
+
- "I want to use Zod for validation" → Capture as: "Runtime schema validation with type inference is required." Note their Zod preference as a constraint but not a requirement.
|
|
65
|
+
- "We'll store it in Drizzle/PostgreSQL" → Capture as: "Persistent storage required for X data with Y query patterns."
|
|
66
|
+
- "I want a React component that..." → Capture as: "A user interface is required that allows users to..."
|
|
67
|
+
- "We should use WebSockets for..." → Capture as: "Real-time updates are required when X changes, with latency under Y."
|
|
68
|
+
- "I want a REST API" → Capture as: "An HTTP-accessible interface is required for X operations"
|
|
69
|
+
- "We need a microservice for X" → Capture as: "X must be independently deployable and scalable"
|
|
70
|
+
- "Use a queue for Y" → Capture as: "Y must be processed asynchronously with guaranteed delivery"
|
|
71
|
+
|
|
72
|
+
**When YOU start drifting into technology:**
|
|
73
|
+
If you catch yourself writing about specific libraries, API designs, database schemas, or implementation patterns — STOP. Ask yourself: "Is this a requirement or an implementation choice?" Rewrite it as the underlying requirement.
|
|
74
|
+
|
|
75
|
+
**The one exception:** When a technology choice IS the requirement (e.g., "must integrate with the existing @repo/auth package" or "must work with our Hono backend"). These are constraints, and they belong in the Constraints section of the PRD, clearly labeled as such.
|
|
76
|
+
|
|
77
|
+
A technology constraint is valid when it stems from organizational mandate, existing infrastructure, or team expertise — not from preference. Ask "Why must it be X specifically?" If the answer is "because we already run X in production," that's a legitimate constraint. If the answer is "because it's fast," capture the performance requirement instead.
|
|
78
|
+
|
|
79
|
+
### Interview Approach
|
|
80
|
+
|
|
81
|
+
**Turn structure:** Output your analysis or context as regular text, then use `AskUserQuestion` for the actual questions. NEVER put questions in your text output — they MUST go through `AskUserQuestion`.
|
|
82
|
+
|
|
83
|
+
**Pacing:** Cover one topic area at a time, asking 2-3 related questions per `AskUserQuestion` 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.
|
|
84
|
+
|
|
85
|
+
**Question strategies** (use these as content for `AskUserQuestion`, 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?":
|
|
86
|
+
- Probe deeper after each answer: failure modes, stakeholders, minimum viable version
|
|
87
|
+
- Challenge assumptions: which users specifically, what does "fast" mean quantitatively
|
|
88
|
+
- Identify edge cases: empty input, concurrent access, scale
|
|
89
|
+
- Capture non-functional requirements: performance, security, accessibility, observability
|
|
90
|
+
- 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
|
|
91
|
+
|
|
92
|
+
**Completion criteria:** The interview is complete when:
|
|
93
|
+
1. Every category in `references/prd-template.md` has been covered with at least one question
|
|
94
|
+
2. The user has confirmed there's nothing else to add
|
|
95
|
+
3. You can draft every PRD section without leaving TBD placeholders
|
|
96
|
+
|
|
97
|
+
Before moving to Step 4, summarize your coverage as text, then use `AskUserQuestion` to ask: "Anything I'm missing?"
|
|
98
|
+
|
|
99
|
+
**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]."
|
|
100
|
+
|
|
101
|
+
**Epic-level concern (backflow):** The parking lot above is for concerns about a *later stage of THIS feature*. If instead the interview reveals the **epic decomposition itself** is wrong — a **sibling feature must be added**, a **frozen boundary between features must move**, a feature must **split**, or a **dependency edge is wrong** — that is an *epic-level* concern and does **not** go in `notes`. It only applies when this feature is an epic member (its `.pipeline-state.json` has an `epic` back-pointer); for a standalone feature there is no epic to reconcile, so treat the concern as same-feature or out of scope. To record one, append an entry to the member state's `epicChangeRequests[]` array (same direct-edit path as `notes`; schema in `references/pipeline-state-schema.json`): `kind` (`add-feature`|`redep`|`move-boundary`|`split`), `target`, `rationale`, `raisedBy: "forge-1-prd"`, `raisedAt` (ISO-8601 UTC), `status: "open"`, and `blocksCurrent`. Set `blocksCurrent: true` when the change alters a contract (`exposes`/`consumes`) or dependency edge this feature relies on for its *next* stage (proceeding would build specs on a soon-to-change decomposition); `false` for a peer/downstream change this feature does not consume. When the change touches a contract/dep edge and the classification is genuinely ambiguous, confirm `blocksCurrent` with a single `AskUserQuestion`, defaulting to `true` (a false negative silently diverges two members' contracts). **Do not** edit `epic-manifest.json` here — recording is not applying; only `/skill:forge-0-epic` edit mode mutates the epic. Then acknowledge without blocking: "That's an epic-level change — I've recorded it so `forge-0-epic` can reconcile it. [Blocking: We'll want to reconcile the epic before writing specs. | Non-blocking: We can finish this feature first and reconcile when convenient.]" and continue the interview.
|
|
102
|
+
|
|
103
|
+
## Step 4: Write the PRD
|
|
104
|
+
|
|
105
|
+
Once the interview is thorough, write `{resolvedFeatureDir}/PRD.md` following the structure in `references/prd-template.md`.
|
|
106
|
+
|
|
107
|
+
Every requirement MUST have a unique ID (e.g., REQ-AUTH-01, REQ-PERF-01). These IDs are referenced by all downstream documents.
|
|
108
|
+
|
|
109
|
+
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.
|
|
110
|
+
|
|
111
|
+
## Step 5: Review with User
|
|
112
|
+
|
|
113
|
+
Present the complete PRD to the user. Ask:
|
|
114
|
+
- "Does this capture everything? Any requirements missing?"
|
|
115
|
+
- "Are the priorities correct?"
|
|
116
|
+
- "Anything in here that should be out of scope?"
|
|
117
|
+
|
|
118
|
+
Use `AskUserQuestion` to collect this feedback.
|
|
119
|
+
|
|
120
|
+
Iterate until the user confirms the PRD is complete.
|
|
121
|
+
|
|
122
|
+
## Step 6: Update Pipeline State and Commit
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
Write pipeline state conforming to `references/pipeline-state-schema.json`.
|
|
127
|
+
|
|
128
|
+
1. Create or update `{resolvedFeatureDir}/.pipeline-state.json`:
|
|
129
|
+
- Set `currentStage` to `forge-2-tech`
|
|
130
|
+
- Set `stages.forge-1-prd.version` to 1 (or increment if revising)
|
|
131
|
+
- Record `artifacts`, `completedAt`
|
|
132
|
+
- Set `stages.forge-1-prd.basedOnVersions` to `{}` (no upstream dependencies)
|
|
133
|
+
- 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`.
|
|
134
|
+
2. **Offer a note — don't force one.** As a statement (not a blocking question), let the user know they can jot anything worth preserving across sessions and you'll store it in the `notes` field. If they volunteer something, store it; otherwise proceed.
|
|
135
|
+
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}"` (marking `stages.forge-1-prd.status` `complete` with `commitHash: null` in that commit), then record the artifact-commit hash via the protocol's two-commit follow-up (never `--amend`) only on success. If commit fails, leave status as `in-progress`.
|
|
136
|
+
4. **Close with the Stage Exit Protocol** (single-sourced in `references/stage-exit-protocol.md`; do not improvise a "Next steps" list):
|
|
137
|
+
|
|
138
|
+
**Close this stage with the Scripted Stage Exit** (contract: `references/stage-exit-protocol.md`; do not improvise a "Next steps" list). Run:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
R="$(bash -c 'for d in "${FEATURE_FORGE_ROOT:-}" "$HOME"/.claude/skills/feature-forge "$HOME"/.claude/plugins/cache/*/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')"
|
|
142
|
+
[ -n "$R" ] || { echo "feature-forge: cannot locate plugin root" >&2; exit 1; }
|
|
143
|
+
python3 "$R/scripts/forge-session.py" stage-exit --feature "{feature}" --stage forge-1-prd --specs-dir "{specsDir}" --host pi
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Obey the DIRECTIVES it prints, in order, per the directive contract: `runInStageVerify: true` → dispatch the in-stage clean-room verify now (honoring `autoFixEligible`); `verifyGate: "standard"` → present the Standard Verify Gate; `verifyGate: "manual-print"` → print the `verifyCommand` for the user; non-empty `invalidAutoVerifyKeys` → print a one-line warning. Then **print the NEXT-STEPS block verbatim as your absolute last output — nothing after its sentinel line.**
|
|
147
|
+
|
|
148
|
+
## Gotchas
|
|
149
|
+
|
|
150
|
+
- Users often front-load their feature description with tech decisions because that's how engineers think. Gently but firmly redirect to requirements. Don't be preachy about it — just reframe what they said.
|
|
151
|
+
- 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.
|
|
152
|
+
- 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.
|
|
153
|
+
- 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.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Host execution notes (Pi)
|
|
158
|
+
|
|
159
|
+
This Pi bundle preserves Claude's `AskUserQuestion` references because it ships a Pi compatibility extension registering an `AskUserQuestion` tool. On Pi:
|
|
160
|
+
|
|
161
|
+
- **User input:** use `AskUserQuestion` for genuine user decisions. It supports multiple questions, option descriptions, recommended ordering, multi-select, previews, and free-form Other/custom answers.
|
|
162
|
+
- **Skill dispatch:** Pi uses `/skill:<name>` commands. If you cannot invoke a skill directly, print the exact `/skill:<name> ...` command for the user to run.
|
|
163
|
+
- **Subagents:** this bundle declares its custom agents (`forge-researcher`, `forge-spec-writer`, `forge-verifier`) as package agents. If a `subagent` tool is registered, dispatch one with `{ agent: "forge-verifier", task: "..." }`, or fan several out concurrently with `{ tasks: [{ agent: "forge-spec-writer", task: "..." }, ...] }`. If no `subagent` tool is available, run that step inline yourself.
|
|
164
|
+
- **Background / monitoring:** run long-lived commands in the foreground and report progress as it arrives.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Feature Forge Pipeline State",
|
|
4
|
+
"description": "Tracks pipeline progress for a single feature across sessions. Lives at {specsDir}/{feature}/.pipeline-state.json",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["feature", "createdAt", "updatedAt", "currentStage", "stages", "pipelineStatus"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"pipelineStatus": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"enum": ["active", "paused", "abandoned"],
|
|
11
|
+
"default": "active"
|
|
12
|
+
},
|
|
13
|
+
"feature": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Feature name (matches directory name under specsDir)"
|
|
16
|
+
},
|
|
17
|
+
"epic": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Back-pointer to the owning epic's name. Absent for standalone features. The epic-manifest.json is canonical on conflict (REQ-STATE-01)."
|
|
20
|
+
},
|
|
21
|
+
"branch": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Git branch this feature's pipeline work is intended to land on, recorded by the Branch Setup block (shared-conventions.md) at the entry stage. Absent when the project isn't a git repo or branchPerFeature is false. Downstream stages and forge-5-loop compare the current branch against this to detect drift back onto the default branch before committing."
|
|
24
|
+
},
|
|
25
|
+
"createdAt": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "date-time"
|
|
28
|
+
},
|
|
29
|
+
"updatedAt": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"format": "date-time"
|
|
32
|
+
},
|
|
33
|
+
"currentStage": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"enum": ["forge-1-prd", "forge-2-tech", "forge-3-specs", "forge-4-backlog", "forge-5-loop", "forge-6-docs", "complete", "forge-verify-prd", "forge-verify-tech", "forge-verify-specs", "forge-verify-backlog", "forge-verify-impl", "forge-0-epic", "forge-verify-epic"],
|
|
36
|
+
"description": "Where the pipeline IS: the most recently started stage — its `stages[<currentStage>].status` is `in-progress` while that stage is being authored, then `complete` once its artifacts are committed. A stage skill sets this to its own id when it starts. This is deliberately NOT 'the next stage to run': the next stage is DERIVED, never stored — it is the first production stage whose `stages[].status` is not `complete` (see `next_stage()` in forge-session.py, surfaced as the navigator/doctor `nextStage`). Consumers that need 'what runs next' compute it from `stages[].status`, not from this field. `complete` here means the whole pipeline is done. (Legacy/absent value: tools fall back to the derived next stage for display only — `build_rows` in forge-session.py.)"
|
|
37
|
+
},
|
|
38
|
+
"notes": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "Free-form notes persisted between sessions (user can add context before stepping away)"
|
|
41
|
+
},
|
|
42
|
+
"epicChangeRequests": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"description": "Epic-level change requests raised by a member stage (forge-1-prd/forge-2-tech) when the epic DECOMPOSITION itself must change — distinct from the same-feature `notes` parking lot. Read by forge-0-epic edit mode (which applies them) and by forge-session stage-exit (which routes the exit on `blocksCurrent`). Absent/empty for standalone features. Additive/optional: legacy states without it validate unchanged.",
|
|
45
|
+
"items": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"required": ["kind", "target", "rationale", "blocksCurrent", "raisedBy", "raisedAt", "status"],
|
|
48
|
+
"additionalProperties": false,
|
|
49
|
+
"properties": {
|
|
50
|
+
"kind": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["add-feature", "redep", "move-boundary", "split"],
|
|
53
|
+
"description": "The decomposition change. add-feature/redep map 1:1 onto edit-mode mutators; move-boundary/split are composite (applied guided-manual in v1)."
|
|
54
|
+
},
|
|
55
|
+
"target": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "The sibling feature to add, or the feature/boundary affected."
|
|
58
|
+
},
|
|
59
|
+
"rationale": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Why the epic must change; seeds the edit-mode charter/prompt when applied."
|
|
62
|
+
},
|
|
63
|
+
"blocksCurrent": {
|
|
64
|
+
"type": "boolean",
|
|
65
|
+
"description": "true → the current feature's next stage would build on a soon-to-change decomposition (pause-now: reconcile before proceeding). false → a peer/downstream change (finish-then-edit). Drives stage-exit routing."
|
|
66
|
+
},
|
|
67
|
+
"raisedBy": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"enum": ["forge-1-prd", "forge-2-tech"],
|
|
70
|
+
"description": "The stage that detected the epic-level concern."
|
|
71
|
+
},
|
|
72
|
+
"raisedAt": { "type": "string", "format": "date-time" },
|
|
73
|
+
"status": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": ["open", "applied", "dismissed"],
|
|
76
|
+
"default": "open",
|
|
77
|
+
"description": "Lifecycle: open → applied|dismissed. Only forge-0-epic edit mode flips open→applied/dismissed; recording stages only create open entries; navigator/verify only read."
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"deferredDecisions": {
|
|
83
|
+
"type": "array",
|
|
84
|
+
"description": "Same-feature decisions deliberately postponed to a LATER stage of THIS feature — a structured alternative to burying them in the free-text `notes` string. Distinct from `notes` (unstructured scratch) and from `epicChangeRequests[]` (the epic DECOMPOSITION must change). Use this when a stage would otherwise be tempted to solicit a decision that properly belongs to a downstream stage (e.g. forge-1-prd deferring the concrete cache backend to forge-2-tech): record it here instead of asking now (see the deferred-decisions rule in `references/stage-exit-protocol.md`), and the target stage addresses it. Additive/optional: legacy states without it validate unchanged.",
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"required": ["question", "raisedBy", "raisedAt", "status"],
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"properties": {
|
|
90
|
+
"question": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"description": "The decision being deferred, phrased as a concrete question for the target stage to answer."
|
|
93
|
+
},
|
|
94
|
+
"rationale": {
|
|
95
|
+
"type": "string",
|
|
96
|
+
"description": "Why it is deferred rather than decided now (e.g. depends on information the target stage produces)."
|
|
97
|
+
},
|
|
98
|
+
"targetStage": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"enum": ["forge-1-prd", "forge-2-tech", "forge-3-specs", "forge-4-backlog", "forge-5-loop", "forge-6-docs"],
|
|
101
|
+
"description": "The stage that should resolve this decision. Omit when unknown/any-later-stage."
|
|
102
|
+
},
|
|
103
|
+
"raisedBy": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": ["forge-1-prd", "forge-2-tech", "forge-3-specs", "forge-4-backlog"],
|
|
106
|
+
"description": "The stage that deferred the decision."
|
|
107
|
+
},
|
|
108
|
+
"raisedAt": { "type": "string", "format": "date-time" },
|
|
109
|
+
"status": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"enum": ["open", "addressed", "dismissed"],
|
|
112
|
+
"default": "open",
|
|
113
|
+
"description": "Lifecycle: open → addressed|dismissed. The target stage flips open→addressed when it resolves the decision (or dismissed if it no longer applies); recording stages only create open entries."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"stages": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": {
|
|
121
|
+
"forge-0-epic": { "$ref": "#/definitions/stageEntry" },
|
|
122
|
+
"forge-verify-epic": { "$ref": "#/definitions/verifyEntry" },
|
|
123
|
+
"forge-1-prd": { "$ref": "#/definitions/stageEntry" },
|
|
124
|
+
"forge-2-tech": { "$ref": "#/definitions/stageEntry" },
|
|
125
|
+
"forge-3-specs": { "$ref": "#/definitions/stageEntry" },
|
|
126
|
+
"forge-verify-specs": { "$ref": "#/definitions/verifyEntry" },
|
|
127
|
+
"forge-4-backlog": { "$ref": "#/definitions/stageEntry" },
|
|
128
|
+
"forge-verify-backlog": { "$ref": "#/definitions/verifyEntry" },
|
|
129
|
+
"forge-5-loop": { "$ref": "#/definitions/stageEntry" },
|
|
130
|
+
"forge-6-docs": { "$ref": "#/definitions/stageEntry" },
|
|
131
|
+
"forge-verify-impl": { "$ref": "#/definitions/verifyEntry" },
|
|
132
|
+
"forge-verify-prd": { "$ref": "#/definitions/verifyEntry" },
|
|
133
|
+
"forge-verify-tech": { "$ref": "#/definitions/verifyEntry" }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"definitions": {
|
|
138
|
+
"stageEntry": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"required": ["status"],
|
|
141
|
+
"properties": {
|
|
142
|
+
"status": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"enum": ["pending", "in-progress", "complete", "stale"]
|
|
145
|
+
},
|
|
146
|
+
"version": {
|
|
147
|
+
"type": "integer",
|
|
148
|
+
"description": "Incremented each time this stage's artifacts are revised"
|
|
149
|
+
},
|
|
150
|
+
"artifacts": {
|
|
151
|
+
"type": "array",
|
|
152
|
+
"items": { "type": "string" },
|
|
153
|
+
"description": "Relative paths to artifacts produced by this stage"
|
|
154
|
+
},
|
|
155
|
+
"startedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
156
|
+
"completedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
157
|
+
"commitHash": {
|
|
158
|
+
"type": ["string", "null"],
|
|
159
|
+
"description": "Git commit SHA of this stage's artifact commit (Commit 1 of the two-commit Git Commit Protocol in shared-conventions.md). Written by a small follow-up commit so it points at the artifact commit itself, never at an orphaned amend or the hash-recording commit. null until recorded (or when there was no new artifact commit)."
|
|
160
|
+
},
|
|
161
|
+
"basedOnVersions": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"description": "Upstream stage versions this artifact was built against",
|
|
164
|
+
"additionalProperties": { "type": "integer" }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"verifyEntry": {
|
|
169
|
+
"type": "object",
|
|
170
|
+
"required": ["status"],
|
|
171
|
+
"properties": {
|
|
172
|
+
"status": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"enum": ["pending", "passed", "findings-reported", "findings-applied", "skipped"]
|
|
175
|
+
},
|
|
176
|
+
"findingsFile": {
|
|
177
|
+
"type": ["string", "null"],
|
|
178
|
+
"description": "Path to the verification findings document"
|
|
179
|
+
},
|
|
180
|
+
"findingsCount": {
|
|
181
|
+
"type": ["integer", "null"],
|
|
182
|
+
"description": "Number of findings reported"
|
|
183
|
+
},
|
|
184
|
+
"verifiedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
185
|
+
"fixedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
186
|
+
"commitHash": { "type": ["string", "null"], "description": "Git commit SHA of the verify/fix artifact commit. Recorded via the two-commit Git Commit Protocol (shared-conventions.md) so it points at the artifact commit, never an orphaned amend." },
|
|
187
|
+
"verifiedStageVersion": { "type": ["integer", "null"], "description": "The production stage's `version` at the moment this verify was resolved. The navigator's freshness ledger compares it to the stage's current `version`: equal means the verify is fresh; a mismatch (artifact revised since) or an absent field (legacy state) means stale, so auto-verify re-fires. Recorded by forge-verify/forge-fix when writing a passed/findings-applied status." }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# PRD Template and Interview Guide
|
|
2
|
+
|
|
3
|
+
This reference defines the standard PRD structure and the interview questions to cover for each section.
|
|
4
|
+
|
|
5
|
+
## PRD Document Structure
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
# {Feature Name} — Product Requirements Document
|
|
9
|
+
|
|
10
|
+
## 1. Problem Statement
|
|
11
|
+
What problem does this feature solve? Who has this problem? Why does it matter now?
|
|
12
|
+
|
|
13
|
+
## 2. User Stories
|
|
14
|
+
As a [role], I want [capability], so that [benefit].
|
|
15
|
+
- Include primary actors and secondary actors
|
|
16
|
+
- Include admin/operator stories, not just end-user stories
|
|
17
|
+
|
|
18
|
+
## 3. Functional Requirements
|
|
19
|
+
|
|
20
|
+
### 3.1 {Capability Area}
|
|
21
|
+
- REQ-{CAT}-01: {Requirement description}
|
|
22
|
+
- Priority: P0 (must have) | P1 (should have) | P2 (nice to have)
|
|
23
|
+
- Notes: {Any clarification}
|
|
24
|
+
|
|
25
|
+
### 3.2 {Another Capability Area}
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
## 4. Non-Functional Requirements
|
|
29
|
+
|
|
30
|
+
### 4.1 Performance
|
|
31
|
+
- REQ-PERF-01: ...
|
|
32
|
+
|
|
33
|
+
### 4.2 Security
|
|
34
|
+
- REQ-SEC-01: ...
|
|
35
|
+
|
|
36
|
+
### 4.3 Observability
|
|
37
|
+
- REQ-OBS-01: ...
|
|
38
|
+
|
|
39
|
+
### 4.4 Accessibility
|
|
40
|
+
- REQ-A11Y-01: ...
|
|
41
|
+
|
|
42
|
+
### 4.5 Scalability
|
|
43
|
+
- REQ-SCALE-01: ...
|
|
44
|
+
|
|
45
|
+
## 5. Constraints
|
|
46
|
+
Technical, organizational, or external constraints that must be respected.
|
|
47
|
+
(This is where technology mandates go — e.g., "must integrate with existing @repo/auth package")
|
|
48
|
+
|
|
49
|
+
## 6. Out of Scope
|
|
50
|
+
Explicitly list what this feature will NOT do in this version.
|
|
51
|
+
|
|
52
|
+
## 7. Open Questions
|
|
53
|
+
Unresolved items that need answers before or during implementation.
|
|
54
|
+
|
|
55
|
+
## 8. Success Criteria
|
|
56
|
+
How do we know this feature is done and working correctly?
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Interview Question Categories
|
|
60
|
+
|
|
61
|
+
Cover ALL of these areas during the interview. Don't move on until each is addressed.
|
|
62
|
+
|
|
63
|
+
### Core Understanding
|
|
64
|
+
- What is the feature in one sentence?
|
|
65
|
+
- Who are the primary users? Secondary users? Admins/operators?
|
|
66
|
+
- What workflow or process does this support?
|
|
67
|
+
- What exists today that this replaces or augments?
|
|
68
|
+
|
|
69
|
+
### Functional Depth
|
|
70
|
+
- Walk me through the happy path end to end
|
|
71
|
+
- What are the key data entities involved?
|
|
72
|
+
- What inputs does the system accept? What are valid/invalid inputs?
|
|
73
|
+
- What outputs does the system produce?
|
|
74
|
+
- What states can things be in? What transitions are allowed?
|
|
75
|
+
- What happens when the user makes a mistake?
|
|
76
|
+
|
|
77
|
+
### Error and Edge Cases
|
|
78
|
+
- What happens when X is unavailable?
|
|
79
|
+
- What if two users do Y at the same time?
|
|
80
|
+
- What happens with empty inputs? Huge inputs? Malformed inputs?
|
|
81
|
+
- What does partial failure look like?
|
|
82
|
+
- How should the system recover from crashes mid-operation?
|
|
83
|
+
|
|
84
|
+
### Integration
|
|
85
|
+
- What existing parts of the system does this interact with?
|
|
86
|
+
- What data does it need from other features?
|
|
87
|
+
- What data does it provide to other features?
|
|
88
|
+
- Are there external systems or APIs involved?
|
|
89
|
+
|
|
90
|
+
### Non-Functional
|
|
91
|
+
- What's the expected load? (requests/sec, concurrent users, data volume)
|
|
92
|
+
- What are the latency requirements?
|
|
93
|
+
- What security considerations exist? (authn, authz, data sensitivity)
|
|
94
|
+
- What needs to be logged, monitored, or alerted on?
|
|
95
|
+
- Are there accessibility requirements?
|
|
96
|
+
|
|
97
|
+
### Scope and Priority
|
|
98
|
+
- What's the minimum viable version of this?
|
|
99
|
+
- What would you cut if you had to ship in half the time?
|
|
100
|
+
- What's explicitly NOT part of this feature?
|
|
101
|
+
- Are there follow-up features that depend on decisions made here?
|
|
102
|
+
|
|
103
|
+
### Success
|
|
104
|
+
- How do you know this feature is working correctly?
|
|
105
|
+
- What would a user complain about if we got it wrong?
|
|
106
|
+
- Are there quantitative targets? (latency < Xms, uptime > Y%)
|