forge-orkes 0.25.0 → 0.28.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-orkes",
3
- "version": "0.25.0",
3
+ "version": "0.28.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"
@@ -355,7 +355,38 @@ User selects per stack.
355
355
  - `.forge/state/index.yml` — regenerate via the `forge` **Rollup** from the milestone file (do not hand-write the registry). It will derive `status: not_started` for milestone 1.
356
356
  - `.forge/state/desire-paths/` — create the (empty) directory for append-only observations.
357
357
  6. Templates as needed
358
- 7. **State-sync commit**: `git add .forge/` then `git commit -m "chore(forge): initialize forge state"` (scoped; never `git add .`) — so the new project's state is in git from the start.
358
+ 7. **Track Forge product files in `.gitignore`.** Forge installs into `.claude/` (skills, agents, hooks, `settings.json`) these are *product files*, not per-machine config, and **must be tracked in git** for two reasons: (a) `/forge` commands only exist in checkouts that have `.claude/skills/`, so a git worktree with `.claude/` fully ignored has no `/forge`; (b) M10 worktrees inherit hooks via tracked files (`.claude/hooks/*.sh`) an ignored `.claude/` silently disables them (see ADR-007 + ADR-010 "related concerns").
359
+
360
+ Detect the failure mode + apply the carve-out:
361
+
362
+ ```bash
363
+ if grep -qE '^[[:space:]]*\.claude/?[[:space:]]*$' .gitignore 2>/dev/null && \
364
+ ! grep -qE '^![[:space:]]*\.claude/(skills|agents|hooks)' .gitignore; then
365
+ echo "[Forge] .gitignore ignores .claude/ wholesale — Forge worktrees won't have /forge."
366
+ fi
367
+ ```
368
+
369
+ Then **replace** any bare `.claude/` rule (or **append** if no `.gitignore` exists) with the recommended carve-out:
370
+
371
+ ```gitignore
372
+ # Claude Code — track Forge product files, ignore per-machine + scratch
373
+ .claude/*
374
+ .claude/.DS_Store
375
+ !.claude/settings.json
376
+ !.claude/skills/
377
+ !.claude/agents/
378
+ !.claude/hooks/
379
+ !.claude/commands/
380
+ .claude/settings.local.json
381
+ .claude/projects/
382
+ .claude/worktrees/
383
+ ```
384
+
385
+ `settings.local.json` (per-machine permission allowlists), `projects/` (Claude Code conversation transcripts), and `worktrees/` (app-managed scratch) **must stay ignored** — they're private/per-machine, not product.
386
+
387
+ **Confirm with the user first** in brownfield (this edits a user-owned file). In greenfield with no existing `.gitignore`, write it directly. Re-run is idempotent — the carve-out lines `grep` to themselves.
388
+
389
+ 8. **State-sync commit**: `git add .gitignore .claude/settings.json .claude/skills/ .claude/agents/ .claude/hooks/ .forge/` then `git commit -m "chore(forge): initialize forge state + track product files"` (scoped; never `git add .`) — so the new project's state and Forge product files are both in git from the start.
359
390
 
360
391
  *"Initialized. Ready?"*
361
392
 
@@ -79,6 +79,7 @@ Tag every finding:
79
79
 
80
80
  For independent topics, research simultaneously:
81
81
  - Spawn separate research agents per topic with focused scope
82
+ - **Pass `model` param** from `project.yml` model routing (`models.skills.researching` → `models.default` → parent). Display: *"Spawning researchers with model: {model} (from {source})"*. Subagents don't inherit skill routing — without the param they run on the parent (often opus), defeating the cost intent.
82
83
  - Collect and synthesize results
83
84
 
84
85
  Never research sequentially when topics are independent.
@@ -350,7 +350,7 @@ Idempotent: a backlog with no terminal items and all-canonical statuses is left
350
350
 
351
351
  ### Route
352
352
 
353
- **HEALTHY/WARNINGS (accepted):** set `current.status: complete` in `milestone-{id}.yml`, then regenerate `index.yml` via the `forge` **Rollup** (do not hand-edit index). *"Milestone [{name}] complete. {N} backlog items."* Beads: `bd complete`.
353
+ **HEALTHY/WARNINGS (accepted):** set `current.status: complete` in `milestone-{id}.yml` (only after the Human Verification Gate in Phase Handoff is satisfied), then regenerate `index.yml` via the `forge` **Rollup** (do not hand-edit index). *"Milestone [{name}] complete. {N} backlog items."* Beads: `bd complete`.
354
354
 
355
355
  **CRITICAL:** Don't complete. A) Fix->`planning` fix mode->re-verify->re-review. B) Accept risk->doc in report->complete.
356
356
 
@@ -400,8 +400,9 @@ If the milestone's phases produced `contract.md` files (planning Step 6.1 Tier 1
400
400
  ## Phase Handoff
401
401
 
402
402
  1. Confirm report + backlog
403
- 2. **Run promoted-milestone completion hook** (above) if `milestone.origin` set
404
- 3. **Run Contract Landing** (above) for any cross-layer phases — fold ratified contracts into their ADRs
405
- 4. Set `current.status: complete` and `current.completed_at: "<ISO 8601 timestamp>"` in `milestone-{id}.yml`, then regenerate `index.yml` via the `forge` **Rollup**
406
- 5. **State-sync commit** (State Commit Protocol): `git add .forge/` then `git commit -m "chore(forge): sync state after reviewing — m{N} complete"` (scoped; never `git add .`).
407
- 6. *"Milestone [{name}] complete. Report: `.forge/audits/milestone-{id}-health-report.md`. {N} backlog items. `/forge` or backlog."*
403
+ 2. **Human Verification Gate (hard block)** — Read `current.human_verified` from `milestone-{id}.yml`. If **absent/null** → **do not complete the milestone.** Code-clean + review-clean is not enough to close (FORGE.md → Human Verification Gate). The milestone needs an explicit human sign-off, normally captured by `verifying`. Either route the user back to verify (then re-review) or capture the sign-off / recorded override here and write `current.human_verified` before proceeding. A recorded override (`method: override`) satisfies this check but **must** be surfaced in the health report. Never silently complete past an unset gate.
404
+ 3. **Run promoted-milestone completion hook** (above) if `milestone.origin` set
405
+ 4. **Run Contract Landing** (above) for any cross-layer phases fold ratified contracts into their ADRs
406
+ 5. Set `current.status: complete` and `current.completed_at: "<ISO 8601 timestamp>"` in `milestone-{id}.yml`, then regenerate `index.yml` via the `forge` **Rollup**
407
+ 6. **State-sync commit** (State Commit Protocol): `git add .forge/` then `git commit -m "chore(forge): sync state after reviewing — m{N} complete"` (scoped; never `git add .`).
408
+ 7. *"Milestone [{name}] complete. Report: `.forge/audits/milestone-{id}-health-report.md`. {N} backlog items. `/forge` or backlog."*
@@ -42,6 +42,7 @@ Read: .github/workflows/* → CI config (ci-check mode, analyst CI sub-check)
42
42
 
43
43
  1. Spawn tester agent via Agent tool, mode = `analyst`:
44
44
  - Pass: milestone id + name, scope paths, stack summary from project.yml
45
+ - **Pass `model` param** from `project.yml` model routing (`models.skills.testing` → `models.default` → parent). Display: *"Spawning tester (analyst) with model: {model} (from {source})"*
45
46
  - Agent scans test files, runs suite with traces/retries, greps anti-patterns
46
47
  2. Agent writes `.forge/testing/suite-health.md`:
47
48
  - **Coverage Gaps** — untested surfaces, missing layers
@@ -106,6 +107,7 @@ Refusal message wording is contract (NFR-009 requires story ID + exact missing f
106
107
  - If project has existing test runner, match it. Don't introduce a second.
107
108
  3. Spawn tester agent via Agent tool, mode = `author`:
108
109
  - Pass: milestone id + name, layer, runner, scope paths, stack summary
110
+ - **Pass `model` param** from `project.yml` model routing (`models.skills.testing` → `models.default` → parent). Display: *"Spawning tester (author) with model: {model} (from {source})"*
109
111
  - Agent scaffolds tests following baked flake-resistant rules (see tester.md)
110
112
  4. Agent commits atomically per executor conventions.
111
113
 
@@ -266,6 +266,47 @@ No-op guarantee: detection exits clean (no prompt) when the backlog is absent, u
266
266
 
267
267
  `upgrading` never edits the backlog directly — migration runs via `quick-tasking`.
268
268
 
269
+ ### Pre-0.28.0 fully-ignored `.claude/`
270
+
271
+ Run from project root:
272
+
273
+ ```bash
274
+ F=.gitignore
275
+ [ -f "$F" ] || exit 0
276
+ # bare ".claude/" or ".claude" rule (no negation lines un-ignoring product files)
277
+ if grep -qE '^[[:space:]]*\.claude/?[[:space:]]*$' "$F" \
278
+ && ! grep -qE '^![[:space:]]*\.claude/(skills|agents|hooks|settings\.json)' "$F"; then
279
+ echo "broad-ignore"
280
+ fi
281
+ ```
282
+
283
+ If the script prints `broad-ignore`, surface:
284
+
285
+ ```
286
+ .claude/ fully ignored — Forge worktrees + hooks silently break (Forge 0.28.0)
287
+ ─────────────────────────────────────────────────────────────────────────────
288
+ Your .gitignore ignores all of `.claude/` without a carve-out. That means:
289
+ • git worktrees (Forge or the app's) have no `.claude/skills/`, so `/forge`
290
+ is missing — typing `/forge` in a worktree prints "Unknown command".
291
+ • M10 worktrees come up with no hooks (forge-claim-check, branch-guard,
292
+ session-id) — coordination + ADR-008 protection are silently disabled.
293
+
294
+ These are PRODUCT files, not per-machine config. The fix is a narrow
295
+ carve-out: track skills/agents/hooks/settings.json; keep settings.local.json,
296
+ projects/, worktrees/ ignored.
297
+
298
+ A migration guide is available at: .forge/migrations/0.28.0-worktree-root.md
299
+ (canonical: https://github.com/Attuned-Media/forge/blob/main/docs/migrations/0.28.0-worktree-root.md)
300
+
301
+ Apply the carve-out now? (yes/no/show guide)
302
+ ```
303
+
304
+ - **yes** → invoke `quick-tasking` skill with the migration guide as the task (edit `.gitignore` in place, `git rm -r --cached .claude/` to clear the ignore-cache, stage `.gitignore` + the four product trees, commit `chore(forge): track .claude/ product files`). The skill MUST confirm with the user before staging anything outside the four product trees.
305
+ - **show guide** → read and display the file, then re-ask
306
+ - **no** → note in upgrade report. The framework keeps working in the main checkout but worktree-mode sessions (M10 / Claude Desktop folder-open) will be missing `/forge` and Forge hooks until migrated.
307
+
308
+ This is a Forge-product-tracking concern, not a state migration — `upgrading` never edits user `.gitignore` directly. Migration runs via `quick-tasking`.
309
+
269
310
  ### Future migrations
270
311
 
271
312
  Add new detection blocks here for each Forge version that changes file layout. Pattern:
@@ -236,6 +236,19 @@ Items that can't be verified automatically (visual appearance, real-time behavio
236
236
  3. [ ] External: Email sends correctly via SendGrid
237
237
  ```
238
238
 
239
+ ## Human Verification Gate (close precondition)
240
+
241
+ Code-level PASS is necessary but **not sufficient** to close a milestone. Before handing off, capture an explicit human sign-off — this is the hard gate that `reviewing`-complete and `orchestrating`-teardown both check (see FORGE.md → Human Verification Gate). It is a precondition, not a peer option: never present milestone close / teardown as an alternative to running this.
242
+
243
+ Run on a PASSED verdict (and after any **HUMAN VERIFICATION NEEDED** items are resolved):
244
+
245
+ 1. Surface what the human should confirm — the Observable Truths, any "Human Verification Items", and any milestone-specific manual check (device session, visual pass, real-device / e2e walk).
246
+ 2. Prompt explicitly: *"Code verification passed. Have you verified the work yourself (device session / visual / e2e walk)? This is required before the milestone can close. [verified | not yet | close without verifying]"*
247
+ 3. Record the response in `current.human_verified` in `.forge/state/milestone-{id}.yml`:
248
+ - **verified** → `{at: "<ISO 8601>", method: "<how they verified>", notes: "<optional>"}`
249
+ - **not yet** → leave `human_verified` unset. **Do NOT route to reviewing** — the milestone cannot close. Tell the human what's outstanding and stop. Re-run this gate after they've done it.
250
+ - **close without verifying** → recorded override: `{at: "<ISO 8601>", method: "override", override: true, reason: "<required free text>"}`. Note the override in the verification report. Satisfies the gate but is flagged downstream.
251
+
239
252
  ## Re-Verification Mode
240
253
 
241
254
  After gap closure:
@@ -289,9 +302,10 @@ Only suggest at 3+ occurrences. One-off issues are noise.
289
302
 
290
303
  After PASSED verdict:
291
304
 
292
- 1. **Persist** — Confirm verification report documented, desire-path files written to `.forge/state/desire-paths/`
293
- 2. **Update state** — Set `current.status` to `reviewing` in `.forge/state/milestone-{id}.yml`
294
- 3. **State-sync commit** (State Commit Protocol): `git add .forge/` then `git commit -m "chore(forge): sync state after verifying — m{N} {phase-name}"` (scoped; never `git add .`).
295
- 4. **Recommend clear:** *"State synced. `/clear` then `/forge` for reviewing."*
305
+ 1. **Human Verification Gate** — capture explicit sign-off and write `current.human_verified` (see "Human Verification Gate" above). If the human answers **not yet** → STOP here; do not advance to reviewing. The milestone stays open until sign-off (or a recorded override) exists.
306
+ 2. **Persist** — Confirm verification report documented, desire-path files written to `.forge/state/desire-paths/`
307
+ 3. **Update state** Set `current.status` to `reviewing` in `.forge/state/milestone-{id}.yml`
308
+ 4. **State-sync commit** (State Commit Protocol): `git add .forge/` then `git commit -m "chore(forge): sync state after verifying — m{N} {phase-name}"` (scoped; never `git add .`).
309
+ 5. **Recommend clear:** *"State synced. `/clear` then `/forge` for reviewing."*
296
310
 
297
311
  If GAPS found, route back to planning in gap-closure mode. Context clear applies after re-verified PASSED verdict.
@@ -51,8 +51,8 @@ Auto-detects complexity. Override: "Use Quick/Standard/Full tier."
51
51
  | Architectural decisions | `architecting` | Full |
52
52
  | Break work into tasks with gates | `planning` | Standard, Full |
53
53
  | Build with deviation rules + atomic commits | `executing` | All |
54
- | Prove work delivers on goals (+ M9 e2e validation gate when `e2e:true` stories present) | `verifying` | Standard, Full |
55
- | Audit health + catalog refactoring (+ M9 e2e soft-cap, orphan-test, flake-rate audits) | `reviewing` | Standard, Full |
54
+ | Prove work delivers on goals (+ M9 e2e validation gate when `e2e:true` stories present; captures the Human Verification Gate sign-off) | `verifying` | Standard, Full |
55
+ | Audit health + catalog refactoring (+ M9 e2e soft-cap, orphan-test, flake-rate audits; hard-blocks completion on the Human Verification Gate) | `reviewing` | Standard, Full |
56
56
  | Small scoped fix | `quick-tasking` | Quick |
57
57
  | UI with design system | `designing` | When UI |
58
58
  | Security review | `securing` | When auth/data/API |
@@ -102,6 +102,8 @@ models:
102
102
  **Precedence:** `skills.X` → `default` → parent model.
103
103
  **All advisory** — forge displays expected model at each transition, suggests `/model` on mismatch. Review gate logs model used. Cannot auto-switch.
104
104
 
105
+ **Subagent inheritance.** When a skill spawns subagents via the Agent tool (parallel research, fresh-context reviewers, executor fan-out, tester author/analyst, etc.), the skill MUST pass the resolved `model` param explicitly. Subagents do NOT inherit skill-level routing automatically — without the param they run on the parent session's model, defeating the routing intent. Resolve using the same precedence chain (`models.skills.{skill}` → `models.default` → parent) and surface it: *"Spawning {role} with model: {model} (from {source})"*.
106
+
105
107
  ## Agents
106
108
 
107
109
  | Agent | Role | Tools | When |
@@ -145,7 +147,7 @@ State lives in `.forge/`:
145
147
  **Milestones** group phases into concurrent streams. Own state file — no conflicts across sessions. Can be deferred (frozen in place) or archive-deleted.
146
148
  `index.yml status` gates routing: `not_started | active | deferred | complete`.
147
149
  **Format**: YAML for machine state, Markdown for human content.
148
- **`current.status` is authoritative.** Complete only at `current.status == complete`. 100% tasks ≠ done — still needs verifying + reviewing.
150
+ **`current.status` is authoritative.** Complete only at `current.status == complete`. 100% tasks ≠ done — still needs verifying + reviewing + a recorded human sign-off (`current.human_verified` — see Verification Gates → Human Verification Gate).
149
151
 
150
152
  ### State Commit Protocol
151
153
 
@@ -211,6 +213,16 @@ verification:
211
213
  - Empty commands = no gate (opt-out)
212
214
  - `verification.e2e_soft_cap` (default 10) — advisory cap on `e2e:true` stories per milestone surfaced by the `reviewing` skill. Soft — never blocks.
213
215
 
216
+ ### Human Verification Gate (close precondition)
217
+
218
+ **No milestone reaches `complete` and no orchestration worktree is torn down until a human has explicitly signed off** — recorded as `current.human_verified` in `milestone-{id}.yml`. Code-level verification (tests, lint, type-check, the 3-level goal-backward pass) is necessary but **never sufficient** to close a milestone. A human must confirm the work in whatever form fits the milestone — device session, visual check, e2e walk, smoke test ("of some sorts").
219
+
220
+ - **Captured** by `verifying` — after the verdict it prompts for explicit sign-off and writes `current.human_verified: {at, method, notes}`. If the human can't verify yet (e.g. a device session is still pending), the field stays unset and downstream close blocks.
221
+ - **Enforced (hard block)** at both close points — `reviewing` refuses to set `current.status: complete`, and `orchestrating` Step 5 refuses teardown, unless `current.human_verified` is present.
222
+ - **Recorded override** is the only bypass. A human may explicitly close without verifying, but the skill writes `human_verified: {method: override, override: true, reason}` and surfaces it in the report. Silent close is impossible — an agent must **never** present milestone close / orchestration teardown as a peer alternative to "do the verification". The verification is a precondition, not an option.
223
+
224
+ Lazy migration: milestones with no `human_verified` field (pre-0.27.0) simply hit the prompt on their next close transition; already-`complete` milestones are never re-gated.
225
+
214
226
  ## Beads Integration (Optional)
215
227
 
216
228
  With Beads installed: `bd prime` (session context), `bd ready` (unblocked tasks), `bd complete` (update deps), `bd compact` (summarize old). Without Beads, `.forge/state/` + Session Memory suffice.
@@ -0,0 +1,168 @@
1
+ # Migration Guide: Repo-scoped worktree root (Forge 0.28.0)
2
+
3
+ Applies to projects using M10 orchestration (experimental). Two related concerns ship under one version:
4
+
5
+ 1. **Worktree dir default changes** from a shared `../forge-worktrees/` to a per-repo `../<repo>-worktrees/` (see [ADR-010](../decisions/ADR-010-repo-scoped-worktree-root.md)). Live worktrees keep working; only new ones use the new default.
6
+ 2. **`.gitignore` carve-out for Forge product files** — repos that ignore `.claude/` wholesale silently break worktree mode (`/forge` is "Unknown command" inside any worktree). 0.28.0 ships detection + a guided fix.
7
+
8
+ If you don't use M10, the worktree-dir change has no effect. If your `.gitignore` is broadly ignoring `.claude/`, the second part still applies (the same gap also affects Claude Desktop's native worktree switcher).
9
+
10
+ ## Part 1 — Worktree dir default
11
+
12
+ ### What changed
13
+
14
+ Before:
15
+
16
+ ```bash
17
+ git worktree add ../forge-worktrees/${anchor} main # shared, cwd-resolved
18
+ ```
19
+
20
+ After:
21
+
22
+ ```bash
23
+ # orchestration.worktree_root from .forge/project.yml, default ../<repo>-worktrees
24
+ # Relative paths resolve against the REPO ROOT (not shell cwd). Absolute + leading ~ honored.
25
+ git worktree add ${wt_root}/${anchor} main
26
+ ```
27
+
28
+ The resolved absolute path is recorded in `lifecycle.worktree_path` and read verbatim by teardown + crash-recovery — so the config knob is forward-looking, not retroactive.
29
+
30
+ ### Detection
31
+
32
+ ```bash
33
+ # Are any of your active milestones pointing at the old shared dir?
34
+ grep -rE '^\s*worktree_path:.*forge-worktrees' .forge/state/ 2>/dev/null | head
35
+ ```
36
+
37
+ Matches = pre-0.28.0 worktrees still in flight. **Leave them alone** — they keep working off their recorded path. Only **new** worktrees pick up the new default.
38
+
39
+ ### Migration
40
+
41
+ **Do nothing.** This is a new-worktree-only change. Future orchestration runs in this repo will create their worktrees in `../<repo>-worktrees/<anchor>` instead of `../forge-worktrees/<anchor>`. Existing worktrees keep functioning; their `lifecycle.worktree_path` is honored.
42
+
43
+ ### Opting back into the old layout
44
+
45
+ If you want the old behavior (shared dir, e.g. because you've already got tooling pointed at `../forge-worktrees/`), set in `.forge/project.yml`:
46
+
47
+ ```yaml
48
+ orchestration:
49
+ worktree_root: "../forge-worktrees" # relative to repo root
50
+ ```
51
+
52
+ ### Other layout choices the new key enables
53
+
54
+ ```yaml
55
+ orchestration:
56
+ worktree_root: "~/.forge/worktrees/<this-repo>" # central home dir
57
+ # or
58
+ worktree_root: "../wt/<this-repo>" # shared dir, repo-namespaced subfolder
59
+ # or
60
+ worktree_root: "/abs/path/to/somewhere" # absolute
61
+ ```
62
+
63
+ **Do not** point this inside the working tree (e.g. `.worktrees/`) — file watchers, language-server indexers, test discovery, and bundlers commonly recurse into the second checkout regardless of `.gitignore`. ADR-010 has the longer analysis.
64
+
65
+ ### Relocating a live worktree (only if you really need to)
66
+
67
+ Use `git worktree move` — it updates the gitdir pointer. A bare `mv` leaves the pointer stale and the worktree unusable.
68
+
69
+ ```bash
70
+ # from the repo root
71
+ git worktree move ../forge-worktrees/m-9-abc12345 ../<repo>-worktrees/m-9-abc12345
72
+ # then update the recorded path in milestone state:
73
+ # .forge/state/milestone-9.yml → lifecycle.worktree_path
74
+ ```
75
+
76
+ Confirm the worktree opens cleanly (`cd <new-path> && git status`) before editing state. **Don't relocate a worktree that's an active orchestration run** without checking with the running session first — its claim state references that path.
77
+
78
+ ## Part 2 — `.gitignore` carve-out for Forge product files
79
+
80
+ ### Why this matters
81
+
82
+ Forge installs into `.claude/` (skills, agents, hooks, `settings.json`). Many Claude Code starters add `.claude/` to `.gitignore` wholesale. Consequences:
83
+
84
+ - **`/forge` is "Unknown command:" in any git worktree.** Worktrees only check out *tracked* files. With `.claude/` fully ignored, `.claude/skills/forge/` doesn't exist in worktrees, so the slash command isn't loaded. Same applies to Claude Desktop's native worktree switcher.
85
+ - **M10 worktrees come up with no hooks.** `forge-claim-check.sh`, `forge-branch-guard.sh`, `forge-session-id.sh` all live in `.claude/hooks/` — ignored = absent = silently disabled. ADR-007 / ADR-008 protection are off.
86
+
87
+ The fix: track product files, keep per-machine/scratch files ignored.
88
+
89
+ ### Detection
90
+
91
+ `upgrading` runs this automatically; you can run it by hand too:
92
+
93
+ ```bash
94
+ F=.gitignore
95
+ [ -f "$F" ] || exit 0
96
+ if grep -qE '^[[:space:]]*\.claude/?[[:space:]]*$' "$F" \
97
+ && ! grep -qE '^![[:space:]]*\.claude/(skills|agents|hooks|settings\.json)' "$F"; then
98
+ echo "broad-ignore — apply the carve-out below"
99
+ fi
100
+ ```
101
+
102
+ ### Migration
103
+
104
+ Replace any bare `.claude/` rule with this carve-out:
105
+
106
+ ```gitignore
107
+ # Claude Code — track Forge product files, ignore per-machine + scratch
108
+ .claude/*
109
+ .claude/.DS_Store
110
+ !.claude/settings.json
111
+ !.claude/skills/
112
+ !.claude/agents/
113
+ !.claude/hooks/
114
+ !.claude/commands/
115
+ .claude/settings.local.json
116
+ .claude/projects/
117
+ .claude/worktrees/
118
+ ```
119
+
120
+ Then refresh git's view of the directory:
121
+
122
+ ```bash
123
+ git rm -r --cached .claude/ 2>/dev/null # drop the wholesale-ignored cache
124
+ git status .claude/ # eyeball what's now untracked
125
+
126
+ # Stage only the four product trees — explicitly, never `git add .claude/`
127
+ git add .gitignore \
128
+ .claude/settings.json \
129
+ .claude/skills/ \
130
+ .claude/agents/ \
131
+ .claude/hooks/
132
+
133
+ # Sanity check — no per-machine files snuck in
134
+ git status # settings.local.json, projects/, worktrees/ should still be untracked-and-ignored
135
+ git diff --cached --stat | head
136
+
137
+ git commit -m "chore(forge): track .claude/ product files (skills, agents, hooks, settings)"
138
+ ```
139
+
140
+ After the commit lands on `main`, every **new** worktree (Forge's or the app's) inherits `/forge` and the hooks. Existing worktrees will see them on their next pull/rebase.
141
+
142
+ ### What stays ignored, and why
143
+
144
+ | Path | Why it stays ignored |
145
+ |---|---|
146
+ | `.claude/settings.local.json` | Per-machine permission allowlists. Build-specific. |
147
+ | `.claude/projects/` | Claude Code conversation transcripts — privacy + repo bloat. |
148
+ | `.claude/worktrees/` | App-managed scratch worktrees — per-machine ephemera. |
149
+ | `.claude/.DS_Store` | macOS metadata. |
150
+ | (project-local) `.mcp.json` if you already ignore it | Per-machine MCP wiring. |
151
+
152
+ ### One-shot vs guided
153
+
154
+ `upgrading` detects this pattern and offers a `quick-tasking` migration that applies the change above for you. Either path works — by-hand is fine if you want to eyeball each step. The migration is **never auto-applied**; `.gitignore` is user-owned.
155
+
156
+ ## Validation
157
+
158
+ After the worktree-root change ships and you've reopened a session:
159
+
160
+ - `cat .forge/project.yml` includes the `orchestration:` block (uncomment `worktree_root` only if you want a non-default value).
161
+ - Run an M10 milestone — confirm the new worktree appears at `../<your-repo>-worktrees/m-{id}-{session_id}/`.
162
+ - `cat .forge/state/milestone-{id}.yml | grep worktree_path` shows an **absolute** path, not the relative input.
163
+
164
+ After the gitignore migration:
165
+
166
+ - `git ls-files .claude/skills/forge/SKILL.md` returns the file.
167
+ - Open or create a worktree, `cd` into it, run `/forge` — the command exists.
168
+ - (If M10) Open a new orchestrating session in the worktree — `.session-id` is written, hooks fire.
@@ -91,6 +91,16 @@ models:
91
91
  debugging: sonnet # Investigation needs solid reasoning
92
92
  discussing: sonnet # Conversation needs natural fluency
93
93
 
94
+ orchestration: # M10 multi-agent orchestration (experimental). Only consulted when M10 is installed.
95
+ # auto: true # false = never auto-route Standard/Full through orchestrating (install = consent; set false to opt out).
96
+ # worktree_root: "../<repo>-worktrees" # Where Forge worktrees live. Default: ../<repo-basename>-worktrees (per-repo sibling — see ADR-010).
97
+ # Relative paths resolve against the REPO ROOT (not shell cwd). Absolute paths and a leading ~ are honored.
98
+ # Editing only affects newly created worktrees; live worktrees keep their recorded lifecycle.worktree_path.
99
+ # Common overrides:
100
+ # ~/.forge/worktrees/<repo> — central home dir, keeps the parent dir of the repo clutter-free
101
+ # ../wt/<repo> — shared dir with per-repo subfolder
102
+ # Do NOT point this inside the repo working tree (file watchers + indexers will recurse into the worktree).
103
+
94
104
  risks: # What could go wrong?
95
105
  - risk: ""
96
106
  mitigation: ""
@@ -22,6 +22,21 @@ current:
22
22
  status: not_started # not_started | researching | discussing | planning | executing | verifying | reviewing | complete
23
23
  completed_at: null # ISO 8601 timestamp — set when status transitions to complete
24
24
  last_updated: null # ISO 8601 — set at each transition; rolled up into index.yml registry for resume ordering
25
+ human_verified: null # Human Verification Gate record — REQUIRED before status can become `complete`
26
+ # or an orchestration worktree can be torn down (FORGE.md → Human Verification Gate).
27
+ # Code-level PASS is necessary but never sufficient. Set by the `verifying` skill
28
+ # when a human signs off (device session, visual check, e2e walk — form is open).
29
+ # Shape when set:
30
+ # human_verified:
31
+ # at: "<ISO 8601>" # when the human confirmed
32
+ # method: "device-session" # free text: how they verified
33
+ # notes: "" # optional free text
34
+ # Recorded-override escape hatch (satisfies the gate, but flagged downstream):
35
+ # human_verified:
36
+ # at: "<ISO 8601>"
37
+ # method: "override"
38
+ # override: true
39
+ # reason: "headless milestone — no human-observable surface"
25
40
 
26
41
  # NO stored progress block. Progress percent is DERIVED on read, never stored.
27
42
  # The forge skill computes it from genuinely-maintained signals: