forge-orkes 0.77.0 → 0.80.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/bin/create-forge.js +27 -0
- package/experimental/m10/README.md +4 -4
- package/experimental/m10/install.sh +10 -9
- package/experimental/m10/source/hooks/protect-primary-checkout.sh +149 -0
- package/package.json +1 -1
- package/template/.claude/hooks/forge-context-migrate.sh +297 -0
- package/template/.claude/hooks/forge-size-gate.sh +175 -0
- package/template/.claude/hooks/forge-state-rollup.sh +135 -2
- package/template/.claude/hooks/protect-primary-checkout.sh +149 -0
- package/template/.claude/hooks/skill-gate-tiers.txt +6 -0
- package/template/.claude/hooks/tests/forge-context-migrate.test.sh +166 -0
- package/template/.claude/hooks/tests/forge-size-gate.test.sh +132 -0
- package/template/.claude/hooks/tests/protect-primary-checkout.test.sh +147 -0
- package/template/.claude/settings.json +14 -1
- package/template/.claude/skills/discussing/SKILL.md +30 -31
- package/template/.claude/skills/executing/SKILL.md +3 -3
- package/template/.claude/skills/forge/SKILL.md +112 -170
- package/template/.claude/skills/forge/references/manual-fallback-procedures.md +54 -0
- package/template/.claude/skills/initializing/SKILL.md +20 -1
- package/template/.claude/skills/planning/SKILL.md +11 -9
- package/template/.claude/skills/researching/SKILL.md +2 -0
- package/template/.claude/skills/reviewing/SKILL.md +17 -0
- package/template/.claude/skills/upgrading/SKILL.md +22 -2
- package/template/.claude/skills/verifying/SKILL.md +2 -2
- package/template/.forge/FORGE.md +81 -90
- package/template/.forge/bin/new-worktree.sh +61 -0
- package/template/.forge/bin/tests/new-worktree.test.sh +70 -0
- package/template/.forge/checks/forge-jarvis-awareness.sh +46 -2
- package/template/.forge/checks/forge-jarvis-relay.sh +64 -16
- package/template/.forge/checks/tests/forge-jarvis-awareness.test.sh +58 -0
- package/template/.forge/checks/tests/forge-jarvis-relay.test.sh +50 -0
- package/template/.forge/git-hooks/pre-commit +57 -0
- package/template/.forge/git-hooks/tests/pre-commit.test.sh +97 -0
- package/template/.forge/migrations/0.78.0-weld-primary-checkout.md +66 -0
- package/template/.forge/migrations/0.80.0-context-md-sharding.md +158 -0
- package/template/.forge/migrations/0.80.0-size-gate-wiring.md +145 -0
- package/template/.forge/templates/constitution.md +1 -1
- package/template/.forge/templates/context-milestone.md +30 -0
- package/template/.forge/templates/slice-runner/config.yml +7 -1
- package/template/.forge/templates/state/desire-path.yml +3 -0
- package/experimental/m10/source/hooks/forge-branch-guard.sh +0 -61
|
@@ -18,55 +18,54 @@ Structured conversation: approach, trade-offs, decisions. Clarity, not artifacts
|
|
|
18
18
|
## Boundaries
|
|
19
19
|
|
|
20
20
|
- No plans or code
|
|
21
|
-
- Writes `context.md` progressively (after each confirmed decision, not just at handoff)
|
|
21
|
+
- Writes `context/{id}.md` progressively (after each confirmed decision, not just at handoff) — `context-log.md` instead in advisory mode (no milestone yet)
|
|
22
22
|
- No phase/plan required
|
|
23
23
|
- Entered via a worktree already, for new work (R10, `forge/SKILL.md` Step 3) — if this skill is somehow invoked directly on the main checkout for new work, enter one now before writing anything.
|
|
24
24
|
|
|
25
25
|
## Progressive Persistence
|
|
26
26
|
|
|
27
27
|
> **HARD GATE — NOT A GUIDELINE. NO EXCEPTIONS.**
|
|
28
|
-
> Write to `.forge/context.md` after EVERY confirmed decision, before asking the next question.
|
|
28
|
+
> Write to `.forge/context/{id}.md` after EVERY confirmed decision, before asking the next question ({id} = the milestone this discussion is scoped to).
|
|
29
29
|
> If you reach convergence without having written each decision individually — you already violated this rule.
|
|
30
30
|
|
|
31
|
-
> **Advisory mode (no milestone yet):** Storage still exists. Use `### M? — {topic} (drafting)` heading. Do NOT wait for milestone creation in Step A to start writing. First decision → create heading → append.
|
|
31
|
+
> **Advisory mode (no milestone yet):** Storage still exists — write to `.forge/context-log.md` instead (there is no `{id}` to shard by yet). Use `### M? — {topic} (drafting)` heading. Do NOT wait for milestone creation in Step A to start writing. First decision → create heading → append. Once Step A creates the milestone, migrate that drafting block from `context-log.md` into the new `.forge/context/{id}.md`.
|
|
32
32
|
|
|
33
33
|
After each user response that confirms a decision:
|
|
34
34
|
|
|
35
35
|
1. **STOP** — do not continue the discussion
|
|
36
|
-
2. **Write to disk** — append to `.forge/context.md` (create from
|
|
37
|
-
- **Path is always `.forge/context.md`** — never `.forge/phases/*/context.md`, never inline memory
|
|
36
|
+
2. **Write to disk** — append to `.forge/context/{id}.md` (create from `.forge/templates/context-milestone.md` if missing); `.forge/context-log.md` instead in advisory mode
|
|
37
|
+
- **Path is always `.forge/context/{id}.md`** (or `.forge/context-log.md` pre-milestone) — never `.forge/phases/*/context.md`, never inline memory, and never the rendered `.forge/context.md` index (derived — read for orientation, never write to it)
|
|
38
38
|
3. **THEN** continue to the next question
|
|
39
39
|
|
|
40
40
|
Never accumulate decisions in working memory. Never batch writes to convergence.
|
|
41
41
|
|
|
42
|
-
**Common failure mode:** Agent says "decisions live in conversation; planning writes context.md." This is WRONG. Discussing writes context.md. Planning reads it.
|
|
42
|
+
**Common failure mode:** Agent says "decisions live in conversation; planning writes context.md." This is WRONG. Discussing writes context/{id}.md. Planning reads it.
|
|
43
43
|
|
|
44
44
|
### Write Protocol
|
|
45
45
|
|
|
46
|
-
`context.md` is **
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **Keep active context active.** Write current/open decisions to `.forge/context.md`. Do not rehydrate old milestone blocks from `.forge/context-archive.md` unless the user is amending that historical decision.
|
|
46
|
+
`context/{id}.md` is **single-owner mutable, per milestone** (ADR-033) — sharding by milestone means different milestones already write different files, so the old shared-file merge-safety rules collapse to one:
|
|
47
|
+
- **Append-only within your file.** When superseding an older decision, *strike through* (`~~old decision~~`) and append the new line below — never rewrite in place. Reading the history of a decision stays possible by inspection.
|
|
48
|
+
- **Keep active context active.** Write current/open decisions to `.forge/context/{id}.md`. Do not rehydrate old milestone blocks from `.forge/context-archive.md` unless the user is amending that historical decision.
|
|
50
49
|
|
|
51
50
|
**On first decision of the session:**
|
|
52
|
-
- Check if `.forge/context.md` exists. If not → create it from `.forge/templates/context.md`
|
|
53
|
-
-
|
|
51
|
+
- Check if `.forge/context/{id}.md` exists. If not → create it from `.forge/templates/context-milestone.md`
|
|
52
|
+
- Heading: `### M{id} — {name} (drafting)` (use "M?" and write to `.forge/context-log.md` instead if no milestone yet — see Advisory mode above)
|
|
54
53
|
- If the needed historical decision is archived, cite the archive in the new active decision instead of copying the whole block back.
|
|
55
|
-
- **Cross-tree liveness check (informational).** If editing an existing
|
|
54
|
+
- **Cross-tree liveness check (informational).** If editing an existing `context/{id}.md` for milestone `{id}`, run `git worktree list --porcelain | awk '/^branch / && $2 ~ /refs\/heads\/forge\/m-'"$id"'(-|$)/ {print}'`. Any hit means m{id} is **live in another worktree** — surface one line: *"m{id} is live in worktree at `{path}`. Edits land cleanly on main but won't be visible to that worktree until it rebases or pulls."* Proceed with the write — main is often the canonical author of `context/{id}.md`, this is a heads-up, not a block.
|
|
56
55
|
|
|
57
56
|
**On each confirmed decision:**
|
|
58
57
|
- Append under the milestone heading: `- **[Topic]**: [Decision]. Reason: [Why]`
|
|
59
58
|
|
|
60
|
-
**On superseding a prior decision
|
|
59
|
+
**On superseding a prior decision:**
|
|
61
60
|
- Find the original line. Wrap it in `~~ ~~` (markdown strikethrough). DO NOT delete it.
|
|
62
61
|
- Append the new decision on a new line below it: `- **[Topic]**: [Decision]. Reason: [Why]. Supersedes ~~prior on {date}~~.`
|
|
63
|
-
- Why:
|
|
62
|
+
- Why: append-only rule. Decisions stay readable as history; concurrent writes from another worktree touching this same milestone's file on a different bullet can't conflict with this one.
|
|
64
63
|
|
|
65
64
|
**On deferred ideas** (user says "not now" / "later" / "skip"):
|
|
66
|
-
- Append to `## Deferred
|
|
65
|
+
- Append to this milestone's `## Deferred` heading in `.forge/context/{id}.md` immediately: `- [Idea] — Deferred because: [reason]`. Genuinely cross-cutting (not owned by this milestone) → `.forge/context/_shared.md`'s `## Deferred Ideas` heading instead — never guess a milestone onto a cross-cutting idea.
|
|
67
66
|
|
|
68
67
|
**On discretion areas** (left to agent judgment):
|
|
69
|
-
- Append to `## Discretion Areas`
|
|
68
|
+
- Append to this milestone's `## Discretion` heading in `.forge/context/{id}.md` immediately. Cross-cutting → `.forge/context/_shared.md`'s `## Discretion Areas` heading instead.
|
|
70
69
|
|
|
71
70
|
**At Phase Handoff:**
|
|
72
71
|
- Rename `(drafting)` → `(locked {date})` — decisions are already written, just finalize the heading
|
|
@@ -113,11 +112,11 @@ If fresh (after `/clear`):
|
|
|
113
112
|
```
|
|
114
113
|
Read: .forge/state/milestone-{id}.yml → current position, progress (skip if no milestone — advisory mode)
|
|
115
114
|
Read: .forge/project.yml → tech stack, project description
|
|
116
|
-
Read: .forge/context.md → existing locked decisions (if exists)
|
|
115
|
+
Read: .forge/context/{id}.md → this milestone's existing locked decisions (if exists)
|
|
117
116
|
Read: .forge/constitution.md → active gates (if exists)
|
|
118
117
|
```
|
|
119
118
|
|
|
120
|
-
**Advisory mode (no milestone):** Skip milestone state load. Progressive persistence still applies — writes go to `.forge/context.md` under `### M? — {topic} (drafting)` heading from the first decision. Milestone gets created in Step A only if scope warrants it.
|
|
119
|
+
**Advisory mode (no milestone):** Skip milestone state load. Progressive persistence still applies — writes go to `.forge/context-log.md` under `### M? — {topic} (drafting)` heading from the first decision. Milestone gets created in Step A only if scope warrants it.
|
|
121
120
|
|
|
122
121
|
Check `.forge/phases/` for research. If inline-only: *"Summarize findings, or re-scan?"*
|
|
123
122
|
|
|
@@ -145,7 +144,7 @@ Brief context paragraph from research.
|
|
|
145
144
|
|
|
146
145
|
Surface 3-5 decisions that matter.
|
|
147
146
|
|
|
148
|
-
**After each user response:** write confirmed decisions to `context.md` immediately (see Progressive Persistence).
|
|
147
|
+
**After each user response:** write confirmed decisions to `context/{id}.md` immediately (see Progressive Persistence).
|
|
149
148
|
|
|
150
149
|
### Step 2: Facilitate, Don't Dictate
|
|
151
150
|
|
|
@@ -176,17 +175,17 @@ AskUserQuestion:
|
|
|
176
175
|
|
|
177
176
|
Open-ended via prose: *"Tried before?" / "Must-haves or must-nots?"* 1-2 at a time.
|
|
178
177
|
|
|
179
|
-
**After each user response:** write confirmed decisions/constraints to `context.md` immediately.
|
|
178
|
+
**After each user response:** write confirmed decisions/constraints to `context/{id}.md` immediately.
|
|
180
179
|
|
|
181
180
|
### Step 4: Functionality Distillation
|
|
182
181
|
|
|
183
182
|
Apply Functionality Distillation (above), grounded in research findings.
|
|
184
183
|
|
|
185
|
-
**After each user response:** write confirmed behavioral decisions to `context.md` immediately.
|
|
184
|
+
**After each user response:** write confirmed behavioral decisions to `context/{id}.md` immediately.
|
|
186
185
|
|
|
187
186
|
### Step 5: Pre-Convergence Audit
|
|
188
187
|
|
|
189
|
-
**Before summarizing, read `.forge/context.md` and verify all confirmed decisions are present.**
|
|
188
|
+
**Before summarizing, read `.forge/context/{id}.md` (or `.forge/context-log.md` in advisory mode) and verify all confirmed decisions are present.**
|
|
190
189
|
|
|
191
190
|
If any decision from the conversation is missing from the file → write it now. Do not proceed to the summary until the file matches the conversation. This is a hard gate.
|
|
192
191
|
|
|
@@ -213,7 +212,7 @@ options:
|
|
|
213
212
|
```
|
|
214
213
|
Read: .forge/phases/milestone-{id}/{phase}-{name}/plan-{NN}.md → the plan
|
|
215
214
|
Read: .forge/requirements/m{N}.yml → source requirements (current milestone)
|
|
216
|
-
Read: .forge/context.md → locked decisions
|
|
215
|
+
Read: .forge/context/{id}.md → this milestone's locked decisions
|
|
217
216
|
Read: .forge/constitution.md → active gates
|
|
218
217
|
```
|
|
219
218
|
|
|
@@ -315,9 +314,9 @@ If no milestone exists (advisory discussion — forge routed here without tier/m
|
|
|
315
314
|
- `current.tier` = detected tier
|
|
316
315
|
- `current.status` = `planning` (Standard) / `architecting` (Full) / `not_started` (Quick)
|
|
317
316
|
- `current.last_updated` = now
|
|
318
|
-
- `decisions[]` = locked decisions from `context.md`
|
|
317
|
+
- `decisions[]` = locked decisions from the `context-log.md` drafting block
|
|
319
318
|
- Regenerate `.forge/state/index.yml` via the `forge` **Rollup** (read all `milestone-*.yml` → rewrite registry). Do not hand-add the entry. (Create `index.yml` from `.forge/templates/state/index.yml` first if missing.)
|
|
320
|
-
4. **
|
|
319
|
+
4. **Migrate the drafting block** — move the `### M? — {topic} (drafting)` block from `.forge/context-log.md` into `.forge/context/{id}.md` (create from `.forge/templates/context-milestone.md` if missing), renaming the heading to `### M{id} — {name} (drafting)`
|
|
321
320
|
5. **Quick tier?** → *"Scope is Quick. `/clear` then `/forge {id}` for quick-tasking."* End.
|
|
322
321
|
6. Proceed to Step B with new milestone.
|
|
323
322
|
|
|
@@ -326,17 +325,17 @@ If milestone exists → skip to Step B.
|
|
|
326
325
|
### Step B: Standard Handoff
|
|
327
326
|
|
|
328
327
|
> **HARD GATE — VERIFY BEFORE HANDOFF.**
|
|
329
|
-
> Read `.forge/context.md` now. Count decisions under
|
|
328
|
+
> Read `.forge/context/{id}.md` now. Count decisions under `## Locked Decisions`. Compare against decisions confirmed in this conversation.
|
|
330
329
|
> - **If counts match** → proceed to handoff steps below.
|
|
331
330
|
> - **If file is missing, heading absent, or decisions undercount** → progressive persistence failed. STOP. Do NOT recommend `/clear`. Write the missing decisions now from conversation memory, then re-verify. Only then proceed.
|
|
332
331
|
> - **Never claim "state written" without having just read the file.** The recommendation `/clear` is destructive to working memory — earn it.
|
|
333
332
|
|
|
334
|
-
1. **Promote decisions in `context.md`** -- Rename milestone heading from `(drafting)` → `(locked {date})`. Decisions already written progressively — just finalize:
|
|
333
|
+
1. **Promote decisions in `context/{id}.md`** -- Rename milestone heading from `(drafting)` → `(locked {date})`. Decisions already written progressively — just finalize:
|
|
335
334
|
- Verify all confirmed decisions present under `## Locked Decisions`
|
|
336
335
|
- Verify deferred items under `## Deferred Ideas`
|
|
337
336
|
- Verify discretion areas under `## Discretion Areas`
|
|
338
|
-
- Add any unresolved items to `## Needs Resolution`
|
|
339
|
-
- If `context.md` already exists (post-planning discussion), update relevant sections + log amendments
|
|
337
|
+
- Add any unresolved items to `.forge/context-log.md`'s `## Needs Resolution`
|
|
338
|
+
- If `context/{id}.md` already exists (post-planning discussion), update relevant sections + log amendments in `context-log.md`'s `## Amendment Log`
|
|
340
339
|
2. **Update state** -- `current.status` = `planning` (`architecting` for Full) in milestone yml
|
|
341
340
|
3. **State-sync commit** (State Commit Protocol): `git -C {worktree_path} add .forge/` then `git -C {worktree_path} commit -m "chore(forge): sync state after discussing — m{N} {name}"` (worktree form — recorded `lifecycle.worktree_path` is authoritative over cwd; see FORGE.md State Commit Protocol. Scoped; never `git add .`).
|
|
342
|
-
4. **Recommend clear:** *"State synced and verified ({N} decisions in context.md). `/clear` then `/forge` for {planning/architecting}."*
|
|
341
|
+
4. **Recommend clear:** *"State synced and verified ({N} decisions in context/{id}.md). `/clear` then `/forge` for {planning/architecting}."*
|
|
@@ -127,7 +127,7 @@ For each task in the plan:
|
|
|
127
127
|
|
|
128
128
|
1. **Read** task XML (name, files, action, verify, done)
|
|
129
129
|
2. **Mark in-progress** — `TaskUpdate` to `in_progress`
|
|
130
|
-
3. **Check** context.md — honor locked decisions exactly
|
|
130
|
+
3. **Check** context/{id}.md — honor locked decisions exactly
|
|
131
131
|
4. **Implement** per action instructions
|
|
132
132
|
5. **Verify** using the verify step
|
|
133
133
|
6. **Confirm** done criteria met
|
|
@@ -317,7 +317,7 @@ Once a task's verification bookkeeping settles (3-Strike result known, declared-
|
|
|
317
317
|
| Task carries a `complexity` tag whose resolved model **differs from the live session model** (COST, M24) | Spawn a fresh executor on that resolved model — even under 40% context (real routing). |
|
|
318
318
|
| Task carries a `complexity` tag but resolves to the **live session model** (e.g. no `models:` block) | Spawn changes nothing — treat the tag as a context signal only: spawn **iff** a row above fires. Otherwise run inline. |
|
|
319
319
|
|
|
320
|
-
**Spawn via Agent tool** with: relevant plan details, specific files, locked decisions from context.md, clear success criteria. **Resolve the model PER TASK**, not once per skill run: `models.by_complexity.{task.complexity}` → `models.skills.executing` → `models.default` → parent (complexity overrides skill — FORGE.md → Model Routing). **Then compare the resolved model to the live session model** (the model this session is actually running on): differ → spawn (mandatory routing); equal → the tag is a context signal, not a routing obligation. Display per spawn: *"Spawning executor with model: {model} (from {source})"*
|
|
320
|
+
**Spawn via Agent tool** with: relevant plan details, specific files, locked decisions from context/{id}.md, clear success criteria. **Resolve the model PER TASK**, not once per skill run: `models.by_complexity.{task.complexity}` → `models.skills.executing` → `models.default` → parent (complexity overrides skill — FORGE.md → Model Routing). **Then compare the resolved model to the live session model** (the model this session is actually running on): differ → spawn (mandatory routing); equal → the tag is a context signal, not a routing obligation. Display per spawn: *"Spawning executor with model: {model} (from {source})"*
|
|
321
321
|
|
|
322
322
|
**Why the tag gates the spawn (predicate A — the spawn must change the model).** Routing only *does* something when a task's resolved model differs from the **live session model**; a same-model spawn is pure briefing overhead — m-30 burned ~315k subagent tokens spawning tasks that resolved straight back to the parent model for zero routing benefit. So the mandatory spawn fires only when resolving actually swaps the model (which requires a `models:` block whose resolution lands on a different tier than the one this session runs on). With **no `models:` block** every resolved model equals the parent == the live session model, so tagged tasks run inline unless a context trigger (20+ files / deep subsystem / >40%) independently calls for a fresh agent. The tag still marks work "worth routing," and an inline task genuinely cannot be re-routed — but that leak only matters when a different model was actually available, which is exactly the resolved-≠-live case the gate keeps mandatory. (A full parent-as-orchestrator model — spawn everything, parent never implements — remains a deferred follow-up, justified by M24 outcome-log evidence, not implemented here.)
|
|
323
323
|
|
|
@@ -360,7 +360,7 @@ Append **one file per observation** to `.forge/state/desire-paths/` — copy `.f
|
|
|
360
360
|
- **User corrections**: Repeated correction matching a prior one → `type: user_correction`
|
|
361
361
|
- **Agent struggles**: Multiple attempts or user guidance needed → `type: agent_struggle`
|
|
362
362
|
|
|
363
|
-
**Set `scope` at capture** (see ADR-012): `framework` when the fix this signal implies targets Forge's own skills/templates (a skill's check, a plan/tier heuristic, a template); `project` when it targets user-owned files (`constitution.md`, `design-system.md`, `context.md`, project setup). Record `suggestion_target` when you know the file/skill it touches. `scope: framework` is what later lets `forge` review route the signal upstream instead of trapping it in this project.
|
|
363
|
+
**Set `scope` at capture** (see ADR-012): `framework` when the fix this signal implies targets Forge's own skills/templates (a skill's check, a plan/tier heuristic, a template); `project` when it targets user-owned files (`constitution.md`, `design-system.md`, `context/{id}.md`, project setup). Record `suggestion_target` when you know the file/skill it touches. `scope: framework` is what later lets `forge` review route the signal upstream instead of trapping it in this project.
|
|
364
364
|
|
|
365
365
|
## Cross-Layer Seam Check
|
|
366
366
|
|