forge-orkes 0.36.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 +51 -53
- package/template/.claude/skills/forge/SKILL.md +3 -1
- package/template/.forge/FORGE.md +12 -3
- package/template/.forge/migrations/0.37.0-derived-stream-registry.md +78 -0
- package/template/.forge/releases.yml +5 -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
|
|
@@ -262,7 +259,7 @@ reason it cannot merge yet.
|
|
|
262
259
|
drifts from main, staleness accrues on shared surfaces, and the eventual merge is
|
|
263
260
|
larger and riskier. This check makes the cadence visible so integration happens
|
|
264
261
|
when work is ready — not at milestone end. Run it at the **start of the Show and
|
|
265
|
-
Sync intents**, after the
|
|
262
|
+
Sync intents**, after the Stream Rollup (which gives it a fresh derived registry).
|
|
266
263
|
|
|
267
264
|
**Advisory — it surfaces and recommends. It never merges, never rebases, and
|
|
268
265
|
never blocks.** Merging and rebasing stay human decisions (conflicts need
|
|
@@ -304,7 +301,8 @@ line (`merge cadence: nothing ready, no rebases needed`) and continue.
|
|
|
304
301
|
|
|
305
302
|
1. Confirm final status: merged, intentionally abandoned, superseded, or split.
|
|
306
303
|
2. Record final outcome in the stream brief.
|
|
307
|
-
3.
|
|
304
|
+
3. Set the **stream file's** `status` to `closed`, then regenerate `active.yml`
|
|
305
|
+
via the Stream Rollup.
|
|
308
306
|
4. Clear `current_stream` if this was the active stream.
|
|
309
307
|
5. Keep closed stream history available until a later archive/compaction pass.
|
|
310
308
|
|
|
@@ -45,7 +45,9 @@ git worktree list --porcelain 2>/dev/null \
|
|
|
45
45
|
|
|
46
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
47
|
|
|
48
|
-
**
|
|
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.
|
|
49
51
|
|
|
50
52
|
### 1.0 State Rollup (index.yml is derived)
|
|
51
53
|
|
package/template/.forge/FORGE.md
CHANGED
|
@@ -202,8 +202,8 @@ State lives in `.forge/`:
|
|
|
202
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).
|
|
203
203
|
- `context.md` — Active locked decisions + deferred ideas (target <=12KB)
|
|
204
204
|
- `context-archive.md` — Historical locked decisions; load only when relevant
|
|
205
|
-
- `streams/active.yml` —
|
|
206
|
-
- `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).
|
|
207
207
|
- `streams/{stream}/brief.md` — Human-readable stream context packet loaded when resuming that stream.
|
|
208
208
|
- `streams/{stream}/packages/{id}.yml` — Work package contract for delegated workers or manual sessions.
|
|
209
209
|
- `research/milestone-{id}.md` — Research findings snapshot (dated, immutable)
|
|
@@ -215,6 +215,15 @@ State lives in `.forge/`:
|
|
|
215
215
|
|
|
216
216
|
**Milestones** group phases into concurrent streams. Own state file — no conflicts across sessions. Can be deferred (frozen in place) or archive-deleted.
|
|
217
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.
|
|
218
227
|
**Format**: YAML for machine state, Markdown for human content.
|
|
219
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).
|
|
220
229
|
|
|
@@ -237,7 +246,7 @@ with the work it describes. Every artifact has a sharing class:
|
|
|
237
246
|
| Class | Files | Write rule |
|
|
238
247
|
|---|---|---|
|
|
239
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. |
|
|
240
|
-
| **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. |
|
|
241
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. |
|
|
242
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. |
|
|
243
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,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).
|
|
@@ -112,6 +112,11 @@ releases:
|
|
|
112
112
|
bump: minor
|
|
113
113
|
reserved_at: "2026-06-21"
|
|
114
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."
|
|
115
120
|
|
|
116
121
|
# Note on the 15 / 0.24.0 ordering: reserved as max(0.23.0)+minor. origin/main was
|
|
117
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
|