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.
- package/bin/create-forge.js +61 -1
- package/package.json +1 -1
- package/template/.claude/agents/planner.md +1 -1
- package/template/.claude/agents/verifier.md +6 -1
- package/template/.claude/skills/discussing/SKILL.md +7 -2
- package/template/.claude/skills/executing/SKILL.md +18 -5
- package/template/.claude/skills/forge/SKILL.md +1 -1
- package/template/.claude/skills/initializing/SKILL.md +3 -3
- package/template/.claude/skills/planning/SKILL.md +10 -6
- package/template/.claude/skills/upgrading/SKILL.md +44 -1
- package/template/.claude/skills/verifying/SKILL.md +27 -2
- package/template/.forge/migrations/0.10.0-per-milestone-requirements.md +140 -0
- package/template/.forge/templates/framework-absorption/generic.md +2 -2
- package/template/.forge/templates/framework-absorption/gsd.md +2 -2
- package/template/.forge/templates/framework-absorption/spec-kit.md +4 -4
- package/template/.forge/templates/requirements.yml +4 -1
- package/template/.forge/templates/roadmap.yml +2 -2
- package/template/CLAUDE.md +2 -2
package/bin/create-forge.js
CHANGED
|
@@ -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
|
@@ -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
|
|
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
|
-
**
|
|
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.
|
|
120
|
-
- YES →
|
|
121
|
-
- NO
|
|
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**
|
|
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
|
-
[
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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).
|
package/template/CLAUDE.md
CHANGED
|
@@ -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` —
|
|
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
|