@izkac/forgekit 0.1.1 → 0.1.3

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 ADDED
@@ -0,0 +1,34 @@
1
+ # @izkac/forgekit
2
+
3
+ Portable agent skills + CLIs. One package, three bins:
4
+
5
+ | Bin | Role |
6
+ |-----|------|
7
+ | **`forgekit`** | Install / list / update / uninstall skills × agents |
8
+ | **`forge`** | Forge workflow sessions |
9
+ | **`review`** | Thorough code review pipeline |
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm i -g @izkac/forgekit
15
+ forgekit install
16
+ ```
17
+
18
+ Interactive install lets you pick **one or more** skills (comma-separated, e.g. `1,3`) or all. Same for agent environments.
19
+
20
+ Non-interactive:
21
+
22
+ ```bash
23
+ forgekit install --skills forge,thorough-code-review --agents cursor,claude --force
24
+ ```
25
+
26
+ ## Docs
27
+
28
+ - After install, full Forge reference: `~/.cursor/skills/forge/docs/forge.md` (or `~/.claude/…` / `~/.codex/…`)
29
+ - [How to use Forgekit](https://github.com/izkac/forgekit/blob/main/docs/usage.md)
30
+ - [Repository README](https://github.com/izkac/forgekit#readme)
31
+
32
+ ## License
33
+
34
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izkac/forgekit",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Forgekit CLIs — forgekit (install), forge (workflow), review (code review)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,5 +42,8 @@
42
42
  "claude",
43
43
  "codex"
44
44
  ],
45
- "license": "MIT"
45
+ "license": "MIT",
46
+ "dependencies": {
47
+ "@inquirer/prompts": "^8.5.2"
48
+ }
46
49
  }
package/src/init.mjs CHANGED
@@ -11,10 +11,9 @@
11
11
 
12
12
  import fs from 'node:fs';
13
13
  import path from 'node:path';
14
- import readline from 'node:readline/promises';
15
14
  import { fileURLToPath, pathToFileURL } from 'node:url';
16
15
  import { spawnSync } from 'node:child_process';
17
- import { stdin as input, stdout as output } from 'node:process';
16
+ import { checkbox, confirm, input } from '@inquirer/prompts';
18
17
  import {
19
18
  DEFAULT_ADR_DIR,
20
19
  disableProjectAdr,
@@ -391,30 +390,15 @@ export function initProject(selected, opts) {
391
390
  }
392
391
 
393
392
  async function promptAgents() {
394
- const rl = readline.createInterface({ input, output });
395
- try {
396
- process.stdout.write(`Init Forge project wiring for which environments?\n`);
397
- process.stdout.write(` 1) Cursor\n`);
398
- process.stdout.write(` 2) Claude Code\n`);
399
- process.stdout.write(` 3) Codex CLI\n`);
400
- process.stdout.write(` 4) All\n`);
401
- process.stdout.write(`Enter numbers separated by commas (e.g. 1,2) or 4 for all: `);
402
- const answer = (await rl.question('')).trim();
403
- if (!answer || answer === '4') return ['cursor', 'claude', 'codex'];
404
- const map = { 1: 'cursor', 2: 'claude', 3: 'codex' };
405
- const picked = [
406
- ...new Set(
407
- answer
408
- .split(/[,\s]+/)
409
- .map((s) => map[s.trim()])
410
- .filter(Boolean),
411
- ),
412
- ];
413
- if (picked.length === 0) throw new Error('No agents selected');
414
- return picked;
415
- } finally {
416
- rl.close();
417
- }
393
+ return checkbox({
394
+ message: 'Init Forge project wiring for which environments?',
395
+ choices: [
396
+ { value: 'cursor', name: 'Cursor' },
397
+ { value: 'claude', name: 'Claude Code' },
398
+ { value: 'codex', name: 'Codex CLI' },
399
+ ],
400
+ required: true,
401
+ });
418
402
  }
419
403
 
420
404
  /**
@@ -422,19 +406,11 @@ async function promptAgents() {
422
406
  * @returns {Promise<boolean>} true = user accepted OpenSpec setup
423
407
  */
424
408
  async function promptOpenSpecSetup() {
425
- const rl = readline.createInterface({ input, output });
426
- try {
427
- const yn = (
428
- await rl.question(
429
- 'OpenSpec is not set up in this project. Install and set it up now? [Y/n] (n = built-in specs engine) ',
430
- )
431
- )
432
- .trim()
433
- .toLowerCase();
434
- return !(yn === 'n' || yn === 'no');
435
- } finally {
436
- rl.close();
437
- }
409
+ return confirm({
410
+ message:
411
+ 'OpenSpec is not set up in this project. Install and set it up now? (No = built-in specs engine)',
412
+ default: true,
413
+ });
438
414
  }
439
415
 
440
416
  /**
@@ -493,25 +469,16 @@ async function resolveInitPlanEngine(opts) {
493
469
  * @returns {Promise<{ enabled: boolean, dir: string }>}
494
470
  */
495
471
  async function promptAdrForInit(defaultDir = DEFAULT_ADR_DIR) {
496
- const rl = readline.createInterface({ input, output });
497
- let enabled = false;
498
- try {
499
- const yn = (
500
- await rl.question(
501
- 'Use Architecture Decision Records (ADRs) in this project? [y/N] ',
502
- )
503
- )
504
- .trim()
505
- .toLowerCase();
506
- enabled = yn === 'y' || yn === 'yes';
507
- if (!enabled) return { enabled: false, dir: defaultDir };
508
- const dirAnswer = (
509
- await rl.question(`ADR directory inside the repo [${defaultDir}]: `)
510
- ).trim();
511
- return { enabled: true, dir: normalizeAdrDir(dirAnswer || defaultDir) };
512
- } finally {
513
- rl.close();
514
- }
472
+ const enabled = await confirm({
473
+ message: 'Use Architecture Decision Records (ADRs) in this project?',
474
+ default: false,
475
+ });
476
+ if (!enabled) return { enabled: false, dir: defaultDir };
477
+ const dir = await input({
478
+ message: 'ADR directory inside the repo',
479
+ default: defaultDir,
480
+ });
481
+ return { enabled: true, dir: normalizeAdrDir(dir.trim() || defaultDir) };
515
482
  }
516
483
 
517
484
  async function main(argv = process.argv.slice(2)) {
@@ -569,6 +536,7 @@ if (isDirect) {
569
536
  main()
570
537
  .then((code) => process.exit(code))
571
538
  .catch((err) => {
539
+ if (err?.name === 'ExitPromptError') process.exit(130);
572
540
  process.stderr.write(`${err.message || err}\n`);
573
541
  process.exit(1);
574
542
  });
package/src/install.mjs CHANGED
@@ -16,9 +16,8 @@
16
16
  import fs from 'node:fs';
17
17
  import os from 'node:os';
18
18
  import path from 'node:path';
19
- import readline from 'node:readline/promises';
20
19
  import { pathToFileURL } from 'node:url';
21
- import { stdin as input, stdout as output } from 'node:process';
20
+ import { checkbox, confirm, input, select } from '@inquirer/prompts';
22
21
  import {
23
22
  ADR_SKILLS,
24
23
  DEFAULT_ADR_DIR,
@@ -414,51 +413,27 @@ export function listInstallStatus(opts = {}) {
414
413
  }
415
414
 
416
415
  /**
417
- * @param {string} question
418
- * @param {Record<string, string>} map number → id
419
- * @param {string[]} allIds
416
+ * @param {string} message
417
+ * @param {string[]} ids
420
418
  * @returns {Promise<string[]>}
421
419
  */
422
- async function promptMulti(question, map, allIds) {
423
- const rl = readline.createInterface({ input, output });
424
- try {
425
- process.stdout.write(`${question}\n`);
426
- const entries = Object.entries(map);
427
- for (const [num, id] of entries) {
428
- const label =
429
- SKILLS[id]?.label ?? AGENTS[id]?.label ?? id;
430
- process.stdout.write(` ${num}) ${label}\n`);
431
- }
432
- const allNum = String(entries.length + 1);
433
- process.stdout.write(` ${allNum}) All\n`);
434
- process.stdout.write(
435
- `Enter numbers separated by commas (e.g. 1,2) or ${allNum} for all: `,
436
- );
437
- const answer = (await rl.question('')).trim();
438
- if (!answer || answer === allNum) return [...allIds];
439
- const picked = [
440
- ...new Set(
441
- answer
442
- .split(/[,\s]+/)
443
- .map((s) => map[s.trim()])
444
- .filter(Boolean),
445
- ),
446
- ];
447
- if (picked.length === 0) throw new Error('Nothing selected');
448
- return picked;
449
- } finally {
450
- rl.close();
451
- }
420
+ async function promptMulti(message, ids) {
421
+ return checkbox({
422
+ message,
423
+ choices: ids.map((id) => ({
424
+ value: id,
425
+ name: SKILLS[id]?.label ?? AGENTS[id]?.label ?? id,
426
+ })),
427
+ required: true,
428
+ });
452
429
  }
453
430
 
454
431
  async function promptSkills() {
455
- const map = Object.fromEntries(SKILL_IDS.map((id, i) => [String(i + 1), id]));
456
- return promptMulti('Install which skills?', map, SKILL_IDS);
432
+ return promptMulti('Install which skills?', SKILL_IDS);
457
433
  }
458
434
 
459
435
  async function promptAgents() {
460
- const map = Object.fromEntries(AGENT_IDS.map((id, i) => [String(i + 1), id]));
461
- return promptMulti('Install for which environments?', map, AGENT_IDS);
436
+ return promptMulti('Install for which environments?', AGENT_IDS);
462
437
  }
463
438
 
464
439
  /**
@@ -466,35 +441,21 @@ async function promptAgents() {
466
441
  * @returns {Promise<string>}
467
442
  */
468
443
  export async function promptAdrDir(defaultDir = DEFAULT_ADR_DIR) {
469
- const rl = readline.createInterface({ input, output });
470
- try {
471
- const dirAnswer = (
472
- await rl.question(`ADR directory inside each repo [${defaultDir}]: `)
473
- ).trim();
474
- return normalizeAdrDir(dirAnswer || defaultDir);
475
- } finally {
476
- rl.close();
477
- }
444
+ const dir = await input({
445
+ message: 'ADR directory inside each repo',
446
+ default: defaultDir,
447
+ });
448
+ return normalizeAdrDir(dir.trim() || defaultDir);
478
449
  }
479
450
 
480
451
  /**
481
452
  * @returns {Promise<{ enabled: boolean, dir: string }>}
482
453
  */
483
454
  export async function promptAdrOptions() {
484
- const rl = readline.createInterface({ input, output });
485
- let enabled = false;
486
- try {
487
- const yn = (
488
- await rl.question(
489
- 'Use Architecture Decision Records (ADRs) after OpenSpec archive? [y/N] ',
490
- )
491
- )
492
- .trim()
493
- .toLowerCase();
494
- enabled = yn === 'y' || yn === 'yes';
495
- } finally {
496
- rl.close();
497
- }
455
+ const enabled = await confirm({
456
+ message: 'Use Architecture Decision Records (ADRs) after OpenSpec archive?',
457
+ default: false,
458
+ });
498
459
  if (!enabled) return { enabled: false, dir: DEFAULT_ADR_DIR };
499
460
  const dir = await promptAdrDir(DEFAULT_ADR_DIR);
500
461
  return { enabled: true, dir };
@@ -504,19 +465,13 @@ export async function promptAdrOptions() {
504
465
  * @returns {Promise<boolean>} true = OpenSpec, false = built-in specs engine
505
466
  */
506
467
  export async function promptOpenSpec() {
507
- const rl = readline.createInterface({ input, output });
508
- try {
509
- const yn = (
510
- await rl.question(
511
- 'Plan with OpenSpec (vendor CLI)? [Y/n] (n = built-in specs engine) ',
512
- )
513
- )
514
- .trim()
515
- .toLowerCase();
516
- return !(yn === 'n' || yn === 'no');
517
- } finally {
518
- rl.close();
519
- }
468
+ return select({
469
+ message: 'Planning engine?',
470
+ choices: [
471
+ { value: true, name: 'OpenSpec (vendor CLI)' },
472
+ { value: false, name: 'Built-in specs engine' },
473
+ ],
474
+ });
520
475
  }
521
476
 
522
477
  /**
@@ -771,6 +726,7 @@ if (isDirect) {
771
726
  runInstall()
772
727
  .then((code) => process.exit(code))
773
728
  .catch((err) => {
729
+ if (err?.name === 'ExitPromptError') process.exit(130);
774
730
  process.stderr.write(`${err.message || err}\n`);
775
731
  process.exit(1);
776
732
  });
@@ -88,7 +88,7 @@ export function buildForgeMessage(info) {
88
88
  lines.push('Resume: invoke the forge skill for the current phase.');
89
89
  lines.push('Honor pace: see forge references/pace.md (`forge prefs`).');
90
90
  lines.push('Skip Forge for this task only: /forge:skip');
91
- lines.push('Guide: Forge skill + forgekit docs/forge.md');
91
+ lines.push('Guide: Forge skill + docs/forge.md (under the installed forge skill)');
92
92
  return lines.join('\n');
93
93
  }
94
94
 
@@ -91,7 +91,7 @@ export function buildForgeTriageMessage(options = {}) {
91
91
  for (const line of sessionLines) lines.push(` ${line}`);
92
92
  }
93
93
  lines.push('3. Skip Forge for this task only: `/forge:skip`');
94
- lines.push('Guide: Forge skill + forgekit docs/forge.md');
94
+ lines.push('Guide: Forge skill + docs/forge.md (under the installed forge skill)');
95
95
  return lines.join('\n');
96
96
  }
97
97
 
@@ -17,7 +17,7 @@ Spec-tracked development pipeline. Planning engine is per-project
17
17
  all workflow skills live under `./skills/` (vendored from Superpowers MIT; see
18
18
  [skills/NOTICE.md](./skills/NOTICE.md)).
19
19
 
20
- Full reference: forgekit `docs/forge.md` (shipped with this skill’s source repo).
20
+ Full reference: [docs/forge.md](./docs/forge.md) (ships with this skill).
21
21
 
22
22
  **Announce at start:** "Using Forge for this work." Include effective pace from
23
23
  `forge status` (e.g. `Pace: auto → brisk (…)`) — see [references/pace.md](./references/pace.md).
@@ -43,7 +43,7 @@ forge doctor # plan-engine readiness (OpenSpec CLI or spe
43
43
 
44
44
  Honor [references/pace.md](./references/pace.md) in implement / verify / review.
45
45
  Hard floor: money/auth/contracts/migrations always get per-task review (even under `standard` mid-group / `brisk` / `lite`).
46
- Local overlays: forgekit `docs/forge.md` § Checkout-local overrides.
46
+ Local overlays: [docs/forge.md](./docs/forge.md) § Checkout-local overrides.
47
47
 
48
48
  ## Bundled skills
49
49
 
@@ -133,4 +133,4 @@ Testing: [references/test-strategy.md](./references/test-strategy.md) — tier 1
133
133
 
134
134
  ## Do not edit vendor OpenSpec skills
135
135
 
136
- OpenSpec vendor skills upgrade in place. Forge behaviour lives in this tree and forgekit `docs/forge.md`. Re-apply vendor patches with `forge overlay` after OpenSpec upgrades.
136
+ OpenSpec vendor skills upgrade in place. Forge behaviour lives in this tree and [docs/forge.md](./docs/forge.md). Re-apply vendor patches with `forge overlay` after OpenSpec upgrades.
@@ -0,0 +1,621 @@
1
+ # Forge — disciplined development workflow
2
+
3
+ Forge is an **OpenSpec-native**, **self-contained** development pipeline.
4
+ All workflow skills (brainstorm, TDD, subagents, verify, review) live under the
5
+ Forge skill’s `skills/` folder — **no Superpowers plugin required**.
6
+
7
+ It does not stop at green unit tests or checked-off tasks: **runtime integrity**
8
+ requires a named production path for every claimed capability, and (for
9
+ jobs/workers) a closed product loop before `forge phase done`. See
10
+ [Runtime integrity](#runtime-integrity).
11
+
12
+ **Using Forgekit for the first time?** Start with the tutorial:
13
+ [**How to use Forgekit**](https://github.com/izkac/forgekit/blob/main/docs/usage.md) (install → init → `/forge:apply` → examples).
14
+
15
+ **Skill:** `forge` (Cursor, Claude Code, Codex CLI)
16
+ **Commands:** `/forge`, `/forge:*` (after `forge init`; Cursor and Claude Code)
17
+ **Scratch space:** `.forge/` (gitignored except README)
18
+ **CLI:** `@izkac/forgekit` → `forgekit` (install) · `forge` (workflow) · `review` (standalone deep review)
19
+
20
+ ---
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ # Preferred — once per machine
26
+ npm i -g @izkac/forgekit
27
+ forgekit install --skills forge --agents cursor,claude
28
+ # or: forge install # alias → --skills forge
29
+ ```
30
+
31
+ ```bash
32
+ # Once per project
33
+ forge init --cursor --claude # commands, rules, hooks, .forge/
34
+ forge init --overlay # optional OpenSpec vendor patches
35
+ ```
36
+
37
+ Hooks call `forge` on PATH. Merge the generated `forge-hooks.snippet.json`
38
+ into your agent settings if hooks are not picked up automatically.
39
+
40
+ ---
41
+
42
+ ## When Forge runs
43
+
44
+ **Default:** agents **triage** every task. Substantial work enters Forge
45
+ automatically unless the user explicitly skips with **`/forge:skip`**.
46
+
47
+ ### Substantial work (enter Forge)
48
+
49
+ **Forge = OpenSpec.** Enter the full flow only when the work warrants a tracked OpenSpec change — when **any** of:
50
+
51
+ - New feature or behavior change
52
+ - Multi-file or multi-package change
53
+ - Public API, contract, or config schema change
54
+ - Cross-product / ecosystem impact
55
+ - User invokes `/forge`, `/forge:brainstorm`, `/forge:plan`, or `/forge:build`
56
+ - Work would likely need an ADR or new OpenSpec capability when done
57
+
58
+ ### Trivial work (skip Forge)
59
+
60
+ Execute directly when **all** of:
61
+
62
+ - Question, explanation, or read-only review
63
+ - Typo, comment, or purely cosmetic edit
64
+ - Single localized change with no contract impact
65
+ - User explicitly says **`/forge:skip`** for this task
66
+
67
+ ---
68
+
69
+ ## End-to-end decision tree
70
+
71
+ This doc uses an **ASCII tree only** — no Mermaid. Lightweight viewers (e.g.
72
+ MarkView) render Mermaid flowcharts with broken fills and connectors; ASCII
73
+ works everywhere.
74
+
75
+ ```
76
+ User request
77
+
78
+ ├─ /forge:skip? ── yes ──► Direct execution (no Forge session)
79
+
80
+ └─ no
81
+
82
+ └─ OpenSpec-worthy / substantial? ── no ──► Direct execution
83
+
84
+ yes
85
+
86
+
87
+ Start / resume Forge session
88
+
89
+
90
+ Phase: Brainstorm
91
+
92
+ ├─ design not approved ──► (loop back to Brainstorm)
93
+
94
+ └─ design approved
95
+
96
+
97
+ Phase: Plan (OpenSpec)
98
+
99
+
100
+ /opsx:propose
101
+ openspec/changes/<name>/
102
+
103
+
104
+ Phase: Implement
105
+
106
+ ┌─────────────┴─────────────┐
107
+ │ PER TASK (loop until done) │
108
+ │ 1. Subagent implementer │
109
+ │ 2. TDD (scoped tests) │
110
+ │ 3. Reviewer (pace): │
111
+ │ thorough=per task │
112
+ │ standard=per group │
113
+ │ └─ fail ──► retry │
114
+ │ (tier 2 narrow evidence) │
115
+ └─────────────┬─────────────┘
116
+
117
+ Verify: audit tier 2 + tier 3 (scope from pace)
118
+ + ## Product loop (or BLOCKED)
119
+ + forge integrity-check
120
+
121
+
122
+ Final review (pace) — spine + product loop
123
+
124
+
125
+ /opsx:archive (+ project ADR follow-up if any)
126
+
127
+
128
+ forge phase done ← integrity gate (refuses if incomplete)
129
+ Done + cleanup .forge session
130
+ ```
131
+
132
+ **Jobs / workers / queues:** spine is mandatory for *every* change (`forge spine
133
+ init` — rows or `notApplicable`). Async work also needs wiring + product-loop
134
+ tasks. See [Runtime integrity](#runtime-integrity).
135
+
136
+ ### Triage (top of tree)
137
+
138
+ | Check | Outcome |
139
+ | ----- | ------- |
140
+ | User sent `/forge:skip` | Direct execution |
141
+ | Not substantial / not tracked-change-worthy | Direct execution |
142
+ | Otherwise | Enter Forge session (tracked change) |
143
+
144
+ ### Planning engine (per project)
145
+
146
+ Forge always produces a tracked change; the **engine** is project config
147
+ (`.forge/config.json` → `plan.engine`, set by `forge init`):
148
+
149
+ | Engine | Change location | Tooling |
150
+ | ------ | --------------- | ------- |
151
+ | `openspec` | `openspec/changes/<name>/` | OpenSpec CLI + `/opsx:*` vendor skills |
152
+ | `specs` | `specs/changes/<name>/` (dir from `plan.dir`) | Built-in — plain markdown, same layout |
153
+
154
+ Selection flow: `forgekit install` asks once for a user default
155
+ (`~/.forgekit/config.json` → `plan.engine`); `forge init` auto-detects
156
+ (`openspec/config.yaml` present → openspec, silent), otherwise offers to
157
+ install + `openspec init`, and falls back to the specs engine on decline
158
+ (`--openspec` / `--no-openspec` skip prompts). Migration later: `openspec
159
+ init`, then move `specs/changes/*` into `openspec/changes/`.
160
+
161
+ ### Planning (after brainstorm)
162
+
163
+ Proceed directly to the configured engine's propose flow — do not ask for a plan mode.
164
+
165
+ | Step | What happens |
166
+ | ---- | ------------ |
167
+ | **Propose** | `/opsx:propose` → `openspec/changes/<name>/` (openspec) or author `specs/changes/<name>/{proposal,tasks}.md` per [plan-specs.md](../phases/plan-specs.md) (specs) |
168
+ | **User approval** | Confirm proposal, design, tasks before implement |
169
+ | **Implement** | `/forge:apply` or `/forge:build` against `tasks.md` |
170
+
171
+ See the Forge skill’s [references/plan-routing.md](../references/plan-routing.md).
172
+
173
+ ---
174
+
175
+ ## Phases
176
+
177
+ | Phase | What happens | Skills / commands |
178
+ | ----- | ------------ | ----------------- |
179
+ | **triage** | Substantial? Skip allowed? Bootstrap session | `forge` skill |
180
+ | **brainstorm** | Explore intent, approaches, approval | `skills/brainstorming` |
181
+ | **plan** | Tracked-change propose; **`forge spine init` every change** (rows or `notApplicable`); wiring + product-loop tasks when async | [plan-routing.md](../references/plan-routing.md) |
182
+ | **implement** | Subagent per task, TDD, tier 2 evidence; update spine rows; `forge defer` for deferred wiring | **`/forge:apply`** (OpenSpec) or `/forge:build` + `skills/subagent-driven-development` + `skills/test-driven-development` + [test-strategy](../references/test-strategy.md) |
183
+ | **verify** | Audit tier 2; tier 3; product-loop evidence; `forge integrity-check` | `skills/verification-before-completion` + `verify-evidence.md` |
184
+ | **review** | Combined task reviewer (spec + quality) per task; final review (spine + product loop) | `skills/requesting-code-review` |
185
+ | **finish** | Archive (+ ADR if the project uses that); `forge phase done` (integrity gate); cleanup | `/opsx:archive`, `forge cleanup` |
186
+
187
+ **Standalone deep review (outside Forge):** for pre-merge audits with adversarial false-positive filtering, use the **thorough code review** skill — see [thorough-code-review.md](https://github.com/izkac/forgekit/blob/main/docs/thorough-code-review.md). Forge's `requesting-code-review` stays the per-task checkpoint during `/forge:build`.
188
+
189
+ ---
190
+
191
+ ## `.forge/` session layout
192
+
193
+ One session per substantial task. **Per-checkout** active pointer — works across
194
+ Cursor, Claude Code, and Codex without requiring a chat ID.
195
+
196
+ ```
197
+ .forge/
198
+ active.json ← current session (gitignored)
199
+ models.local.json ← optional billing overlay
200
+ preferences.local.json ← optional pace overlay
201
+ sessions/
202
+ 2026-06-05T143022Z-my-feature-a3f9b2/
203
+ session.json ← phase, planType, openspecChange, pace
204
+ status.json ← machine-readable progress
205
+ brainstorm/
206
+ notes.md
207
+ decisions.md
208
+ plan.md ← legacy throwaway plans only (deprecated)
209
+ verify-evidence.md ← tier 3 + ## Product loop (or BLOCKED)
210
+ deferrals.json ← forge defer registry (when used)
211
+ spine.json ← fallback if no tracked change dir
212
+ scorecard.md / scorecard.json ← L2 session score (written at done/finish)
213
+ tasks/
214
+ 01-first-task/
215
+ brief.md
216
+ test-evidence.md
217
+ task-review.md ← combined spec + quality verdict
218
+ reviews/
219
+ final-review.md
220
+ ```
221
+
222
+ For OpenSpec / specs-engine changes, the canonical **spine matrix** lives next to
223
+ the plan: `openspec/changes/<name>/spine.json` (or `<specsDir>/changes/<name>/spine.json`).
224
+
225
+ **Session ID:** `<UTC-compact>-<kebab-slug>-<6-hex>`
226
+
227
+ **Retention:** 14 days. Finished sessions (`phase: done|skipped`) are removed
228
+ on cleanup. Active session is never removed unless `--include-active`.
229
+
230
+ Optional `cursorChatId` on `session.json` when a hook can supply it — not
231
+ required for correctness.
232
+
233
+ ---
234
+
235
+ ## Commands (project slash)
236
+
237
+ | Command | Purpose |
238
+ | ------- | ------- |
239
+ | `/forge` | Start or resume from active session / current phase |
240
+ | `/forge:brainstorm` | Brainstorm phase only |
241
+ | `/forge:plan` | Plan phase — tracked-change propose (engine from `.forge/config.json`) |
242
+ | `/forge:apply` | **Tracked-change implement** — subagent TDD + verify + review (preferred over `/opsx:apply`) |
243
+ | `/forge:build` | Implement phase (`tasks.md` from either engine) |
244
+ | `/forge:status` | Show active session progress |
245
+ | `/forge:skip` | **Explicit** opt-out of Forge for this task |
246
+
247
+ OpenSpec commands remain available standalone (OpenSpec-engine projects):
248
+
249
+ | Command | Purpose |
250
+ | ------- | ------- |
251
+ | `/opsx:propose` | Create OpenSpec change + artifacts |
252
+ | `/opsx:apply` | Vendor OpenSpec task loop — **re-overlay** with Forge via `forge overlay`; prefer **`/forge:apply`** |
253
+ | `/opsx:archive` | Archive completed change |
254
+ | `/opsx:explore` | Explore without committing to a change |
255
+
256
+ ---
257
+
258
+ ## CLI (`forge`)
259
+
260
+ ```bash
261
+ forge new <slug> [--signal "…"] # new session + set active (resolves pace; warn-only doctor)
262
+ forge status # active session JSON (+ effective pace)
263
+ forge phase <phase> […] # update phase / openspec / task counters
264
+ forge cleanup [--dry-run] # prune sessions >14 days or finished
265
+ forge evidence --task <nn>-<slug> --command "<cmd>" --exit 0 --summary "<text>"
266
+ # stamp tier-2 test-evidence.md
267
+ forge resolve-model --tier <fast|standard|capable>
268
+ # JSON model resolution (included billing by default)
269
+ forge models # print effective billing (does NOT write a file)
270
+ forge models included|metered # WRITE .forge/models.local.json
271
+ forge prefs # print effective pace (does NOT write a file)
272
+ forge prefs auto|thorough|standard|brisk|lite
273
+ # WRITE .forge/preferences.local.json
274
+ forge prefs --session-set lite # pin active session only
275
+ forge doctor # plan-engine readiness (OpenSpec or specs layout)
276
+ forge doctor --install # attempt npm install -g @fission-ai/openspec
277
+ forge spine init|check # capability→runtime spine matrix (spine.json in change dir)
278
+ forge defer add|resolve|list # deferral registry — deferred wiring is tracked debt
279
+ forge integrity-check # mechanical gate: spine + deferrals + product-loop evidence
280
+ forge score [--write] [--md] # L2 session scorecard (also auto-written at phase done)
281
+ forge overlay # re-apply OpenSpec vendor overlays in this project
282
+ forge init […] # wire project commands / hooks / rules
283
+ forge install […] # alias → forgekit install --skills forge
284
+ ```
285
+
286
+ Meta install (skills × agents):
287
+
288
+ ```bash
289
+ forgekit install
290
+ forgekit install --skills forge,thorough-code-review --agents cursor,claude
291
+ forgekit list
292
+ ```
293
+
294
+ ---
295
+
296
+ ## Checkout-local overrides (per developer)
297
+
298
+ Forge has two **optional**, **gitignored** overlays under `.forge/`.
299
+ They appear on disk **only after you set them**. Bare get commands only print the
300
+ merged effective value from package defaults.
301
+
302
+ | Concern | Defaults (in `@izkac/forgekit`) | Local file (gitignored) | Get (print only) | Set (creates/updates file) |
303
+ | ------- | ----------------------------- | ----------------------- | ---------------- | -------------------------- |
304
+ | Subagent **billing** (`included` / `metered`) | `packages/cli/src/models.defaults.json` | `.forge/models.local.json` | `forge models` | `forge models included\|metered` |
305
+ | Forge **pace** (review / verify ceremony) | `packages/cli/src/preferences.defaults.json` | `.forge/preferences.local.json` | `forge prefs` | `forge prefs auto\|thorough\|…` |
306
+
307
+ ```bash
308
+ # Example: you ran forge models and only saw "included" —
309
+ # that means the default lane is in effect. No models.local.json exists yet.
310
+ forge models --json # localExists: false until you set
311
+ forge models included # now creates .forge/models.local.json
312
+
313
+ forge prefs --session-set lite # pin active session only; no local file
314
+ ```
315
+
316
+ These are **per-checkout** (each developer’s clone), not committed to git — same
317
+ idea as a personal `.env`.
318
+
319
+ ---
320
+
321
+ ## Pace (thoroughness)
322
+
323
+ Forge ceremony (per-task review, final review, tier-3 verify, model bias, brainstorm
324
+ depth) is controlled by a **pace** preset. Default is **`auto`**: resolve once at
325
+ session start from risk signals, sticky for the session.
326
+
327
+ | Pace | Intent |
328
+ |------|--------|
329
+ | `auto` | Pick thorough / standard / brisk / lite from signals (default) |
330
+ | `thorough` | Always review **each task**; full-workspace tier 3 |
331
+ | `standard` | Review once per **OpenSpec group**; full-workspace tier 3 |
332
+ | `brisk` | Review high-risk tasks only; affected-workspace tier 3 |
333
+ | `lite` | Skip reviews for low-risk; audit tier-2 only at verify |
334
+
335
+ ### Effort matrix (exact knobs)
336
+
337
+ Defaults from `packages/cli/src/preferences.defaults.json`:
338
+
339
+ | Knob | `thorough` | `standard` | `brisk` | `lite` |
340
+ |------|------------|------------|---------|--------|
341
+ | **review.perTask** | always | per-group | high-risk-only | never\* |
342
+ | **review.final** | always | always | high-risk-only | never\* |
343
+ | **review.depth** | full | full | spec-only | spec-only |
344
+ | **review.maxRounds** | 3 | 2 | 1 | 0 |
345
+ | **verify.tier3** | full-workspace | full-workspace | affected-only | audit-tier2-only |
346
+ | **models.bias** | default | default | prefer-fast | prefer-fast |
347
+ | **brainstorm.depth** | full | full | short (≤2–3 options) | minimal |
348
+
349
+ \*Hard floor: money / auth / contracts / migrations / secrets still get per-task review (and final if the session touched high-risk), even under `brisk` / `lite` / mid-group `standard`.
350
+
351
+ **`thorough` vs `standard`:** thorough reviews every task; standard reviews once per OpenSpec `tasks.md` group (`##` section), except high-risk tasks which still get an immediate per-task review.
352
+
353
+ **`auto`** is not a preset — it picks one of the four once at session start (sticky):
354
+
355
+ 1. money / payment / auth / secret / migration / contract / gdpr → **thorough**
356
+ 2. ecosystem / API / multi-file / shared package / worker / job queue / pipeline / etl / platform / orchestration / openspec → **standard**
357
+ 3. docs / typo / rename / scaffold / changelog → **lite**
358
+ 4. fix / tweak / toolbar / style / padding (explicitly small) → **brisk**
359
+ 5. else (including empty / unrecognized) → **standard** (fail closed)
360
+
361
+ When `--tasks-total N` is set with **N ≥ 15** and resolved pace is still `brisk`/`lite` (not user-pinned), Forge escalates the session to **standard**.
362
+
363
+ **Unchanged on all paces:** tier-1 TDD + tier-2 evidence, no autonomous commit, OpenSpec when in Forge. Runtime integrity (below) applies at every pace.
364
+
365
+ Agent rules for each knob: [pace.md](../references/pace.md).
366
+
367
+ Prefs are gitignored (`.forge/preferences.local.json`), same pattern as `models.local.json`.
368
+
369
+ ### OpenSpec doctor
370
+
371
+ `forge doctor` checks `openspec/config.yaml` and that `openspec` is on PATH.
372
+ If the CLI is missing, it warns and offers `npm install -g @fission-ai/openspec`
373
+ (`--install` to attempt). `forge new` runs doctor warn-only so a missing CLI does
374
+ not block session creation.
375
+
376
+ ---
377
+
378
+ ## Runtime integrity
379
+
380
+ Forge’s job is to ship **working product paths**, not green checkboxes over
381
+ orphan libraries. Integrity rules live in
382
+ [runtime-integrity.md](../references/runtime-integrity.md) and are
383
+ enforced by both skill prompts and the CLI.
384
+
385
+ ### The problem it prevents
386
+
387
+ Without integrity, a large change can look “done” while the product is hollow:
388
+
389
+ - Libraries (matcher, BI exporter, …) are unit-tested and marked complete
390
+ - A worker job logs and marks `succeeded` (or a thin concat job writes a `.sav`)
391
+ - The UI can enqueue kinds nobody handles, or read collections nobody writes
392
+ - OpenSpec shows 57/57 — but upload → analyze → ratify → run never works
393
+
394
+ Integrity upgrades Forge from “no false job success” to **product-loop acceptance**.
395
+
396
+ ### Rules (plain language)
397
+
398
+ 1. **No stubs / false success** — a handler that only logs and succeeds is forbidden.
399
+ 2. **Runtime owner required** — a library alone does not satisfy a capability; name the production caller (job, endpoint, CLI).
400
+ 3. **Tests must fail on a no-op** — asserting “job status became succeeded” is not enough.
401
+ 4. **Specs beat narrow tasks** — capability specs win when they conflict with a thin task reading.
402
+ 5. **E2E = product loop** — produce → consume → decision changes output. A single job slice (ingest → Parquet) is **not** platform E2E.
403
+ 6. **Job-kind closure** — every product-surface job kind is wired end-to-end **or deleted** before complete. “Fail closed” is only a temporary `BLOCKED` state.
404
+ 7. **Consumer–producer** — if UI/API reads it, production must write it (proven in evidence).
405
+ 8. **Deferrals are tracked** — “wiring later” only via `forge defer`; unresolved deferrals block `done`.
406
+
407
+ ### Mechanics
408
+
409
+ | Tool | Purpose |
410
+ |------|---------|
411
+ | `forge spine init\|check` | **Mandatory every change.** `spine.json`: rows **or** `notApplicable`. Not keyword-gated. |
412
+ | `forge defer add\|resolve\|list` | Deferred wiring as tracked debt in the session |
413
+ | `forge integrity-check` | Combined gate — also run automatically by `forge phase done\|finish` |
414
+
415
+ Defaults (`integrity.forbidStubs`, `specsBeatNarrowTasks`, `requireE2E`) live in
416
+ `preferences.defaults.json` and appear in `forge status`.
417
+
418
+ Escape hatch: `forge phase done --allow-incomplete "<reason>"` records an honest
419
+ exception in the session — it does not silently checkbox past gaps.
420
+
421
+ ### What runs automatically every session
422
+
423
+ You do **not** paste a long definition-of-done prompt. After
424
+ `forgekit install --skills forge`, every Forge session gets:
425
+
426
+ | Automatic (CLI / hooks) | Agent-driven (skill phases — required) |
427
+ | ----------------------- | -------------------------------------- |
428
+ | Integrity reminder on every session/prompt hook | Plan: **`forge spine init` every change** — fill rows or `notApplicable` |
429
+ | Pace `auto` fail-closed to **standard**; task-count escalation at ≥15 | Implement: update spine rows; `forge defer add` if wiring is deferred |
430
+ | `forge phase done\|finish` requires valid spine + writes L2 scorecard | Verify: `## Product loop` when spine has rows (sync-only → prefer `notApplicable`) |
431
+ | `forge status` surfaces `integrity.*` defaults | After done: answer L3 ship-check in `scorecard.md` |
432
+
433
+ **Gates are automatic. Filling evidence is part of the normal phase flow.**
434
+ Skipping those steps fails at `forge phase done`, not silently.
435
+
436
+ ### Worked example (jobs / workers change)
437
+
438
+ **Plan**
439
+
440
+ ```bash
441
+ forge spine init
442
+ # edit openspec/changes/<name>/spine.json — one row per capability
443
+ ```
444
+
445
+ ```json
446
+ {
447
+ "change": "etl-surveydb-pipeline-closure",
448
+ "notApplicable": null,
449
+ "rows": [
450
+ {
451
+ "capability": "REQ-GOV-01 matching",
452
+ "library": "services/etl-core/src/etl_core/matcher.py",
453
+ "runtimeOwner": "worker job analyze_study",
454
+ "writes": "study_proposals",
455
+ "reads": "N/A",
456
+ "uiConsumer": "Proposals page",
457
+ "evidence": "tasks/12-analyze/test-evidence.md"
458
+ },
459
+ {
460
+ "capability": "REQ-OUT-BI star schema",
461
+ "library": "services/etl-core/src/etl_core/bi_star.py",
462
+ "runtimeOwner": "worker job harmonization_run",
463
+ "writes": "runs/<id>/bi/*.parquet",
464
+ "reads": "decisions tip + weight_map tips",
465
+ "uiConsumer": "Runs artifact download",
466
+ "evidence": "verify-evidence.md#product-loop"
467
+ }
468
+ ]
469
+ }
470
+ ```
471
+
472
+ Docs-only / no-runtime changes may set `"notApplicable": "docs-only change"` instead of rows.
473
+
474
+ **If wiring must wait for a later task**
475
+
476
+ ```bash
477
+ forge defer add --task 9.7 --reason "analyze_study handler lands in 9.7"
478
+ # … when 9.7 is done:
479
+ forge defer resolve --task 9.7
480
+ ```
481
+
482
+ **Verify evidence** (required when spine has rows):
483
+
484
+ ```markdown
485
+ # Verify evidence — tier 3
486
+
487
+ - **Command:** `pytest …` / `npm test …`
488
+ - **Exit code:** 0
489
+
490
+ ## Product loop
491
+
492
+ Fixture: OP1086 three sources
493
+
494
+ 1. ingest_source ×3 → study_sources + Parquet
495
+ 2. analyze_study → study_proposals (match / loop)
496
+ 3. ratify subset via API → decisions tip at revision R
497
+ 4. harmonization_run @R → .sav + Master QML + BI
498
+ 5. Assert: output at R differs from unratified baseline
499
+ ```
500
+
501
+ Or an explicit `BLOCKED: …` line — then `forge phase done` refuses until unblocked
502
+ or the user passes `--allow-incomplete`.
503
+
504
+ **Finish**
505
+
506
+ ```bash
507
+ forge integrity-check # optional preview
508
+ forge phase done # same checks; exit 1 if incomplete
509
+ ```
510
+
511
+ ---
512
+
513
+ ## Subagent model
514
+
515
+ Each implementation task:
516
+
517
+ 1. Coordinator writes `tasks/<nn>-<slug>/brief.md` (task text + file paths + constraints — **no chat history**).
518
+ 2. **Implementer** subagent — must follow `skills/test-driven-development` first.
519
+ 3. **Task reviewer** subagent (spec then quality) — unless pace skips low-risk tasks.
520
+ 4. Mark task complete (`tasks.md` checkbox or session progress).
521
+ 5. After all tasks: **verify** (tier 3 scope from pace) → **final reviewer** (unless pace skips) → finish.
522
+
523
+ Test tiers: [test-strategy.md](../references/test-strategy.md) — scoped TDD per task, narrow evidence per task, full workspace **once** at verify when pace requires it (not every task).
524
+
525
+ ### Model selection (capability × billing)
526
+
527
+ Subagents resolve models through **two axes** so Cursor / Claude Code / Codex stay on **subscription/included** pools by default:
528
+
529
+ | Axis | Values | Default |
530
+ | ---- | ------ | ------- |
531
+ | Capability | `fast` · `standard` · `capable` | role-based |
532
+ | Billing | `included` · `metered` | **`included`** |
533
+
534
+ ```bash
535
+ forge resolve-model --tier standard # JSON: { model, omitModel, billing, … }
536
+ forge models # print effective billing (no file write)
537
+ forge models metered # WRITE .forge/models.local.json
538
+ ```
539
+
540
+ - Defaults: `packages/cli/src/models.defaults.json` (Cursor `included` = `inherit` → omit Task `model`).
541
+ - Local overlay is optional — see **Checkout-local overrides** above.
542
+ - **Never invent** host model slugs; honor `omitModel` / `model` from the resolver.
543
+ - Escalate **capability** within `included` on `BLOCKED`; switch to `metered` only on explicit user request.
544
+ - Keep the **parent** session on Auto/Composer (Cursor) or Max (Claude Code) — `inherit` follows the parent.
545
+
546
+ Guardrails in every subagent brief (honor the **project’s** agent docs too):
547
+
548
+ - No autonomous `git commit` / push unless the user asks
549
+ - Implementer runs tier 1 (scoped) + tier 2 (narrow) tests; coordinator saves `tasks/<nn>-<slug>/test-evidence.md` before marking task done
550
+ - Trace downstream consumers when contracts change
551
+
552
+ Prompt templates: [subagents/](../subagents/)
553
+
554
+ ---
555
+
556
+ ## Bundled skills (self-contained)
557
+
558
+ Forge vendors adapted Superpowers skills (MIT) under `skills/forge/skills/`.
559
+ See [skills/NOTICE.md](../skills/NOTICE.md).
560
+
561
+ | Skill | Purpose |
562
+ | ----- | ------- |
563
+ | brainstorming | Brainstorm phase |
564
+ | test-driven-development | Implement — per task |
565
+ | subagent-driven-development | Implement — orchestration |
566
+ | systematic-debugging | Blockers during implement |
567
+ | verification-before-completion | Verify phase |
568
+ | requesting-code-review | Review phase |
569
+
570
+ The bundled skills are a **maintained fork** of Superpowers (MIT — see `skills/NOTICE.md`), restructured for Forge (single task reviewer, tiered testing, trimmed prose). Do not re-vendor from upstream; edit `skills/forge/` in this repo and run `forgekit install --skills forge --force`.
571
+
572
+ ## Relationship to OpenSpec
573
+
574
+ | Piece | Source | Policy |
575
+ | ----- | ------ | ------ |
576
+ | Brainstorm, TDD, subagents, verify, review | **skills/forge/skills/** (bundled) | Self-contained; Superpowers plugin not required |
577
+ | Planning sink | OpenSpec or built-in specs engine | Engine per project (`.forge/config.json`); no throwaway or direct modes for new work |
578
+ | OpenSpec skills | Vendor (`openspec-*`, `opsx:*`) | **Do not hand-edit** — run `forge overlay` after upgrade |
579
+ | OpenSpec implement | Forge **`/forge:apply`** | Full subagent TDD + verify + review; survives OpenSpec upgrades |
580
+ | Archive follow-up | Optional ADRs (`forge init --adr`) | When `.forge/config.json` has `adr.enabled`, run **archive-to-adr** (path from `adr.dir`, default `docs/adr`) |
581
+
582
+ ---
583
+
584
+ ## Agent surfaces
585
+
586
+ Same workflow across Cursor, Claude Code, and Codex CLI. Install the skill once
587
+ per machine with `forgekit install`; wire project commands/hooks with `forge init`.
588
+
589
+ | Agent | Skill (after install) | Project wiring (`forge init`) | Session hooks |
590
+ | ----- | --------------------- | ----------------------------- | ------------- |
591
+ | **Cursor** | `~/.cursor/skills/forge/` | commands, `forge.mdc`, SessionStart hook | SessionStart → active session reminder |
592
+ | **Claude Code** | `~/.claude/skills/forge/` | commands, `forge.md`, SessionStart + prompt hooks | SessionStart + substantial-work UserPromptSubmit + `/forge` UserPromptSubmit |
593
+ | **Codex CLI** | `~/.codex/skills/forge/` | thin rule | *(none — read skill on substantial work)* |
594
+
595
+ ### Slash commands (Cursor + Claude Code)
596
+
597
+ | Command | Purpose |
598
+ | ------- | ------- |
599
+ | `/forge` | Start or resume current phase |
600
+ | `/forge:brainstorm` | Brainstorm only |
601
+ | `/forge:plan` | Tracked-change propose (engine from `.forge/config.json`) |
602
+ | `/forge:apply` | Tracked-change implement + verify + review (preferred) |
603
+ | `/forge:build` | Implement phase (`tasks.md` from either engine) |
604
+ | `/forge:status` | Session progress |
605
+ | `/forge:skip` | Explicit skip for this task |
606
+
607
+ ### Codex CLI
608
+
609
+ No slash commands. On substantial work: read the **`forge`** skill, check
610
+ `forge status`, bootstrap with `forge new <slug>` when needed.
611
+ After brainstorm, proceed directly to the configured engine's propose flow — see
612
+ [plan-routing.md](../references/plan-routing.md).
613
+ User can say “skip forge” or `/forge:skip` to opt out.
614
+
615
+ ---
616
+
617
+ ## What we deliberately dropped from Superpowers
618
+
619
+ - `docs/superpowers/plans/` and `docs/superpowers/specs/` — use OpenSpec / `specs/changes/` + `.forge` (the built-in specs engine covers the no-OpenSpec case with an OpenSpec-compatible layout)
620
+ - Mandatory git worktree per brainstorm — optional
621
+ - Autonomous commits in subagent prompts — forbidden unless the user asks
@@ -43,7 +43,7 @@ Optional `cursorChatId` on `session.json` when available — not required.
43
43
 
44
44
  Bare `forge models` / `forge:prefs` **print** effective values from committed
45
45
  defaults and do **not** create the `*.local.json` files. See [pace.md](./pace.md) and
46
- [docs/forge.md](../../../docs/forge.md) § Checkout-local overrides.
46
+ [docs/forge.md](../docs/forge.md) § Checkout-local overrides.
47
47
 
48
48
  ## session.json fields
49
49
 
@@ -15,7 +15,7 @@ forge doctor # OpenSpec project + CLI
15
15
 
16
16
  Billing lane (orthogonal): `forge models` prints only;
17
17
  `forge models included|metered` writes `.forge/models.local.json`.
18
- See [docs/forge.md](../../../docs/forge.md) § Checkout-local overrides.
18
+ See [docs/forge.md](../docs/forge.md) § Checkout-local overrides.
19
19
 
20
20
  ## Announce
21
21
 
@@ -231,7 +231,7 @@ When reviewing a project that documents accepted risks:
231
231
 
232
232
  ## Model selection for subagents
233
233
 
234
- **Choose the model tier per dispatch — never default to the most capable (priciest) model.** Match the tier to the judgment the role actually needs. Map roles to Forge capability tiers (`fast` / `standard` / `capable`) and resolve via `forge resolve-model --tier <…>` so billing stays on the **`included`** (subscription) lane unless the user explicitly asks for metered/API models — see forgekit `docs/forge.md` § Subagent model.
234
+ **Choose the model tier per dispatch — never default to the most capable (priciest) model.** Match the tier to the judgment the role actually needs. Map roles to Forge capability tiers (`fast` / `standard` / `capable`) and resolve via `forge resolve-model --tier <…>` so billing stays on the **`included`** (subscription) lane unless the user explicitly asks for metered/API models — see forge skill [docs/forge.md](../forge/docs/forge.md) § Subagent model.
235
235
 
236
236
  | Role | Tier | Why |
237
237
  | ---- | ---- | --- |
@@ -7,7 +7,7 @@ tags: [workflow, forge, openspec]
7
7
 
8
8
  **Forge-owned command.** Use this instead of bare `/opsx:apply` for disciplined implementation of a tracked change (OpenSpec or built-in specs engine — `.forge/config.json` → `plan.engine`).
9
9
 
10
- Read the Forge skill (`~/.claude/skills/forge/SKILL.md`) and forgekit `docs/forge.md`.
10
+ Read the Forge skill (`~/.claude/skills/forge/SKILL.md`) and `~/.claude/skills/forge/docs/forge.md`.
11
11
 
12
12
  **Input**: Optionally specify a change name (e.g., `/forge:apply add-auth`). If omitted, infer from context or active Forge session.
13
13
 
@@ -13,4 +13,4 @@ forge status
13
13
 
14
14
  Summarize `phase`, `planType`, `openspecChange`, and task progress for the user.
15
15
 
16
- Reference: forgekit `docs/forge.md`
16
+ Reference: `~/.claude/skills/forge/docs/forge.md`
@@ -7,7 +7,7 @@ tags: [workflow, forge, openspec]
7
7
 
8
8
  Run the **Forge** workflow for substantial work.
9
9
 
10
- Read and follow the Forge skill (`~/.claude/skills/forge/SKILL.md`) and forgekit `docs/forge.md`.
10
+ Read and follow the Forge skill (`~/.claude/skills/forge/SKILL.md`) and `~/.claude/skills/forge/docs/forge.md`.
11
11
 
12
12
  1. Triage — substantial work? (skip only if user said `/forge:skip`)
13
13
  2. Resume from `.forge/active.json` or `forge new <slug>`
@@ -1,6 +1,6 @@
1
1
  # Forge (thin rule)
2
2
 
3
- Full workflow: forgekit `docs/forge.md` · Skill: user-installed **Forge** (`~/.claude/skills/forge/SKILL.md` after `forge install`).
3
+ Full workflow: `~/.claude/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.claude/skills/forge/SKILL.md` after `forge install`).
4
4
 
5
5
  **Default:** triage before implementation. Substantial work → **Forge**
6
6
  (brainstorm → OpenSpec → subagent TDD implement → review).
@@ -1,6 +1,6 @@
1
1
  # Forge (thin rule)
2
2
 
3
- Full workflow: forgekit `docs/forge.md` · Skill: user-installed **Forge** (`~/.codex/skills/forge/SKILL.md` after `forge install`).
3
+ Full workflow: `~/.codex/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.codex/skills/forge/SKILL.md` after `forge install`).
4
4
 
5
5
  **Default:** triage before implementation. Substantial work → **Forge**
6
6
  (brainstorm → OpenSpec → subagent TDD implement → review).
@@ -7,7 +7,7 @@ description: Forge — apply a tracked change with subagent TDD, verify, and rev
7
7
 
8
8
  **Forge-owned command.** Use this instead of bare `/opsx:apply` for disciplined implementation of a tracked change (OpenSpec or built-in specs engine — `.forge/config.json` → `plan.engine`).
9
9
 
10
- Read the Forge skill (`~/.cursor/skills/forge/SKILL.md`) and forgekit `docs/forge.md`.
10
+ Read the Forge skill (`~/.cursor/skills/forge/SKILL.md`) and `~/.cursor/skills/forge/docs/forge.md`.
11
11
 
12
12
  **Input**: Optionally specify a change name (e.g., `/forge:apply add-auth`). If omitted, infer from context or active Forge session.
13
13
 
@@ -13,4 +13,4 @@ forge status
13
13
 
14
14
  Summarize `phase`, `planType`, `openspecChange`, and task progress for the user.
15
15
 
16
- Reference: forgekit `docs/forge.md`
16
+ Reference: `~/.cursor/skills/forge/docs/forge.md`
@@ -7,7 +7,7 @@ description: Forge — start or resume disciplined development (brainstorm → p
7
7
 
8
8
  Run the **Forge** workflow for substantial work.
9
9
 
10
- Read and follow the Forge skill (`~/.cursor/skills/forge/SKILL.md`) and forgekit `docs/forge.md`.
10
+ Read and follow the Forge skill (`~/.cursor/skills/forge/SKILL.md`) and `~/.cursor/skills/forge/docs/forge.md`.
11
11
 
12
12
  1. Triage — substantial work? (skip only if user said `/forge:skip`)
13
13
  2. Resume from `.forge/active.json` or `forge new <slug>`
@@ -5,7 +5,7 @@ alwaysApply: true
5
5
 
6
6
  # Forge (thin rule)
7
7
 
8
- Full workflow: forgekit `docs/forge.md` · Skill: user-installed **Forge** (`~/.cursor/skills/forge/SKILL.md` after `forge install`).
8
+ Full workflow: `~/.cursor/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.cursor/skills/forge/SKILL.md` after `forge install`).
9
9
 
10
10
  **Default:** triage before implementation. Substantial work → **Forge**
11
11
  (brainstorm → OpenSpec → subagent TDD implement → review).