@jamie-tam/forge 6.1.0 → 6.2.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/README.md CHANGED
@@ -28,7 +28,7 @@ The v6 schema (`templates/manifests/v6/SCHEMA.md`) adds `phase_plan:` at the top
28
28
  ## Key Features
29
29
 
30
30
  - **31 skills** spanning the prototype-driven pipeline plus production-grade quality gates
31
- - **13 commands** for discovery, setup, workflows, knowledge capture, evolution, and validation
31
+ - **15 commands** for discovery, setup, workflows, knowledge capture, evolution, and validation
32
32
  - **17 specialized agents** with explicit phase-context (prototype-builder for Phase 3-4, builder for Phase 6, plus architects, reviewers, hunters, dreamers)
33
33
  - **8 common rules** auto-loaded every session (one — `testing.md` — is paths-conditional, loading only on test files and source code) + **8 common references** for skill authoring, agent coordination, and workflow protocol
34
34
  - **Work manifests** with `phase_plan` (preflight intent), `phases` (gate state), `slice_graph` (build decomposition), and `artifacts` (phase outputs + lock signals)
@@ -47,7 +47,7 @@ npx @jamie-tam/forge init
47
47
  This installs everything into your project's `.claude/` directory:
48
48
  - **Rules** — 8 common rules auto-loaded every session (one is paths-conditional) + language-specific rules layered per detected stack
49
49
  - **Skills** — 31 atomic skills covering the prototype-driven pipeline + production gates
50
- - **Commands** — 13 slash commands for discovery, setup, workflows, knowledge capture, evolution, and validation
50
+ - **Commands** — 15 slash commands for discovery, setup, workflows, knowledge capture, evolution, and validation
51
51
  - **Agents** — 17 specialized subagents with MCP server access (context7, playwright)
52
52
  - **Hooks** — gate-enforcer, wiki-lint, telemetry, state preservation, session checkpoints
53
53
  - **CLAUDE.md** — project configuration template
@@ -157,33 +157,35 @@ Commands (workflows) Skills (prefix-grouped) Rules (auto-l
157
157
  /refactor build-scaffold common/quality-gates
158
158
  /hotfix build-tdd [Phase 6] common/git-workflow
159
159
  /note (capture) build-pr-workflow common/testing (paths-conditional)
160
- /parallel (parallel) quality-code-review
161
- /status quality-test-plan
162
- /resume quality-test-execution References (load on demand)
163
- /forge-evolve quality-security-audit ----------------------------
164
- /validate quality-uiux common/
165
- deliver-deploy [Phase 7] agent-coordination
166
- deliver-db-migration io-protocol
167
- Work Manifests (v6) deliver-onboarding skill-authoring
168
- ------------------- discover-requirements skill-compliance
169
- .forge/work/ discover-codebase-analysis phases (canonical vocab)
170
- {type}/ plan-brainstorm coding-standards
171
- {name}/ plan-architecture quality-gates
172
- manifest.yaml plan-design-system feature-tracking
173
- schema_version: "6" plan-task-decompose typescript/ python/ react/
174
- phase_plan: {…} support-system-guide [extensible]
175
- phases: {…} support-debug
176
- slice_graph: {…} support-gotcha Protocols (read on demand)
177
- artifacts: {…} support-wiki-lint --------------------------
178
- support-wiki-bootstrap protocols/codex.md
179
- aiwiki/ (knowledge layer) support-dream protocols/graphify.md
180
- ------------------------- support-parallel
181
- decisions/ support-runtime-reachability Hooks
182
- gotchas/ support-skill-validator ------
183
- conventions/ gate-enforcer
184
- architecture/ wiki-lint
185
- sessions/ session-start / pre-compact
186
- raw/ telemetry
160
+ /dream (capture) quality-code-review
161
+ /wrap (capture) quality-test-plan
162
+ /parallel (parallel) quality-test-execution References (load on demand)
163
+ /status quality-security-audit ----------------------------
164
+ /resume quality-uiux common/
165
+ /forge-evolve deliver-deploy [Phase 7] agent-coordination
166
+ /validate deliver-db-migration io-protocol
167
+ deliver-onboarding skill-authoring
168
+ Work Manifests (v6) discover-requirements skill-compliance
169
+ ------------------- discover-codebase-analysis phases (canonical vocab)
170
+ .forge/work/ plan-brainstorm coding-standards
171
+ {type}/ plan-architecture quality-gates
172
+ {name}/ plan-design-system feature-tracking
173
+ manifest.yaml plan-task-decompose typescript/ python/ react/
174
+ schema_version: "6" support-system-guide [extensible]
175
+ phase_plan: {…} support-debug
176
+ phases: {…} support-gotcha Protocols (read on demand)
177
+ slice_graph: {…} support-wiki-lint --------------------------
178
+ artifacts: {…} support-wiki-bootstrap protocols/codex.md
179
+ support-dream protocols/graphify.md
180
+ aiwiki/ (knowledge layer) support-parallel
181
+ ------------------------- support-runtime-reachability Hooks
182
+ decisions/ support-skill-validator ------
183
+ gotchas/ gate-enforcer
184
+ conventions/ wiki-lint
185
+ architecture/ session-start / pre-compact
186
+ sessions/ (per-session) telemetry
187
+ raw/ (free-form notes)
188
+ oracles/ (prototype contracts)
187
189
  proposed/ (dream queue)
188
190
  schemas/
189
191
  CLAUDE.md (usage rules)
@@ -203,6 +205,8 @@ aiwiki/ (knowledge layer) support-dream protocols/gra
203
205
  | `/refactor` | Analyze, plan approach, restructure with tests, PR | Code needs cleanup without new functionality |
204
206
  | `/hotfix` | Emergency compressed flow -- debug, minimal test, deploy | Production is down, need a fix now |
205
207
  | `/note` | Append an ad-hoc research note or brainstorm to `aiwiki/raw/{date}.md` | Phase 1-2 research, half-formed thoughts, anything that doesn't yet fit a typed page |
208
+ | `/dream` | Manually trigger aiwiki consolidation (merge duplicates, promote raw → typed, prune stale) | After a refactor, branch merge, or whenever `aiwiki/` feels noisy. Auto-fires at phase-close + PreCompact too. |
209
+ | `/wrap` | Capture & finalize the current Claude session — fills `aiwiki/sessions/{date}-{id}.md` with Files touched / Decisions / Gotchas / Open questions / Next steps | At the natural end of a working session, before a long break, or before switching focus mid-day. Next session-start hook reads it. |
206
210
  | `/parallel` | Dispatch parallel agents for a punch list of ad-hoc tasks; phase-aware sizing | Multiple independent small tasks to crunch in one pass |
207
211
  | `/status` | List in-flight `.forge/work` items and their current phase | Check what's open before starting new work |
208
212
  | `/resume` | Continue a paused work item from its current phase | Pick up a `.forge/work` item left mid-flow |
package/agents/dreamer.md CHANGED
@@ -61,10 +61,14 @@ Apply operations in this order:
61
61
  3. **Prune stale** — for each entry whose cited code no longer exists OR whose decision is superseded:
62
62
  - Mark for deletion in the manifest's `operations` (`op: prune`)
63
63
  - Do NOT write a "tombstone" file; absence in proposed/ means delete on accept
64
- 4. **Refresh session file (PreCompact only, conditional)** — for `aiwiki/sessions/{current}.md`:
65
- - **Check first**: does `aiwiki/sessions/{current}.md` exist? Session-checkpoint hooks (SessionStart create + PostToolUse append) are currently **deferred** per `templates/aiwiki/schemas/session.md`. If the file does NOT exist, SKIP this step entirely no failure, no fresh-write. Proceed with raw + typed page consolidation only.
66
- - If it DOES exist: read it (the hook-maintained event log), consolidate the event log into the schema sections (Files touched, Decisions made, Gotchas surfaced, Open questions, Next steps), and write the refined version to `aiwiki/proposed/{dream_id}/sessions/{current}.md`.
67
- - DO NOT recreate the file if missing that would generate speculation (`templates/aiwiki/CLAUDE.md.template:76` forbids it). The skip-if-missing branch handles the deferred-hooks state cleanly.
64
+ 4. **Refine the active session file (PreCompact and phase-close triggers)** — locate `aiwiki/sessions/{date}-{session_id_short}.md`:
65
+ - **The file is expected to be present.** `hooks/scripts/pre-compact.sh` creates it lazily on first PreCompact fire; `/wrap`, `/dream`, and `harden` also create it lazily if absent. By the time you run, one of those has fired during this session so the file exists.
66
+ - **If it is truly missing** (no in-session writer fired before you, no `aiwiki/sessions/{today}-*.md` matches), this is a non-fatal anomaly: log it in the dream manifest's `lint_warnings` as `session_file_missing: true` and proceed with raw + typed page consolidation only. Do NOT fabricate a session file — let the next writer (pre-compact, /wrap, harden) create it cleanly.
67
+ - **If it exists**: read it. The `## Checkpoints` section is append-only event log written by pre-compact and dream itself. Your refinement work targets:
68
+ - **Trim `## Checkpoints`**: if more than 10 entries, summarize older ones into a single "## Checkpoint summary {date-range}" entry. Preserve any `Status: unconsumed` entries as-is.
69
+ - **Pre-populate index sections** (`## Files touched`, `## Decisions made`, `## Gotchas surfaced`, `## Open questions`, `## Next steps`) from git diff + aiwiki writes during this session. Mark each line with a `<!-- dream-suggested -->` HTML comment so `/wrap` knows what dream proposed vs what the user wrote.
70
+ - **Do NOT set `status: done`** — that's `/wrap`'s responsibility. Leave `status: active`.
71
+ - Write the refined version to `aiwiki/proposed/{dream_id}/sessions/{date}-{session_id_short}.md`.
68
72
 
69
73
  ### Phase 4: Prune & index
70
74
 
@@ -93,7 +97,7 @@ Apply operations in this order:
93
97
  - ANY file in `aiwiki/` (input store untouched)
94
98
  - ANY file in `.forge/work/` (operational state, not knowledge)
95
99
  - Tombstone files for prunes (manifest's `operations` log records the prune; absence in proposed/ means delete on accept)
96
- - A fresh `aiwiki/sessions/{current}.md` if it doesn't exist — session-checkpoint hooks are currently deferred per `templates/aiwiki/schemas/session.md`; SKIP session-file refinement instead (no failure, no speculation-write)
100
+ - A fresh `aiwiki/sessions/{date}-{session_id_short}.md` if it doesn't exist — let the next pre-compact / /wrap / harden writer create it cleanly. If it's truly missing when you run, log `session_file_missing: true` in the dream manifest's `lint_warnings` and skip session-file refinement (no failure, no speculation-write)
97
101
  - Any file outside `aiwiki/proposed/{dream_id}/`
98
102
 
99
103
  ## Provider Mode (for `anthropic-managed` only)
@@ -110,7 +114,7 @@ If dispatched with `provider: anthropic-managed`:
110
114
 
111
115
  | Mistake | Fix |
112
116
  |---|---|
113
- | Recreating `aiwiki/sessions/{current}.md` instead of refining the existing one | The session file MUST exist (hook created it). If absent, FAIL — don't paper over an upstream bug. |
117
+ | Recreating `aiwiki/sessions/{date}-{session_id_short}.md` instead of refining the existing one | The session file is expected to exist (pre-compact / /wrap / harden creates it lazily). If absent when you run, log `session_file_missing: true` in the manifest and skip session refinement — don't fabricate a session file. The next writer will create it cleanly. |
114
118
  | Promoting a raw entry that doesn't satisfy the target schema | Validate against schema first; failures go into `lint_warnings`, not into `aiwiki/proposed/{type}/` |
115
119
  | Merging unrelated typed pages because they share a keyword | Merge requires shared root cause / topic, not surface-level term overlap |
116
120
  | Pruning an entry without checking if the citation still resolves | Re-check the cited file/symbol before marking prune; LINT staleness != prune trigger |
@@ -70,6 +70,8 @@ State commands
70
70
 
71
71
  Knowledge commands
72
72
  /note <text> append a research note / brainstorm to aiwiki/raw/{date}.md
73
+ /dream [scope] consolidate aiwiki — merge duplicates, promote raw → typed, prune stale
74
+ /wrap [focus] capture & finalize current session into aiwiki/sessions/{date}-{id}.md
73
75
 
74
76
  System commands
75
77
  /setup detect stack, fill project profile, scaffold .forge/ + aiwiki/
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: dream
3
+ description: "Manually trigger aiwiki consolidation. Merges duplicate notes, promotes raw → typed pages, prunes stale entries. Output is written to aiwiki/proposed/{dream_id}/ for review — input store is never modified. Use after a major refactor, a long session, or whenever aiwiki/ feels noisy. Optional argument: scope (default = full aiwiki/; alternatives = aiwiki/raw/, aiwiki/gotchas/, etc.)."
4
+ ---
5
+
6
+ # /dream — Consolidate aiwiki
7
+
8
+ Manual trigger for `support-dream`. Produces a reviewable consolidation proposal in `aiwiki/proposed/{dream_id}/`; you accept or reject via the web view (`forge wiki ui`) or CLI (`forge wiki review {dream_id}`).
9
+
10
+ This is the user-driven trigger. Dream also fires automatically:
11
+ - **PreCompact** — `hooks/scripts/pre-compact.sh` appends a `**Dream directive (unconsumed)**` block to the active session file's `## Checkpoints` section (`aiwiki/sessions/{date}-{session_id_short}.md`, created lazily). The post-compact agent reads the session file, finds the directive, and invokes `support-dream`.
12
+ - **Phase-close** — `iterate-prototype`, `harden`, `build-pr-workflow`, and `deliver-deploy` dispatch `support-dream` after writing their respective `artifacts.{phase}.locked_at` lock signal.
13
+
14
+ The manual `/dream` invocation is the escape hatch for between-trigger consolidation.
15
+
16
+ ## Steps
17
+
18
+ 1. **Parse scope** from the user's argument:
19
+ - No argument → scope is the full `aiwiki/` tree.
20
+ - One token (`raw`, `gotchas`, `decisions`, `conventions`, `architecture`, `sessions`) → scope is `aiwiki/{token}/`.
21
+ - Multiple tokens or explicit path → scope is the union of those paths.
22
+ 2. **Verify aiwiki exists.** If `aiwiki/` is missing, dispatch `support-wiki-bootstrap` first.
23
+ 3. **Check for pending dreams.** If `aiwiki/proposed/{dream_id}/` directories already exist with `review_status: pending` in their manifest, surface them to the user and ask whether to queue a new dream or review the pending ones first. Do not silently overwrite.
24
+ 4. **Invoke `support-dream` skill** with the parsed scope and `trigger: manual`. The skill dispatches the `dreamer` subagent and writes the proposed output.
25
+ 5. **Report to the user**: new `dream_id`, list of `changed_pages` / `new_pages` / `deleted_pages` counts, lint status, and the path to review:
26
+ ```
27
+ Dream complete: 2026-05-18-1742-manual
28
+ Proposals: aiwiki/proposed/2026-05-18-1742-manual/
29
+ Changed: 3 New: 1 Deleted: 0 Lint: passed
30
+ Review: `forge wiki review 2026-05-18-1742-manual` or open `forge wiki ui`
31
+ ```
32
+
33
+ ## Example
34
+
35
+ User: `/dream`
36
+ → Full aiwiki consolidation, dispatched as `trigger: manual`.
37
+
38
+ User: `/dream raw gotchas`
39
+ → Scope limited to `aiwiki/raw/` + `aiwiki/gotchas/`.
40
+
41
+ User: `/dream after the auth refactor`
42
+ → Free-form description folded into `trigger_detail`; scope defaults to full aiwiki.
43
+
44
+ ## When to use
45
+
46
+ - After a **major refactor** or **branch merge** brought in lots of new wiki entries.
47
+ - When `aiwiki/raw/` has accumulated unclassified notes from `/note` invocations.
48
+ - When you suspect **duplicate gotchas** across recent debugging sessions.
49
+ - Before **handoff** to a new contributor — get the wiki into curated shape first.
50
+ - When `forge wiki status` shows no pending dreams but the aiwiki feels noisy.
51
+
52
+ ## When NOT to use
53
+
54
+ - A dream is already pending review (`forge wiki status` lists it). Review the existing one first; queueing a new dream against the same source state produces overlapping proposals.
55
+ - `aiwiki/` has no recent activity — there's nothing to consolidate; the cycle would no-op.
56
+ - You want to **edit a single page**. Edit it directly. Dream is for *merging / promoting / pruning across pages*, not per-page revision.
57
+
58
+ ## I/O Contract
59
+
60
+ | Field | Value |
61
+ |---|---|
62
+ | **Requires** | `aiwiki/` (scaffolded by `/setup`), `aiwiki/schemas/` |
63
+ | **Produces** | `aiwiki/proposed/{dream_id}/` (mirror structure) + `.dream-manifest.json` |
64
+ | **Dispatches** | `support-dream` skill → `dreamer` subagent |
65
+ | **Review surface** | `forge wiki ui` (web view at 127.0.0.1:8765) or `forge wiki review/accept/reject` CLI |
66
+
67
+ ## Do NOT
68
+
69
+ - Do NOT modify `aiwiki/` directly inside this flow — that is `support-dream`'s invariant.
70
+ - Do NOT queue a new dream while one is pending review against the same source state.
71
+ - Do NOT skip the lint pass — `support-dream` runs lint on the proposed output before marking the dream complete.
@@ -206,7 +206,12 @@ Execute the slice graph from Phase 5. Per slice:
206
206
  2. REQUIRED SUB-SKILL: Use **quality-code-review**
207
207
  3. Fix any Critical or Important findings
208
208
  4. Per-slice user-confirm
209
- 5. Per-slice dream consolidates slice-scoped wiki updates
209
+ 5. **Per-slice dream (auto-fire on slice close).** After the slice's gates pass (`gate-passed: true` on the slice's `code-review` + `runtime-reach`), invoke the **support-dream** skill with:
210
+ - **scope:** `aiwiki/gotchas/`, `aiwiki/conventions/` (any subfolders the slice's builder + reviewer subagents wrote to; check git diff on `aiwiki/` since the slice started for a precise list)
211
+ - **trigger:** `phase-close`
212
+ - **trigger_detail:** `"Phase 6 per-slice — {slice_id}"`
213
+ Dream output goes to `aiwiki/proposed/{dream_id}/`. Surface the id + review path to the user. The next slice can start while the proposal is pending review (per-slice dreams do NOT block forward motion — only phase-close gates do).
214
+ **Skip when:** the slice's build wrote nothing to `aiwiki/` (pure code change with no new gotcha or convention). No-op dreams add noise.
210
215
 
211
216
  For `--size major` features: also escalate to `quality-security-audit` on slices that touch auth/payments/PII.
212
217
 
@@ -214,7 +219,7 @@ Optional: `/autopilot production` for Ralph-loop hands-off slice execution *(pla
214
219
 
215
220
  ### GATE: All Slices Complete
216
221
 
217
- All slices `gate-passed: true`. Update manifest: `artifacts.production-build.locked_at` (the slice terminal state + the production code ARE the production-build artifacts).
222
+ All slices `gate-passed: true`. Update manifest: `artifacts.production-build.locked_at` (the slice terminal state + the production code ARE the production-build artifacts). Any pending per-slice dream proposals from Step 8.5 must be reviewed before Phase 7 (deliver) starts — Phase 7's retrospective dream depends on a consolidated wiki state.
218
223
 
219
224
  ## Step 9: Test Plan + Execution
220
225
 
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: wrap
3
+ description: "Capture and finalize the current Claude session. Writes ## Files touched / ## Decisions made / ## Gotchas surfaced / ## Open questions / ## Next steps into aiwiki/sessions/{date}-{session_id_short}.md, then sets status: done. Use at the natural end of a working session so the next session-start hook can surface a meaningful handoff. Optional argument: a one-line focus statement (otherwise inferred from the active manifest)."
4
+ ---
5
+
6
+ # /wrap — Capture and finalize the current session
7
+
8
+ Finalize this Claude session's handoff artifact. Writes the index sections (Files touched / Decisions / Gotchas / Open questions / Next steps) into `aiwiki/sessions/{date}-{session_id_short}.md` so the next session-start hook can surface a meaningful handoff.
9
+
10
+ **Distinct from `/dream`:** `/wrap` captures *this session's* knowledge (what was worked on, what was decided). `/dream` consolidates *the whole aiwiki* (merges duplicates, promotes raw → typed). The two can be run sequentially at session end (`/wrap` first, then `/dream`) but they answer different questions.
11
+
12
+ ## Steps
13
+
14
+ 1. **Determine session file path.**
15
+ - Read `session_id` from the most recent SessionStart context (Claude Code provides this in the hook payload; if running standalone, ask the user or read from `aiwiki/sessions/*.md` mtime).
16
+ - Path: `aiwiki/sessions/{ISO-date}-{session_id_short7}.md` (the same path pre-compact would have used). If the file already exists (created by pre-compact), append to it. If not, create it lazily here.
17
+
18
+ 2. **Determine focus.**
19
+ - If `/wrap <focus statement>` was supplied, use that.
20
+ - Else: read the active work item from `.forge/work/*/*/manifest.yaml` where `status: in-progress`. Focus = `{type}/{name}` (e.g. `feature/wire-dream`).
21
+ - Else: ask the user "What was this session about?" — one-line answer.
22
+
23
+ 3. **Read the session file** (if it already has content from pre-compact).
24
+ - The `## Checkpoints` section stays as-is — that's event log, not user-facing summary.
25
+ - The index sections (`## Files touched`, etc.) are what you fill.
26
+
27
+ 4. **Capture `## Files touched`.**
28
+ - Run `git diff --name-only $(git merge-base HEAD main)..HEAD` (or `HEAD~10..HEAD` for non-branch work) to find files changed during the session.
29
+ - For each: cite as `[path](path:line)` if a specific line range was the focus; else `[path](path)`.
30
+ - LINT will auto-fill `@<sha7>` on save.
31
+ - Skip generated files, dependency lockfiles, build artifacts.
32
+
33
+ 5. **Capture `## Decisions made`.**
34
+ - List ADRs in `aiwiki/decisions/` written or modified during this session.
35
+ - Format: `- [decision-NNNN: short title](aiwiki/decisions/NNNN-slug.md)`.
36
+ - If none were written but a decision-worthy choice was made conversationally, note: "DEFERRED: {one-line description} — should become an ADR but wasn't written this session."
37
+
38
+ 6. **Capture `## Gotchas surfaced`.**
39
+ - List gotchas in `aiwiki/gotchas/` created or updated this session.
40
+ - Same link format.
41
+ - If a gotcha was hit but not captured, note it as DEFERRED.
42
+
43
+ 7. **Capture `## Open questions`.**
44
+ - List raw notes in `aiwiki/raw/{today}.md` that represent unresolved questions (entries starting with "TBD", "open", "?", or that were /note'd as questions).
45
+ - Format: `- [HH:MM question title](aiwiki/raw/{date}.md#anchor)`.
46
+ - If no /note questions were captured but threads are open, list them as bare bullets.
47
+
48
+ 8. **Capture `## Next steps`.**
49
+ - 2-5 bullets: what the next session should do.
50
+ - Each bullet should reference a file/manifest/issue. No vague "continue working on X."
51
+ - Examples:
52
+ - "Resume `feature/wire-dream` at Phase 6 (slice graph in manifest) — first slice: `wire-pre-compact-hook`."
53
+ - "Review pending dream `aiwiki/proposed/2026-05-18-1742-manual/` before next phase."
54
+ - "Address open question on token rotation policy — see `aiwiki/raw/2026-05-18.md#14-23`."
55
+
56
+ 9. **Update frontmatter.**
57
+ - Set `focus: {focus}` (from Step 2).
58
+ - Set `status: done`.
59
+ - Set `date_end: {today ISO date}`.
60
+ - Set `last_commit: {git rev-parse --short HEAD}` if in a git repo with commits.
61
+
62
+ 10. **Confirm with the user.**
63
+ - Surface the drafted session file content.
64
+ - Ask: "Save this as your session handoff?" — yes / edit / skip.
65
+ - If edit: take inline edits, re-render, ask again.
66
+ - If skip: leave the file's `status: active` (next session-start will surface it as unfinalized).
67
+
68
+ 11. **Save and lint.**
69
+ - Write the file.
70
+ - `wiki-lint` runs automatically on save (PostToolUse hook).
71
+ - If lint surfaces warnings (missing citations, stale `@<sha7>`, etc.), address before considering /wrap complete.
72
+
73
+ 12. **Suggest follow-ups.**
74
+ - If `aiwiki/raw/{today}.md` has unconsolidated entries, suggest: "You have N raw notes from this session — consider `/dream raw` to consolidate before next session."
75
+ - If a pending dream proposal exists in `aiwiki/proposed/`, surface: "N pending dream proposals — review via `forge wiki ui` before next session."
76
+
77
+ ## Example
78
+
79
+ ```
80
+ User: /wrap
81
+
82
+ Agent: Session 2026-05-18-7e8a3f2 (focus: feature/wire-dream).
83
+ Drafted handoff with:
84
+ - 11 files touched (skills/, hooks/, commands/, templates/)
85
+ - 1 decision (consolidate notepad → sessions/)
86
+ - 0 new gotchas this session
87
+ - 2 open questions
88
+ - 4 next-step bullets
89
+
90
+ [Renders the proposed file content]
91
+
92
+ Save?
93
+
94
+ User: yes
95
+
96
+ Agent: Saved aiwiki/sessions/2026-05-18-7e8a3f2.md (status: done).
97
+ Suggestion: 3 raw notes from /note today — consider /dream raw to
98
+ consolidate before next session.
99
+ ```
100
+
101
+ ## When to use
102
+
103
+ - **At the natural end of a working session** before exiting Claude Code. Even a 30-second wrap-up preserves the handoff signal.
104
+ - **Before a long break** (overnight, end of day). The next session-start surfaces this file so you don't lose context.
105
+ - **Before a major context shift** (switching to a different feature mid-day). Wrap the current focus, then start fresh.
106
+ - **After a phase locks** if the natural pause is also a session end. (Phase-close already triggers a dream — `/wrap` is the complementary capture for what *you* did, while dream consolidates the *wiki state*.)
107
+
108
+ ## When NOT to use
109
+
110
+ - **Trivial sessions** (a single read, a one-line edit). No handoff signal — skip /wrap and let the next session-start surface "no recent session" (silence is fine).
111
+ - **Mid-task interruptions** where you'll be right back. /wrap is for genuine session boundaries.
112
+ - **As a substitute for typed-page writes.** Decisions belong in `aiwiki/decisions/` directly; gotchas in `aiwiki/gotchas/`. /wrap is the *index* of what was written elsewhere — it doesn't replace writing the artifacts themselves.
113
+ - **As a substitute for `/dream`.** /wrap captures this session's work; /dream consolidates the whole aiwiki. Use both at the right times.
114
+
115
+ ## I/O Contract
116
+
117
+ | Field | Value |
118
+ |---|---|
119
+ | **Requires** | `aiwiki/sessions/` (scaffolded by `/setup`), Claude Code's hook context for `session_id` (or interactive fallback) |
120
+ | **Produces** | `aiwiki/sessions/{date}-{session_id_short}.md` with index sections filled and `status: done` |
121
+ | **Triggers** | `wiki-lint` PostToolUse hook on save |
122
+ | **Feeds into** | `session-start.sh` (next session reads it), `support-dream` (refines on next dream cycle) |
123
+
124
+ ## Do NOT
125
+
126
+ - Do NOT auto-fire `/dream` from inside `/wrap`. The two are separate concerns; user decides which to run. /wrap can SUGGEST /dream when raw notes accumulated, but does not invoke it.
127
+ - Do NOT overwrite the `## Checkpoints` section if pre-compact wrote to it during the session — that's append-only event log, preserved as-is.
128
+ - Do NOT write vague prose. Index of links, not narrative. Future sessions follow the links to actual artifacts.
129
+ - Do NOT capture every file diff. Skip dependency lockfiles, build artifacts, anything ≤2 lines of cosmetic change. Index the meaningful work.
130
+ - Do NOT set `status: done` if the user said "skip" at Step 10 — leave `status: active` so the next session-start surfaces it.
package/dist/init.js CHANGED
@@ -12,7 +12,7 @@ import { hasForgeMarkers, mergeForgeBlock } from "./merge.js";
12
12
  * entries the user does not already have. Creates .gitignore if absent.
13
13
  *
14
14
  * Entries:
15
- * .forge/state/ — operational state (notepad, telemetry, dream history)
15
+ * .forge/state/ — operational state (telemetry, dream history; session handoff lives in aiwiki/sessions/)
16
16
  * .forge/local.yaml — per-user preferences (Codex/Graphify consent, etc.)
17
17
  *
18
18
  * Why at install time: pre-compact.sh used to add `.forge/state/` from the
@@ -1,5 +1,5 @@
1
1
  {
2
- "_comment": "Maps manifest gate names to required skill and agent invocations. Used by gate-enforcer.sh to verify prerequisites before allowing gate-passed: true. Agents are dispatched by skills internally — listed here so the enforcer can verify they were invoked via telemetry.",
2
+ "_comment": "Maps manifest gate names to required skill and agent invocations. Used by gate-enforcer.sh to verify prerequisites before allowing gate-passed: true. Enforcement is work_id-scoped (v6.2+): the enforcer filters .forge/state/telemetry.jsonl to records whose work_id matches the manifest being edited (extracted from .forge/work/{type}/{name}/manifest.yaml). A stale invocation from another work item, or a legacy record written before work_id was added, does NOT satisfy a fresh gate. Agents are dispatched by skills internally — listed here so the enforcer can verify they were invoked via telemetry.",
3
3
  "requirements": {
4
4
  "skill": "discover-requirements",
5
5
  "agent": null
@@ -83,6 +83,14 @@ if [ ! -f "$CONFIG" ]; then
83
83
  exit 0
84
84
  fi
85
85
 
86
+ # Extract work_id from the manifest path: .forge/work/{type}/{name}/manifest.yaml
87
+ # Used to filter telemetry by work item so a stale invocation from another work
88
+ # item cannot satisfy this gate (closes P0-5 from v6.1-beta audit).
89
+ WORK_ID=""
90
+ if [[ "$FILE_PATH" =~ \.forge/work/([^/]+)/([^/]+)/manifest\.yaml$ ]]; then
91
+ WORK_ID="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
92
+ fi
93
+
86
94
  # Check each gate being passed against requirements
87
95
  BLOCKED_REASONS=""
88
96
 
@@ -126,18 +134,55 @@ for GATE in $(jq -r 'keys[] | select(. != "_comment")' "$CONFIG"); do
126
134
  # Resolve required agents: agents array first, then single agent field
127
135
  REQUIRED_AGENTS=$(jq -r "if .\"$GATE\".agents then .\"$GATE\".agents[] else .\"$GATE\".agent // empty end" "$CONFIG" 2>/dev/null)
128
136
 
129
- # Check skill invocation in telemetry
137
+ # Telemetry check is work_id-scoped (closes P0-5 cross-work-item bypass).
138
+ # Records without work_id (legacy or no-active-work) are NOT counted —
139
+ # an untagged invocation can't satisfy a gate on a specific work item.
140
+ # Records lacking jq-parsable shape are also ignored (jq returns null per line;
141
+ # `select(...)` filters them out).
142
+ check_invocation() {
143
+ local NAME="$1"
144
+ if [ ! -f "$TELEMETRY" ]; then
145
+ return 1
146
+ fi
147
+ if [ -z "$WORK_ID" ]; then
148
+ # No work_id resolved from path — should be rare; fall back to bare-name
149
+ # check so we don't accidentally hard-block manifest edits made outside
150
+ # the .forge/work/{type}/{name}/ tree (unlikely given the path filter
151
+ # at line ~43 already excluded non-manifest paths, but defensive).
152
+ grep -q "\"name\":\"$NAME\"" "$TELEMETRY" 2>/dev/null
153
+ else
154
+ # jq -s collects all JSONL lines into an array. select() narrows to the
155
+ # exact work_id + name pair. length > 0 means at least one invocation
156
+ # in this work item. The 2>/dev/null swallows parse errors on
157
+ # malformed records (treated as no match — correct behavior).
158
+ local COUNT
159
+ COUNT=$(jq -s --arg work_id "$WORK_ID" --arg name "$NAME" \
160
+ 'map(select(.work_id == $work_id and .name == $name)) | length' \
161
+ "$TELEMETRY" 2>/dev/null || echo 0)
162
+ [ "$COUNT" != "0" ] && [ -n "$COUNT" ]
163
+ fi
164
+ }
165
+
166
+ # Check skill invocation in telemetry (work_id-scoped)
130
167
  if [ -n "$REQUIRED_SKILL" ]; then
131
- if [ ! -f "$TELEMETRY" ] || ! grep -q "\"name\":\"$REQUIRED_SKILL\"" "$TELEMETRY"; then
132
- BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires skill '$REQUIRED_SKILL' (not found in telemetry). "
168
+ if ! check_invocation "$REQUIRED_SKILL"; then
169
+ if [ -n "$WORK_ID" ]; then
170
+ BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires skill '$REQUIRED_SKILL' (not invoked for work_id '$WORK_ID'). "
171
+ else
172
+ BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires skill '$REQUIRED_SKILL' (not found in telemetry). "
173
+ fi
133
174
  fi
134
175
  fi
135
176
 
136
- # Check agent dispatch in telemetry
177
+ # Check agent dispatch in telemetry (work_id-scoped)
137
178
  for AGENT in $REQUIRED_AGENTS; do
138
179
  if [ -n "$AGENT" ] && [ "$AGENT" != "null" ]; then
139
- if [ ! -f "$TELEMETRY" ] || ! grep -q "\"name\":\"$AGENT\"" "$TELEMETRY"; then
140
- BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires agent '$AGENT' (not found in telemetry). "
180
+ if ! check_invocation "$AGENT"; then
181
+ if [ -n "$WORK_ID" ]; then
182
+ BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires agent '$AGENT' (not dispatched for work_id '$WORK_ID'). "
183
+ else
184
+ BLOCKED_REASONS="${BLOCKED_REASONS}Gate '$GATE' requires agent '$AGENT' (not found in telemetry). "
185
+ fi
141
186
  fi
142
187
  fi
143
188
  done