forge-orkes 0.32.0 → 0.34.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.
@@ -37,6 +37,16 @@ const FRAMEWORK_OWNED_DIRS = ['.claude/agents', '.claude/skills'];
37
37
  // Experimental / opt-in skills installed separately (e.g. from experimental/m10).
38
38
  // They are NOT in the shipped base template, so the framework-owned auto-clean
39
39
  // would otherwise delete them on upgrade. Preserve them instead.
40
+ //
41
+ // The npm tarball ships only bin/ + template/ — NOT experimental/ — so this route
42
+ // cannot diff or re-sync an experimental skill against its source. Preserving
43
+ // blindly is what silently froze them pre-0.33.0 (issue #5): a base migration that
44
+ // changed experimental-skill behavior became a no-op. The structural fix lives
45
+ // elsewhere — (a) the clone-based `upgrading` skill (Step 3b) offers a real
46
+ // re-sync against experimental/*/source, and (b) load-bearing conventions are
47
+ // promoted to base (FORGE.md) so they no longer depend on the frozen skill. Here
48
+ // we can only PRESERVE + flag, so the report below tells the user staleness was
49
+ // not checked and how to refresh.
40
50
  const EXPERIMENTAL_SKILL_PATHS = ['.claude/skills/orchestrating'];
41
51
 
42
52
  function isExperimentalSkillPath(displayPath) {
@@ -623,8 +633,17 @@ async function upgrade() {
623
633
  if (results.preserved.length > 0) {
624
634
  console.log(` Preserved (${results.preserved.length}):`);
625
635
  for (const f of results.preserved) {
626
- console.log(` ${f} (kept — opt-in experimental skill)`);
636
+ console.log(` ${f} (kept — opt-in experimental skill; staleness not checked by npm)`);
627
637
  }
638
+ console.log(
639
+ ` ↳ The npm upgrade does not ship experimental sources, so it cannot`
640
+ );
641
+ console.log(
642
+ ` re-sync these. To refresh against a Forge clone, run the \`upgrading\``
643
+ );
644
+ console.log(
645
+ ` skill (offers a re-sync), or re-run \`experimental/<pkg>/install.sh\`.`
646
+ );
628
647
  console.log();
629
648
  }
630
649
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-orkes",
3
- "version": "0.32.0",
3
+ "version": "0.34.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"
@@ -56,17 +56,55 @@ packages, plans, verification reports, commits, and archived artifacts.
56
56
 
57
57
  | Intent | Examples | Action |
58
58
  |--------|----------|--------|
59
- | Show | "show streams", "active streams", "what is running?" | Summarize registry without loading all deep history |
59
+ | Show | "show streams", "active streams", "what is running?" | Run Registry Drift Check, then summarize registry without loading all deep history |
60
60
  | Start | "start stream X", "new stream for billing" | Snapshot current stream, create stream files, register stream |
61
61
  | Pause | "pause stream X" | Update brief, mark paused, keep next action explicit |
62
62
  | Resume | "resume stream X" | Load stream context, set active, surface blockers and ownership |
63
63
  | Delegate | "delegate stream X", "farm this out" | Create or update a work package and handoff prompt |
64
64
  | Adopt M10 | "adopt existing M10 worktrees", "migrate active orchestrating sessions" | Wrap live M10 worktrees as streams without teardown |
65
- | Sync | "sync streams" | Refresh registry summaries from active stream briefs |
65
+ | Sync | "sync streams" | Run Registry Drift Check, then refresh registry summaries from active stream briefs |
66
66
  | Detect Conflicts | "detect conflicts", "check stream conflicts" | Compare ownership and dependencies |
67
67
  | Merge Safe | "merge safe?", "what can land?" | Identify ready streams with no blocking conflicts |
68
68
  | Close | "close stream X" | Record final status, archive/mark closed, clear active pointer if needed |
69
69
 
70
+ ## Registry Drift Check
71
+
72
+ Forge keeps two registries that both describe "what work is active," with no
73
+ automatic reconciliation: `.forge/state/index.yml` (milestones, owned by the
74
+ `forge` skill) and `.forge/streams/active.yml` (streams, owned by the Chief).
75
+ `/forge` and `/chief-of-staff` can therefore present different pictures of the
76
+ project. Run this check at the **start of the Show and Sync intents** so the
77
+ divergence is surfaced instead of silently left to the operator.
78
+
79
+ This is **advisory — it never blocks, never auto-creates a milestone, and never
80
+ auto-writes a stream.** It reports, and offers.
81
+
82
+ 1. Read active milestones from `.forge/state/index.yml` (those with
83
+ `status: active`). If the file is absent, skip the check silently — a
84
+ streams-only project has nothing to reconcile.
85
+ - Note: invoking `/chief-of-staff` directly bypasses `forge`'s boot preflight,
86
+ so `index.yml` may be stale (it is regenerated by `forge`'s Rollup, not by
87
+ the Chief). Read it as-is; do not run Rollup from the Chief. If it looks
88
+ stale, say so and suggest a `/forge` pass.
89
+ 2. Read the stream registry from `.forge/streams/active.yml`.
90
+ 3. Map each active milestone to a stream by id, trying these forms in order:
91
+ `m-{id}`, `milestone-{id}`, bare `{id}`, and any stream whose
92
+ `context.milestone` points at `.forge/state/milestone-{id}.yml`.
93
+ 4. Report each mismatch:
94
+ - **Active milestone with no stream** → offer to add it as a `paused` stream
95
+ (do not create it automatically). Quick-fix milestones legitimately may not
96
+ warrant a stream — let the operator decide.
97
+ - **Stream pointing at a `deferred`, `complete`, or absent milestone** → the
98
+ stream's status should follow its milestone; offer to update it (pause a
99
+ stream whose milestone deferred, close one whose milestone completed).
100
+ - **Stream with no milestone counterpart** → informational only. Quick-fix
101
+ streams are valid; never auto-create a milestone for them.
102
+ 5. If everything maps cleanly, say so in one line (`registries aligned`) and
103
+ continue to the intent.
104
+
105
+ Keep the output compact — a few lines under a `Registry drift:` header, then
106
+ proceed with the requested Show/Sync.
107
+
70
108
  ## Start Stream Flow
71
109
 
72
110
  1. Read the registry.
@@ -119,7 +157,12 @@ existing M10 state.
119
157
  6. Populate the stream file:
120
158
  - `stream.id`, `goal`, `status`, `tier`
121
159
  - `runtime.branch` from `lifecycle.worktree_branch`
122
- - `runtime.worktree` from `lifecycle.worktree_path`
160
+ - `runtime.worktree` from `lifecycle.worktree_path`. **If no path was
161
+ recorded** (a manual `git worktree add`, or pre-convention state), resolve
162
+ it from the base **Worktree Convention** in `FORGE.md` —
163
+ `{orchestration.worktree_root or ../<repo>-worktrees}/{anchor}` — rather
164
+ than assuming the experimental `orchestrating` skill's internal default.
165
+ Confirm the resolved path with `git worktree list` before recording it.
123
166
  - `runtime.worker_sessions` with the M10 session / claim ids
124
167
  - `ownership.owned_surfaces`, `shared_surfaces`, and `read_only_surfaces`
125
168
  as empty lists if unknown
@@ -28,8 +28,8 @@ git worktree list --porcelain 2>/dev/null \
28
28
  ```
29
29
 
30
30
  **If `in_main_checkout: true`** AND any Forge worktrees are reported:
31
- - Surface them at the top of the boot output, one line each: *"m{id} is live in worktree `{path}` on branch `{branch}`. Edits to its milestone state belong there; shared-doc edits here (`context.md`, `refactor-backlog.yml`) won't be visible to it until it rebases or pulls."*
32
- - This is informational `forge` continues to Rollup + selection. The operator now knows. (See FORGE.md State Ownership for the full taxonomy.)
31
+ - Surface them at the top of the boot output, one line each: *"m{id} is live in worktree `{path}` on branch `{branch}`. Its milestone state is **owned there** — selecting it from main triggers the Live-Worktree Ownership Gate (1.1a). Shared-doc edits here (`context.md`, `refactor-backlog.yml`) won't be visible to it until it rebases or pulls."*
32
+ - Surfacing continues to Rollup + selection — but it is **no longer purely informational**. Enforcement is deferred to **1.1a**, which fires only for the *selected* milestone (booting from main to work an unrelated milestone stays free). Record which worktrees were reported here so 1.1a can match the selection against them. (See FORGE.md State Ownership for the full taxonomy.)
33
33
 
34
34
  **If `in_main_checkout: false`** (this session is itself a worktree) AND `forge.worktree_rebase_check: true` in `.forge/project.yml` (default `false` — opt-in):
35
35
  - Diff `.forge/` between this worktree's `HEAD` and `origin/main` (or `main` if no remote), restricted to the **shared-mutable** + **stable-shared** files per the FORGE.md taxonomy (`context.md`, `refactor-backlog.yml`, `project.yml`, `constitution.md`, `design-system.md`, `roadmap.yml`, `requirements/m{N}.yml`).
@@ -74,7 +74,7 @@ Check state files:
74
74
  4. **Multiple (no arg, no anchor):** Show active + not_started milestones with status + `last_updated`. Default most recent. After main list, show **Deferred:** section (id, name, frozen status `was: {current.status}`, defer date, reason). *"{N} active. Most recent: [{name}] ({current.status}, {date}). This one, or switch?"*
75
75
  5. **One:** Auto-select. *"Resuming: [{name}] -- {current.status}, {percent}%"*
76
76
  6. **None active:** If deferred exist, mention them: *"No active milestones. {N} deferred — 'resume milestone {id}' to reactivate."* Else → init or create.
77
- 7. Load `milestone-{id}.yml`
77
+ 7. Load `milestone-{id}.yml`, then run the **Live-Worktree Ownership Gate (1.1a)** — it can block routing before any milestone-owned write.
78
78
  8. **Route on `current.status`, NOT `{percent}`.** Complete only at `complete`. 100% phases ≠ done -- verifying + reviewing must run.
79
79
  9. Report + **immediately route** (Step 3). Show: `current.status`, phase labels (Executed/Verified/Pending/In progress -- **never "Complete" for unverified**), `{percent}`. **No menus.** Position → action → invoke.
80
80
 
@@ -89,6 +89,35 @@ Beads enabled (`forge.beads_integration: true`) → `bd prime`. Optional.
89
89
 
90
90
  Read `.forge/context.md`. **Needs Resolution** unchecked → warn: *"{N} unresolved discrepancies."* Quick proceeds; Standard/Full blocked at planning.
91
91
 
92
+ ### 1.1a Live-Worktree Ownership Gate (enforced)
93
+
94
+ Single-owner-mutable state must be written by exactly one checkout. When this session is on **main** and the **selected** milestone has a **live worktree**, writing its state from here forks the cursor — main records one `current.status`, the worktree another, and a later resume anchored to the worktree silently contradicts main's claim. FORGE.md State Ownership forbids this; this gate is where the entrypoint **enforces** it, before routing to any skill that writes milestone-owned files. (See FORGE.md → State Ownership.)
95
+
96
+ **Trigger.** `in_main_checkout: true` (from the Step 1 preflight) **AND** the selected milestone has a live worktree — any of:
97
+ - the preflight's `git worktree list` reported a `forge/m-{id}-*` / `forge/{id}` branch for this milestone; or
98
+ - `milestone-{id}.yml` `lifecycle.worktree_mode` is `active` or `degraded` and a `lifecycle.worktree_path` is recorded; or
99
+ - `.forge/streams/active.yml` shows a stream for this milestone with a `runtime.worktree`.
100
+
101
+ Resolve the worktree path from the recorded `lifecycle.worktree_path` / `runtime.worktree`, or — if absent — from the base **Worktree Convention** (FORGE.md).
102
+
103
+ **When it does NOT trigger** (no-op — continue to routing): no live worktree for the selected milestone; or this session **is** the owning worktree (`in_main_checkout: false` and the branch anchors to this milestone); or the milestone has a recorded, still-current `lifecycle.ownership_override` (see option 4).
104
+
105
+ **When it triggers — STOP. Do not route** to `planning`, `executing`, `verifying`, `reviewing`, `quick-tasking` against this milestone, and do not write any of:
106
+ - `.forge/state/milestone-{id}.yml`
107
+ - `.forge/phases/milestone-{id}/`
108
+ - `.forge/research/milestone-{id}.md`
109
+
110
+ Present the four resolutions and wait for an explicit choice:
111
+
112
+ 1. **Enter the worktree** *(recommended)* — print the exact command (`cd {worktree_path}` then `/forge`); re-running there anchors to this milestone and writes land in the owner. This session does nothing further to the milestone.
113
+ 2. **Sync, then continue in the worktree** — bring main's commits in (`git -C {worktree_path} rebase main`, or merge), then work from the worktree. Use when main has changes the worktree needs first.
114
+ 3. **Retire the worktree** — only if it is dead/superseded. Close the stream, `git worktree remove {worktree_path}`, and clear `lifecycle.worktree_*` on the milestone — which ends its ownership so main may write. **Confirm before removing; never auto-remove a worktree.**
115
+ 4. **Recorded override** — deliberately write from main anyway. Write `lifecycle.ownership_override: {at: {ISO}, from: main, reason: "{operator's reason}"}` into `milestone-{id}.yml`, echo it in the boot line, and carry it into the next `reviewing` report. This is the **only** way past the block and it is **never silent**. (An override is scoped to this milestone; clear it once the worktree is retired or synced.)
116
+
117
+ **Shared project docs** (`context.md`, `refactor-backlog.yml`, `project.yml`, `constitution.md`, `roadmap.yml`, `requirements/m{N}.yml`) stay writable from main even when the gate is up — but warn they won't be visible to the live worktree until it pulls/rebases (same note as the preflight).
118
+
119
+ An agent must never present "override" as a peer default. Lead with option 1; reach for 4 only on the operator's explicit instruction with a reason.
120
+
92
121
  ### 1.2 Backlog + Desire Paths
93
122
 
94
123
  Check `.forge/refactor-backlog.yml`:
@@ -43,7 +43,7 @@ Read the source version (`{source}/packages/create-forge/package.json` `version`
43
43
 
44
44
  **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`.
45
45
 
46
- **Preserve experimental skills.** Opt-in skills installed separately (e.g. `.claude/skills/orchestrating/` from `experimental/m10/`) are not in the base template. Never flag them as "removed from template" or delete them leave them untouched.
46
+ **Experimental skills — re-sync, don't blanket-skip.** Opt-in skills installed separately (e.g. `.claude/skills/orchestrating/` from `experimental/m10/`) are not in the base template, so they never appear in the Step 3 base sync. Earlier guidance was to leave them *untouched* — but that silently froze them at install-time content, so a base-template migration that changes behavior living only in an experimental skill became a no-op (the version stamp advanced and the migration doc shipped, yet the behavior never landed — e.g. the 0.28.0 repo-scoped worktree root). Step 3b now gives experimental skills their own **detect-and-offer-re-sync** pass against their `experimental/*/source/` origin. Never auto-overwrite and never flag them "removed from template" but never leave staleness invisible either.
47
47
 
48
48
  ## Step 3: Sync Framework-Owned Files
49
49
 
@@ -53,7 +53,31 @@ For each framework-owned file in the source template:
53
53
  2. Different → overwrite local, report **updated**
54
54
  3. Same → report **unchanged**
55
55
  4. Source has new file → copy, report **added**
56
- 5. Local has file not in source → report **removed from template** (don't delete -- let user decide)
56
+ 5. Local has file not in source → it may be an **experimental** skill — defer the verdict to Step 3b, which distinguishes "experimental, has a known source" from "genuinely removed from template." Only skills with no experimental source are reported **removed from template** (don't delete -- let user decide).
57
+
58
+ ## Step 3b: Re-sync Experimental Skills (detect + offer, never blanket-skip)
59
+
60
+ Experimental skills are installed from `{source}/packages/create-forge/experimental/<pkg>/source/skills/<name>/`, not the base template — so Step 3 never sees them. Without this pass they freeze at install-time content forever (issue #5). This pass makes staleness **visible and one-click-fixable** while staying non-destructive.
61
+
62
+ For each skill dir present in the project's `.claude/skills/` but **absent from the base template**:
63
+
64
+ 1. Search the source for a matching experimental origin: `{source}/packages/create-forge/experimental/*/source/skills/<name>/`.
65
+ 2. **No match** → genuinely local / removed-from-template. Report **removed from template** (don't delete) as before. Done.
66
+ 3. **Match found** → it is an experimental skill with a known upstream. Diff each markdown file in the installed dir against the source dir (`SKILL.md` and any siblings, e.g. `bootstrap-checks.md`):
67
+ - **All identical** → report `{name}: experimental, unchanged`.
68
+ - **Differs** → report `{name}: experimental, STALE (pinned at install; source has changes)` and **offer** a re-sync with the same preview/confirm UX as base skills:
69
+
70
+ ```
71
+ {name} is an experimental skill (from experimental/{pkg}/) pinned at install time.
72
+ The release ships newer content. Files that differ: {list}.
73
+ Re-sync from experimental/{pkg}/source? (yes / show diff / no)
74
+ ```
75
+
76
+ - **yes** → overwrite the installed skill's markdown files from source; report **updated (experimental)**.
77
+ - **show diff** → display the diff(s), then re-ask.
78
+ - **no** → leave untouched; note in the report that it stays pinned.
79
+
80
+ **Default is non-destructive** — never overwrite an experimental skill without an explicit `yes`. **Scope:** this pass re-syncs the skill's **markdown** (the behavior-bearing prose). It does **not** touch the experimental package's hooks, MCP server, or `settings.json`/`.mcp.json` wiring — those are owned by the package's own installer. When a re-sync lands, add one line: *"Hooks / MCP server for {pkg} are not re-synced here — re-run `experimental/{pkg}/install.sh` if the release changed them."*
57
81
 
58
82
  ## Step 4: Sync Template-Only Files
59
83
 
@@ -97,6 +121,10 @@ Added: {N} files
97
121
  - .claude/skills/new-skill/SKILL.md
98
122
  - ...
99
123
 
124
+ Experimental skills: {N}
125
+ - orchestrating (from experimental/m10) — updated [or: unchanged / STALE, declined]
126
+ - ...
127
+
100
128
  Removed from template: {N} files
101
129
  - .claude/agents/old-agent.md (still in your project)
102
130
  - ...
@@ -37,6 +37,21 @@ Forge has three runtime coordination layers: Project, Stream, and Work Package.
37
37
 
38
38
  Use ordinary Quick/Standard/Full tiers inside a stream. Use Project Chief / Chief of Staff when coordinating multiple active streams or pivoting without dropping context. Workers never coordinate laterally; they report to the stream or project chief. M10 worktrees remain an optional backend for isolation/merge discipline, not the primary UX.
39
39
 
40
+ ### Worktree Convention (base)
41
+
42
+ Worktrees are a **base concern** — Chief/Streams creates and references them with plain `git worktree`, independent of the experimental `orchestrating` skill. This convention is the single source of truth for *where worktrees live and what they're named*, so it lives here in base (not buried in an experimental skill) and stays upgrade-synced for every install (see [ADR-010](../docs/decisions/ADR-010-repo-scoped-worktree-root.md)).
43
+
44
+ | Element | Convention |
45
+ |---|---|
46
+ | **Root** | `orchestration.worktree_root` from `project.yml`; if unset, default `../<repo-basename>-worktrees/`. Relative paths resolve against the **repo root** (not shell cwd); absolute and leading-`~` paths are honored verbatim. Per-repo sibling dirs keep each repo's worktrees from pooling into one shared dir. |
47
+ | **Anchor** | `{milestone-id}-{session}` (e.g. `m-9-a1b2c3d4`). For a manual stream worktree with no session, the milestone/stream id alone is acceptable (`m-PLUG01`). |
48
+ | **Path** | `{worktree_root}/{anchor}` — the resolved **absolute** path. |
49
+ | **Branch** | `forge/{anchor}`. |
50
+
51
+ **Recorded path is authoritative once set.** When a worktree is created through `orchestrating`, the resolved absolute path is recorded in `lifecycle.worktree_path` (in `state/milestone-{id}.yml`) or in a stream's `runtime.worktree`, and every later operation reads it verbatim — never re-derives. Changing `orchestration.worktree_root` later only affects **new** worktrees; live ones keep working off their recorded path. Move a live worktree only with `git worktree move` (a bare `mv` strips the gitdir pointer), then update the recorded path.
52
+
53
+ **Fallback when no path was recorded.** A worktree created outside `orchestrating` (a manual `git worktree add`, an adopted stream) may have no recorded path. Resolve it from this convention — `{worktree_root}/{anchor}` — rather than assuming the experimental skill's internal default. Chief/Streams uses this fallback; `orchestrating` (when installed) implements the same scheme for the worktrees it creates.
54
+
40
55
  ## Workflow Tiers
41
56
 
42
57
  Auto-detects complexity. Override: "Use Quick/Standard/Full tier."
@@ -217,14 +232,18 @@ with the work it describes. Every artifact has a sharing class:
217
232
  | **Stable shared** | `project.yml`, `constitution.md`, `design-system.md`, `roadmap.yml`, `FORGE.md` | Rarely changes after init. Canonical on main. Worktrees lag and pull on rebase. No special protocol — git handles it because the conflict surface is tiny. |
218
233
 
219
234
  Cross-tree edits land on the current branch and are invisible to other worktrees
220
- until they pull/rebase. `forge` surfaces live worktrees at boot; `discussing`
221
- and `reviewing` warn before touching shared-mutable blocks; optional
222
- `forge.worktree_rebase_check` detects stale shared files inside worktrees. See
235
+ until they pull/rebase. `forge` surfaces live worktrees at boot **and enforces
236
+ the Live-Worktree Ownership Gate** (forge SKILL 1.1a): when invoked from main for
237
+ a milestone that has a live worktree, milestone-owned writes are **blocked**
238
+ until the operator enters the worktree, syncs it, retires it, or records an
239
+ explicit `lifecycle.ownership_override`. `discussing` and `reviewing` warn before
240
+ touching shared-mutable blocks; optional `forge.worktree_rebase_check` detects
241
+ stale shared files inside worktrees. See
223
242
  [ADR-011](../docs/decisions/ADR-011-shared-state-taxonomy.md) for rationale.
224
243
 
225
244
  ### State Ownership rules (quick reference)
226
245
 
227
- - `state/milestone-{id}.yml` is the **single source of truth**; exactly one agent owns it at a time. **Other worktrees never write it** — promoted from advice to explicit rule, because catching yourself before the first wrong edit is the part the framework can help with.
246
+ - `state/milestone-{id}.yml` is the **single source of truth**; exactly one agent owns it at a time. **Other worktrees never write it** — and from a main checkout this is **enforced**, not just advised: the Live-Worktree Ownership Gate (forge SKILL 1.1a) blocks milestone-owned writes from main while a live worktree owns the milestone, with a recorded `lifecycle.ownership_override` as the only (never-silent) bypass.
228
247
  - Worktree / parallel agents write **only** their own milestone file and **append** desire-path files. They **never** write `index.yml`.
229
248
  - `index.yml` is **regenerated by rollup** (read every `milestone-*.yml` → rewrite the registry) by the main/orchestrator session — on `forge` resume and at `orchestrating` teardown. The rollup is deterministic + idempotent, so it **is** the reconcile step — never a hand-merge.
230
249
  - For shared-mutable files: write only your milestone's block; within a block, append-only (strike through, don't rewrite).
@@ -0,0 +1,64 @@
1
+ # Migration Guide: Chief Front Door (Forge 0.32.1)
2
+
3
+ Forge 0.32.0 introduced Project Chief / Streams and could adopt active M10
4
+ worktrees as streams, but the migration guide only asked whether to set
5
+ `orchestration.auto: false`. If that decision was skipped, a project could have
6
+ adopted streams while legacy M10 auto-routing still acted as the default front
7
+ door.
8
+
9
+ This migration detects that ambiguous state and asks the operator to choose.
10
+
11
+ ## Detection
12
+
13
+ Prints `MIGRATE` when a project has adopted worktree-backed streams but has not
14
+ explicitly opted out of legacy M10 auto-routing. Silent + exit 0 means no
15
+ migration needed.
16
+
17
+ ```bash
18
+ [ -f .forge/streams/active.yml ] || exit 0
19
+
20
+ if grep -qE '^[[:space:]]+worktree:[[:space:]]*"?[^"[:space:]]+' .forge/streams/active.yml .forge/streams/*.yml 2>/dev/null; then
21
+ if ! awk '
22
+ /^orchestration:[[:space:]]*$/ { in_block=1; next }
23
+ /^[^[:space:]#][^:]*:/ { in_block=0 }
24
+ in_block && /^[[:space:]]+auto:[[:space:]]*false[[:space:]]*(#.*)?$/ { found=1 }
25
+ END { exit found ? 0 : 1 }
26
+ ' .forge/project.yml 2>/dev/null; then
27
+ echo "MIGRATE - adopted Chief streams still have legacy orchestration.auto enabled or unset"
28
+ fi
29
+ fi
30
+ ```
31
+
32
+ ## Migration Steps
33
+
34
+ 1. Show the operator the current active streams:
35
+ - `.forge/streams/active.yml`
36
+ - any stream whose `runtime.worktree` or registry `worktree` points at a live
37
+ Forge worktree
38
+ 2. Explain the choice:
39
+ - `orchestration.auto: false` makes Chief/Streams the front door.
40
+ - M10 remains available when the Chief explicitly chooses worktree isolation
41
+ or the user explicitly asks for multi-agent/worktree mode.
42
+ - Leaving auto-routing enabled preserves legacy behavior where Standard/Full
43
+ `/forge` work can route straight to `orchestrating`.
44
+ 3. Ask: `Make Chief/Streams the front door now? (yes/no)`
45
+ 4. If yes, update `.forge/project.yml` in place:
46
+
47
+ ```yaml
48
+ orchestration:
49
+ auto: false
50
+ ```
51
+
52
+ If an `orchestration:` block already exists, add or update only its `auto` key.
53
+ Do not modify other project settings.
54
+
55
+ If no, record the operator's decision in the upgrade report. Do not edit
56
+ `.forge/project.yml`.
57
+
58
+ ## Validation
59
+
60
+ - `.forge/project.yml` contains `orchestration.auto: false` when the operator
61
+ chose Chief/Streams as the front door.
62
+ - `.forge/streams/active.yml` and per-stream runtime files were not overwritten.
63
+ - Explicit M10 use still works through Chief-selected or user-requested
64
+ orchestration.
@@ -0,0 +1,94 @@
1
+ # Migration Guide: Worktree convention promoted to base (Forge 0.33.0)
2
+
3
+ Applies to projects that installed the experimental M10 `orchestrating` skill
4
+ (`.claude/skills/orchestrating/`). Projects without M10 have nothing to migrate.
5
+
6
+ 0.33.0 closes a silent-freeze class (issues
7
+ [#5](https://github.com/Attuned-Media/forge/issues/5) /
8
+ [#6](https://github.com/Attuned-Media/forge/issues/6)). Three things changed:
9
+
10
+ 1. **The worktree path/naming/anchor convention is now base** — documented in
11
+ `FORGE.md` ("Worktree Convention"), so Chief/Streams has a fallback when a
12
+ worktree was created outside `orchestrating`, and the convention stays
13
+ upgrade-synced for every install regardless of the experimental skill (see
14
+ [ADR-010](../decisions/ADR-010-repo-scoped-worktree-root.md)).
15
+ 2. **`upgrading` no longer blanket-skips experimental skills** — Step 3b now
16
+ diffs an installed experimental skill against its `experimental/*/source/`
17
+ origin and offers a preview/confirm re-sync.
18
+ 3. **`chief-of-staff` gained an advisory Registry Drift Check** reconciling
19
+ `state/index.yml` against `streams/active.yml` (issue
20
+ [#4](https://github.com/Attuned-Media/forge/issues/4)). No on-disk migration —
21
+ it just runs on the next Show/Sync.
22
+
23
+ The only thing that needs migrating on disk is an `orchestrating` skill that was
24
+ **frozen before 0.28.0** and is therefore still pinned to the old shared
25
+ `../forge-worktrees/` root. Against a frozen skill the 0.28.0 migration was a
26
+ no-op, so new worktrees kept landing in the shared dir instead of the per-repo
27
+ `../<repo>-worktrees/`. This guide detects that and offers the re-sync that
28
+ 0.28.0's "do nothing" note assumed had already happened.
29
+
30
+ ## Prerequisites
31
+
32
+ 1. On the new version's framework files (run `npx forge-orkes upgrade`, or the
33
+ `upgrading` skill against a local dev checkout, first).
34
+ 2. Working tree clean or changes committed — the fix re-syncs one skill dir.
35
+
36
+ ## Detection
37
+
38
+ Prints `MIGRATE` only when the experimental `orchestrating` skill is installed
39
+ **and** still pinned to the pre-0.28.0 shared worktree root (has `forge-worktrees`,
40
+ lacks `<repo>-worktrees`). Silent + exit 0 otherwise — not installed, or already
41
+ current. This is a **content** check, not a version-stamp check, because the
42
+ skill is experimental and `upgrading` never force-overwrites it (the very gap
43
+ this release closes).
44
+
45
+ ```bash
46
+ S=.claude/skills/orchestrating/SKILL.md
47
+ [ -f "$S" ] || exit 0
48
+ if grep -q 'forge-worktrees' "$S" && ! grep -q '<repo>-worktrees' "$S"; then
49
+ echo "MIGRATE — experimental orchestrating skill is pinned to the pre-0.28.0 shared worktree root; re-sync it from experimental/m10"
50
+ fi
51
+ ```
52
+
53
+ ## Migration steps
54
+
55
+ ### 1. Re-sync the experimental skill
56
+
57
+ Run the `upgrading` skill. Its new **Step 3b** detects the stale `orchestrating`
58
+ skill and offers a re-sync from `experimental/m10/source/skills/orchestrating/`.
59
+ Answer **yes** to update the skill's markdown to the current convention
60
+ (per-repo `../<repo>-worktrees/` default).
61
+
62
+ Equivalent by hand (from the project root, with a Forge source checkout at
63
+ `{source}`):
64
+
65
+ ```bash
66
+ cp {source}/packages/create-forge/experimental/m10/source/skills/orchestrating/SKILL.md \
67
+ .claude/skills/orchestrating/SKILL.md
68
+ cp {source}/packages/create-forge/experimental/m10/source/skills/orchestrating/bootstrap-checks.md \
69
+ .claude/skills/orchestrating/bootstrap-checks.md 2>/dev/null || true
70
+ ```
71
+
72
+ ### 2. (If the release changed them) re-run the M10 installer for hooks/MCP
73
+
74
+ `upgrading` re-syncs only the skill markdown. If this release also changed M10
75
+ hooks or the MCP server, re-run `experimental/m10/install.sh`. For 0.33.0 it did
76
+ not — skill-only.
77
+
78
+ ### 3. Leave live worktrees alone
79
+
80
+ Existing worktrees keep working off their recorded `lifecycle.worktree_path`.
81
+ Only **new** worktrees pick up the per-repo default. Do not relocate a live
82
+ worktree except via `git worktree move`.
83
+
84
+ <!-- The migration is NEVER auto-applied. In Claude Code it runs via the
85
+ `quick-tasking` skill, which the `upgrading` Step-7 prompt hands this guide to on
86
+ "yes". -->
87
+
88
+ ## Validation
89
+
90
+ - `grep -c '<repo>-worktrees' .claude/skills/orchestrating/SKILL.md` returns ≥ 1
91
+ and `grep -c 'forge-worktrees' .claude/skills/orchestrating/SKILL.md` returns 0.
92
+ - `FORGE.md` contains a "Worktree Convention (base)" subsection.
93
+ - Start a new M10 milestone (or `git worktree add` manually) — the worktree
94
+ appears under `../<your-repo>-worktrees/`, not the shared `../forge-worktrees/`.
@@ -0,0 +1,66 @@
1
+ # Migration Guide: Live-Worktree Ownership Gate (Forge 0.34.0)
2
+
3
+ Applies to every project, but it is **framework-behavior only — nothing on disk
4
+ to migrate**. The change lives entirely in framework-owned files that
5
+ `upgrading` overwrites for you (`forge/SKILL.md`, `FORGE.md`). This guide exists
6
+ so the change is recorded and discoverable; its Detection is an intentional no-op
7
+ (issue [#7](https://github.com/Attuned-Media/forge/issues/7)).
8
+
9
+ ## What changed
10
+
11
+ `forge` boot already surfaced live Forge worktrees, but the warning was
12
+ **informational** — a session on `main` could still write single-owner-mutable
13
+ milestone state while a worktree owned that milestone, forking the cursor (main
14
+ says `reviewing`, the worktree says `planning`, a later resume contradicts the
15
+ earlier claim).
16
+
17
+ 0.34.0 promotes that warning to an **enforced gate** (forge SKILL **1.1a**):
18
+
19
+ - **Trigger** — invoked from `main` AND the selected milestone has a live
20
+ worktree (recorded `lifecycle.worktree_path` / `lifecycle.worktree_mode`,
21
+ a `forge/m-{id}-*` branch in `git worktree list`, or a stream `runtime.worktree`).
22
+ - **Effect** — milestone-owned writes are blocked
23
+ (`state/milestone-{id}.yml`, `phases/milestone-{id}/`, `research/milestone-{id}.md`)
24
+ and routing stops until the operator picks one resolution: **enter** the
25
+ worktree, **sync** it, **retire** it, or record an explicit
26
+ `lifecycle.ownership_override: {at, from: main, reason}` — the only,
27
+ never-silent bypass.
28
+ - Shared project docs (`context.md`, `refactor-backlog.yml`, `project.yml`, …)
29
+ stay writable from `main`, with the existing "not visible to the worktree
30
+ until it pulls/rebases" warning.
31
+
32
+ `FORGE.md` State Ownership is updated from advice to enforcement to match.
33
+
34
+ ## Prerequisites
35
+
36
+ 1. On the new version's framework files (`npx forge-orkes upgrade`, or the
37
+ `upgrading` skill).
38
+
39
+ ## Detection
40
+
41
+ No on-disk migration — the new behavior ships in framework-owned files that the
42
+ upgrade already overwrote. The `lifecycle.ownership_override` field is written
43
+ lazily, only when an operator records an override; absent means "no override,"
44
+ which is the correct default. Intentional no-op:
45
+
46
+ ```bash
47
+ # Skill-behavior change only — enforcement lives in forge/SKILL.md + FORGE.md,
48
+ # both framework-owned and synced by the upgrade. Nothing on disk to migrate.
49
+ exit 0
50
+ ```
51
+
52
+ ## Migration steps
53
+
54
+ None. After the upgrade, the next `/forge` invoked from `main` against a
55
+ milestone with a live worktree will enforce the gate automatically.
56
+
57
+ ## Validation
58
+
59
+ - `grep -c '1.1a Live-Worktree Ownership Gate' .claude/skills/forge/SKILL.md`
60
+ returns 1.
61
+ - From a `main` checkout with a live `forge/m-*` worktree, run `/forge` and
62
+ select that milestone — Forge blocks milestone-owned writes and offers the
63
+ enter / sync / retire / recorded-override choices instead of routing straight
64
+ into planning/executing/verifying/reviewing.
65
+ - From the owning worktree (or for a milestone with no live worktree), `/forge`
66
+ routes normally — the gate is a no-op.
@@ -87,6 +87,21 @@ releases:
87
87
  bump: minor
88
88
  reserved_at: "2026-06-18"
89
89
  summary: "Project Chief / Streams orchestration — adds Project/Stream/Work Package runtime layers, Chief of Staff routing, stream/work-package templates, active context compaction, framework-wide size audit, and an idempotent migration guide. M10 is repositioned as an optional backend for worktree isolation, merge queue support, and experimental file claims."
90
+ - milestone: 16
91
+ version: "0.32.1"
92
+ bump: patch
93
+ reserved_at: "2026-06-20"
94
+ summary: "Chief front-door follow-up — detects projects that adopted worktree-backed streams but left legacy orchestration.auto enabled or unset, then prompts to set orchestration.auto: false so Chief/Streams is the default entry point while M10 remains explicit."
95
+ - milestone: 16
96
+ version: "0.33.0"
97
+ bump: minor
98
+ reserved_at: "2026-06-21"
99
+ summary: "Worktree convention promoted to base + experimental-skill drift fix + Chief registry drift check (issues #4/#5/#6). (1) FORGE.md gains a base 'Worktree Convention' (path/anchor/branch + orchestration.worktree_root resolution + lifecycle.worktree_path authority) so Chief/Streams has a fallback when a worktree was created outside orchestrating, and the convention stays upgrade-synced regardless of the experimental skill. (2) upgrading no longer blanket-skips installed experimental skills — it diffs them against experimental/*/source and offers a preview/confirm re-sync (warn at minimum), closing the silent-freeze where base migrations (e.g. 0.28.0 worktree-root) became no-ops against a frozen orchestrating skill. (3) migration-guide template gains an authoring guard: guides whose behavior lives in an experimental skill must detect the skill's content, not just the version stamp. (4) chief-of-staff gains an advisory Registry Drift Check (Show + Sync) reconciling state/index.yml active milestones against streams/active.yml."
100
+ - milestone: 16
101
+ version: "0.34.0"
102
+ bump: minor
103
+ reserved_at: "2026-06-21"
104
+ summary: "Live-Worktree Ownership Gate (issue #7). forge boot's worktree surfacing was advisory, so a session on main could write single-owner-mutable milestone state (milestone-{id}.yml, phases/, research/) while a live worktree owned the milestone — forking the cursor (main 'reviewing' vs worktree 'planning'). forge SKILL gains an enforced gate (1.1a): when invoked from main and the selected milestone has a live worktree, milestone-owned writes are blocked and routing stops until the operator enters the worktree, syncs it, retires it, or records an explicit lifecycle.ownership_override (the only, never-silent bypass). Shared project docs stay writable from main with a not-visible-until-sync warning. FORGE.md State Ownership promoted from advice to enforcement. Also folds in dev/template skill drift cleanup: forge/discussing/planning dev .claude/skills copies were behind the template (chief-streams + context-archive content) — brought to parity."
90
105
 
91
106
  # Note on the 15 / 0.24.0 ordering: reserved as max(0.23.0)+minor. origin/main was
92
107
  # already at 0.23.0 when this shipped (M10/M12/M13/M14 all merged), so 0.24.0 is a
@@ -45,6 +45,37 @@ its version runs it once, and after the version is stamped it falls out of range
45
45
  ledger, no per-version code, no staleness. (It also closes the install-run blind spot:
46
46
  detection keys off the freshly-synced guides on disk, not the skill's own pre-sync code.)
47
47
 
48
+ ### Experimental-skill guard (read if your change lives in an experimental skill)
49
+
50
+ If the behavior your guide migrates is implemented **only inside an experimental,
51
+ opt-in skill** (e.g. `.claude/skills/orchestrating/` from `experimental/m10/`),
52
+ a version-stamp check is **not enough**. `upgrading` never overwrites an
53
+ experimental skill in its base sync (it offers a re-sync in Step 3b, which the
54
+ user may decline), so the skill can stay pinned at install-time content while the
55
+ version stamp advances — and a stamp-only Detection block would report "nothing
56
+ to migrate" while the behavior is silently absent. This is exactly how the 0.28.0
57
+ repo-scoped worktree root became a no-op (issue #5).
58
+
59
+ So when your change touches experimental-skill behavior, the Detection block MUST
60
+ inspect the **skill's content on disk**, not the version, and emit `MIGRATE` when
61
+ the skill is stale:
62
+
63
+ ```bash
64
+ # The behavior lives in an experimental skill — check its CONTENT, not the version.
65
+ S=.claude/skills/orchestrating/SKILL.md
66
+ [ -f "$S" ] || exit 0 # skill not installed → nothing to do
67
+ if grep -q 'forge-worktrees' "$S" \
68
+ && ! grep -q '<repo>-worktrees' "$S"; then
69
+ echo "MIGRATE — experimental orchestrating skill is pinned to the pre-0.28.0 worktree root; re-sync it"
70
+ fi
71
+ ```
72
+
73
+ Better still, **also promote the load-bearing convention into base** (`FORGE.md`
74
+ or a base skill) so it is upgrade-synced regardless of the experimental skill's
75
+ state — then the base workflow no longer depends on experimental internals at all
76
+ (issue #6). The content-check Detection above is the floor; base promotion is the
77
+ durable fix.
78
+
48
79
  ### Detection block skeleton (applies)
49
80
 
50
81
  ```bash
@@ -106,6 +137,7 @@ must be confirmed with the user.>
106
137
  - [ ] Exactly one `## Detection` heading; exactly one ` ```bash ` block under it.
107
138
  - [ ] Block emits `MIGRATE` on stdout iff the migration applies; silent + exit 0 otherwise.
108
139
  - [ ] Block is safe on a clean/empty project (no errors, exit 0).
140
+ - [ ] If the change lives in an experimental skill, Detection checks the skill's **content** (not just the version stamp) — see the Experimental-skill guard above.
109
141
  - [ ] Any new accumulating artifact declares owner, size gate, archive/compaction rule, derived vs source-of-truth status, and future migration behavior.
110
142
  - [ ] Mirrored byte-identical to `docs/migrations/{same-name}.md`.
111
143
  - [ ] No edit to `upgrading/SKILL.md` or `create-forge.js` was needed (the loop covers it).