forge-orkes 0.11.0 → 0.13.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/deferred/SKILL.md +85 -0
- package/template/.claude/skills/discussing/SKILL.md +12 -2
- package/template/.claude/skills/executing/SKILL.md +2 -0
- package/template/.claude/skills/forge/SKILL.md +42 -1
- package/template/.claude/skills/reviewing/SKILL.md +20 -6
- package/template/.forge/templates/refactor-backlog.yml +22 -1
- package/template/.forge/templates/state/milestone.yml +16 -0
package/package.json
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deferred
|
|
3
|
+
description: Read-only aggregator. Show all deferred work in this project grouped by surface (milestones, refactor backlog, phases/tasks inside active milestones). Trigger:`/forge deferred`, "show deferred", "deferred items", "what's deferred".
|
|
4
|
+
model: haiku
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Deferred
|
|
8
|
+
|
|
9
|
+
Read-only. Surface all deferred work across three storage surfaces so user need not remember where each kind lives. Never mutates state. No agents, no Skill invocations, no Write/Edit.
|
|
10
|
+
|
|
11
|
+
Three surfaces:
|
|
12
|
+
|
|
13
|
+
1. **Milestones** — `.forge/state/index.yml` entries with `status: deferred`. Strategic punts (whole milestone frozen).
|
|
14
|
+
2. **Refactor backlog** — `.forge/refactor-backlog.yml` items with `status: deferred`. Code-quality punts.
|
|
15
|
+
3. **Inside active milestones** — phase/task entries with `status: deferred` or `deferred: true` inside `.forge/state/milestone-*.yml`. Tactical punts within in-flight work.
|
|
16
|
+
|
|
17
|
+
## Step 1: Read three surfaces
|
|
18
|
+
|
|
19
|
+
**Surface 1 — Deferred milestones.** Read `.forge/state/index.yml`. Collect every entry under `milestones:` where `status: deferred`. Pull `id`, `name`, `lifecycle.deferred_at` (if present at top level fall back to `last_updated`), `lifecycle.deferred_reason` (may live in the milestone state file — read `.forge/state/milestone-{id}.yml → lifecycle.deferred_at / deferred_reason` for accuracy).
|
|
20
|
+
|
|
21
|
+
**Surface 2 — Deferred refactor items.** Read `.forge/refactor-backlog.yml`. Collect every item with `status: deferred`. Pull `id` (e.g. R-007), `description` (first line, truncate ≤80 chars), `deferred_at`, `deferred_reason`.
|
|
22
|
+
|
|
23
|
+
**Surface 3 — Deferred phases/tasks inside active milestones.** Glob `.forge/state/milestone-*.yml`. For each file:
|
|
24
|
+
|
|
25
|
+
- Look up that milestone's status in `index.yml`.
|
|
26
|
+
- **Only process if `status: active`.** Skip `complete` and `deferred` milestones.
|
|
27
|
+
- *Why:* a deferred milestone's own `lifecycle.deferred_at` block is already counted by Surface 1. Including it here double-counts. Skipping `complete` avoids historical noise.
|
|
28
|
+
- Within the file, find phase or task entries with `status: deferred` or `deferred: true`. Pull milestone id, phase/task name, `deferred_at`, `deferred_reason`.
|
|
29
|
+
|
|
30
|
+
Missing source files → that section renders `(none)`. Never error.
|
|
31
|
+
|
|
32
|
+
## Step 2: Normalize
|
|
33
|
+
|
|
34
|
+
Each entry → tuple `{ surface, id, name, deferred_at, deferred_reason }`. Missing `deferred_at` → null. Missing `deferred_reason` → null.
|
|
35
|
+
|
|
36
|
+
## Step 3: Sort
|
|
37
|
+
|
|
38
|
+
Within each section, sort by `deferred_at` ascending (oldest first). Null dates sort last.
|
|
39
|
+
|
|
40
|
+
## Step 4: Render
|
|
41
|
+
|
|
42
|
+
Exact format:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Deferred work in this project:
|
|
46
|
+
|
|
47
|
+
## Milestones ({count})
|
|
48
|
+
- M{id} — {name} (deferred {deferred_at | "date unknown"})
|
|
49
|
+
Reason: {deferred_reason | "—"}
|
|
50
|
+
|
|
51
|
+
## Refactor Backlog ({count})
|
|
52
|
+
- {R-id} — {description} (deferred {deferred_at | "unknown"})
|
|
53
|
+
Reason: {deferred_reason | "—"}
|
|
54
|
+
|
|
55
|
+
## Inside Active Milestones ({count})
|
|
56
|
+
- M{milestone_id} → {phase or task name} (deferred {deferred_at | "unknown"})
|
|
57
|
+
Reason: {deferred_reason | "—"}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Section with count 0 → render header + `(none)` line beneath.
|
|
61
|
+
|
|
62
|
+
## Empty state
|
|
63
|
+
|
|
64
|
+
All three counts zero → print exactly:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
No deferred work in this project.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then exit.
|
|
71
|
+
|
|
72
|
+
## Graceful degradation
|
|
73
|
+
|
|
74
|
+
- Missing `.forge/state/index.yml` → cannot proceed. Print `No forge state found in this project.` exit.
|
|
75
|
+
- Missing `.forge/refactor-backlog.yml` → Surface 2 renders `(none)`. Continue.
|
|
76
|
+
- No `milestone-*.yml` matches → Surface 3 renders `(none)`. Continue.
|
|
77
|
+
- Malformed YAML in any source → skip that source, render `(unreadable)` beneath header, continue others.
|
|
78
|
+
|
|
79
|
+
## Boundaries
|
|
80
|
+
|
|
81
|
+
- Read-only. No Write, no Edit, no Bash mutations.
|
|
82
|
+
- No agent dispatch. Mechanical aggregation only.
|
|
83
|
+
- No filter subcommands. Grouped-only view (locked decision).
|
|
84
|
+
- No auto-close, no rot detection, no promotion. Deferred to v2.
|
|
85
|
+
- Do not invoke other skills.
|
|
@@ -27,6 +27,8 @@ Structured conversation: approach, trade-offs, decisions. Clarity, not artifacts
|
|
|
27
27
|
> Write to `.forge/context.md` after EVERY confirmed decision, before asking the next question.
|
|
28
28
|
> If you reach convergence without having written each decision individually — you already violated this rule.
|
|
29
29
|
|
|
30
|
+
> **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. Same protocol as milestone-bound discussions.
|
|
31
|
+
|
|
30
32
|
After each user response that confirms a decision:
|
|
31
33
|
|
|
32
34
|
1. **STOP** — do not continue the discussion
|
|
@@ -96,12 +98,14 @@ options:
|
|
|
96
98
|
If fresh (after `/clear`):
|
|
97
99
|
|
|
98
100
|
```
|
|
99
|
-
Read: .forge/state/milestone-{id}.yml → current position, progress
|
|
101
|
+
Read: .forge/state/milestone-{id}.yml → current position, progress (skip if no milestone — advisory mode)
|
|
100
102
|
Read: .forge/project.yml → tech stack, project description
|
|
101
103
|
Read: .forge/context.md → existing locked decisions (if exists)
|
|
102
104
|
Read: .forge/constitution.md → active gates (if exists)
|
|
103
105
|
```
|
|
104
106
|
|
|
107
|
+
**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.
|
|
108
|
+
|
|
105
109
|
Check `.forge/phases/` for research. If inline-only: *"Summarize findings, or re-scan?"*
|
|
106
110
|
|
|
107
111
|
### Step 1: Present Decisions with AskUserQuestion
|
|
@@ -306,6 +310,12 @@ If milestone exists → skip to Step B.
|
|
|
306
310
|
|
|
307
311
|
### Step B: Standard Handoff
|
|
308
312
|
|
|
313
|
+
> **HARD GATE — VERIFY BEFORE HANDOFF.**
|
|
314
|
+
> Read `.forge/context.md` now. Count decisions under the active milestone heading. Compare against decisions confirmed in this conversation.
|
|
315
|
+
> - **If counts match** → proceed to handoff steps below.
|
|
316
|
+
> - **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.
|
|
317
|
+
> - **Never claim "state written" without having just read the file.** The recommendation `/clear` is destructive to working memory — earn it.
|
|
318
|
+
|
|
309
319
|
1. **Promote decisions in `context.md`** -- Rename milestone heading from `(drafting)` → `(locked {date})`. Decisions already written progressively — just finalize:
|
|
310
320
|
- Verify all confirmed decisions present under `## Locked Decisions`
|
|
311
321
|
- Verify deferred items under `## Deferred Ideas`
|
|
@@ -313,4 +323,4 @@ If milestone exists → skip to Step B.
|
|
|
313
323
|
- Add any unresolved items to `## Needs Resolution`
|
|
314
324
|
- If `context.md` already exists (post-planning discussion), update relevant sections + log amendments
|
|
315
325
|
2. **Update state** -- `current.status` = `planning` (`architecting` for Full) in milestone yml
|
|
316
|
-
3. **Recommend clear:** *"State written. `/clear` then `/forge` for {planning/architecting}."*
|
|
326
|
+
3. **Recommend clear:** *"State written and verified ({N} decisions in context.md). `/clear` then `/forge` for {planning/architecting}."*
|
|
@@ -212,6 +212,8 @@ Do NOT list test failures here — pre-existing failures belong in deferred-issu
|
|
|
212
212
|
3. Update `.forge/state/index.yml` — set `last_updated` timestamp
|
|
213
213
|
4. All plans in phase complete → transition to `verifying`
|
|
214
214
|
|
|
215
|
+
**When deferring an individual phase or task** (writing `status: deferred` or `deferred: true` to a phase/task entry inside the milestone state file — as opposed to milestone-wide defer which goes through the forge skill's lifecycle flow): write `deferred_at` (ISO date today) and `deferred_reason` (one-line) siblings. Old entries without these fields parse fine — lazy migration. These feed the `deferred` aggregator skill.
|
|
216
|
+
|
|
215
217
|
## Desire Path Signals
|
|
216
218
|
|
|
217
219
|
Log to `.forge/state/index.yml → desire_paths` (global, not per-milestone):
|
|
@@ -37,7 +37,40 @@ Read `.forge/context.md`. **Needs Resolution** unchecked → warn: *"{N} unresol
|
|
|
37
37
|
|
|
38
38
|
Check `.forge/refactor-backlog.yml`:
|
|
39
39
|
- *"{N} refactors ({Q} quick, {S} standard). Tackle first?"*
|
|
40
|
-
- Pick →
|
|
40
|
+
- Pick item → branch on `effort`:
|
|
41
|
+
- `effort: quick` → `quick-tasking`, set `status: in_progress`. Unchanged.
|
|
42
|
+
- `effort: standard` → **Promote to milestone** (procedure below), then fall through to Step 3 Standard routing.
|
|
43
|
+
- Decline → proceed.
|
|
44
|
+
|
|
45
|
+
**Promotion procedure (effort: standard only):**
|
|
46
|
+
|
|
47
|
+
1. Read backlog item `id` (e.g. `R61-002`). Synthesize milestone id `m-{R-id}` (e.g. `m-R61-002`).
|
|
48
|
+
2. Copy `.forge/templates/state/milestone.yml` → `.forge/state/milestone-{m-R-id}.yml`. Populate:
|
|
49
|
+
- `milestone.id: m-{R-id}`
|
|
50
|
+
- `milestone.name: "Promoted from {R-id}: {backlog item title}"`
|
|
51
|
+
- `milestone.origin: {R-id}`
|
|
52
|
+
- `current.tier: standard`, `current.status: researching`
|
|
53
|
+
- `progress.last_update: {ISO date}`
|
|
54
|
+
3. Append to `.forge/state/index.yml` `milestones:`:
|
|
55
|
+
```yaml
|
|
56
|
+
- id: m-{R-id}
|
|
57
|
+
name: "Promoted from {R-id}: {title}"
|
|
58
|
+
status: active
|
|
59
|
+
last_updated: "{ISO date}"
|
|
60
|
+
```
|
|
61
|
+
4. Append to `.forge/roadmap.yml` — one milestone entry + one phase (`refactor-{R-id}`, `requirements_source: refactor-backlog.yml#{R-id}`, `dependencies: []`).
|
|
62
|
+
5. Update `.forge/refactor-backlog.yml` item: `status: in_progress`, add `promoted_to: m-{R-id}`.
|
|
63
|
+
6. Confirm: *"Promoted {R-id} → milestone m-{R-id}. State + roadmap created. Routing to researching."*
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
backlog pickup → effort: standard
|
|
67
|
+
├─ write milestone-{m-R-id}.yml (origin: {R-id})
|
|
68
|
+
├─ append index.yml + roadmap.yml
|
|
69
|
+
├─ flip backlog item (in_progress + promoted_to)
|
|
70
|
+
└─ fall through → Standard tier routing
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Downstream skills (researching, discussing, planning, executing, verifying, reviewing) see a normal milestone — no special branching.
|
|
41
74
|
|
|
42
75
|
Check `desire_paths` 3+ occurrences:
|
|
43
76
|
- *"Recurring: [{description}] ({N}x). Fix via [suggestion]?"*
|
|
@@ -59,9 +92,15 @@ Before tier detection, check if user request matches lifecycle patterns:
|
|
|
59
92
|
- "defer milestone {id}" / "defer {id}" / "pause milestone {id}" → **Defer**
|
|
60
93
|
- "resume milestone {id}" / "undefer {id}" / "reactivate milestone {id}" → **Resume**
|
|
61
94
|
- "delete milestone {id}" / "archive milestone {id}" / "remove milestone {id}" → **Delete** (see below)
|
|
95
|
+
- "deferred" / "show deferred" / "deferred items" / "what's deferred" / "deferred work" → **Show Deferred**
|
|
62
96
|
|
|
63
97
|
No match → fall through to Step 2B (tier detection).
|
|
64
98
|
|
|
99
|
+
### Show Deferred
|
|
100
|
+
|
|
101
|
+
1. Invoke `Skill(deferred)` directly.
|
|
102
|
+
2. Do not enter tier detection. Do not prompt for milestone. The deferred skill is read-only and self-contained.
|
|
103
|
+
|
|
65
104
|
### Defer Operation
|
|
66
105
|
|
|
67
106
|
1. Validate: milestone in `index.yml`, status not `deferred`
|
|
@@ -185,6 +224,7 @@ Where `{source}` = `skills.{name}` | `models.default` | `parent session`. Suppre
|
|
|
185
224
|
| quick-tasking | haiku | Speed |
|
|
186
225
|
| discussing | sonnet | Conversation |
|
|
187
226
|
| testing | sonnet | Code gen (author) + audit judgment (analyst) — matches executing/reviewing |
|
|
227
|
+
| deferred | haiku | Read + format only |
|
|
188
228
|
|
|
189
229
|
| `current.status` | Route To |
|
|
190
230
|
|-------------------|----------|
|
|
@@ -199,6 +239,7 @@ Where `{source}` = `skills.{name}` | `models.default` | `parent session`. Suppre
|
|
|
199
239
|
| `complete` | Done. Ask what's next. |
|
|
200
240
|
| `deferred` | Milestone frozen. *"Resume milestone {id}" to reactivate.* |
|
|
201
241
|
| `quick-tasking` | `Skill(quick-tasking)` |
|
|
242
|
+
| (keyword: `deferred` / "show deferred") | `Skill(deferred)` — read-only aggregator |
|
|
202
243
|
|
|
203
244
|
### Status Advancement Check
|
|
204
245
|
|
|
@@ -285,6 +285,8 @@ items:
|
|
|
285
285
|
|
|
286
286
|
Missing? Create from `.forge/templates/refactor-backlog.yml`.
|
|
287
287
|
|
|
288
|
+
**When deferring an individual refactor item** (status flipped to `deferred`, as opposed to milestone-wide defer which goes through the forge skill): write `deferred_at` (ISO date today) and `deferred_reason` (one-line) siblings to `status: deferred`. Pre-existing items without these fields parse fine — lazy migration. These feed the `deferred` aggregator skill.
|
|
289
|
+
|
|
288
290
|
### Route
|
|
289
291
|
|
|
290
292
|
**HEALTHY/WARNINGS (accepted):** `current.status: complete` in milestone + index. *"Milestone [{name}] complete. {N} backlog items."* Beads: `bd complete`.
|
|
@@ -304,16 +306,28 @@ Report = audit trail.
|
|
|
304
306
|
## Backlog Lifecycle
|
|
305
307
|
|
|
306
308
|
```
|
|
307
|
-
pending → in_progress →
|
|
308
|
-
pending →
|
|
309
|
+
pending → in_progress → resolved
|
|
310
|
+
pending → wontfix (during triage or later)
|
|
309
311
|
```
|
|
310
312
|
|
|
311
|
-
`quick` -> `quick-tasking`. `standard` ->
|
|
313
|
+
`quick` -> `quick-tasking`. `standard` -> promoted to milestone via `forge` Step 1.2.
|
|
314
|
+
|
|
315
|
+
`forge` surfaces -> user selects -> route by effort -> on completion, `status: resolved` + date.
|
|
316
|
+
|
|
317
|
+
Legacy items may use `done`/`dismissed` — both still readable; new transitions use `resolved`/`wontfix`.
|
|
318
|
+
|
|
319
|
+
## Promoted Milestone Completion Hook
|
|
320
|
+
|
|
321
|
+
If the milestone being completed has `milestone.origin: {R-id}` set (promoted from refactor-backlog), flip the originating item before exit:
|
|
312
322
|
|
|
313
|
-
`
|
|
323
|
+
1. Read `milestone.origin` from `milestone-{id}.yml`. If null → skip (fresh milestone, no hook).
|
|
324
|
+
2. Open `.forge/refactor-backlog.yml`. Find item with matching `id`.
|
|
325
|
+
3. Update item: `status: resolved`, set `completed: "<ISO 8601 date>"`. Keep `promoted_to: {milestone-id}` intact for audit trail.
|
|
326
|
+
4. Log in summary: *"Backlog item {R-id} → resolved (promoted milestone {id} complete)."*
|
|
314
327
|
|
|
315
328
|
## Phase Handoff
|
|
316
329
|
|
|
317
330
|
1. Confirm report + backlog
|
|
318
|
-
2.
|
|
319
|
-
3.
|
|
331
|
+
2. **Run promoted-milestone completion hook** (above) if `milestone.origin` set
|
|
332
|
+
3. Set `current.status: complete` and `current.completed_at: "<ISO 8601 timestamp>"`
|
|
333
|
+
4. *"Milestone [{name}] complete. Report: `.forge/audits/milestone-{id}-health-report.md`. {N} backlog items. `/forge` or backlog."*
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# Forge Refactor Backlog
|
|
2
2
|
# Auto-managed by the refactoring skill. Items added after milestone audits.
|
|
3
3
|
# Work items via quick-tasking (effort: quick) or Standard tier (effort: standard).
|
|
4
|
+
#
|
|
5
|
+
# Status vocab: pending | in_progress | done | dismissed | deferred
|
|
6
|
+
# Optional fields (lazy migration — only required on entries set to status: deferred going forward):
|
|
7
|
+
# deferred_at: ISO date when status flipped to deferred
|
|
8
|
+
# deferred_reason: one-line why; revisited when status changes
|
|
9
|
+
# Pre-existing items without these fields parse fine.
|
|
4
10
|
|
|
5
11
|
items:
|
|
6
12
|
- id: R001 # Sequential ID: R001, R002, ...
|
|
@@ -11,6 +17,21 @@ items:
|
|
|
11
17
|
description: "Brief description of the refactoring opportunity"
|
|
12
18
|
effort: quick # quick (< 30 min, < 50 lines) | standard (needs planning)
|
|
13
19
|
suggested_approach: "Concrete suggestion for how to address it"
|
|
14
|
-
status: pending # pending | in_progress | done | dismissed
|
|
20
|
+
status: pending # pending | in_progress | done | dismissed | deferred
|
|
15
21
|
added: "2026-01-01" # ISO 8601 date when added
|
|
16
22
|
completed: null # ISO 8601 date when done, null otherwise
|
|
23
|
+
|
|
24
|
+
# Example of a deferred item — note the two optional sibling fields:
|
|
25
|
+
- id: R002
|
|
26
|
+
milestone: 1
|
|
27
|
+
category: abstraction
|
|
28
|
+
file: "src/legacy.ts"
|
|
29
|
+
lines: "1-200"
|
|
30
|
+
description: "Extract module — blocked on upstream API change"
|
|
31
|
+
effort: standard
|
|
32
|
+
suggested_approach: "Wait for v2 API, then extract"
|
|
33
|
+
status: deferred
|
|
34
|
+
deferred_at: "2026-05-29" # ISO date when status flipped to deferred
|
|
35
|
+
deferred_reason: "Blocked on upstream v2 API; revisit Q3"
|
|
36
|
+
added: "2026-01-15"
|
|
37
|
+
completed: null
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
milestone:
|
|
7
7
|
id: null # Milestone ID from roadmap
|
|
8
8
|
name: "" # Human-readable milestone name
|
|
9
|
+
origin: null # Backlog item ID if this milestone was promoted from refactor-backlog.yml. null for fresh milestones.
|
|
9
10
|
|
|
10
11
|
current:
|
|
11
12
|
tier: null # quick | standard | full
|
|
@@ -49,8 +50,23 @@ deviations: # Tracked deviations during execution
|
|
|
49
50
|
|
|
50
51
|
# Lifecycle — events separate from workflow position (current:).
|
|
51
52
|
# current.status stays frozen when deferred — it IS the resume point.
|
|
53
|
+
# This block handles MILESTONE-LEVEL deferral (whole milestone frozen).
|
|
52
54
|
lifecycle:
|
|
53
55
|
deferred_at: null # ISO 8601 — when milestone was deferred
|
|
54
56
|
deferred_reason: "" # User-provided reason for deferring
|
|
55
57
|
status_before_defer: null # Workflow status when deferred (mirrors frozen current.status)
|
|
56
58
|
resumed_at: null # ISO 8601 — when milestone was resumed
|
|
59
|
+
|
|
60
|
+
# Phase/task-level deferral (separate scope from milestone-level lifecycle above):
|
|
61
|
+
# When marking an individual phase or task deferred INSIDE an active milestone,
|
|
62
|
+
# add deferred_at + deferred_reason adjacent to that entry's status field.
|
|
63
|
+
# Fields are OPTIONAL (lazy migration — old entries lacking them parse fine).
|
|
64
|
+
# These feed the `deferred` aggregator skill.
|
|
65
|
+
#
|
|
66
|
+
# Example (this template doesn't model concrete phases, but when a skill
|
|
67
|
+
# writes such an entry, follow this shape):
|
|
68
|
+
# phases:
|
|
69
|
+
# - id: 3
|
|
70
|
+
# status: deferred
|
|
71
|
+
# deferred_at: "2026-05-29"
|
|
72
|
+
# deferred_reason: "Blocked on upstream API; revisit when X ships"
|