forge-orkes 0.1.0 → 0.3.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.
@@ -6,6 +6,23 @@ const readline = require('readline');
6
6
 
7
7
  const templateDir = path.join(__dirname, '..', 'template');
8
8
  const targetDir = process.cwd();
9
+ const pkgVersion = require('../package.json').version;
10
+
11
+ // --- File classification for upgrades ---
12
+
13
+ // Framework-owned: Forge controls these entirely
14
+ const FRAMEWORK_OWNED_DIRS = ['.claude/agents', '.claude/skills'];
15
+
16
+ // Template-only: reference templates Forge controls
17
+ const TEMPLATE_ONLY_DIRS = ['.forge/templates'];
18
+
19
+ // Merge-owned: never auto-overwrite, stage for review
20
+ const MERGE_OWNED_FILES = ['CLAUDE.md'];
21
+
22
+ // Settings file gets smart-merge (overwrite forge.* keys, preserve user hooks)
23
+ const SETTINGS_FILE = '.claude/settings.json';
24
+
25
+ // --- Helpers ---
9
26
 
10
27
  function copyDirRecursive(src, dest) {
11
28
  let count = 0;
@@ -38,7 +55,132 @@ function prompt(question) {
38
55
  });
39
56
  }
40
57
 
41
- async function main() {
58
+ function stampVersion(settingsPath) {
59
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
60
+ if (settings.forge) {
61
+ settings.forge.version = pkgVersion;
62
+ }
63
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
64
+ }
65
+
66
+ /**
67
+ * Recursively collect all relative file paths under a directory.
68
+ */
69
+ function collectFiles(dir, base) {
70
+ const results = [];
71
+ if (!fs.existsSync(dir)) return results;
72
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
73
+ const rel = path.join(base, entry.name);
74
+ if (entry.isDirectory()) {
75
+ results.push(...collectFiles(path.join(dir, entry.name), rel));
76
+ } else {
77
+ results.push(rel);
78
+ }
79
+ }
80
+ return results;
81
+ }
82
+
83
+ /**
84
+ * Compare and overwrite framework-owned or template-only files.
85
+ * Returns { updated, added, unchanged, removed } arrays of relative paths.
86
+ */
87
+ function upgradeDir(relDir) {
88
+ const srcDir = path.join(templateDir, relDir);
89
+ const destDir = path.join(targetDir, relDir);
90
+
91
+ const result = { updated: [], added: [], unchanged: [], removed: [] };
92
+
93
+ if (!fs.existsSync(srcDir)) return result;
94
+
95
+ const srcFiles = collectFiles(srcDir, '');
96
+ const destFiles = new Set(collectFiles(destDir, ''));
97
+
98
+ for (const rel of srcFiles) {
99
+ const srcPath = path.join(srcDir, rel);
100
+ const destPath = path.join(destDir, rel);
101
+ const displayPath = path.join(relDir, rel);
102
+
103
+ if (!fs.existsSync(destPath)) {
104
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
105
+ fs.copyFileSync(srcPath, destPath);
106
+ result.added.push(displayPath);
107
+ } else {
108
+ const srcContent = fs.readFileSync(srcPath);
109
+ const destContent = fs.readFileSync(destPath);
110
+ if (Buffer.compare(srcContent, destContent) !== 0) {
111
+ fs.copyFileSync(srcPath, destPath);
112
+ result.updated.push(displayPath);
113
+ } else {
114
+ result.unchanged.push(displayPath);
115
+ }
116
+ }
117
+ }
118
+
119
+ // Detect files in dest that are no longer in template
120
+ for (const rel of destFiles) {
121
+ const srcPath = path.join(srcDir, rel);
122
+ if (!fs.existsSync(srcPath)) {
123
+ result.removed.push(path.join(relDir, rel));
124
+ }
125
+ }
126
+
127
+ return result;
128
+ }
129
+
130
+ /**
131
+ * Handle merge-owned files: stage new version for manual review if different.
132
+ */
133
+ function handleMergeFile(relFile) {
134
+ const srcPath = path.join(templateDir, relFile);
135
+ const destPath = path.join(targetDir, relFile);
136
+
137
+ if (!fs.existsSync(srcPath)) return null;
138
+ if (!fs.existsSync(destPath)) return null;
139
+
140
+ const srcContent = fs.readFileSync(srcPath, 'utf-8');
141
+ const destContent = fs.readFileSync(destPath, 'utf-8');
142
+
143
+ if (srcContent === destContent) return 'unchanged';
144
+
145
+ // Stage the new version for manual review
146
+ const upgradeDir = path.join(targetDir, '.forge', 'upgrade');
147
+ fs.mkdirSync(upgradeDir, { recursive: true });
148
+ const basename = path.basename(relFile);
149
+ const newPath = path.join(upgradeDir, `${basename}.new`);
150
+ fs.writeFileSync(newPath, srcContent);
151
+ return 'staged';
152
+ }
153
+
154
+ /**
155
+ * Smart-merge settings.json: overwrite forge.* keys from template, preserve user hooks.
156
+ */
157
+ function upgradeSettings() {
158
+ const srcPath = path.join(templateDir, SETTINGS_FILE);
159
+ const destPath = path.join(targetDir, SETTINGS_FILE);
160
+
161
+ if (!fs.existsSync(destPath)) return 'missing';
162
+ if (!fs.existsSync(srcPath)) return 'missing';
163
+
164
+ const srcSettings = JSON.parse(fs.readFileSync(srcPath, 'utf-8'));
165
+ const destSettings = JSON.parse(fs.readFileSync(destPath, 'utf-8'));
166
+
167
+ const before = JSON.stringify(destSettings);
168
+
169
+ // Overwrite forge.* keys from template
170
+ destSettings.forge = { ...destSettings.forge, ...srcSettings.forge };
171
+ // Always stamp current package version
172
+ destSettings.forge.version = pkgVersion;
173
+
174
+ const after = JSON.stringify(destSettings);
175
+ if (before === after) return 'unchanged';
176
+
177
+ fs.writeFileSync(destPath, JSON.stringify(destSettings, null, 2) + '\n');
178
+ return 'updated';
179
+ }
180
+
181
+ // --- Commands ---
182
+
183
+ async function install() {
42
184
  console.log('\n Forge - Meta-prompting framework for Claude Code\n');
43
185
 
44
186
  // Handle CLAUDE.md
@@ -94,10 +236,139 @@ async function main() {
94
236
  const forgeCount = copyDirRecursive(srcForge, destForge);
95
237
  console.log(` Installed .forge/templates/ (${forgeCount} files)`);
96
238
 
97
- console.log('\n Forge is ready. Start with: /forge\n');
239
+ // Stamp version from package.json into settings.json
240
+ const settingsPath = path.join(targetDir, SETTINGS_FILE);
241
+ if (fs.existsSync(settingsPath)) {
242
+ stampVersion(settingsPath);
243
+ }
244
+
245
+ console.log(`\n Forge v${pkgVersion} is ready. Start with: /forge\n`);
98
246
  }
99
247
 
100
- main().catch((err) => {
101
- console.error('Error:', err.message);
102
- process.exit(1);
103
- });
248
+ async function upgrade() {
249
+ console.log('\n Forge Upgrade\n');
250
+
251
+ // Verify Forge is installed
252
+ const settingsPath = path.join(targetDir, SETTINGS_FILE);
253
+ if (!fs.existsSync(settingsPath)) {
254
+ console.error(
255
+ ' Forge is not installed in this directory.\n Run `npx forge-orkes` first to install.\n'
256
+ );
257
+ process.exit(1);
258
+ }
259
+
260
+ // Read installed version
261
+ let installedVersion = 'unknown';
262
+ try {
263
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
264
+ installedVersion = settings.forge?.version || 'unknown';
265
+ } catch {
266
+ // proceed with unknown version
267
+ }
268
+
269
+ console.log(` Installed: v${installedVersion}`);
270
+ console.log(` Available: v${pkgVersion}\n`);
271
+
272
+ const results = {
273
+ updated: [],
274
+ added: [],
275
+ unchanged: [],
276
+ removed: [],
277
+ needsReview: [],
278
+ };
279
+
280
+ // 1. Process framework-owned directories
281
+ for (const dir of FRAMEWORK_OWNED_DIRS) {
282
+ const dirResult = upgradeDir(dir);
283
+ results.updated.push(...dirResult.updated);
284
+ results.added.push(...dirResult.added);
285
+ results.unchanged.push(...dirResult.unchanged);
286
+ results.removed.push(...dirResult.removed);
287
+ }
288
+
289
+ // 2. Process template-only directories
290
+ for (const dir of TEMPLATE_ONLY_DIRS) {
291
+ const dirResult = upgradeDir(dir);
292
+ results.updated.push(...dirResult.updated);
293
+ results.added.push(...dirResult.added);
294
+ results.unchanged.push(...dirResult.unchanged);
295
+ results.removed.push(...dirResult.removed);
296
+ }
297
+
298
+ // 3. Process merge-owned files
299
+ for (const file of MERGE_OWNED_FILES) {
300
+ const status = handleMergeFile(file);
301
+ if (status === 'staged') {
302
+ results.needsReview.push(file);
303
+ } else if (status === 'unchanged') {
304
+ results.unchanged.push(file);
305
+ }
306
+ }
307
+
308
+ // 4. Smart-merge settings.json
309
+ const settingsStatus = upgradeSettings();
310
+ if (settingsStatus === 'updated') {
311
+ results.updated.push(SETTINGS_FILE);
312
+ } else if (settingsStatus === 'unchanged') {
313
+ results.unchanged.push(SETTINGS_FILE);
314
+ }
315
+
316
+ // Report results
317
+ const totalChanges =
318
+ results.updated.length + results.added.length + results.needsReview.length;
319
+
320
+ if (totalChanges === 0 && results.removed.length === 0) {
321
+ console.log(' Already up to date.\n');
322
+ return;
323
+ }
324
+
325
+ if (results.updated.length > 0) {
326
+ console.log(` Updated (${results.updated.length}):`);
327
+ for (const f of results.updated) {
328
+ console.log(` ${f}`);
329
+ }
330
+ console.log();
331
+ }
332
+
333
+ if (results.added.length > 0) {
334
+ console.log(` Added (${results.added.length}):`);
335
+ for (const f of results.added) {
336
+ console.log(` ${f}`);
337
+ }
338
+ console.log();
339
+ }
340
+
341
+ if (results.needsReview.length > 0) {
342
+ console.log(` Needs manual review (${results.needsReview.length}):`);
343
+ for (const f of results.needsReview) {
344
+ console.log(` ${f} → .forge/upgrade/${path.basename(f)}.new`);
345
+ }
346
+ console.log();
347
+ }
348
+
349
+ if (results.removed.length > 0) {
350
+ console.log(` Removed from template (${results.removed.length}):`);
351
+ for (const f of results.removed) {
352
+ console.log(` ${f} (still in your project — delete manually if unused)`);
353
+ }
354
+ console.log();
355
+ }
356
+
357
+ console.log(` Upgraded to v${pkgVersion}\n`);
358
+ }
359
+
360
+ // --- Entry point ---
361
+
362
+ const subcommand = process.argv[2];
363
+
364
+ if (subcommand === 'upgrade') {
365
+ upgrade().catch((err) => {
366
+ console.error('Error:', err.message);
367
+ process.exit(1);
368
+ });
369
+ } else {
370
+ install().catch((err) => {
371
+ console.error('Error:', err.message);
372
+ process.exit(1);
373
+ });
374
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-orkes",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Set up the Forge meta-prompting framework for Claude Code in your project",
5
5
  "bin": {
6
6
  "create-forge": "./bin/create-forge.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "forge": {
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "default_tier": "standard",
5
5
  "beads_integration": false,
6
6
  "context_gates": {
@@ -10,7 +10,14 @@
10
10
  "constitution_md_max_kb": 10
11
11
  },
12
12
  "commit_format": "{type}({scope}): {description}",
13
- "commit_types": ["feat", "fix", "test", "refactor", "chore", "docs"]
13
+ "commit_types": [
14
+ "feat",
15
+ "fix",
16
+ "test",
17
+ "refactor",
18
+ "chore",
19
+ "docs"
20
+ ]
14
21
  },
15
22
  "hooks": {
16
23
  "PostToolUse": [
@@ -23,9 +30,27 @@
23
30
  "async": true
24
31
  }
25
32
  ]
33
+ },
34
+ {
35
+ "matcher": "Skill",
36
+ "hooks": [
37
+ {
38
+ "type": "command",
39
+ "command": "mkdir -p .forge && echo \"$TOOL_INPUT\" > .forge/.active-skill"
40
+ }
41
+ ]
26
42
  }
27
43
  ],
28
44
  "PreToolUse": [
45
+ {
46
+ "matcher": "Write|Edit",
47
+ "hooks": [
48
+ {
49
+ "type": "command",
50
+ "command": "if [ ! -f .forge/.active-skill ]; then echo \"[Forge] No active skill. Invoke /forge or /quick-tasking before editing code. To bypass: touch .forge/.active-skill\" >&2; exit 2; fi"
51
+ }
52
+ ]
53
+ },
29
54
  {
30
55
  "matcher": "Bash(git commit)",
31
56
  "hooks": [
@@ -119,3 +119,15 @@ After completing architectural work:
119
119
  3. API contracts defined (if applicable)
120
120
  4. Constitutional gates verified
121
121
  5. User has approved significant decisions
122
+
123
+ ## Phase Handoff
124
+
125
+ After architectural decisions are documented:
126
+
127
+ 1. **Verify persistence** — Confirm ADRs are written to `.forge/decisions/`, data models and API contracts to `.forge/phases/{N}-{name}/`
128
+ 2. **Update state** — Set `current.status` to `planning` in `.forge/state/milestone-{id}.yml`
129
+ 3. **Recommend context clear:**
130
+
131
+ *"Architecting phase complete. Decisions are documented in `.forge/decisions/` and phase artifacts. I recommend clearing context (`/clear`) before starting the planning phase — the planner will load ADRs, contracts, and state from disk.*
132
+
133
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
@@ -300,3 +300,15 @@ This is a soft gate — critical issues strongly recommend fixing before complet
300
300
  - The user always has final authority over ship decisions
301
301
 
302
302
  The report documents the decision either way, creating an audit trail.
303
+
304
+ ## Phase Handoff
305
+
306
+ After auditing routes to refactoring (all three paths: HEALTHY, accepted risk, accepted warnings):
307
+
308
+ 1. **Verify persistence** — Confirm health report is written to `.forge/audits/milestone-{id}-health-report.md`
309
+ 2. **Update state** — Set `current.status` to `refactoring` in `.forge/state/milestone-{id}.yml`
310
+ 3. **Recommend context clear:**
311
+
312
+ *"Health audit complete. Report written to `.forge/audits/`. I recommend clearing context (`/clear`) before the refactoring review — the refactoring scanner spawns a fresh agent with the git diff and health report, so a clean context ensures accurate scanning.*
313
+
314
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
@@ -29,46 +29,94 @@ The only output is the conversation itself and, at the end, a summary of decisio
29
29
 
30
30
  ## Pre-Planning Discussion
31
31
 
32
- When entering from `researching` with findings in hand:
32
+ When entering from `researching` (potentially after a context clear):
33
33
 
34
- ### Step 1: Present the Landscape
34
+ ### Step 0: Load Context
35
+
36
+ If entering with a fresh context (after `/clear`):
37
+
38
+ ```
39
+ Read: .forge/state/milestone-{id}.yml → current position, progress
40
+ Read: .forge/project.yml → tech stack, project description
41
+ Read: .forge/context.md → any existing locked decisions (if exists)
42
+ Read: .forge/constitution.md → active gates (if exists)
43
+ ```
44
+
45
+ Check if research findings were written to files (`.forge/phases/` or similar). If so, read them. If research was inline-only (conversation context), the findings may need to be re-summarized from the user — ask briefly: *"We're picking up after the research phase. Can you summarize the key findings, or should I re-scan the relevant areas?"*
46
+
47
+ ### Step 1: Present Decisions with AskUserQuestion
35
48
 
36
49
  Summarize what research found, structured around decisions the user needs to make — not a data dump.
37
50
 
38
- *"Based on what I found, here are the key decisions before we plan:"*
51
+ **Use the `AskUserQuestion` tool for every decision point.** This gives users a clean, scannable interface instead of walls of text. You can batch up to 4 questions per `AskUserQuestion` call.
52
+
53
+ For each decision:
54
+ 1. Write a **brief prose intro** (2-3 sentences max) setting context for the decision — what's the problem, why does it matter.
55
+ 2. Then immediately call `AskUserQuestion` with:
56
+ - `question`: The decision stated plainly, ending with `?`
57
+ - `header`: Short label (e.g., "Strategy", "Approach", "Scope")
58
+ - `options`: 2-4 realistic approaches. Each option gets:
59
+ - `label`: Concise name (1-5 words). Put your recommendation first with "(Recommended)" suffix.
60
+ - `description`: Trade-offs — what you gain and what you lose. Be honest about costs.
61
+ - `multiSelect`: false for mutually exclusive choices, true when combinations are valid.
62
+
63
+ **Batch related decisions.** If you have 3-5 decisions, group them into 1-2 `AskUserQuestion` calls (max 4 questions each) rather than asking one at a time. This lets the user see the full landscape and make coherent choices.
64
+
65
+ **When NOT to use AskUserQuestion:** For open-ended exploration questions where the answer isn't one of a few discrete options (e.g., "Walk me through the ideal user flow"), use regular prose. The tool is for decisions with concrete choices, not brainstorming.
66
+
67
+ Example structure for a discussion with 3 decisions:
68
+
69
+ ```
70
+ Brief context paragraph explaining the landscape from research.
39
71
 
40
- For each decision point:
41
- - **What needs deciding** the question, stated plainly
42
- - **Options** 2-3 realistic approaches (not exhaustive lists)
43
- - **Trade-offs** what you gain and what you lose with each
44
- - **Recommendation** if you have one, say so and say why. If you don't, say that too.
72
+ AskUserQuestion with questions:
73
+ 1. "Which recovery strategy should we use?" (header: "Recovery")
74
+ - "Sweep timer (Recommended)" / "Sweep timer + queue refactor" / ...
75
+ 2. "Where should observability live?" (header: "Observability")
76
+ - "Server-side logs only" / "PostHog events" / "Both" / ...
77
+ 3. "How should we handle the 704 contradictory records?" (header: "Data cleanup")
78
+ - "Migration + constraints" / "Let sweep handle it" / "Migration only" / ...
79
+ ```
45
80
 
46
- Keep it conversational. Don't present a 20-item matrix. Surface the 3-5 decisions that actually matter for this work.
81
+ Surface the 3-5 decisions that actually matter. Don't present a 20-item matrix.
47
82
 
48
83
  ### Step 2: Facilitate, Don't Dictate
49
84
 
50
- Your role is to help the user think, not to push them toward your preference.
85
+ After the user responds to decisions, your role is to help them think deeper — not to push your preference.
86
+
87
+ **Use `AskUserQuestion` for follow-up decisions** that emerge from their answers. Use prose for open-ended exploration.
51
88
 
52
89
  Good facilitation patterns:
53
- - *"The main tension here is between X and Y. Which matters more for your project?"*
54
- - *"Option A is simpler now but harder to change later. Option B is more work upfront but more flexible. What's your timeline pressure like?"*
55
- - *"I'd lean toward X because [reason], but Y makes sense if [condition]. What's your read?"*
56
- - *"You mentioned [earlier decision] — that makes Option B a more natural fit. Does that match your thinking?"*
90
+ - *"The main tension here is between X and Y."* then `AskUserQuestion` with the concrete options
91
+ - Referencing earlier decisions: *"You chose Option A for recovery that makes X a more natural fit for observability."* then `AskUserQuestion` with refined options
92
+ - When trade-offs need explicit weighing `AskUserQuestion` with `description` fields that name the costs
57
93
 
58
94
  Bad facilitation patterns:
59
- - Presenting options without trade-offs (just a list)
60
- - Asking "what do you think?" without giving the user something to react to
95
+ - Presenting options as prose paragraphs when they could be `AskUserQuestion` choices
96
+ - Asking "what do you think?" without giving the user something concrete to react to
61
97
  - Overwhelming with edge cases before the main path is clear
62
98
  - Treating every decision as equally important
63
99
 
64
100
  ### Step 3: Probe for Hidden Constraints
65
101
 
66
- Research often misses things the user knows but hasn't mentioned. Ask about:
67
- - **Timeline pressure** — does this need to ship by a date?
68
- - **Audience/users** — who actually uses this? (affects complexity trade-offs)
69
- - **Future direction** — is this a throwaway or the foundation for more?
70
- - **Past experience** have they tried something similar before? What went wrong?
71
- - **Strong preferences** — anything they definitely want or definitely don't want?
102
+ Research often misses things the user knows but hasn't mentioned. Use `AskUserQuestion` for structured probes where the answer shapes the plan:
103
+
104
+ ```
105
+ AskUserQuestion:
106
+ question: "What's the timeline pressure for this work?"
107
+ header: "Timeline"
108
+ options:
109
+ - label: "Ship this week"
110
+ description: "Minimal scope, skip nice-to-haves"
111
+ - label: "Ship this month"
112
+ description: "Room for polish and edge cases"
113
+ - label: "No hard deadline"
114
+ description: "Do it right, scope is flexible"
115
+ ```
116
+
117
+ For open-ended probes where you need the user to explain (not choose), use prose:
118
+ - *"Have you tried something similar before? What went wrong?"*
119
+ - *"Anything you definitely want or definitely don't want?"*
72
120
 
73
121
  One or two questions at a time. Don't interrogate.
74
122
 
@@ -123,6 +171,21 @@ Don't mechanically walk through all 5 layers for every requirement — that woul
123
171
 
124
172
  Ask 2-3 questions at a time, let the user respond, then go deeper where their answers reveal uncertainty. The conversation should feel like a collaborative design session, not an interrogation.
125
173
 
174
+ **Use `AskUserQuestion` for behavior decisions within distillation.** When a question has discrete answers (retry vs. fail vs. alert, real-time vs. polling, roles A/B/C), use the tool. When you need the user to describe or explain something open-ended, use prose.
175
+
176
+ Example — Layer 3 question as `AskUserQuestion`:
177
+ ```
178
+ question: "When the external enrichment API is down, what should the system do?"
179
+ header: "Failure mode"
180
+ options:
181
+ - label: "Retry with backoff (Recommended)"
182
+ description: "Queue retries at 1m/5m/30m intervals. Adds complexity but self-heals."
183
+ - label: "Fail and alert"
184
+ description: "Mark as failed, send alert. Simple but requires manual re-trigger."
185
+ - label: "Skip and continue"
186
+ description: "Process remaining items, revisit failures in next sweep."
187
+ ```
188
+
126
189
  **What you're listening for:**
127
190
 
128
191
  - **Contradictions** — "It should be simple" but also "it needs to handle 12 different states." Surface these gently.
@@ -132,14 +195,25 @@ Ask 2-3 questions at a time, let the user respond, then go deeper where their an
132
195
 
133
196
  ### Step 5: Converge on Decisions
134
197
 
135
- When the conversation has covered the key points, summarize what's been decided:
198
+ When the conversation has covered the key points, summarize what's been decided as a brief prose list, then use `AskUserQuestion` for final confirmation:
136
199
 
137
- *"Here's where I think we've landed:*
200
+ *"Here's where I think we've landed:"*
138
201
  - *[Decision 1]: [what was decided and why]*
139
202
  - *[Decision 2]: [what was decided and why]*
140
203
  - *[Open question]: [what's still unresolved and how to handle it]*
141
204
 
142
- *Does this match your understanding? If so, I'll carry these into planning."*
205
+ Then confirm with `AskUserQuestion`:
206
+ ```
207
+ question: "Does this match your understanding? Ready to move to planning?"
208
+ header: "Confirm"
209
+ options:
210
+ - label: "Looks good, proceed"
211
+ description: "Lock these decisions and move to planning phase."
212
+ - label: "I want to adjust something"
213
+ description: "Revisit one or more decisions before locking."
214
+ - label: "More to discuss"
215
+ description: "There are topics we haven't covered yet."
216
+ ```
143
217
 
144
218
  These decisions flow into `context.md` as **Locked Decisions** when the `planning` skill runs next.
145
219
 
@@ -169,12 +243,12 @@ Don't just recite the plan back. Translate it into what it means:
169
243
 
170
244
  ### Step 3: Surface What's Worth Discussing
171
245
 
172
- Don't wait for the user to spot issues. Proactively surface:
246
+ Don't wait for the user to spot issues. Proactively surface concerns, then **use `AskUserQuestion` for any that have discrete choices:**
173
247
 
174
- - **Assumptions you're not confident about** "Plan 01 assumes the API returns paginated results. I didn't verify this."
175
- - **Decisions that could go either way** — "I split this into 3 plans for parallelism, but you could also do it as 2 larger plans if you prefer fewer context switches."
176
- - **Risks the plan doesn't address** "There's no fallback if the external API is slow. Worth adding, or accept the risk?"
177
- - **Scope questions** "Plan 03 includes admin-only features. Ship those in v1, or defer?"
248
+ - **Decisions that could go either way** `AskUserQuestion` with the options and trade-offs
249
+ - **Scope questions** `AskUserQuestion` (e.g., "Ship admin features in v1?" with "Yes, include" / "Defer to v2" options)
250
+ - **Risks the plan doesn't address** `AskUserQuestion` (e.g., "Worth adding a fallback?" with "Add fallback" / "Accept risk" options)
251
+ - **Assumptions you're not confident about** Prose, since these need the user to confirm or correct rather than choose
178
252
 
179
253
  ### Step 4: Drill into Functionality
180
254
 
@@ -188,23 +262,43 @@ This is where post-planning discussion earns its keep — the plan makes the fea
188
262
 
189
263
  ### Step 5: Discuss and Revise Direction
190
264
 
191
- The user may want to:
192
- - **Change approach** — "Let's use WebSockets instead of polling." → Note this. Planning skill will rebuild the affected plans.
193
- - **Adjust scope** — "Defer the admin features." → Note this for deferred items.
194
- - **Reorder priorities** "Do the dashboard before the settings page." → Note the new wave order.
195
- - **Ask questions** — "What happens if we skip the caching layer?" → Discuss implications honestly.
196
- - **Approve as-is** — "Looks good, proceed." → Move to executing.
265
+ The user may want to change approach, adjust scope, reorder priorities, ask questions, or approve as-is. Use `AskUserQuestion` to give them a clear way to signal their intent:
266
+
267
+ ```
268
+ question: "How would you like to proceed with this plan?"
269
+ header: "Direction"
270
+ options:
271
+ - label: "Approve as-is"
272
+ description: "Lock decisions and move to execution."
273
+ - label: "Adjust scope"
274
+ description: "Defer or add features before building."
275
+ - label: "Change approach"
276
+ description: "Revisit a technical decision in the plan."
277
+ - label: "More questions"
278
+ description: "I want to discuss specific parts further."
279
+ ```
280
+
281
+ Based on their response, either drill deeper with follow-up `AskUserQuestion` calls or move to summarizing.
197
282
 
198
283
  ### Step 6: Summarize Changes
199
284
 
200
- If the discussion produced changes to the plan direction:
285
+ If the discussion produced changes to the plan direction, summarize as prose:
201
286
 
202
287
  *"Based on our discussion:*
203
288
  - *[Change 1]: [what changed and why]*
204
289
  - *[Change 2]: [what changed and why]*
205
290
  - *[Unchanged]: [what stays the same]*
206
291
 
207
- *Next step: I'll update the plans to reflect this. Want me to proceed with re-planning, or is there more to discuss?"*
292
+ Then confirm next steps with `AskUserQuestion`:
293
+ ```
294
+ question: "Ready to update the plans, or more to discuss?"
295
+ header: "Next step"
296
+ options:
297
+ - label: "Update plans"
298
+ description: "Re-plan affected areas with the revised decisions."
299
+ - label: "More to discuss"
300
+ description: "There are topics we haven't covered yet."
301
+ ```
208
302
 
209
303
  If re-planning is needed, route back to the `planning` skill with the discussion summary as input. The planning skill will update plans, requirements, and context.md accordingly.
210
304
 
@@ -227,3 +321,15 @@ If re-planning is needed, route back to the `planning` skill with the discussion
227
321
  - **Premature convergence** — locking decisions before the user has had a chance to think. Don't rush the summary.
228
322
  - **Scope creep via discussion** — "While we're at it, should we also..." Keep discussion focused on the work at hand.
229
323
  - **Discussion as procrastination** — if the user keeps wanting to discuss but never approves a plan, gently surface the pattern.
324
+
325
+ ## Phase Handoff
326
+
327
+ After discussion converges on decisions:
328
+
329
+ 1. **Persist decisions** — The decision summary from Step 5 (pre-planning) or Step 6 (post-planning) will flow into `context.md` when the planning skill runs. For post-planning revisions, note the changes clearly so planning can pick them up.
330
+ 2. **Update state** — Set `current.status` to `planning` (or `architecting` for Full tier) in `.forge/state/milestone-{id}.yml`
331
+ 3. **Recommend context clear:**
332
+
333
+ *"Discussion phase complete. Decisions are captured and will be written to context.md during planning. I recommend clearing context (`/clear`) before starting the {planning/architecting} phase — the planner will load everything it needs from `.forge/` state files.*
334
+
335
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
@@ -152,3 +152,17 @@ While executing, watch for and log these patterns in `.forge/state/index.yml →
152
152
  - **Agent struggles**: If you need multiple attempts to get something right, or the user has to guide you through it, log the task type as an `agent_struggle`.
153
153
 
154
154
  This takes seconds per signal. Don't skip it — this data drives framework evolution.
155
+
156
+ ## Phase Handoff
157
+
158
+ After all plans in the phase are executed:
159
+
160
+ 1. **Verify persistence** — Confirm execution summary is documented, all commits are made, milestone state is updated with progress and deviations, and desire path signals are logged
161
+ 2. **Update state** — Set `current.status` to `verifying` in `.forge/state/milestone-{id}.yml`
162
+ 3. **Recommend context clear:**
163
+
164
+ *"Execution phase complete. All tasks committed, state updated, deviations logged. I recommend clearing context (`/clear`) before starting verification — the verifier needs a fresh window to objectively assess the work against must_haves, without carrying the executor's assumptions.*
165
+
166
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
167
+
168
+ This handoff is especially important after execution — the verifier should approach the code with fresh eyes, not the executor's memory of what it intended to build.
@@ -481,6 +481,12 @@ Match ANY:
481
481
  → Add `designing` if UI work involved
482
482
  → Add `securing` if auth/data/API touched
483
483
 
484
+ ### Direct Utility Skills
485
+ Match ANY:
486
+ - User says "upgrade", "update forge", "sync forge"
487
+
488
+ → Route to `upgrading` skill (bypasses tier detection)
489
+
484
490
  ### User Override
485
491
  If user explicitly says "Use Quick/Standard/Full tier" — honor it. No arguments.
486
492
 
@@ -512,13 +518,64 @@ While working at any tier, if you encounter:
512
518
 
513
519
  When uncertain → Rule 4 (ask). Never silently make architectural decisions.
514
520
 
521
+ ## Context Handoff Protocol
522
+
523
+ Phase transitions are natural context-clearing boundaries. After each phase completes and writes its state to disk, **recommend the user clear context** before the next phase begins. This prevents context rot — the #1 cause of quality degradation in long sessions.
524
+
525
+ ### Why Clear Between Phases
526
+
527
+ Each phase produces persistent artifacts (state files, plans, reports, backlogs) that the next phase reads from disk. The next phase does NOT need the previous phase's working memory — it needs the artifacts. Carrying forward stale context wastes tokens and degrades output quality.
528
+
529
+ ### When to Recommend
530
+
531
+ Recommend clearing context at every phase boundary in Standard and Full tiers:
532
+
533
+ ```
534
+ researching → [clear] → discussing → [clear] → architecting → [clear] → planning → [clear] → executing → [clear] → verifying → [clear] → auditing → [clear] → refactoring
535
+ ```
536
+
537
+ **Skip the recommendation when:**
538
+ - Quick tier (single phase, no boundary to clear)
539
+ - The phase was very short (under 5 minutes of work) and context is well under 40%
540
+ - The user has explicitly said they don't want context-clearing prompts
541
+
542
+ ### The Handoff Prompt
543
+
544
+ Each skill ends with a standard handoff message. The pattern is:
545
+
546
+ 1. **Confirm state is written** — skill verifies its outputs are persisted to `.forge/`
547
+ 2. **Summarize what was produced** — brief list of artifacts the next phase will need
548
+ 3. **Recommend clearing context** — present the prompt to the user:
549
+
550
+ *"Phase complete. All state has been written to disk. I recommend clearing context (`/clear`) before starting {next phase} — this gives the next phase a fresh context window to work with. The {next phase} skill will load everything it needs from `.forge/` state files.*
551
+
552
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
553
+
554
+ 4. **If user declines** — proceed normally. The recommendation is advisory, not blocking.
555
+
556
+ ### What Each Phase Writes (Handoff Artifacts)
557
+
558
+ | Phase | Writes to Disk | Next Phase Reads |
559
+ |-------|---------------|------------------|
560
+ | researching | Research summary (markdown in conversation or `.forge/` files) | discussing reads research findings |
561
+ | discussing | Decision summary → carried into planning via context.md | planning reads context.md |
562
+ | architecting | ADRs in `.forge/decisions/`, data models, API contracts | planning reads decisions |
563
+ | planning | Plans in `.forge/phases/`, requirements.yml, roadmap.yml, context.md | executing reads plans |
564
+ | executing | Committed code, execution summary, milestone state updated | verifying reads must_haves from plans |
565
+ | verifying | Verification report, desire paths updated | auditing reads project.yml + source files |
566
+ | auditing | Health report in `.forge/audits/` | refactoring reads health report + git diff |
567
+
568
+ ### Context Loading on Resume
569
+
570
+ When a skill starts after a context clear, it must load its required state from disk. Each skill's "Read Context" or "Pre-Execution Checklist" step handles this. The `forge` orchestrator reads `milestone-{id}.yml` to determine which skill to route to, then that skill loads its own dependencies.
571
+
515
572
  ## State Transitions
516
573
 
517
574
  ```
518
- not_started → [init if new] → researching → discussing → planning → executing → verifying → auditing → refactoring → complete
519
- ↗ debugging (if stuck)
520
- ↗ designing (if UI)
521
- ↗ securing (if auth/data)
575
+ not_started → [init if new] → researching → [clear] → discussing → [clear] → planning → [clear] → executing → [clear] → verifying → [clear] → auditing → [clear] → refactoring → complete
576
+ ↗ debugging (if stuck)
577
+ ↗ designing (if UI)
578
+ ↗ securing (if auth/data)
522
579
  ```
523
580
 
524
581
  Update `.forge/state/milestone-{id}.yml` at each transition. Update `.forge/state/index.yml` milestone `last_updated` timestamp.
@@ -223,3 +223,15 @@ Show the user:
223
223
  4. Ask: "Does this plan match your expectations? Any changes?"
224
224
 
225
225
  Planning is complete when user approves.
226
+
227
+ ## Phase Handoff
228
+
229
+ After the user approves the plan:
230
+
231
+ 1. **Verify persistence** — Confirm all plans are written to `.forge/phases/{N}-{name}/plan-{NN}.md`, requirements to `.forge/requirements.yml`, roadmap to `.forge/roadmap.yml`, and context to `.forge/context.md`
232
+ 2. **Update state** — Set `current.status` to `executing` in `.forge/state/milestone-{id}.yml`
233
+ 3. **Recommend context clear:**
234
+
235
+ *"Planning phase complete. Plans, requirements, and context are all written to `.forge/`. I recommend clearing context (`/clear`) before starting execution — the executor will load the plan files and context.md fresh, giving it maximum context window for building.*
236
+
237
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
@@ -115,3 +115,15 @@ Research output should be under 500 lines. If larger, split into focused documen
115
115
  - `research-codebase.md` for codebase findings
116
116
  - `research-tech.md` for technology evaluation
117
117
  - `research-requirements.md` for requirements analysis
118
+
119
+ ## Phase Handoff
120
+
121
+ After research is complete:
122
+
123
+ 1. **Persist findings** — Write research summary to `.forge/phases/` or present inline (for Standard tier, inline is fine; for Full tier with multiple research topics, write to files)
124
+ 2. **Update state** — Set `current.status` to `discussing` in `.forge/state/milestone-{id}.yml`
125
+ 3. **Recommend context clear:**
126
+
127
+ *"Research phase complete. Findings are summarized above [or written to .forge/phases/]. I recommend clearing context (`/clear`) before starting the discussion phase — this gives discussing a fresh window to work with. The discussing skill will reference the research findings.*
128
+
129
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: upgrading
3
+ description: "Sync Forge framework files from a local dev repo or NPM. Use when developing Forge itself or applying updates to an installed project."
4
+ ---
5
+
6
+ # Upgrading: Local Dev Sync
7
+
8
+ Sync framework files from a local Forge source repo into the current project. Use this during Forge development to test changes without publishing to NPM.
9
+
10
+ For published upgrades, use `npx forge-orkes upgrade` instead.
11
+
12
+ ## Step 1: Resolve Source Path
13
+
14
+ Check if `.forge/dev-source` exists in the project root.
15
+
16
+ - **If it exists:** read the path from the file (first line, trimmed). Verify the path exists and contains `packages/create-forge/template/`.
17
+ - **If it doesn't exist:** ask the user: *"Where is your local Forge repo? (e.g., ~/Dev/forge)"*
18
+ - Validate the path has `packages/create-forge/template/`
19
+ - Save the path to `.forge/dev-source` for next time
20
+
21
+ The template directory is `{source}/packages/create-forge/template/`.
22
+
23
+ ## Step 2: File Classification
24
+
25
+ Files are classified into three categories:
26
+
27
+ | Category | Paths | Behavior |
28
+ |----------|-------|----------|
29
+ | **Framework-owned** | `.claude/agents/*.md`, `.claude/skills/*/SKILL.md` | Overwrite — these are Forge's |
30
+ | **Merge-owned** | `CLAUDE.md`, `.claude/settings.json` | Never auto-overwrite |
31
+ | **Template-only** | `.forge/templates/**` | Overwrite — reference templates |
32
+
33
+ **Never touch** user-generated files: `.forge/project.yml`, `.forge/state/`, `.forge/constitution.md`, `.forge/context.md`, `.forge/requirements.yml`, `.forge/roadmap.yml`, `.forge/design-system.md`, `.forge/refactor-backlog.yml`.
34
+
35
+ ## Step 3: Sync Framework-Owned Files
36
+
37
+ For each framework-owned file in the source template:
38
+
39
+ 1. Read the source file content
40
+ 2. Read the local file content (if it exists)
41
+ 3. If different → overwrite local with source, report as **updated**
42
+ 4. If same → report as **unchanged**
43
+ 5. If source has a new file not in local → copy it, report as **added**
44
+ 6. If local has a file not in source → report as **removed from template** (don't delete — let user decide)
45
+
46
+ ## Step 4: Sync Template-Only Files
47
+
48
+ Same process as Step 3, but for `.forge/templates/**`.
49
+
50
+ ## Step 5: Handle Merge-Owned Files
51
+
52
+ For `CLAUDE.md`:
53
+ 1. Read source and local versions
54
+ 2. If different → **do not overwrite**. Instead, summarize what changed in prose (new sections, removed sections, modified text)
55
+ 3. Present the summary to the user and let them decide how to merge
56
+
57
+ For `.claude/settings.json`:
58
+ 1. Read source and local versions
59
+ 2. Compare the `forge.*` keys only
60
+ 3. If forge keys differ → update only `forge.*` keys in local, preserve user's `hooks` and any other custom keys
61
+ 4. Update `forge.version` to match the source package version
62
+
63
+ ## Step 6: Report
64
+
65
+ Present a summary:
66
+
67
+ ```
68
+ Forge Local Sync Complete
69
+ ─────────────────────────
70
+ Source: {path}
71
+ Version: {old} → {new}
72
+
73
+ Updated: {N} files
74
+ - .claude/skills/executing/SKILL.md
75
+ - ...
76
+
77
+ Added: {N} files
78
+ - .claude/skills/new-skill/SKILL.md
79
+ - ...
80
+
81
+ Removed from template: {N} files
82
+ - .claude/agents/old-agent.md (still in your project)
83
+ - ...
84
+
85
+ Needs manual review: {N} files
86
+ - CLAUDE.md (new sections: "Upgrade Mechanism", modified: "Skill Routing")
87
+ - ...
88
+
89
+ Unchanged: {N} files
90
+ ```
@@ -12,6 +12,20 @@ Prove completed work actually delivers what was promised. Task completion ≠ go
12
12
  Don't ask: "Did we complete all the tasks?"
13
13
  Ask: "Does the user get what they were promised?"
14
14
 
15
+ ## Load Context
16
+
17
+ When entering with a fresh context (after `/clear`):
18
+
19
+ ```
20
+ Read: .forge/state/milestone-{id}.yml → current phase, plans completed
21
+ Read: .forge/project.yml → tech stack (for running tests)
22
+ Read: .forge/phases/{N}-{name}/plan-{NN}.md → must_haves (truths, artifacts, key_links)
23
+ Read: .forge/context.md → locked decisions (to understand intent)
24
+ Read: .forge/requirements.yml → requirement IDs for coverage check
25
+ ```
26
+
27
+ This is critical — the verifier should assess the code with fresh eyes, not carry the executor's assumptions. Load must_haves from the plan files and verify against the actual codebase.
28
+
15
29
  ## 3-Level Goal-Backward Verification
16
30
 
17
31
  ### Level 1: Observable Truths
@@ -199,3 +213,17 @@ When any pattern reaches **3+ occurrences**, surface it to the user:
199
213
  - *"Should I add a new constitutional article: 'Error Boundaries Required'?"*
200
214
 
201
215
  Only suggest changes when there's clear evidence (3+ occurrences). One-off issues are noise, not signal.
216
+
217
+ ## Phase Handoff
218
+
219
+ After verification completes with a PASSED verdict:
220
+
221
+ 1. **Verify persistence** — Confirm verification results are documented, desire paths retrospective is logged to `.forge/state/index.yml`
222
+ 2. **Update state** — Set `current.status` to `auditing` in `.forge/state/milestone-{id}.yml`
223
+ 3. **Recommend context clear:**
224
+
225
+ *"Verification phase complete — all truths verified, artifacts substantive and wired. I recommend clearing context (`/clear`) before the health audit — the auditing skill spawns fresh subagents anyway, and a clean orchestrator context ensures nothing is missed.*
226
+
227
+ *Ready to continue? Clear context and invoke `/forge` to resume."*
228
+
229
+ Note: If verification found GAPS, route back to planning in gap-closure mode instead. The context clear recommendation applies after the re-verified PASSED verdict.
@@ -46,6 +46,7 @@ Forge auto-detects complexity. Override with: "Use Quick/Standard/Full tier."
46
46
  | Build UI with design system consistency | `designing` | When UI involved |
47
47
  | Review security before shipping | `securing` | When auth/data/API involved |
48
48
  | Debug systematically with hypotheses | `debugging` | When stuck |
49
+ | Upgrade Forge framework files | `upgrading` | On-demand |
49
50
  | Use Beads for cross-session memory | `beads-integration` | When Beads installed |
50
51
 
51
52
  ## Context Engineering
@@ -61,6 +62,9 @@ Forge auto-detects complexity. Override with: "Use Quick/Standard/Full tier."
61
62
  ### Fresh Agent Pattern
62
63
  When a task touches 20+ files or a complex subsystem, spawn a fresh executor agent with isolated context. This prevents context rot — the #1 cause of quality degradation in long sessions.
63
64
 
65
+ ### Context Handoff Between Phases
66
+ Each phase writes its outputs to `.forge/` before completing. At every phase boundary (researching → discussing → planning → executing → verifying → auditing → refactoring), the completing skill recommends clearing context (`/clear`) before the next phase begins. The next phase loads what it needs from disk. This is advisory — skip for short phases where context is under 40%. See the `forge` skill's "Context Handoff Protocol" for full details.
67
+
64
68
  ### Lazy Loading
65
69
  Skills load only when invoked. CLAUDE.md stays in context; skill details load on demand. This keeps base context lean (~300 lines) while making full framework available.
66
70