forge-orkes 0.9.5 → 0.10.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.
@@ -19,7 +19,7 @@ const FORGE_END = '<!-- forge:end -->';
19
19
  const FRAMEWORK_OWNED_DIRS = ['.claude/agents', '.claude/skills'];
20
20
 
21
21
  // Template-only: reference templates Forge controls
22
- const TEMPLATE_ONLY_DIRS = ['.forge/templates'];
22
+ const TEMPLATE_ONLY_DIRS = ['.forge/templates', '.forge/migrations'];
23
23
 
24
24
  // Settings file gets smart-merge (overwrite forge.* keys, preserve user hooks)
25
25
  const SETTINGS_FILE = '.claude/settings.json';
@@ -284,6 +284,64 @@ async function install() {
284
284
  console.log(`\n Forge v${pkgVersion} is ready. Start with: /forge\n`);
285
285
  }
286
286
 
287
+ /**
288
+ * Detect pre-0.10.0 requirements layouts (single top-level file, suffixed top-level,
289
+ * or per-phase files). Returns array of legacy paths found, relative to project root.
290
+ */
291
+ function detectLegacyRequirementsLayout() {
292
+ const forgeDir = path.join(targetDir, '.forge');
293
+ if (!fs.existsSync(forgeDir)) return [];
294
+
295
+ const legacy = [];
296
+
297
+ for (const entry of fs.readdirSync(forgeDir, { withFileTypes: true })) {
298
+ if (!entry.isFile()) continue;
299
+ if (entry.name === 'requirements.yml') {
300
+ legacy.push(path.join('.forge', entry.name));
301
+ } else if (/^requirements-m\d+\.yml$/.test(entry.name)) {
302
+ legacy.push(path.join('.forge', entry.name));
303
+ }
304
+ }
305
+
306
+ const phasesDir = path.join(forgeDir, 'phases');
307
+ if (fs.existsSync(phasesDir)) {
308
+ for (const phase of fs.readdirSync(phasesDir, { withFileTypes: true })) {
309
+ if (!phase.isDirectory()) continue;
310
+ const reqPath = path.join(phasesDir, phase.name, 'requirements.yml');
311
+ if (fs.existsSync(reqPath)) {
312
+ legacy.push(path.join('.forge', 'phases', phase.name, 'requirements.yml'));
313
+ }
314
+ }
315
+ }
316
+
317
+ return legacy;
318
+ }
319
+
320
+ /**
321
+ * After upgrade, surface any detected legacy file layouts that the new framework
322
+ * version no longer writes. Non-interactive — prints a warning with a pointer to
323
+ * the migration guide. Add new detection blocks here as future versions change layout.
324
+ */
325
+ function runPostUpgradeMigrationChecks() {
326
+ const legacyReqs = detectLegacyRequirementsLayout();
327
+ if (legacyReqs.length === 0) return;
328
+
329
+ console.log(' ⚠ Pre-0.10.0 requirements layout detected');
330
+ console.log(' ─────────────────────────────────────────');
331
+ console.log(' Found:');
332
+ for (const p of legacyReqs) {
333
+ console.log(` ${p}`);
334
+ }
335
+ console.log();
336
+ console.log(' Forge 0.10.0+ uses per-milestone files at .forge/requirements/m{N}.yml.');
337
+ console.log(' Migration guide: .forge/migrations/0.10.0-per-milestone-requirements.md');
338
+ console.log();
339
+ console.log(' Run the migration before your next planning cycle. In Claude Code:');
340
+ console.log(' /forge then hand the guide to quick-tasking, or invoke Skill(quick-tasking)');
341
+ console.log(' with the guide path as the task definition.');
342
+ console.log();
343
+ }
344
+
287
345
  async function upgrade() {
288
346
  console.log('\n Forge Upgrade\n');
289
347
 
@@ -384,6 +442,8 @@ async function upgrade() {
384
442
  }
385
443
 
386
444
  console.log(` Upgraded to v${pkgVersion}\n`);
445
+
446
+ runPostUpgradeMigrationChecks();
387
447
  }
388
448
 
389
449
  // --- Entry point ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-orkes",
3
- "version": "0.9.5",
3
+ "version": "0.10.0",
4
4
  "description": "Set up the Forge meta-prompting framework for Claude Code in your project",
5
5
  "bin": {
6
6
  "create-forge": "./bin/create-forge.js"
@@ -18,7 +18,7 @@ Research -> actionable plans. Every plan passes constitutional gates with verifi
18
18
  Research findings, `.forge/templates/project.yml`, `constitution.md`, `context.md`, `state/milestone-{id}.yml` (if resuming).
19
19
 
20
20
  ## Output
21
- `.forge/` files: `phases/m{M}-{N}-{name}/plan.md` (XML tasks), `specs/`, `requirements.yml`, `context.md`, `state/milestone-{id}.yml`.
21
+ `.forge/` files: `phases/m{M}-{N}-{name}/plan.md` (XML tasks), `specs/`, `requirements/m{N}.yml`, `context.md`, `state/milestone-{id}.yml`.
22
22
 
23
23
  ## Process
24
24
 
@@ -60,6 +60,7 @@ Run: {n} | Passed: {n} | Failed: {n} | Coverage: {if available}
60
60
  Read: .forge/phases/m{M}-{N}-{name}/plan.md → extract must_haves
61
61
  Read: .forge/state/milestone-{id}.yml → reported progress
62
62
  Read: .forge/context.md → locked decisions
63
+ Read: .forge/deferred-issues.md → known pre-existing failures (if exists; treat as advisory)
63
64
  ```
64
65
 
65
66
  ### 2. Truths
@@ -90,6 +91,10 @@ npm run build 2>&1
90
91
  npm run lint 2>&1
91
92
  ```
92
93
 
94
+ Cross-reference failures against `deferred-issues.md`:
95
+ - Match on test name or summary → advisory; label "Pre-existing (deferred: DI-{N})"
96
+ - No match → regression; include in Issues (Critical) and gaps
97
+
93
98
  ### 6. Anti-Pattern Scan
94
99
 
95
100
  | Pattern | Command | Severity |
@@ -101,7 +106,7 @@ npm run lint 2>&1
101
106
  | Missing error handling | `grep -rn "\.catch()" src/` | Warning |
102
107
 
103
108
  ### 7. Requirements
104
- Cross-ref `requirements.yml`: `must-have` implemented, criteria testable, flag gaps.
109
+ Cross-ref `requirements/m{N}.yml` (current milestone): `must-have` implemented, criteria testable, flag gaps.
105
110
 
106
111
  ### 8. Report
107
112
  **PASS**: all truths, substantive+wired, tests pass. **PARTIAL**: some gaps. **FAIL**: unverified, stubs, failing tests.
@@ -23,16 +23,21 @@ Structured conversation: approach, trade-offs, decisions. Clarity, not artifacts
23
23
 
24
24
  ## Progressive Persistence
25
25
 
26
- **Decisions persist immediately. This is a hard gate — not a guideline.**
26
+ > **HARD GATE NOT A GUIDELINE. NO EXCEPTIONS.**
27
+ > Write to `.forge/context.md` after EVERY confirmed decision, before asking the next question.
28
+ > If you reach convergence without having written each decision individually — you already violated this rule.
27
29
 
28
30
  After each user response that confirms a decision:
29
31
 
30
32
  1. **STOP** — do not continue the discussion
31
33
  2. **Write to disk** — append to `.forge/context.md` (create from template if missing)
34
+ - **Path is always `.forge/context.md`** — never `.forge/phases/*/context.md`, never inline memory
32
35
  3. **THEN** continue to the next question
33
36
 
34
37
  Never accumulate decisions in working memory. Never batch writes to convergence.
35
38
 
39
+ **Common failure mode:** Agent says "decisions live in conversation; planning writes context.md." This is WRONG. Discussing writes context.md. Planning reads it.
40
+
36
41
  ### Write Protocol
37
42
 
38
43
  **On first decision of the session:**
@@ -190,7 +195,7 @@ options:
190
195
 
191
196
  ```
192
197
  Read: .forge/phases/m{M}-{N}-{name}/plan-{NN}.md → the plan
193
- Read: .forge/requirements.yml → source requirements
198
+ Read: .forge/requirements/m{N}.yml → source requirements (current milestone)
194
199
  Read: .forge/context.md → locked decisions
195
200
  Read: .forge/constitution.md → active gates
196
201
  ```
@@ -10,6 +10,18 @@ description: "Build to plan with atomic commits, deviation rules, and context en
10
10
  - [ ] Context.md locked decisions noted
11
11
  - [ ] Constitution.md gates satisfied
12
12
  - [ ] Milestone state updated to `status: executing`
13
+ - [ ] Baseline snapshot captured (see below)
14
+
15
+ ## Baseline Snapshot
16
+
17
+ Run **before the first task begins**. Makes failure causality mechanical — no self-assessment.
18
+
19
+ 1. Run all non-advisory verification commands
20
+ 2. Record which tests/checks pass and which fail — this is the baseline
21
+ 3. After each commit: failures **not in baseline** = introduced by this task = **must fix under Rule 3**
22
+ 4. Failures **present in baseline** = pre-existing → append to `.forge/deferred-issues.md`, mark `status: pending`
23
+
24
+ Skip only if re-entering an in-progress execution and `deferred-issues.md` already documents all current failures.
13
25
 
14
26
  ## Deviation Rules
15
27
 
@@ -116,9 +128,9 @@ For each command, in order:
116
128
  ```
117
129
  Attempt 1:
118
130
  1. Read error output
119
- 2. Caused by current task?
120
- - YES → fix code, stage fixes, amend commit
121
- - NO mark advisory for this session; append to .forge/deferred-issues.md; continue
131
+ 2. In baseline snapshot?
132
+ - YES (pre-existing) mark advisory for this session; append to .forge/deferred-issues.md; continue
133
+ - NO (introduced by this task) fix code, stage fixes, amend commit
122
134
  3. Re-run command
123
135
  4. Pass → next command
124
136
  5. Fail → next attempt (up to max_retries)
@@ -133,7 +145,7 @@ After max_retries exhausted:
133
145
  Verification retries count toward the task's 3-strike limit. 2 strikes used = 1 verification retry max.
134
146
 
135
147
  ### Do NOT Fix
136
- - **Pre-existing failures** not from current task → mark advisory; append to `.forge/deferred-issues.md`
148
+ - **Pre-existing failures** present in baseline snapshot → mark advisory; append to `.forge/deferred-issues.md`
137
149
  - **Flaky tests** passing on re-run without changes → note in summary, no strike
138
150
  - **Unrelated warnings** (deprecation, non-blocking lint) → ignore
139
151
 
@@ -190,7 +202,8 @@ After completing all tasks in a plan:
190
202
  - src/components/Login.tsx (created)
191
203
 
192
204
  ## Notes
193
- [Anything the verifier should know]
205
+ [Genuine handoff context only: environment requirements, seed data, external services needed (e.g. "Redis must be running for auth tests").
206
+ Do NOT list test failures here — pre-existing failures belong in deferred-issues.md; task-introduced failures must be fixed before committing.]
194
207
  ```
195
208
 
196
209
  ## State Updates
@@ -246,7 +246,7 @@ Phase transitions = clear boundaries. **Recommend `/clear`** after writing state
246
246
  | researching | `.forge/research/milestone-{id}.md` | discussing |
247
247
  | discussing | `.forge/context.md` (locked decisions, deferrals, discretion) | planning |
248
248
  | architecting | ADRs, data models, API contracts | planning |
249
- | planning | `.forge/phases/m{M}-{N}-{name}/`, requirements.yml, roadmap.yml | executing |
249
+ | planning | `.forge/phases/m{M}-{N}-{name}/`, `.forge/requirements/m{N}.yml`, roadmap.yml | executing |
250
250
  | executing | Committed code, execution summary, state | verifying |
251
251
  | verifying | Verification report, desire paths | reviewing |
252
252
 
@@ -57,7 +57,7 @@ Check: Any structured agent/workflow system
57
57
  | Source | Target |
58
58
  |--------|--------|
59
59
  | Project descriptions | `.forge/project.yml` |
60
- | Requirements | `.forge/requirements.yml` |
60
+ | Requirements | `.forge/requirements/m1.yml` (first milestone; subsequent milestones get their own file) |
61
61
  | Roadmaps/plans | `.forge/roadmap.yml` |
62
62
  | Context/decisions | `.forge/context.md` |
63
63
  | State/progress | `.forge/state/index.yml` + `.forge/state/milestone-{id}.yml` |
@@ -75,7 +75,7 @@ Check: Any structured agent/workflow system
75
75
  | GSD Source | Extract | Write to Forge |
76
76
  |-----------|---------|---------------|
77
77
  | `PROJECT.md` | Project name, description, tech stack, goals | `.forge/project.yml` |
78
- | `REQUIREMENTS.md` | Feature requirements, acceptance criteria → YAML with IDs | `.forge/requirements.yml` |
78
+ | `REQUIREMENTS.md` | Feature requirements, acceptance criteria → YAML with IDs | `.forge/requirements/m1.yml` |
79
79
  | `ROADMAP.md` | Phases, milestones, dependencies → YAML with refs | `.forge/roadmap.yml` |
80
80
  | `STATE.md` | Current phase, progress, blockers | `.forge/state/index.yml` + `.forge/state/milestone-{id}.yml` |
81
81
  | `CONTEXT.md` | NON-NEGOTIABLE decisions, DEFERRED ideas | `.forge/context.md` |
@@ -89,7 +89,7 @@ Check: Any structured agent/workflow system
89
89
  | Spec-Kit Source | Extract | Write to Forge |
90
90
  |----------------|---------|---------------|
91
91
  | `spec-driven.md` | Governance patterns | `.forge/constitution.md` |
92
- | `templates/spec-template.md` | Requirements format | `.forge/requirements.yml` |
92
+ | `templates/spec-template.md` | Requirements format | `.forge/requirements/m1.yml` |
93
93
  | `templates/constitution-template.md` | Immutable gates | `.forge/constitution.md` |
94
94
  | `extensions/` | Specialized skills | `.claude/skills/` (if relevant) |
95
95
  | Project specs (if filled in) | Locked decisions | `.forge/context.md` |
@@ -16,7 +16,7 @@ Read `.forge/context.md` **Needs Resolution**. If unchecked `- [ ]` items:
16
16
  |--------|--------|
17
17
  | Lock | Record in Locked Decisions |
18
18
  | Defer | Move to Deferred Ideas + revisit date |
19
- | Fix | Add as FR-xxx in `.forge/requirements.yml` |
19
+ | Fix | Add as FR-xxx in `.forge/requirements/m{N}.yml` (current milestone) |
20
20
  | Drop | Note in Amendment Log |
21
21
 
22
22
  Mark resolved `- [x]`. Target: 2-5 min.
@@ -43,16 +43,20 @@ Must complete BEFORE plans. Plans reference context.md.
43
43
 
44
44
  ## Step 4: Structure Requirements
45
45
 
46
- If `.forge/requirements.yml` missing, create from template:
46
+ Resolve current milestone ID from `.forge/state/index.yml` (active milestone) or invocation context. Target file: `.forge/requirements/m{N}.yml`.
47
+
48
+ If missing, create from `.forge/templates/requirements.yml`:
47
49
  1. Extract from user description + research
48
- 2. IDs: FR-001, FR-002...
50
+ 2. IDs: FR-001, FR-002... **Globally unique across milestones** -- check existing `.forge/requirements/*.yml` for highest FR-ID, continue sequence
49
51
  3. Acceptance: Given/When/Then
50
52
  4. Uncertain: `[NEEDS CLARIFICATION]`
51
53
  5. P1 (must) / P2 (should) / P3 (nice)
52
- 6. Deferred: DEF-001...
54
+ 6. Deferred: DEF-001... (also globally unique)
53
55
 
54
56
  **Blocks until all P1 `[NEEDS CLARIFICATION]` resolved.**
55
57
 
58
+ Never write to top-level `.forge/requirements.yml` -- that path is deprecated.
59
+
56
60
  ## Step 5: Create Roadmap
57
61
 
58
62
  If `.forge/roadmap.yml` missing (Full only):
@@ -193,7 +197,7 @@ Step 7 intentionally skips UI — that coverage is owned by `testing` skill (e2e
193
197
  **Auto-suggest heuristic:** When requirements contain UI signals, prompt user once (pre-code) to invoke `testing`:
194
198
 
195
199
  Signals (any match):
196
- - `requirements.yml` description mentions: "UI", "page", "flow", "form", "dashboard", "component", "screen"
200
+ - `requirements/m{N}.yml` description mentions: "UI", "page", "flow", "form", "dashboard", "component", "screen"
197
201
  - Tasks in Step 6 have files matching: `src/components/**`, `src/pages/**`, `src/app/**`, `*.tsx`, `*.vue`, `*.svelte`
198
202
  - `project.yml` stack includes web framework (Next.js, React, Vue, Svelte, Astro, Remix)
199
203
 
@@ -231,6 +235,6 @@ Done when approved.
231
235
 
232
236
  ## Handoff
233
237
 
234
- 1. **Persist** -- plans `.forge/phases/`, reqs `.forge/requirements.yml`, roadmap `.forge/roadmap.yml`, context `.forge/context.md`
238
+ 1. **Persist** -- plans `.forge/phases/`, reqs `.forge/requirements/m{N}.yml`, roadmap `.forge/roadmap.yml`, context `.forge/context.md`
235
239
  2. **State** -- `current.status` = `executing` in `.forge/state/milestone-{id}.yml`
236
240
  3. *"Plan written. `/clear` then `/forge` to continue."*
@@ -26,7 +26,7 @@ Template directory: `{source}/packages/create-forge/template/`.
26
26
  | **Merge-owned** | `CLAUDE.md`, `.claude/settings.json` | Never auto-overwrite |
27
27
  | **Template-only** | `.forge/templates/**` | Overwrite |
28
28
 
29
- **Never touch** user-generated files: `.forge/project.yml`, `.forge/state/`, `.forge/constitution.md`, `.forge/context.md`, `.forge/requirements.yml`, `.forge/roadmap.yml`, `.forge/design-system.md`, `.forge/refactor-backlog.yml`.
29
+ **Never touch** user-generated files: `.forge/project.yml`, `.forge/state/`, `.forge/constitution.md`, `.forge/context.md`, `.forge/requirements/`, `.forge/roadmap.yml`, `.forge/design-system.md`, `.forge/refactor-backlog.yml`.
30
30
 
31
31
  ## Step 3: Sync Framework-Owned Files
32
32
 
@@ -80,3 +80,46 @@ Needs manual review: {N} files
80
80
 
81
81
  Unchanged: {N} files
82
82
  ```
83
+
84
+ ## Step 7: Post-Upgrade Migration Checks
85
+
86
+ After sync completes, detect legacy file layouts that the new framework version no longer writes but may still read in compatibility mode. For each match, surface a migration prompt — do not auto-migrate.
87
+
88
+ ### Pre-0.10.0 requirements layout
89
+
90
+ Run from project root:
91
+
92
+ ```bash
93
+ find .forge -maxdepth 2 -type f \( -name "requirements.yml" -o -name "requirements-m*.yml" \) \
94
+ | grep -v "^.forge/templates/" \
95
+ | grep -v "^.forge/requirements/"
96
+
97
+ find .forge/phases -type f -name "requirements.yml" 2>/dev/null
98
+ ```
99
+
100
+ If either command returns matches, surface:
101
+
102
+ ```
103
+ Pre-0.10.0 requirements layout detected
104
+ ───────────────────────────────────────
105
+ Found: {list of legacy paths}
106
+
107
+ Forge 0.10.0 uses per-milestone files at .forge/requirements/m{N}.yml.
108
+ A migration guide is available at: .forge/migrations/0.10.0-per-milestone-requirements.md
109
+ (installed alongside Forge; canonical copy at
110
+ https://github.com/Attuned-Media/forge/blob/main/docs/migrations/0.10.0-per-milestone-requirements.md)
111
+
112
+ Run the migration now? (yes/no/show guide)
113
+ ```
114
+
115
+ - **yes** → invoke `quick-tasking` skill, hand it the migration guide as the task definition
116
+ - **show guide** → read and display the file, then re-ask
117
+ - **no** → note in upgrade report. Skills will continue reading the legacy path as deprecated; new writes still go to the new path, causing split-brain state. Recommend running migration before next planning cycle.
118
+
119
+ ### Future migrations
120
+
121
+ Add new detection blocks here for each Forge version that changes file layout. Pattern:
122
+ 1. Detection command(s)
123
+ 2. Single-line description of the drift
124
+ 3. Pointer to `.forge/migrations/{version}-{slug}.md` (installed copy; canonical at `docs/migrations/...` in the Forge source repo)
125
+ 4. Three-way prompt (yes/no/show guide)
@@ -20,9 +20,34 @@ Read: .forge/state/milestone-{id}.yml → current phase, plans completed
20
20
  Read: .forge/project.yml → tech stack (for running tests)
21
21
  Read: .forge/phases/m{M}-{N}-{name}/plan-{NN}.md → must_haves (truths, artifacts, key_links)
22
22
  Read: .forge/context.md → locked decisions
23
- Read: .forge/requirements.yml → requirement IDs for coverage check
23
+ Read: .forge/requirements/m{N}.yml → requirement IDs for coverage check (current milestone, resolved from state)
24
+ Read: .forge/deferred-issues.md → known pre-existing failures (if exists; treat as advisory)
24
25
  ```
25
26
 
27
+ ## Deferred Issues
28
+
29
+ If `.forge/deferred-issues.md` exists, load it before running any tests.
30
+
31
+ When test results come in, cross-reference failures against known deferred issue IDs:
32
+
33
+ - **Failure matches a deferred ID** → advisory only — note as "Pre-existing (deferred: DI-{N})", do NOT fail verification for this
34
+ - **Failure not in deferred-issues.md** → regression introduced after the baseline — **FAIL** and include in gaps
35
+
36
+ In the Test Results section of the report, split accordingly:
37
+
38
+ ```markdown
39
+ ## Test Results
40
+ Run: {n} | Passed: {n} | Failed: {n}
41
+
42
+ ### Regressions (block release)
43
+ - {test name}: {error}
44
+
45
+ ### Pre-existing / Deferred (advisory)
46
+ - DI-{N}: {test name} — {summary from deferred-issues.md}
47
+ ```
48
+
49
+ Verdict: FAIL only triggers for regressions. Known deferred failures do not block a PASSED verdict — they are tracked separately and must be worked off via the refactor backlog or a dedicated fix phase.
50
+
26
51
  ## Interface Testing Gate
27
52
 
28
53
  Read `interface` from `.forge/project.yml`. If absent, `[]`, or `[none]` → skip gate, proceed to 3-level verification.
@@ -137,7 +162,7 @@ After 3-level verification:
137
162
 
138
163
  ## Requirements Coverage
139
164
 
140
- Cross-reference against `.forge/requirements.yml`:
165
+ Cross-reference against `.forge/requirements/m{N}.yml` (current milestone):
141
166
 
142
167
  ```markdown
143
168
  | Requirement | Status | Evidence |
@@ -0,0 +1,140 @@
1
+ # Migration Guide: Per-Milestone Requirements (Forge 0.10.0)
2
+
3
+ Forge 0.10.0 splits requirements from a single `.forge/requirements.yml` into per-milestone files under `.forge/requirements/m{N}.yml`. FR-IDs remain globally unique across all milestone files.
4
+
5
+ This guide migrates pre-0.10.0 layouts to the new convention. Safe for an agent to run autonomously.
6
+
7
+ ## Why
8
+
9
+ The pre-0.10.0 spec had a single top-level `.forge/requirements.yml` "refreshed per milestone." Projects with concurrent active milestones produced ad-hoc adaptations (per-phase `requirements.yml`, suffixed `requirements-m{N}.yml`). Per-milestone files formalize the desire path: each active milestone owns its own file, no cross-stream contention, mirroring the existing `state/milestone-{id}.yml` pattern.
10
+
11
+ ## Prerequisites
12
+
13
+ 1. Forge framework files upgraded to ≥0.10.0 (run `Skill(upgrading)` first).
14
+ 2. Working tree clean or changes committed — migration is mechanical but touches several files.
15
+
16
+ ## Detection
17
+
18
+ Run from project root. Any match below means migration is needed:
19
+
20
+ ```bash
21
+ # Off-spec layout signals
22
+ ls .forge/requirements.yml 2>/dev/null # legacy single file
23
+ ls .forge/requirements-m*.yml 2>/dev/null # suffixed top-level
24
+ find .forge/phases -name "requirements.yml" 2>/dev/null # per-phase files
25
+ ```
26
+
27
+ If `.forge/requirements/` already exists as a directory and the legacy paths above are absent, migration is complete — stop here.
28
+
29
+ ## Migration steps
30
+
31
+ ### 1. Inventory existing files
32
+
33
+ List every `requirements*.yml` outside the new `requirements/` subdir:
34
+
35
+ ```bash
36
+ find .forge -type f \( -name "requirements.yml" -o -name "requirements-m*.yml" \) \
37
+ | grep -v "^.forge/requirements/" \
38
+ | grep -v "^.forge/templates/"
39
+ ```
40
+
41
+ For each path found, determine which milestone it belongs to:
42
+
43
+ | Source pattern | Milestone ID |
44
+ |----------------|--------------|
45
+ | `.forge/requirements.yml` | Read `state/index.yml` — usually the most recently active milestone, or the one referenced by the file's content. If ambiguous, ask the user. |
46
+ | `.forge/requirements-m{N}.yml` | `{N}` from the filename |
47
+ | `.forge/phases/m{N}-{name}/requirements.yml` | `{N}` from the phase directory |
48
+
49
+ ### 2. Create the subdirectory
50
+
51
+ ```bash
52
+ mkdir -p .forge/requirements
53
+ ```
54
+
55
+ ### 3. Move each file
56
+
57
+ For each source file, move to `.forge/requirements/m{N}.yml`:
58
+
59
+ ```bash
60
+ # Example patterns — adapt to actual filenames found in step 1
61
+ mv .forge/requirements.yml .forge/requirements/m{N}.yml
62
+ mv .forge/requirements-m53.yml .forge/requirements/m53.yml
63
+ mv .forge/phases/m51-*/requirements.yml .forge/requirements/m51.yml
64
+ ```
65
+
66
+ If multiple source files map to the same milestone (e.g., multiple per-phase files for the same milestone), merge them into one target file: concatenate the `functional`, `non_functional`, and `deferred` arrays. Preserve all FR-IDs.
67
+
68
+ ### 4. Add the `milestone:` field
69
+
70
+ Each migrated file needs a top-level `milestone:` declaration matching the milestone ID in `state/index.yml`:
71
+
72
+ ```yaml
73
+ milestone: 53 # add this line at the top
74
+ version: "v1"
75
+ functional:
76
+ - id: FR-001
77
+ ...
78
+ ```
79
+
80
+ ### 5. Audit FR-ID uniqueness
81
+
82
+ FR-IDs (and DEF-IDs, NFR-IDs) are globally unique across all milestone files. Check for collisions:
83
+
84
+ ```bash
85
+ grep -h "^\s*- id: FR-" .forge/requirements/*.yml | sort | uniq -d
86
+ grep -h "^\s*- id: DEF-" .forge/requirements/*.yml | sort | uniq -d
87
+ grep -h "^\s*- id: NFR-" .forge/requirements/*.yml | sort | uniq -d
88
+ ```
89
+
90
+ If duplicates appear: keep the older milestone's ID, renumber the newer one to the next free integer across all files. Update any references in `.forge/phases/m{N}-*/plan-*.md` that cite the renumbered IDs.
91
+
92
+ ### 6. Update references in state files
93
+
94
+ State files may cite the old paths in `decisions`, `blockers`, or `quick_tasks_history`:
95
+
96
+ ```bash
97
+ grep -rn "requirements\.yml\|requirements-m" .forge/state/
98
+ ```
99
+
100
+ Replace each match with the new per-milestone path. State file content is human-readable YAML — straightforward find/replace.
101
+
102
+ ### 7. Verify roadmap coverage
103
+
104
+ `.forge/roadmap.yml` coverage check must now cover all milestone files. Every FR-ID across `.forge/requirements/*.yml` for active milestones should appear in exactly one phase. Run a planning skill pass to refresh the `coverage_verified` flag, or check manually.
105
+
106
+ ## Post-migration verification
107
+
108
+ After completing all steps:
109
+
110
+ ```bash
111
+ # Should be empty (no legacy paths left)
112
+ find .forge -type f \( -name "requirements.yml" -o -name "requirements-m*.yml" \) \
113
+ | grep -v "^.forge/requirements/" \
114
+ | grep -v "^.forge/templates/"
115
+
116
+ # Should list one file per active milestone
117
+ ls .forge/requirements/
118
+
119
+ # Should be empty (no duplicate FR-IDs)
120
+ grep -h "^\s*- id: FR-" .forge/requirements/*.yml | sort | uniq -d
121
+ ```
122
+
123
+ Commit the migration as a single change:
124
+
125
+ ```
126
+ refactor(requirements): migrate to per-milestone files (Forge 0.10.0)
127
+ ```
128
+
129
+ ## What changes downstream
130
+
131
+ After migration, all Forge skills read/write the new paths automatically:
132
+
133
+ - `planning` writes to `.forge/requirements/m{N}.yml` using the current milestone ID
134
+ - `verifying` and `discussing` read the same path
135
+ - `upgrading` protects the whole `.forge/requirements/` directory
136
+ - Top-level `.forge/requirements.yml` is deprecated — delete if a stale copy is recreated by any non-upgraded tool
137
+
138
+ ## Rollback
139
+
140
+ Migration is reversible by `git revert` of the migration commit (paths revert, content preserved). The 0.10.0 skills still understand the legacy paths only as deprecated targets — downgrading the framework alongside the revert is required if you need full pre-0.10.0 behavior.
@@ -23,7 +23,7 @@ Since the framework is unknown, use the `researching` skill to understand it:
23
23
  2. **Map the structure** — List all directories and key files
24
24
  3. **Classify content** — For each file, determine if it contains:
25
25
  - Project information (→ `.forge/project.yml`)
26
- - Requirements or specifications (→ `.forge/requirements.yml`)
26
+ - Requirements or specifications (→ `.forge/requirements/m1.yml`)
27
27
  - Plans or roadmaps (→ `.forge/roadmap.yml`)
28
28
  - State or progress tracking (→ `.forge/state/index.yml` + `.forge/state/milestone-{id}.yml`)
29
29
  - Decisions or constraints (→ `.forge/context.md`)
@@ -45,7 +45,7 @@ Since the framework is unknown, use the `researching` skill to understand it:
45
45
  - [ ] Framework structure mapped and understood
46
46
  - [ ] All content files classified by type
47
47
  - [ ] Project info extracted to `.forge/project.yml`
48
- - [ ] Requirements extracted to `.forge/requirements.yml`
48
+ - [ ] Requirements extracted to `.forge/requirements/m1.yml`
49
49
  - [ ] Governance rules mapped to `.forge/constitution.md`
50
50
  - [ ] Remaining knowledge captured in `.forge/context.md`
51
51
  - [ ] Original framework files archived in `.forge/archive/{name}/`
@@ -18,7 +18,7 @@ CONTEXT.md with "NON-NEGOTIABLE" or "DEFERRED" sections
18
18
  | GSD Source | Forge Target | Conversion Notes |
19
19
  |-----------|-------------|-----------------|
20
20
  | `PROJECT.md` | `.forge/project.yml` | Extract project name, description, tech stack, goals. Convert prose to YAML structure. |
21
- | `REQUIREMENTS.md` | `.forge/requirements.yml` | Assign FR-IDs to each requirement. Convert acceptance criteria to Given/When/Then. Mark unknowns as `[NEEDS CLARIFICATION]`. |
21
+ | `REQUIREMENTS.md` | `.forge/requirements/m1.yml` | Assign FR-IDs to each requirement. Convert acceptance criteria to Given/When/Then. Mark unknowns as `[NEEDS CLARIFICATION]`. |
22
22
  | `ROADMAP.md` | `.forge/roadmap.yml` | Extract phases, milestones. Add dependency references between phases. Convert to YAML. |
23
23
  | `STATE.md` | `.forge/state/index.yml` + `.forge/state/milestone-{id}.yml` | Extract current phase number, progress, active blockers, recent decisions. Split into global index and per-milestone state. |
24
24
  | `CONTEXT.md` | `.forge/context.md` | NON-NEGOTIABLE → Locked Decisions. DEFERRED → Deferred Ideas. DISCRETION → Discretion Areas. Minimal format change needed. |
@@ -159,7 +159,7 @@ Flag any discrepancies to the user. The codebase is the source of truth, not the
159
159
  - [ ] All GSD state files read and content extracted
160
160
  - [ ] **Documentation verified against actual codebase** (discrepancies flagged)
161
161
  - [ ] Project info converted to `.forge/project.yml`
162
- - [ ] Requirements converted to `.forge/requirements.yml` with IDs
162
+ - [ ] Requirements converted to `.forge/requirements/m1.yml` with IDs
163
163
  - [ ] Roadmap converted to `.forge/roadmap.yml`
164
164
  - [ ] Current state captured in `.forge/state/` (index.yml + milestone files, verified against code reality)
165
165
  - [ ] Context/decisions preserved in `.forge/context.md`
@@ -17,9 +17,9 @@ AGENTS.md # Agent definitions
17
17
  | Spec-Kit Source | Forge Target | Conversion Notes |
18
18
  |----------------|-------------|-----------------|
19
19
  | `spec-driven.md` | `.forge/constitution.md` | Extract governance rules. Map to Forge's 9 articles or create project-specific ones. |
20
- | `templates/spec-template.md` | `.forge/requirements.yml` | Convert spec structure to YAML requirements with IDs. |
20
+ | `templates/spec-template.md` | `.forge/requirements/m1.yml` | Convert spec structure to YAML requirements with IDs. |
21
21
  | `templates/constitution-template.md` | `.forge/constitution.md` | Merge with Forge's article template. Preserve project-specific gates. |
22
- | Filled-in specs (project-specific) | `.forge/project.yml` + `.forge/requirements.yml` | Extract project info and requirements separately. |
22
+ | Filled-in specs (project-specific) | `.forge/project.yml` + `.forge/requirements/m1.yml` | Extract project info and requirements separately. |
23
23
  | `extensions/` configs | `.claude/skills/` | Evaluate each extension. Create Forge skills for valuable ones. |
24
24
  | `AGENTS.md` | `.claude/agents/` | Map agent definitions to Forge's 5 agents. |
25
25
  | `templates/checklist-template.md` | Informs verification skill | Extract checklist patterns for verifier. |
@@ -29,7 +29,7 @@ AGENTS.md # Agent definitions
29
29
 
30
30
  - **Constitutional governance** — Spec-Kit's core strength. Directly maps to Forge's constitution.
31
31
  - **Template-driven behavior** — Forge uses templates similarly, just in YAML where machine-readable.
32
- - **Structured specs** — Maps to Forge's requirements.yml with Given/When/Then.
32
+ - **Structured specs** — Maps to Forge's `requirements/m{N}.yml` with Given/When/Then.
33
33
  - **`[NEEDS CLARIFICATION]` markers** — Identical concept in Forge.
34
34
 
35
35
  ## What's New (Not in Spec-Kit)
@@ -44,7 +44,7 @@ AGENTS.md # Agent definitions
44
44
  ## Absorption Checklist
45
45
 
46
46
  - [ ] Spec-driven governance rules extracted and mapped to constitution articles
47
- - [ ] Project specs converted to project.yml and requirements.yml
47
+ - [ ] Project specs converted to project.yml and `requirements/m1.yml`
48
48
  - [ ] Constitutional articles merged (Spec-Kit's + Forge's template)
49
49
  - [ ] Extensions evaluated for skill conversion
50
50
  - [ ] Agent definitions mapped to Forge's 5 agents
@@ -1,7 +1,10 @@
1
1
  # Forge Requirements Template
2
- # Copy to .forge/requirements.yml and customize. Keep under 50 KB.
2
+ # Copy to .forge/requirements/m{N}.yml (per-milestone) and customize. Keep each file under 50 KB.
3
+ # FR-IDs are globally unique across all milestone files — check existing requirements/*.yml
4
+ # for highest FR-ID and continue the sequence. Same applies to DEF-IDs and NFR-IDs.
3
5
  # Mark uncertain items with [NEEDS CLARIFICATION] — planning blocks until resolved.
4
6
 
7
+ milestone: 1 # Milestone this file belongs to (matches state/milestone-{id}.yml)
5
8
  version: "v1" # v1 = MVP, v2 = next iteration
6
9
 
7
10
  functional:
@@ -36,8 +36,8 @@ roadmap:
36
36
  estimated_hours: null
37
37
  status: pending
38
38
 
39
- # Coverage check: every FR-ID in requirements.yml must appear in exactly one phase.
40
- # Orphaned requirements = planning failure.
39
+ # Coverage check: every FR-ID across all `.forge/requirements/m{N}.yml` files for active
40
+ # milestones must appear in exactly one phase. Orphaned requirements = planning failure.
41
41
  coverage_verified: false
42
42
 
43
43
  # Wave analysis: phases with no dependencies can run in parallel (Wave 1).
@@ -67,7 +67,7 @@ Auto-detects complexity. Override: "Use Quick/Standard/Full tier."
67
67
  | Artifact | Max | Reason |
68
68
  |----------|-----|--------|
69
69
  | `project.yml` | 5 KB | Forces clarity |
70
- | `requirements.yml` | 50 KB | Prevents scope creep |
70
+ | `requirements/m{N}.yml` | 50 KB/file | Prevents scope creep |
71
71
  | `plan.md` | 30 KB | Keeps executor context <50% |
72
72
  | `constitution.md` | 10 KB | Gates must be scannable |
73
73
 
@@ -125,7 +125,7 @@ State lives in `.forge/`:
125
125
  - `project.yml` — Vision, stack, design system, verification, constraints (<5KB)
126
126
  - `constitution.md` — Active architectural gates
127
127
  - `design-system.md` — Component mapping table
128
- - `requirements.yml` — Structured requirements with `[NEEDS CLARIFICATION]` markers
128
+ - `requirements/m{N}.yml` — Per-milestone structured requirements with `[NEEDS CLARIFICATION]` markers. FR-IDs are globally unique across milestones (`FR-001` in `m1.yml` and `FR-042` in `m2.yml` don't collide). Concurrent milestones each own their file — no cross-stream contention.
129
129
  - `roadmap.yml` — Phases, milestones, dependencies
130
130
  - `state/index.yml` — Global: active milestones, desire_paths, metrics
131
131
  - `state/milestone-{id}.yml` — Per-milestone cursor: position, progress, decisions, blockers