forge-orkes 0.34.0 → 0.37.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 +101 -53
- package/template/.claude/skills/forge/SKILL.md +13 -0
- package/template/.claude/skills/planning/SKILL.md +10 -1
- package/template/.claude/skills/verifying/SKILL.md +23 -1
- package/template/.forge/FORGE.md +23 -3
- 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/migrations/0.37.0-derived-stream-registry.md +78 -0
- package/template/.forge/releases.yml +15 -0
- package/template/.forge/templates/streams/active.yml +23 -10
- package/template/.forge/templates/streams/stream.yml +4 -1
package/package.json
CHANGED
|
@@ -41,12 +41,13 @@ questions return to the Chief before work continues.
|
|
|
41
41
|
|
|
42
42
|
## Context Loading
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
`active.yml` is **derived** (ADR-015) — regenerate it, don't read a possibly-stale copy and never hand-edit it.
|
|
45
|
+
|
|
46
|
+
1. **Run the Stream Rollup** (below) to regenerate `.forge/streams/active.yml` from the per-stream files + active milestones, then read it. No `streams/` dir and no active milestones → nothing to roll up.
|
|
47
|
+
2. The per-stream files `.forge/streams/{stream}.yml` are the **source of truth** — load the selected stream's file for detail.
|
|
48
|
+
3. Load the selected stream's `brief.md` when the user needs status, handoff,
|
|
48
49
|
conflict context, or resume context.
|
|
49
|
-
|
|
50
|
+
4. Load work packages only when delegating, checking worker status, or closing
|
|
50
51
|
a stream.
|
|
51
52
|
|
|
52
53
|
Keep summaries in the registry short. Deep history belongs in stream briefs,
|
|
@@ -56,54 +57,50 @@ packages, plans, verification reports, commits, and archived artifacts.
|
|
|
56
57
|
|
|
57
58
|
| Intent | Examples | Action |
|
|
58
59
|
|--------|----------|--------|
|
|
59
|
-
| Show | "show streams", "active streams", "what is running?" | Run
|
|
60
|
+
| Show | "show streams", "active streams", "what is running?" | Run Stream Rollup + Merge Cadence Check, then summarize the derived registry without loading all deep history |
|
|
60
61
|
| Start | "start stream X", "new stream for billing" | Snapshot current stream, create stream files, register stream |
|
|
61
62
|
| Pause | "pause stream X" | Update brief, mark paused, keep next action explicit |
|
|
62
63
|
| Resume | "resume stream X" | Load stream context, set active, surface blockers and ownership |
|
|
63
64
|
| Delegate | "delegate stream X", "farm this out" | Create or update a work package and handoff prompt |
|
|
64
65
|
| Adopt M10 | "adopt existing M10 worktrees", "migrate active orchestrating sessions" | Wrap live M10 worktrees as streams without teardown |
|
|
65
|
-
| Sync | "sync streams" |
|
|
66
|
+
| Sync | "sync streams" | Update per-stream files from briefs, run Stream Rollup + Merge Cadence Check to regenerate the derived registry |
|
|
66
67
|
| Detect Conflicts | "detect conflicts", "check stream conflicts" | Compare ownership and dependencies |
|
|
67
68
|
| Merge Safe | "merge safe?", "what can land?" | Identify ready streams with no blocking conflicts |
|
|
68
69
|
| Close | "close stream X" | Record final status, archive/mark closed, clear active pointer if needed |
|
|
69
70
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
1.
|
|
83
|
-
`status
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
3.
|
|
91
|
-
`
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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.
|
|
71
|
+
## Stream Rollup (active.yml is derived)
|
|
72
|
+
|
|
73
|
+
`active.yml` is a **derived projection**, not a hand-maintained registry — it is
|
|
74
|
+
regenerated by joining the per-stream files with active milestones (ADR-015,
|
|
75
|
+
FORGE.md → Stream Rollup). This **replaces** the old advisory Registry Drift Check:
|
|
76
|
+
drift between the milestone view and the stream view can no longer occur, because
|
|
77
|
+
every field has one source and coverage is computed into the artifact. Run the
|
|
78
|
+
rollup at the **start of Show and Sync**, and after any Start/Resume/Pause/Close
|
|
79
|
+
edit to a stream file.
|
|
80
|
+
|
|
81
|
+
Procedure (deterministic + idempotent — never hand-edit `active.yml`):
|
|
82
|
+
|
|
83
|
+
1. Glob `.forge/streams/{stream}.yml`. Each → a row: `coordination` = the file's
|
|
84
|
+
`status`; plus goal, runtime (branch/worktree), ownership summary,
|
|
85
|
+
`merge_readiness` (from `merge.readiness`), `blocked_by`, `next_action`.
|
|
86
|
+
2. For a stream with `stream.milestone: m-{id}`, read `phase` + activity from
|
|
87
|
+
`.forge/state/milestone-{id}.yml` (`current.status`, `last_updated`) — do not
|
|
88
|
+
store workflow phase in the stream file. Linked milestone `deferred`/`complete`/
|
|
89
|
+
absent → `phase` reflects that (and surface it: a deferred milestone's stream
|
|
90
|
+
should likely pause; offer it).
|
|
91
|
+
3. Glob active milestones (`index.yml` `status: active`). Any with **no** stream
|
|
92
|
+
file → emit a derived `stream: implicit` row (phase from the milestone, no
|
|
93
|
+
coordination) so coverage is guaranteed — an active milestone is never silently
|
|
94
|
+
missing. Offer to materialize a stream file if it needs coordination (never
|
|
95
|
+
auto-create).
|
|
96
|
+
4. Derive `merge_queue:` — one entry per stream with `merge.readiness: ready`.
|
|
97
|
+
5. Write `active.yml` (`version`, `updated_at`, derived `streams:` sorted by id,
|
|
98
|
+
derived `merge_queue:`). No hand-edited keys.
|
|
99
|
+
|
|
100
|
+
Note: invoked directly, `/chief-of-staff` does not run `forge`'s milestone Rollup,
|
|
101
|
+
so `index.yml` may be slightly stale; read it as-is for step 3 and suggest a
|
|
102
|
+
`/forge` pass if it looks off. The Chief writes `active.yml` (derived class); it
|
|
103
|
+
never writes `index.yml` or any milestone file.
|
|
107
104
|
|
|
108
105
|
## Start Stream Flow
|
|
109
106
|
|
|
@@ -117,7 +114,7 @@ proceed with the requested Show/Sync.
|
|
|
117
114
|
- `.forge/streams/{id}.yml` from `.forge/templates/streams/stream.yml`
|
|
118
115
|
- `.forge/streams/{id}/brief.md` from `.forge/templates/streams/brief.md`
|
|
119
116
|
- `.forge/streams/{id}/packages/`
|
|
120
|
-
5.
|
|
117
|
+
5. Set the new stream file's `stream.milestone` link if it backs a milestone (else leave null for a standalone stream), then **regenerate `active.yml` via the Stream Rollup** — do not hand-write a registry entry.
|
|
121
118
|
6. Declare ownership:
|
|
122
119
|
- `owned_surfaces` for files or areas the stream may edit
|
|
123
120
|
- `shared_surfaces` for contracts, APIs, schemas, or docs touched with care
|
|
@@ -133,7 +130,7 @@ user asks to move to Chief/Streams. Do not teardown, merge, rebase, or remove
|
|
|
133
130
|
worktrees as part of adoption. Adoption only creates stream metadata around
|
|
134
131
|
existing M10 state.
|
|
135
132
|
|
|
136
|
-
1.
|
|
133
|
+
1. Ensure the `.forge/streams/` dir exists (`active.yml` is derived — it will be regenerated by the rollup in step 8, not hand-created).
|
|
137
134
|
2. Discover live M10 worktrees from both sources:
|
|
138
135
|
- `git worktree list --porcelain` branches matching `refs/heads/forge/m-*`
|
|
139
136
|
- `.forge/state/milestone-*.yml` with
|
|
@@ -174,7 +171,7 @@ existing M10 state.
|
|
|
174
171
|
- known blockers
|
|
175
172
|
- unknown ownership surfaces marked as needing declaration
|
|
176
173
|
- next action from milestone state or "declare ownership and sync"
|
|
177
|
-
8.
|
|
174
|
+
8. **Regenerate `active.yml` via the Stream Rollup** (do not hand-write the entry); set the adopted stream's `stream.milestone` link so its phase derives from milestone state.
|
|
178
175
|
9. Run conflict detection. Missing ownership is a conflict until clarified, but
|
|
179
176
|
it does not block adoption.
|
|
180
177
|
10. Ask before changing `.forge/project.yml`:
|
|
@@ -190,14 +187,14 @@ or path, update its summary and brief instead of creating a duplicate stream.
|
|
|
190
187
|
Pause:
|
|
191
188
|
1. Update the stream brief with current state, decisions, blockers, and next
|
|
192
189
|
action.
|
|
193
|
-
2. Set
|
|
194
|
-
|
|
190
|
+
2. Set the **stream file's** `status` to `paused` (or `delegated` if handed off),
|
|
191
|
+
then regenerate `active.yml` via the Stream Rollup.
|
|
195
192
|
3. Clear `current_stream` only if no stream remains active in this session.
|
|
196
193
|
|
|
197
194
|
Resume:
|
|
198
|
-
1.
|
|
195
|
+
1. Run the Stream Rollup, then load the stream file and brief.
|
|
199
196
|
2. Surface status, blockers, owned surfaces, shared surfaces, and next action.
|
|
200
|
-
3. Set the stream to `active`.
|
|
197
|
+
3. Set the **stream file's** `status` to `active`, then regenerate `active.yml`.
|
|
201
198
|
4. Run conflict detection before continuing.
|
|
202
199
|
|
|
203
200
|
## Delegate Flow
|
|
@@ -256,11 +253,56 @@ Use "merge safe" to identify streams that can land:
|
|
|
256
253
|
If any condition fails, mark the stream blocked or keep it ready with a named
|
|
257
254
|
reason it cannot merge yet.
|
|
258
255
|
|
|
256
|
+
## Merge Cadence Check
|
|
257
|
+
|
|
258
|
+
**Merge often and early** (FORGE.md Project Streams). Ready work integrated late
|
|
259
|
+
drifts from main, staleness accrues on shared surfaces, and the eventual merge is
|
|
260
|
+
larger and riskier. This check makes the cadence visible so integration happens
|
|
261
|
+
when work is ready — not at milestone end. Run it at the **start of the Show and
|
|
262
|
+
Sync intents**, after the Stream Rollup (which gives it a fresh derived registry).
|
|
263
|
+
|
|
264
|
+
**Advisory — it surfaces and recommends. It never merges, never rebases, and
|
|
265
|
+
never blocks.** Merging and rebasing stay human decisions (conflicts need
|
|
266
|
+
judgment); the Chief's job is to make "this is ready, integrate it now" impossible
|
|
267
|
+
to miss.
|
|
268
|
+
|
|
269
|
+
Streams that use **integration checkpoints** (FORGE.md → Stream Integration
|
|
270
|
+
Checkpoints) already fast-forward verified phases onto main automatically, so this
|
|
271
|
+
check focuses on what they don't cover: streams/phases **without** a checkpoint,
|
|
272
|
+
diverged streams whose publish was rejected (non-ff — they need a manual
|
|
273
|
+
merge/rebase), and **cross-stream merge order**. A checkpoint stream that is
|
|
274
|
+
cleanly auto-publishing needs no nudge here.
|
|
275
|
+
|
|
276
|
+
1. **Ready-to-merge surfacing.** From `active.yml`, collect streams with
|
|
277
|
+
`status: ready` (and any `merge_queue` entries). For each, run the Merge Safe
|
|
278
|
+
Flow conditions. Unblocked + no conflicts → list under **Ready to merge** with
|
|
279
|
+
a one-line *"ready — integrate now"* and, if known, how long it has been ready
|
|
280
|
+
(from the stream's `last_sync` / brief date). Add/refresh its `merge_queue`
|
|
281
|
+
entry (`status: waiting`). Blocked → list the named reason instead.
|
|
282
|
+
2. **Idle-ready nudge.** A stream that has sat `ready` across **multiple Show/Sync
|
|
283
|
+
passes** or whose branch is mergeable but untouched is the cadence smell.
|
|
284
|
+
Recommend integrating it before more divergence accrues. No magic threshold —
|
|
285
|
+
report the age and let the operator decide; the point is visibility, not a hard
|
|
286
|
+
cutoff.
|
|
287
|
+
3. **Sibling-rebase nudge.** When main has advanced on a **shared** or
|
|
288
|
+
**depended-on** surface since a live worktree branched, surface
|
|
289
|
+
*"main moved on {surface} — rebase worktree {stream} ({path}) before it drifts"*
|
|
290
|
+
for each affected live stream. Cheap detection: compare each live stream's
|
|
291
|
+
branch point against main for the shared surfaces it declares
|
|
292
|
+
(`git -C {worktree} rev-list --count HEAD..main -- {shared_surface}` > 0).
|
|
293
|
+
This is the cadence-driven form of the boot-time `forge.worktree_rebase_check`.
|
|
294
|
+
4. **Order.** When more than one stream is ready, recommend a merge order
|
|
295
|
+
(fewest shared-surface conflicts first; depended-on streams before dependents).
|
|
296
|
+
|
|
297
|
+
If nothing is ready and no worktree is behind on a shared surface, say so in one
|
|
298
|
+
line (`merge cadence: nothing ready, no rebases needed`) and continue.
|
|
299
|
+
|
|
259
300
|
## Close Flow
|
|
260
301
|
|
|
261
302
|
1. Confirm final status: merged, intentionally abandoned, superseded, or split.
|
|
262
303
|
2. Record final outcome in the stream brief.
|
|
263
|
-
3.
|
|
304
|
+
3. Set the **stream file's** `status` to `closed`, then regenerate `active.yml`
|
|
305
|
+
via the Stream Rollup.
|
|
264
306
|
4. Clear `current_stream` if this was the active stream.
|
|
265
307
|
5. Keep closed stream history available until a later archive/compaction pass.
|
|
266
308
|
|
|
@@ -273,9 +315,15 @@ Streams:
|
|
|
273
315
|
- billing-webhooks — active — owns api/billing, shared db/schema — next: verify webhook retries
|
|
274
316
|
- settings-ui — paused — owns app/settings — next: resume form validation
|
|
275
317
|
|
|
318
|
+
Ready to merge:
|
|
319
|
+
- reporting-export — ready 2 passes ago — no conflicts — integrate now (merge often and early)
|
|
320
|
+
|
|
321
|
+
Rebase needed:
|
|
322
|
+
- billing-webhooks — main moved on db/schema since it branched — rebase ../app-worktrees/billing-webhooks
|
|
323
|
+
|
|
276
324
|
Conflicts:
|
|
277
325
|
- billing-webhooks and reporting-export both touch db/schema. Contract owner needed before either merges.
|
|
278
326
|
|
|
279
327
|
Next:
|
|
280
|
-
-
|
|
328
|
+
- Merge reporting-export, then rebase billing-webhooks onto the new main.
|
|
281
329
|
```
|
|
@@ -36,6 +36,19 @@ git worktree list --porcelain 2>/dev/null \
|
|
|
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
|
+
**Stream Rollup (active.yml is derived).** If `.forge/streams/` has any stream files, regenerate `.forge/streams/active.yml` from them + active milestones per FORGE.md → Stream Rollup, the same way step 1.0 regenerates `index.yml`. `active.yml` is derived — never read it as authoritative without rolling up first, and never hand-edit it. Runs in the main checkout (worktrees never write `active.yml`). No `streams/` dir → skip.
|
|
49
|
+
|
|
50
|
+
**Ready-to-merge nudge (main checkout / streams without checkpoints).** From the just-regenerated `active.yml`, scan for streams with `coordination: 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.
|
|
51
|
+
|
|
39
52
|
### 1.0 State Rollup (index.yml is derived)
|
|
40
53
|
|
|
41
54
|
`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`.**
|
|
@@ -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)).
|
|
@@ -191,8 +202,8 @@ State lives in `.forge/`:
|
|
|
191
202
|
- `state/desire-paths/` — Append-only framework-usage observations, one file per observation. Occurrence counts derived by globbing (no mutable counter). Each carries `scope: project | framework` (set at capture; absent ⇒ project). **`forge` boot is the single review owner**: at 3+ occurrences it surfaces a concrete fix from the co-located suggestion table, persists declines to `declined/` (no re-nag), and for `scope: framework` signals routes them upstream — a portable block to `upstream/` plus a `gh issue` offer against `forge.upstream_repo`. This closes Principle 7's capture→act loop; `verifying` captures but no longer surfaces. See [ADR-012](../docs/decisions/ADR-012-upstream-desire-path-feedback-channel.md).
|
|
192
203
|
- `context.md` — Active locked decisions + deferred ideas (target <=12KB)
|
|
193
204
|
- `context-archive.md` — Historical locked decisions; load only when relevant
|
|
194
|
-
- `streams/active.yml` —
|
|
195
|
-
- `streams/{stream}.yml` — Per-stream
|
|
205
|
+
- `streams/active.yml` — **DERIVED** Project Chief traffic map. Regenerated by the Stream Rollup from the per-stream files + active milestone files (see Stream Rollup below). **Never hand-edited**, like `index.yml`. Each row carries the two orthogonal dimensions side by side: `phase` (from the milestone, for milestone-backed streams) and `coordination` (from the stream file). See [ADR-015](../docs/decisions/ADR-015-derived-stream-registry.md).
|
|
206
|
+
- `streams/{stream}.yml` — Per-stream **source of truth**: coordination lifecycle, ownership, shared surfaces, blockers, merge readiness, and an optional `stream.milestone: m-{id}` link. Standalone (quick-fix) streams own their `status` here; milestone-backed streams omit workflow phase (the rollup reads it from the milestone).
|
|
196
207
|
- `streams/{stream}/brief.md` — Human-readable stream context packet loaded when resuming that stream.
|
|
197
208
|
- `streams/{stream}/packages/{id}.yml` — Work package contract for delegated workers or manual sessions.
|
|
198
209
|
- `research/milestone-{id}.md` — Research findings snapshot (dated, immutable)
|
|
@@ -204,6 +215,15 @@ State lives in `.forge/`:
|
|
|
204
215
|
|
|
205
216
|
**Milestones** group phases into concurrent streams. Own state file — no conflicts across sessions. Can be deferred (frozen in place) or archive-deleted.
|
|
206
217
|
`index.yml status` gates routing: `not_started | active | deferred | complete`.
|
|
218
|
+
|
|
219
|
+
**Stream Rollup (`active.yml` is derived).** Mirrors the milestone Rollup: `active.yml` is a pure projection, regenerated — never hand-edited — by a deterministic, idempotent **join** of two single-sourced inputs (ADR-015). Run by the main/orchestrator session and at `chief-of-staff` Show/Sync; worktrees never write it. Procedure:
|
|
220
|
+
1. Glob `streams/{stream}.yml`. Each → a row carrying its coordination state (`coordination` = the file's `status`), goal, runtime, ownership summary, `merge.readiness`, blockers, next action — all from the stream file.
|
|
221
|
+
2. For a stream with `stream.milestone: m-{id}`, read `phase`/activity from `milestone-{id}.yml` (`current.status`, `last_updated`) — **not** stored in the stream file. A linked milestone that is `deferred`/`complete`/absent → the row's `phase` reflects that.
|
|
222
|
+
3. Glob active milestones (from `index.yml`). Any active milestone with **no** stream file → emit a derived `stream: implicit` row (phase from the milestone, no coordination state) so coverage is guaranteed in the artifact — an active milestone can never be silently missing.
|
|
223
|
+
4. Derive `merge_queue:` — one entry per stream with `merge.readiness: ready`.
|
|
224
|
+
5. Write `active.yml` (`version`, `updated_at`, derived `streams:` sorted by id, derived `merge_queue:`). No hand-edited keys.
|
|
225
|
+
|
|
226
|
+
Because each field has exactly one source and coverage is computed, the two-registry drift class (issue #4) cannot occur — this **supersedes** the advisory Registry Drift Check shipped in 0.33.0.
|
|
207
227
|
**Format**: YAML for machine state, Markdown for human content.
|
|
208
228
|
**`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).
|
|
209
229
|
|
|
@@ -226,7 +246,7 @@ with the work it describes. Every artifact has a sharing class:
|
|
|
226
246
|
| Class | Files | Write rule |
|
|
227
247
|
|---|---|---|
|
|
228
248
|
| **Single-owner mutable** | `state/milestone-{id}.yml`, `phases/milestone-{id}/`, `research/milestone-{id}.md` | Exactly one writer at a time — the worktree (or main session) currently driving that milestone. **Other worktrees never touch it**, not even to read-then-write — they pull from main if they need it. |
|
|
229
|
-
| **Derived** | `state/index.yml` | Never hand-edited. Regenerated by
|
|
249
|
+
| **Derived** | `state/index.yml`, `streams/active.yml` | Never hand-edited. Regenerated by rollup from their sources (`index.yml` ← `milestone-*.yml` via Rollup 1.0; `active.yml` ← per-stream files + active milestones via the Stream Rollup). Only the main/orchestrator session (and `chief-of-staff` for `active.yml`) runs rollup. |
|
|
230
250
|
| **Append-only shared** | `releases.yml` (version reservations), `state/desire-paths/*` (one file per observation) | Many writers OK; structure prevents collision. `releases.yml` uses the Version Reservation Protocol (append + commit + push before depending on the slot); desire-paths use distinct filenames so two writers never touch the same file. |
|
|
231
251
|
| **Shared mutable** | `context.md`, `refactor-backlog.yml`, `requirements/m{N}.yml` (ID space `FR-`/`DEF-`/`NFR-` is globally shared even though each milestone owns its file) | Write only to your milestone/stream block. Within a block, append-only; strike through instead of rewriting. |
|
|
232
252
|
| **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. |
|
|
@@ -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).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Migration Guide: Derived stream registry / Stream Rollup (Forge 0.37.0)
|
|
2
|
+
|
|
3
|
+
Applies to projects using Chief/Streams that have a **hand-maintained
|
|
4
|
+
`.forge/streams/active.yml` with stream entries**. `active.yml` becomes a
|
|
5
|
+
**derived projection** (ADR-015) — regenerated by the Stream Rollup from the
|
|
6
|
+
per-stream files + active milestones, never hand-edited. This is the durable fix
|
|
7
|
+
for issue [#4](https://github.com/Attuned-Media/forge/issues/4) and supersedes
|
|
8
|
+
the 0.33.0 Registry Drift Check.
|
|
9
|
+
|
|
10
|
+
The only thing that needs migrating is **data that lives only in `active.yml`**:
|
|
11
|
+
if a stream was tracked as a registry row but has no `.forge/streams/{stream}.yml`
|
|
12
|
+
source file, the rollup (which reads per-stream files) would drop it. The
|
|
13
|
+
migration materializes those files first, then lets the rollup regenerate
|
|
14
|
+
`active.yml`.
|
|
15
|
+
|
|
16
|
+
Projects with no streams, or whose `active.yml` is the empty stub, need nothing —
|
|
17
|
+
the next `forge` boot / `chief-of-staff` Show simply regenerates it in the derived
|
|
18
|
+
shape. (That is why Detection only fires when there are real stream rows.)
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
1. On the new version's framework files (`npx forge-orkes upgrade`, or the
|
|
23
|
+
`upgrading` skill).
|
|
24
|
+
2. Working tree clean or changes committed — the migration writes per-stream
|
|
25
|
+
files and rewrites `active.yml`.
|
|
26
|
+
|
|
27
|
+
## Detection
|
|
28
|
+
|
|
29
|
+
Fires only when `active.yml` is the **old hand-maintained shape** (no derived
|
|
30
|
+
marker) **and** carries real stream rows. Silent otherwise — already derived, no
|
|
31
|
+
streams, or no file:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
F=.forge/streams/active.yml
|
|
35
|
+
[ -f "$F" ] || exit 0
|
|
36
|
+
grep -q 'DO NOT HAND-EDIT' "$F" && exit 0 # already derived (new template marker)
|
|
37
|
+
if grep -qE '^[[:space:]]*-?[[:space:]]*id:[[:space:]]*\S' "$F"; then
|
|
38
|
+
echo "MIGRATE — active.yml is hand-maintained with stream entries (pre-ADR-015); materialize per-stream files, then it becomes derived"
|
|
39
|
+
fi
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Migration steps
|
|
43
|
+
|
|
44
|
+
### 1. Ensure every registry stream has a source file
|
|
45
|
+
|
|
46
|
+
For each stream row in the current `active.yml`, confirm a
|
|
47
|
+
`.forge/streams/{id}.yml` exists. For any that don't, create one from
|
|
48
|
+
`.forge/templates/streams/stream.yml` and copy the row's data into it:
|
|
49
|
+
|
|
50
|
+
- `stream.status` ← the row's status (coordination lifecycle);
|
|
51
|
+
- `stream.milestone` ← `m-{id}` if the stream backs a milestone, else leave
|
|
52
|
+
`null` (standalone / quick-fix stream);
|
|
53
|
+
- `runtime.branch` / `runtime.worktree`, `ownership.*`, `merge.readiness`,
|
|
54
|
+
`blockers`, `next_action` ← from the row.
|
|
55
|
+
|
|
56
|
+
Do **not** copy a workflow phase into the stream file — that derives from the
|
|
57
|
+
linked milestone.
|
|
58
|
+
|
|
59
|
+
### 2. Regenerate `active.yml` (derived)
|
|
60
|
+
|
|
61
|
+
Run `chief-of-staff` Show (or `/forge` boot) — it runs the Stream Rollup and
|
|
62
|
+
rewrites `active.yml` in the derived shape (header marker, `phase` + `coordination`
|
|
63
|
+
per row, derived `merge_queue`, plus `implicit` rows for active milestones with no
|
|
64
|
+
stream file). From here `active.yml` is regenerated, never hand-edited.
|
|
65
|
+
|
|
66
|
+
<!-- Lossy step (materializing files from registry rows) — confirm with the user
|
|
67
|
+
before writing if any row's data is ambiguous. Runs via quick-tasking. -->
|
|
68
|
+
|
|
69
|
+
## Validation
|
|
70
|
+
|
|
71
|
+
- `head -5 .forge/streams/active.yml` shows the `DERIVED — DO NOT HAND-EDIT`
|
|
72
|
+
marker.
|
|
73
|
+
- Every stream that was in the old registry has a `.forge/streams/{id}.yml`
|
|
74
|
+
source file.
|
|
75
|
+
- Re-running `chief-of-staff` Show produces byte-identical `active.yml` (the
|
|
76
|
+
rollup is idempotent).
|
|
77
|
+
- No active milestone is missing from the map (active milestones with no stream
|
|
78
|
+
file appear as `stream: implicit` rows).
|
|
@@ -102,6 +102,21 @@ releases:
|
|
|
102
102
|
bump: minor
|
|
103
103
|
reserved_at: "2026-06-21"
|
|
104
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."
|
|
115
|
+
- milestone: 16
|
|
116
|
+
version: "0.37.0"
|
|
117
|
+
bump: minor
|
|
118
|
+
reserved_at: "2026-06-22"
|
|
119
|
+
summary: "Derived stream registry / Stream Rollup (ADR-015) — the durable structural fix for issue #4's registry drift, superseding the 0.33.0 advisory Registry Drift Check. streams/active.yml becomes a DERIVED projection (like state/index.yml), never hand-edited, regenerated by a deterministic join-rollup over two single-sourced inputs: per-stream files streams/{stream}.yml (coordination lifecycle + ownership/runtime/merge/blockers) and active milestone files (workflow phase). Resolves the not-1:1 milestone↔stream relationship by keeping workflow phase and coordination status as orthogonal dimensions side by side in each derived row (phase from milestone, coordination from stream file) rather than collapsing one into the other; coverage is computed (active milestone with no stream file → derived 'implicit' row) so #4's exact symptom is structurally impossible. Adds stream.milestone link field (lazy; absent ⇒ standalone). forge boot + chief-of-staff Show/Sync run the Stream Rollup; chief Start/Pause/Resume/Close/Adopt write per-stream files then regenerate. Registry Drift Check removed. active.yml put in the derived state-ownership class (ADR-011); worktrees never write it. Migration: materialize per-stream files from a hand-maintained active.yml, then regenerate."
|
|
105
120
|
|
|
106
121
|
# Note on the 15 / 0.24.0 ordering: reserved as max(0.23.0)+minor. origin/main was
|
|
107
122
|
# already at 0.23.0 when this shipped (M10/M12/M13/M14 all merged), so 0.24.0 is a
|
|
@@ -1,32 +1,45 @@
|
|
|
1
1
|
# Forge Streams — Active Project Map
|
|
2
|
-
#
|
|
3
|
-
#
|
|
2
|
+
#
|
|
3
|
+
# DERIVED — DO NOT HAND-EDIT. This file is a projection regenerated by the
|
|
4
|
+
# Stream Rollup (FORGE.md → Stream Rollup) from two sources:
|
|
5
|
+
# - per-stream files .forge/streams/{stream}.yml (coordination + stream-only state)
|
|
6
|
+
# - active milestones .forge/state/milestone-*.yml (workflow phase)
|
|
7
|
+
# Edit those sources, then let `forge` boot or `chief-of-staff` Show/Sync
|
|
8
|
+
# regenerate this file. Hand edits are overwritten on the next rollup.
|
|
9
|
+
#
|
|
10
|
+
# Size gate: keep this file <= 20 KB. Summaries only; deep history lives in
|
|
11
|
+
# streams/{stream}/. See ADR-015.
|
|
4
12
|
|
|
5
13
|
version: 1
|
|
6
|
-
updated_at: null
|
|
14
|
+
updated_at: null # set by the rollup
|
|
7
15
|
|
|
8
16
|
project_chief:
|
|
9
17
|
current_stream: null
|
|
10
18
|
merge_policy: "chief-owned"
|
|
11
19
|
notes: ""
|
|
12
20
|
|
|
21
|
+
# Each row is DERIVED. `phase` comes from the linked milestone (milestone-backed
|
|
22
|
+
# rows); `coordination` comes from the stream file. `stream: implicit` marks an
|
|
23
|
+
# active milestone that has no stream file yet (coverage — materialize a stream
|
|
24
|
+
# file if it needs coordination).
|
|
13
25
|
streams:
|
|
14
26
|
# - id: "billing-retries"
|
|
15
|
-
#
|
|
27
|
+
# stream: explicit # explicit (has a stream file) | implicit (milestone-only)
|
|
28
|
+
# milestone: "m-12" # link, if milestone-backed; absent ⇒ standalone
|
|
29
|
+
# phase: executing # DERIVED from milestone current.status (backed rows only)
|
|
30
|
+
# coordination: active # DERIVED from stream file status: draft|active|paused|delegated|blocked|ready|merged|closed
|
|
16
31
|
# goal: "Fix checkout retry handling"
|
|
17
32
|
# branch: "forge/stream-billing-retries"
|
|
18
33
|
# worktree: "../app-worktrees/billing-retries"
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# shared_surfaces:
|
|
23
|
-
# - "src/lib/events.ts"
|
|
34
|
+
# owned_surfaces: ["src/billing/**"]
|
|
35
|
+
# shared_surfaces: ["src/lib/events.ts"]
|
|
36
|
+
# merge_readiness: not_ready # not_ready | ready | blocked | merged
|
|
24
37
|
# risk: medium # low | medium | high | unknown
|
|
25
38
|
# blocked_by: []
|
|
26
39
|
# next_action: "Review event contract before editing shared surface"
|
|
27
|
-
# last_sync: null
|
|
28
40
|
[]
|
|
29
41
|
|
|
42
|
+
# DERIVED — one entry per stream whose stream file has merge.readiness: ready.
|
|
30
43
|
merge_queue:
|
|
31
44
|
# - stream: "billing-retries"
|
|
32
45
|
# status: waiting # waiting | merging | blocked | merged
|
|
@@ -7,7 +7,10 @@ version: 1
|
|
|
7
7
|
stream:
|
|
8
8
|
id: ""
|
|
9
9
|
goal: ""
|
|
10
|
-
status: draft # draft | active | paused | delegated | blocked | ready | merged | closed
|
|
10
|
+
status: draft # COORDINATION lifecycle: draft | active | paused | delegated | blocked | ready | merged | closed
|
|
11
|
+
milestone: null # link to a milestone (e.g. "m-12"); null ⇒ standalone (quick-fix) stream.
|
|
12
|
+
# Set → Stream Rollup derives workflow `phase` from the milestone; do NOT
|
|
13
|
+
# duplicate workflow status here. This `status` stays the coordination dimension.
|
|
11
14
|
tier: null # quick | standard | full | null until known
|
|
12
15
|
created_at: null
|
|
13
16
|
updated_at: null
|