forge-orkes 0.33.0 → 0.36.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 +1 -1
- package/template/.claude/skills/chief-of-staff/SKILL.md +53 -3
- package/template/.claude/skills/forge/SKILL.md +43 -3
- package/template/.claude/skills/planning/SKILL.md +10 -1
- package/template/.claude/skills/verifying/SKILL.md +23 -1
- package/template/.forge/FORGE.md +19 -4
- package/template/.forge/migrations/0.34.0-live-worktree-ownership-gate.md +66 -0
- package/template/.forge/migrations/0.35.0-merge-often-and-early.md +56 -0
- package/template/.forge/migrations/0.36.0-stream-integration-checkpoints.md +66 -0
- package/template/.forge/releases.yml +15 -0
package/package.json
CHANGED
|
@@ -56,13 +56,13 @@ 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?" | Run Registry Drift Check, then summarize registry without loading all deep history |
|
|
59
|
+
| Show | "show streams", "active streams", "what is running?" | Run Registry Drift Check + Merge Cadence 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" | Run Registry Drift Check, then refresh registry summaries from active stream briefs |
|
|
65
|
+
| Sync | "sync streams" | Run Registry Drift Check + Merge Cadence 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 |
|
|
@@ -256,6 +256,50 @@ Use "merge safe" to identify streams that can land:
|
|
|
256
256
|
If any condition fails, mark the stream blocked or keep it ready with a named
|
|
257
257
|
reason it cannot merge yet.
|
|
258
258
|
|
|
259
|
+
## Merge Cadence Check
|
|
260
|
+
|
|
261
|
+
**Merge often and early** (FORGE.md Project Streams). Ready work integrated late
|
|
262
|
+
drifts from main, staleness accrues on shared surfaces, and the eventual merge is
|
|
263
|
+
larger and riskier. This check makes the cadence visible so integration happens
|
|
264
|
+
when work is ready — not at milestone end. Run it at the **start of the Show and
|
|
265
|
+
Sync intents**, after the Registry Drift Check.
|
|
266
|
+
|
|
267
|
+
**Advisory — it surfaces and recommends. It never merges, never rebases, and
|
|
268
|
+
never blocks.** Merging and rebasing stay human decisions (conflicts need
|
|
269
|
+
judgment); the Chief's job is to make "this is ready, integrate it now" impossible
|
|
270
|
+
to miss.
|
|
271
|
+
|
|
272
|
+
Streams that use **integration checkpoints** (FORGE.md → Stream Integration
|
|
273
|
+
Checkpoints) already fast-forward verified phases onto main automatically, so this
|
|
274
|
+
check focuses on what they don't cover: streams/phases **without** a checkpoint,
|
|
275
|
+
diverged streams whose publish was rejected (non-ff — they need a manual
|
|
276
|
+
merge/rebase), and **cross-stream merge order**. A checkpoint stream that is
|
|
277
|
+
cleanly auto-publishing needs no nudge here.
|
|
278
|
+
|
|
279
|
+
1. **Ready-to-merge surfacing.** From `active.yml`, collect streams with
|
|
280
|
+
`status: ready` (and any `merge_queue` entries). For each, run the Merge Safe
|
|
281
|
+
Flow conditions. Unblocked + no conflicts → list under **Ready to merge** with
|
|
282
|
+
a one-line *"ready — integrate now"* and, if known, how long it has been ready
|
|
283
|
+
(from the stream's `last_sync` / brief date). Add/refresh its `merge_queue`
|
|
284
|
+
entry (`status: waiting`). Blocked → list the named reason instead.
|
|
285
|
+
2. **Idle-ready nudge.** A stream that has sat `ready` across **multiple Show/Sync
|
|
286
|
+
passes** or whose branch is mergeable but untouched is the cadence smell.
|
|
287
|
+
Recommend integrating it before more divergence accrues. No magic threshold —
|
|
288
|
+
report the age and let the operator decide; the point is visibility, not a hard
|
|
289
|
+
cutoff.
|
|
290
|
+
3. **Sibling-rebase nudge.** When main has advanced on a **shared** or
|
|
291
|
+
**depended-on** surface since a live worktree branched, surface
|
|
292
|
+
*"main moved on {surface} — rebase worktree {stream} ({path}) before it drifts"*
|
|
293
|
+
for each affected live stream. Cheap detection: compare each live stream's
|
|
294
|
+
branch point against main for the shared surfaces it declares
|
|
295
|
+
(`git -C {worktree} rev-list --count HEAD..main -- {shared_surface}` > 0).
|
|
296
|
+
This is the cadence-driven form of the boot-time `forge.worktree_rebase_check`.
|
|
297
|
+
4. **Order.** When more than one stream is ready, recommend a merge order
|
|
298
|
+
(fewest shared-surface conflicts first; depended-on streams before dependents).
|
|
299
|
+
|
|
300
|
+
If nothing is ready and no worktree is behind on a shared surface, say so in one
|
|
301
|
+
line (`merge cadence: nothing ready, no rebases needed`) and continue.
|
|
302
|
+
|
|
259
303
|
## Close Flow
|
|
260
304
|
|
|
261
305
|
1. Confirm final status: merged, intentionally abandoned, superseded, or split.
|
|
@@ -273,9 +317,15 @@ Streams:
|
|
|
273
317
|
- billing-webhooks — active — owns api/billing, shared db/schema — next: verify webhook retries
|
|
274
318
|
- settings-ui — paused — owns app/settings — next: resume form validation
|
|
275
319
|
|
|
320
|
+
Ready to merge:
|
|
321
|
+
- reporting-export — ready 2 passes ago — no conflicts — integrate now (merge often and early)
|
|
322
|
+
|
|
323
|
+
Rebase needed:
|
|
324
|
+
- billing-webhooks — main moved on db/schema since it branched — rebase ../app-worktrees/billing-webhooks
|
|
325
|
+
|
|
276
326
|
Conflicts:
|
|
277
327
|
- billing-webhooks and reporting-export both touch db/schema. Contract owner needed before either merges.
|
|
278
328
|
|
|
279
329
|
Next:
|
|
280
|
-
-
|
|
330
|
+
- Merge reporting-export, then rebase billing-webhooks onto the new main.
|
|
281
331
|
```
|
|
@@ -28,14 +28,25 @@ 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}`.
|
|
32
|
-
-
|
|
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`).
|
|
36
36
|
- Any differ → surface: *"`{file}` has changed on main since this worktree branched. Pull just this file (`git restore --source main -- {file}`), rebase, or skip?"* — operator decides.
|
|
37
37
|
- Setting absent or `false` → no-op.
|
|
38
38
|
|
|
39
|
+
**Integration flag check (consumer — worktree only).** When `in_main_checkout: false`, check whether a checkpoint publish has landed work on main that this worktree should pull (FORGE.md → Stream Integration Checkpoints). Event-driven, not polled — read the flag first; act only if it is set:
|
|
40
|
+
|
|
41
|
+
- Read `.git/forge/integration-pending` (in the git common dir — set by a producer's checkpoint publish, shared across this machine's worktrees). Absent, or its main sha already seen by this worktree → **skip** (no fetch, no scan). This is the cheap gate: no flag → no work.
|
|
42
|
+
- Flag set with an unseen sha → confirm against the ref: `behind=$(git rev-list --count HEAD..main 2>/dev/null)` (one targeted `git fetch origin main` first if a remote and the local ref is stale). `behind` is 0 → mark seen, skip.
|
|
43
|
+
- `behind > 0` and the worktree has **no divergent local commits** (`git rev-list --count main..HEAD` is 0) → **fast-forward automatically**: `git merge --ff-only main`. A fast-forward is conflict-free by definition, so do it without asking; report *"pulled {N} commit(s) from main (checkpoint integration)."* Mark the sha seen.
|
|
44
|
+
- `behind > 0` **and** the worktree has diverged → **surface, do not auto-rebase**: *"main advanced on {surfaces} since this worktree branched — rebase onto main? (`git rebase main`)"* — rebase can conflict; the operator decides.
|
|
45
|
+
|
|
46
|
+
Cross-machine note: the flag file is machine-local, so a worktree on another laptop relies on the opt-in `forge.worktree_rebase_check` / a periodic fetch instead — eventual, not instant.
|
|
47
|
+
|
|
48
|
+
**Ready-to-merge nudge (main checkout / streams without checkpoints).** If `.forge/streams/active.yml` exists, scan for streams with `status: ready` or a non-empty `merge_queue` **that are not auto-publishing via checkpoints**. Any present → one line: *"{N} stream(s) ready to merge — run `/chief-of-staff` (merge safe) to integrate."* Pointer only — the cadence logic lives in the Chief's Merge Cadence Check; `forge` never merges. Nothing pending → silent.
|
|
49
|
+
|
|
39
50
|
### 1.0 State Rollup (index.yml is derived)
|
|
40
51
|
|
|
41
52
|
`index.yml` is a **derived registry** — regenerate it from the milestone files before reading, and after any milestone CRUD (promote/defer/resume/delete). **Never hand-edit `index.yml`.**
|
|
@@ -74,7 +85,7 @@ Check state files:
|
|
|
74
85
|
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
86
|
5. **One:** Auto-select. *"Resuming: [{name}] -- {current.status}, {percent}%"*
|
|
76
87
|
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
|
|
88
|
+
7. Load `milestone-{id}.yml`, then run the **Live-Worktree Ownership Gate (1.1a)** — it can block routing before any milestone-owned write.
|
|
78
89
|
8. **Route on `current.status`, NOT `{percent}`.** Complete only at `complete`. 100% phases ≠ done -- verifying + reviewing must run.
|
|
79
90
|
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
91
|
|
|
@@ -89,6 +100,35 @@ Beads enabled (`forge.beads_integration: true`) → `bd prime`. Optional.
|
|
|
89
100
|
|
|
90
101
|
Read `.forge/context.md`. **Needs Resolution** unchecked → warn: *"{N} unresolved discrepancies."* Quick proceeds; Standard/Full blocked at planning.
|
|
91
102
|
|
|
103
|
+
### 1.1a Live-Worktree Ownership Gate (enforced)
|
|
104
|
+
|
|
105
|
+
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.)
|
|
106
|
+
|
|
107
|
+
**Trigger.** `in_main_checkout: true` (from the Step 1 preflight) **AND** the selected milestone has a live worktree — any of:
|
|
108
|
+
- the preflight's `git worktree list` reported a `forge/m-{id}-*` / `forge/{id}` branch for this milestone; or
|
|
109
|
+
- `milestone-{id}.yml` `lifecycle.worktree_mode` is `active` or `degraded` and a `lifecycle.worktree_path` is recorded; or
|
|
110
|
+
- `.forge/streams/active.yml` shows a stream for this milestone with a `runtime.worktree`.
|
|
111
|
+
|
|
112
|
+
Resolve the worktree path from the recorded `lifecycle.worktree_path` / `runtime.worktree`, or — if absent — from the base **Worktree Convention** (FORGE.md).
|
|
113
|
+
|
|
114
|
+
**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).
|
|
115
|
+
|
|
116
|
+
**When it triggers — STOP. Do not route** to `planning`, `executing`, `verifying`, `reviewing`, `quick-tasking` against this milestone, and do not write any of:
|
|
117
|
+
- `.forge/state/milestone-{id}.yml`
|
|
118
|
+
- `.forge/phases/milestone-{id}/`
|
|
119
|
+
- `.forge/research/milestone-{id}.md`
|
|
120
|
+
|
|
121
|
+
Present the four resolutions and wait for an explicit choice:
|
|
122
|
+
|
|
123
|
+
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.
|
|
124
|
+
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.
|
|
125
|
+
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.**
|
|
126
|
+
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.)
|
|
127
|
+
|
|
128
|
+
**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).
|
|
129
|
+
|
|
130
|
+
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.
|
|
131
|
+
|
|
92
132
|
### 1.2 Backlog + Desire Paths
|
|
93
133
|
|
|
94
134
|
Check `.forge/refactor-backlog.yml`:
|
|
@@ -188,7 +188,7 @@ Plan naming reflects the slice: `plan-01-user-signs-up.md`, not `plan-01-models.
|
|
|
188
188
|
1. `.forge/templates/plan.md` -> `.forge/phases/milestone-{id}/{phase}-{name}/plan-{NN}.md`
|
|
189
189
|
- `{id}`=milestone, `{phase}`=phase# (preserved verbatim, NOT renumbered), `{name}`=kebab, `{NN}`=seq
|
|
190
190
|
- Ex: `.forge/phases/milestone-3/2-providers/plan-01.md`
|
|
191
|
-
2. Frontmatter: phase, plan#, wave, deps, `slice_exception:` (optional, see Core Principle)
|
|
191
|
+
2. Frontmatter: phase, plan#, wave, deps, `slice_exception:` (optional, see Core Principle), `integration_checkpoint:` (optional, see below)
|
|
192
192
|
3. must_haves:
|
|
193
193
|
- **Truths:** User-observable outcomes (3-7). MUST be phrased as something the user can see, click, or receive -- not "model X exists" or "table Y created".
|
|
194
194
|
- **Artifacts:** Must exist, substantive not stubs. Slice plans typically span 2-4 layers (e.g., component + handler + repo).
|
|
@@ -205,6 +205,15 @@ Plan naming reflects the slice: `plan-01-user-signs-up.md`, not `plan-01-models.
|
|
|
205
205
|
</task>
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
#### Integration Checkpoints (merge often and early)
|
|
209
|
+
|
|
210
|
+
Mark the phases where a verified slice should **land on main**, so a stream integrates continuously instead of batching at milestone end (FORGE.md → Stream Integration Checkpoints). Set `integration_checkpoint: true` in the plan frontmatter for those phases.
|
|
211
|
+
|
|
212
|
+
- **Default heuristic to propose:** the milestone's **last phase**, plus **any phase another stream or phase depends on** (a depended-on slice should be on main before its dependents build against it).
|
|
213
|
+
- **Advisory — propose, don't impose.** Surface the suggested checkpoints and let the operator confirm/adjust: *"Mark phases {N, …} as integration checkpoints? Verified work there fast-forwards onto main automatically."*
|
|
214
|
+
- **The mark is the opt-in.** A plan with no `integration_checkpoint` never auto-publishes — leave it unset for phases that should not land mid-flight (spikes, exploratory work, anything not independently shippable).
|
|
215
|
+
- Only the **producer** (a worktree session) acts on the mark; `verifying` does the fast-forward-only publish on PASS. In a single-checkout project the mark is a no-op.
|
|
216
|
+
|
|
208
217
|
#### Plan Anchors (drift-resistant references)
|
|
209
218
|
|
|
210
219
|
Tasks reference concrete code — symbols, paths, line numbers, contract shapes, versions. These are **anchors**: snapshotted at planning time, relied on at execution time, *after* the codebase has moved. Make them re-derivable instead of fragile:
|
|
@@ -292,6 +292,28 @@ After PASSED verdict:
|
|
|
292
292
|
2. **Persist** — Confirm verification report documented, desire-path files written to `.forge/state/desire-paths/`
|
|
293
293
|
3. **Update state** — Set `current.status` to `reviewing` in `.forge/state/milestone-{id}.yml`
|
|
294
294
|
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 .`).
|
|
295
|
-
5. **
|
|
295
|
+
5. **Integration Checkpoint Publish** (see below) — if this phase is a checkpoint and the session is a worktree, fast-forward-only publish to main.
|
|
296
|
+
6. **Recommend clear:** *"State synced. `/clear` then `/forge` for reviewing."*
|
|
296
297
|
|
|
297
298
|
If GAPS found, route back to planning in gap-closure mode. Context clear applies after re-verified PASSED verdict.
|
|
299
|
+
|
|
300
|
+
### Integration Checkpoint Publish (merge often and early)
|
|
301
|
+
|
|
302
|
+
Realizes producer-side continuous integration (FORGE.md → Stream Integration Checkpoints). Runs at Phase Handoff step 5, **only when all hold**:
|
|
303
|
+
|
|
304
|
+
- the phase's plan frontmatter has `integration_checkpoint: true`;
|
|
305
|
+
- the verdict is PASSED **and** `current.human_verified` is set (where required) — never publish unverified work;
|
|
306
|
+
- the session is a **worktree** (`git rev-parse --git-dir` ≠ `--git-common-dir`). In a single checkout, skip — there is no main to fast-forward into.
|
|
307
|
+
|
|
308
|
+
Then publish **fast-forward only**:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Push this worktree's verified commits to main. FF-only is the safety:
|
|
312
|
+
# git refuses a non-ff push, so a diverged main is surfaced, never forced.
|
|
313
|
+
git push origin HEAD:main # remote present
|
|
314
|
+
# no remote → fast-forward the local main ref where possible, else report ready-to-ff
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
- **Success** → set the integration flag for sibling worktrees: write `.git/forge/integration-pending` (in the git common dir) with the new main sha, this stream/milestone, and the shared surfaces this phase changed. Report: *"Checkpoint published — phase {N} fast-forwarded onto main; siblings will pick it up on next boot."*
|
|
318
|
+
- **Rejected (non-ff — main diverged)** → **do not force.** Surface: *"main has advanced since this worktree branched — publish needs a manual merge/rebase first."* Leave the work on the branch; the Chief's Merge Cadence Check / a human resolves it.
|
|
319
|
+
- Never auto-resolve a conflict, never force-push.
|
package/template/.forge/FORGE.md
CHANGED
|
@@ -37,6 +37,17 @@ 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
|
+
**Merge often and early.** Integrate ready work **as soon as it is ready**, not at milestone end. Long-lived stream branches drift from main, shared surfaces go stale, and the merge gets larger and riskier the longer it waits — the opposite of the merge discipline streams exist to provide. The default posture is continuous integration, realized two ways: **producer-side** by publishing at verified checkpoints (below), and **project-side** by the Chief's Merge Cadence Check (cross-stream order + streams without checkpoints). Forge never force-pushes, never auto-resolves a conflict, and never auto-rebases.
|
|
41
|
+
|
|
42
|
+
### Stream Integration Checkpoints
|
|
43
|
+
|
|
44
|
+
Integration is **event-driven, not polled**: a stream publishes its work to main at plan-marked phase boundaries, and a lightweight flag tells sibling worktrees there is something to pull. No flag set → boot does no integration work.
|
|
45
|
+
|
|
46
|
+
- **Checkpoints (plan-marked).** `planning` marks selected phases as integration checkpoints (`integration_checkpoint: true` in the plan frontmatter) — the points where a verified slice should land on main. Default heuristic: the last phase, plus any phase another stream/phase depends on. Advisory — planning proposes, the operator confirms. **The mark is the opt-in:** a plan with no marked checkpoint never auto-publishes, so existing/unmarked work is unaffected.
|
|
47
|
+
- **Producer — publish on verified checkpoint (fast-forward only).** When `verifying` returns PASS for a checkpoint phase *and the session is a worktree*, it integrates that phase to main with a **fast-forward-only** push: `git push origin HEAD:main`. Git rejects a non-ff push — that *is* the safety: a diverged main is surfaced for a human merge, never force-pushed. On success it sets the **integration flag**. (No remote → fast-forward local `main` where possible, else record ready-to-ff for the primary checkout.)
|
|
48
|
+
- **Flag (cheap, set by the producer).** A marker in the shared git common dir — `.git/forge/integration-pending` — records the new main sha, the publishing stream, and the shared surfaces that changed. It is shared across all of a repo's worktrees on a machine, so any boot reads it for free; absent or already-seen → skip. The `main` ref is the source of truth the marker points at. Cross-machine (the marker is machine-local) falls back to the opt-in `forge.worktree_rebase_check` / a periodic fetch — eventual, not instant.
|
|
49
|
+
- **Consumer — auto fast-forward, else prompt.** `forge` boot in a worktree checks the flag. Flag set (main advanced past this worktree's merge-base) and the worktree has **no divergent local commits** → **fast-forward it automatically** (`git merge --ff-only main`) and report — a fast-forward is conflict-free by definition, so it is safe without asking. Worktree has **diverged** → **surface a rebase prompt** (never auto-rebase; rebase can conflict and needs human judgment). Flag not set → no fetch, no scan, continue boot.
|
|
50
|
+
|
|
40
51
|
### Worktree Convention (base)
|
|
41
52
|
|
|
42
53
|
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)).
|
|
@@ -232,14 +243,18 @@ with the work it describes. Every artifact has a sharing class:
|
|
|
232
243
|
| **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. |
|
|
233
244
|
|
|
234
245
|
Cross-tree edits land on the current branch and are invisible to other worktrees
|
|
235
|
-
until they pull/rebase. `forge` surfaces live worktrees at boot
|
|
236
|
-
|
|
237
|
-
|
|
246
|
+
until they pull/rebase. `forge` surfaces live worktrees at boot **and enforces
|
|
247
|
+
the Live-Worktree Ownership Gate** (forge SKILL 1.1a): when invoked from main for
|
|
248
|
+
a milestone that has a live worktree, milestone-owned writes are **blocked**
|
|
249
|
+
until the operator enters the worktree, syncs it, retires it, or records an
|
|
250
|
+
explicit `lifecycle.ownership_override`. `discussing` and `reviewing` warn before
|
|
251
|
+
touching shared-mutable blocks; optional `forge.worktree_rebase_check` detects
|
|
252
|
+
stale shared files inside worktrees. See
|
|
238
253
|
[ADR-011](../docs/decisions/ADR-011-shared-state-taxonomy.md) for rationale.
|
|
239
254
|
|
|
240
255
|
### State Ownership rules (quick reference)
|
|
241
256
|
|
|
242
|
-
- `state/milestone-{id}.yml` is the **single source of truth**; exactly one agent owns it at a time. **Other worktrees never write it** —
|
|
257
|
+
- `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.
|
|
243
258
|
- Worktree / parallel agents write **only** their own milestone file and **append** desire-path files. They **never** write `index.yml`.
|
|
244
259
|
- `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.
|
|
245
260
|
- For shared-mutable files: write only your milestone's block; within a block, append-only (strike through, don't rewrite).
|
|
@@ -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.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Migration Guide: Merge often and early (Forge 0.35.0)
|
|
2
|
+
|
|
3
|
+
Applies to every project that uses Chief/Streams, but it is **framework-behavior
|
|
4
|
+
only — nothing on disk to migrate**. The change lives in framework-owned files
|
|
5
|
+
that `upgrading` overwrites for you (`FORGE.md`, `chief-of-staff`, `forge`
|
|
6
|
+
skills) (issue [#8](https://github.com/Attuned-Media/forge/issues/8)).
|
|
7
|
+
|
|
8
|
+
## What changed
|
|
9
|
+
|
|
10
|
+
Stream integration was pull-based and deferred — a delivered + verified stream
|
|
11
|
+
sat on its branch until someone manually merged at milestone end, drifting from
|
|
12
|
+
main and staling shared surfaces. 0.35.0 makes **continuous integration** the
|
|
13
|
+
default posture:
|
|
14
|
+
|
|
15
|
+
- **Stated principle** in `FORGE.md` Project Streams: *merge often and early —
|
|
16
|
+
integrate ready work as soon as it is ready.* Surfacing only; Forge never
|
|
17
|
+
auto-merges or auto-rebases.
|
|
18
|
+
- **`chief-of-staff` Merge Cadence Check** (advisory, run at Show + Sync):
|
|
19
|
+
ready-to-merge surfacing from `active.yml` `status: ready` + `merge_queue`, an
|
|
20
|
+
idle-ready nudge, a sibling-rebase nudge when main advanced on a shared surface,
|
|
21
|
+
and a merge-order recommendation.
|
|
22
|
+
- **`forge` boot** gains a light ready-to-merge nudge (one line pointing at
|
|
23
|
+
`/chief-of-staff`) when `active.yml` shows ready streams.
|
|
24
|
+
|
|
25
|
+
The `merge_queue:` block already exists in the `active.yml` template — no schema
|
|
26
|
+
change. The Chief just keeps it current and surfaces it.
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
1. On the new version's framework files (`npx forge-orkes upgrade`, or the
|
|
31
|
+
`upgrading` skill).
|
|
32
|
+
|
|
33
|
+
## Detection
|
|
34
|
+
|
|
35
|
+
No on-disk migration — the behavior ships in framework-owned files the upgrade
|
|
36
|
+
already overwrote, and `active.yml` already carries `merge_queue`. Intentional
|
|
37
|
+
no-op:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Skill-behavior change only — merge cadence lives in chief-of-staff/forge/FORGE.md,
|
|
41
|
+
# all framework-owned and synced by the upgrade. active.yml merge_queue is unchanged.
|
|
42
|
+
exit 0
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Migration steps
|
|
46
|
+
|
|
47
|
+
None. After the upgrade, the next `/chief-of-staff` Show/Sync runs the Merge
|
|
48
|
+
Cadence Check, and `/forge` boot nudges when ready streams exist.
|
|
49
|
+
|
|
50
|
+
## Validation
|
|
51
|
+
|
|
52
|
+
- `grep -c 'Merge Cadence Check' .claude/skills/chief-of-staff/SKILL.md` returns ≥ 1.
|
|
53
|
+
- `grep -c 'Merge often and early' .forge/FORGE.md` returns ≥ 1.
|
|
54
|
+
- With a stream at `status: ready` in `.forge/streams/active.yml`, run
|
|
55
|
+
`/chief-of-staff show` — it lists the stream under **Ready to merge** with an
|
|
56
|
+
"integrate now" recommendation, and never merges on its own.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Migration Guide: Stream Integration Checkpoints (Forge 0.36.0)
|
|
2
|
+
|
|
3
|
+
Applies to projects that run Chief/Streams in worktrees, but it is
|
|
4
|
+
**framework-behavior only — nothing on disk to migrate**. The change lives in
|
|
5
|
+
framework-owned files that `upgrading` overwrites (`FORGE.md`, `planning`,
|
|
6
|
+
`verifying`, `forge`, `chief-of-staff`), and it is **fully opt-in**: a phase only
|
|
7
|
+
auto-publishes once its plan is marked `integration_checkpoint: true`, so
|
|
8
|
+
existing plans are unaffected until you choose to mark one.
|
|
9
|
+
|
|
10
|
+
This is the event-driven follow-up to 0.35.0's "merge often and early" (issue
|
|
11
|
+
[#8](https://github.com/Attuned-Media/forge/issues/8)).
|
|
12
|
+
|
|
13
|
+
## What changed
|
|
14
|
+
|
|
15
|
+
Continuous integration becomes producer-driven and event-based instead of polled:
|
|
16
|
+
|
|
17
|
+
- **`planning`** marks integration-checkpoint phases (`integration_checkpoint:
|
|
18
|
+
true` in plan frontmatter; default heuristic = last phase + depended-on
|
|
19
|
+
phases; advisory).
|
|
20
|
+
- **`verifying`** (producer): on a PASSED + human-verified checkpoint phase in a
|
|
21
|
+
worktree, fast-forward-only publishes to main (`git push origin HEAD:main` —
|
|
22
|
+
git rejects a non-ff, which is the safety; a diverged main is surfaced, never
|
|
23
|
+
forced) and sets an integration flag at `.git/forge/integration-pending` (git
|
|
24
|
+
common dir, shared across a machine's worktrees).
|
|
25
|
+
- **`forge` boot** (consumer): in a worktree, reads the flag cheaply — set + no
|
|
26
|
+
divergence → auto `git merge --ff-only main` (conflict-free); diverged →
|
|
27
|
+
surface a rebase prompt; not set → skip. Supersedes the 0.35.0 boot polling
|
|
28
|
+
pointer.
|
|
29
|
+
|
|
30
|
+
No state-shape change: the plan field is new and optional, and the flag lives in
|
|
31
|
+
`.git/` (machine-local runtime), not tracked state.
|
|
32
|
+
|
|
33
|
+
## Prerequisites
|
|
34
|
+
|
|
35
|
+
1. On the new version's framework files (`npx forge-orkes upgrade`, or the
|
|
36
|
+
`upgrading` skill).
|
|
37
|
+
|
|
38
|
+
## Detection
|
|
39
|
+
|
|
40
|
+
No on-disk migration — behavior ships in framework-owned files the upgrade
|
|
41
|
+
overwrote; the plan field and the `.git/` flag are created lazily on first use.
|
|
42
|
+
Intentional no-op:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Skill-behavior change only — checkpoint publish/consume lives in
|
|
46
|
+
# planning/verifying/forge/FORGE.md (framework-owned, synced by the upgrade).
|
|
47
|
+
# The optional plan field + .git/forge flag are created on first use; nothing to migrate.
|
|
48
|
+
exit 0
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Migration steps
|
|
52
|
+
|
|
53
|
+
None. To start using it: when `planning` next runs, accept the proposed
|
|
54
|
+
integration checkpoints (or add `integration_checkpoint: true` to a plan's
|
|
55
|
+
frontmatter). Verified work in those phases will fast-forward onto main from its
|
|
56
|
+
worktree, and sibling worktrees pick it up on next `/forge` boot.
|
|
57
|
+
|
|
58
|
+
## Validation
|
|
59
|
+
|
|
60
|
+
- `grep -c 'Stream Integration Checkpoints' .forge/FORGE.md` returns ≥ 1.
|
|
61
|
+
- `grep -c 'integration_checkpoint' .claude/skills/planning/SKILL.md` returns ≥ 1.
|
|
62
|
+
- `grep -c 'Integration Checkpoint Publish' .claude/skills/verifying/SKILL.md`
|
|
63
|
+
returns ≥ 1.
|
|
64
|
+
- With a checkpoint phase verified in a worktree, main fast-forwards to include
|
|
65
|
+
it and `.git/forge/integration-pending` is written; a sibling worktree's next
|
|
66
|
+
`/forge` boot fast-forwards (clean) or prompts to rebase (diverged).
|
|
@@ -97,6 +97,21 @@ releases:
|
|
|
97
97
|
bump: minor
|
|
98
98
|
reserved_at: "2026-06-21"
|
|
99
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."
|
|
105
|
+
- milestone: 16
|
|
106
|
+
version: "0.35.0"
|
|
107
|
+
bump: minor
|
|
108
|
+
reserved_at: "2026-06-21"
|
|
109
|
+
summary: "Merge often and early (issue #8). Stream integration was pull-based and deferred — ready work sat on its branch until milestone end, drifting from main and staling shared surfaces. Adds the stated principle to FORGE.md Project Streams (continuous integration posture; surfacing only, never auto-merge/auto-rebase). chief-of-staff gains an advisory Merge Cadence Check (Show + Sync): ready-to-merge surfacing from active.yml status:ready + merge_queue, idle-ready nudge, sibling-rebase nudge when main advanced on a shared surface, and merge-order recommendation. forge boot gains a light ready-to-merge nudge pointing to chief-of-staff. All advisory — never blocks, never merges, never rebases."
|
|
110
|
+
- milestone: 16
|
|
111
|
+
version: "0.36.0"
|
|
112
|
+
bump: minor
|
|
113
|
+
reserved_at: "2026-06-21"
|
|
114
|
+
summary: "Stream Integration Checkpoints — event-driven continuous integration, the producer/flag/consumer follow-up to #8's polling-based cadence check. (1) planning marks integration_checkpoint phases in plan frontmatter (advisory; default = last phase + depended-on phases; the mark is the opt-in so unmarked/existing work is unaffected). (2) Producer: verifying, on a PASSED + human-verified checkpoint phase in a worktree, fast-forward-only publishes to main (git push origin HEAD:main — git rejects non-ff, which is the safety; diverged main is surfaced, never forced) and sets an integration flag in .git/forge/integration-pending (git common dir, shared across a machine's worktrees). (3) Consumer: forge boot in a worktree reads the flag cheaply — set + no divergence → auto git merge --ff-only main (conflict-free); diverged → surface a rebase prompt; not set → skip (no fetch, no scan). Supersedes the 0.35.0 forge-boot polling pointer with event-driven detection. Cross-machine falls back to opt-in worktree_rebase_check. Never force-pushes, auto-resolves a conflict, or auto-rebases."
|
|
100
115
|
|
|
101
116
|
# Note on the 15 / 0.24.0 ordering: reserved as max(0.23.0)+minor. origin/main was
|
|
102
117
|
# already at 0.23.0 when this shipped (M10/M12/M13/M14 all merged), so 0.24.0 is a
|