@izkac/forgekit 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/init.mjs +13 -6
- package/src/init.test.mjs +32 -1
- package/vendor/templates/project/claude/commands/forge.md +1 -1
- package/vendor/templates/project/claude/rules/forge.md +20 -16
- package/vendor/templates/project/codex/rules/forge.md +12 -10
- package/vendor/templates/project/cursor/rules/forge.mdc +25 -21
package/package.json
CHANGED
package/src/init.mjs
CHANGED
|
@@ -100,7 +100,8 @@ Options:
|
|
|
100
100
|
--no-adr Disable ADRs for this project
|
|
101
101
|
--adr-dir <path> ADR directory (default: ${DEFAULT_ADR_DIR} or ~/.forgekit preference)
|
|
102
102
|
--overlay Also run \`forge overlay\` (OpenSpec vendor patches)
|
|
103
|
-
--force, -f
|
|
103
|
+
--force, -f Force re-scaffold of ADR/specs docs (managed command,
|
|
104
|
+
rule, and hook files always refresh to the latest template)
|
|
104
105
|
--cwd <path> Project root (default: cwd)
|
|
105
106
|
--help
|
|
106
107
|
|
|
@@ -124,16 +125,22 @@ export function resolveTemplatesRoot() {
|
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
/**
|
|
128
|
+
* Copy a forgekit-managed template file. These are regenerated pointers
|
|
129
|
+
* (forge-* commands/rules/hooks) with no user-owned content, so re-running
|
|
130
|
+
* `forge init` refreshes them in place — that's how template fixes propagate.
|
|
127
131
|
* @param {string} src
|
|
128
132
|
* @param {string} dest
|
|
129
|
-
* @param {{ force?: boolean }}
|
|
133
|
+
* @param {{ force?: boolean }} _opts
|
|
130
134
|
*/
|
|
131
|
-
function copyFile(src, dest,
|
|
135
|
+
function copyFile(src, dest, _opts) {
|
|
132
136
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
const next = fs.readFileSync(src);
|
|
138
|
+
if (fs.existsSync(dest)) {
|
|
139
|
+
if (fs.readFileSync(dest).equals(next)) return 'unchanged';
|
|
140
|
+
fs.writeFileSync(dest, next);
|
|
141
|
+
return 'updated';
|
|
135
142
|
}
|
|
136
|
-
fs.
|
|
143
|
+
fs.writeFileSync(dest, next);
|
|
137
144
|
return 'written';
|
|
138
145
|
}
|
|
139
146
|
|
package/src/init.test.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { parseArgs, initProject, rememberedAgents } from './init.mjs';
|
|
6
|
+
import { parseArgs, initProject, rememberedAgents, resolveTemplatesRoot } from './init.mjs';
|
|
7
7
|
import { installSkillsToAgents } from './install.mjs';
|
|
8
8
|
import { saveUserConfig } from './config.mjs';
|
|
9
9
|
|
|
@@ -35,6 +35,37 @@ test('rememberedAgents unions install config, installed skills, and project wiri
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
test('re-running init refreshes stale managed rule files in place', () => {
|
|
39
|
+
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'forgekit-refresh-'));
|
|
40
|
+
try {
|
|
41
|
+
initProject(['claude'], { cwd, adr: false, planEngine: null });
|
|
42
|
+
const rule = path.join(cwd, '.claude', 'rules', 'forge.md');
|
|
43
|
+
// Simulate an older install with a stale reference.
|
|
44
|
+
fs.writeFileSync(rule, 'Full workflow: forgekit `docs/forge.md`\n', 'utf8');
|
|
45
|
+
|
|
46
|
+
const report = initProject(['claude'], { cwd, adr: false, planEngine: null });
|
|
47
|
+
const updated = fs.readFileSync(rule, 'utf8');
|
|
48
|
+
assert.ok(!updated.includes('forgekit `docs/forge.md`'), 'stale ref replaced');
|
|
49
|
+
assert.ok(updated.includes('~/.claude/skills/forge/docs/forge.md'), 'points to global skill doc');
|
|
50
|
+
assert.ok(
|
|
51
|
+
report.files.some((f) => f.file.includes('forge.md') && f.status === 'updated'),
|
|
52
|
+
'reports the refresh as updated',
|
|
53
|
+
);
|
|
54
|
+
} finally {
|
|
55
|
+
fs.rmSync(cwd, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('thin-rule templates are engine-neutral (no hardcoded OpenSpec-only flow)', () => {
|
|
60
|
+
const root = resolveTemplatesRoot();
|
|
61
|
+
for (const rel of ['claude/rules/forge.md', 'cursor/rules/forge.mdc', 'codex/rules/forge.md']) {
|
|
62
|
+
const body = fs.readFileSync(path.join(root, ...rel.split('/')), 'utf8');
|
|
63
|
+
assert.ok(!/Forge = OpenSpec/.test(body), `${rel} still says "Forge = OpenSpec"`);
|
|
64
|
+
assert.ok(body.includes('forge change new'), `${rel} missing built-in specs command`);
|
|
65
|
+
assert.ok(body.includes('/opsx:propose'), `${rel} missing OpenSpec command`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
38
69
|
test('initProject wires templated envs and marks the rest skill-only', () => {
|
|
39
70
|
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'forgekit-init-'));
|
|
40
71
|
try {
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
# Forge (thin rule)
|
|
2
|
-
|
|
3
|
-
Full workflow: `~/.claude/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.claude/skills/forge/SKILL.md` after `forge install`).
|
|
4
|
-
|
|
5
|
-
**Default:** triage before implementation. Substantial work → **Forge**
|
|
6
|
-
(brainstorm →
|
|
7
|
-
|
|
8
|
-
**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
# Forge (thin rule)
|
|
2
|
+
|
|
3
|
+
Full workflow: `~/.claude/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.claude/skills/forge/SKILL.md` after `forge install`).
|
|
4
|
+
|
|
5
|
+
**Default:** triage before implementation. Substantial work → **Forge**
|
|
6
|
+
(brainstorm → plan → subagent TDD implement → review).
|
|
7
|
+
|
|
8
|
+
**Planning engine:** this project's engine is recorded in `.forge/config.json` (`plan.engine`). After brainstorm, create the change spec directly — do not ask for a plan mode:
|
|
9
|
+
- OpenSpec → `/opsx:propose`
|
|
10
|
+
- built-in specs → `forge change new <slug>`
|
|
11
|
+
|
|
12
|
+
Work too small to spec should skip Forge (`/forge:skip` or direct execution).
|
|
13
|
+
|
|
14
|
+
**Skip Forge** only when work is trivial OR user sends **`/forge:skip`**.
|
|
15
|
+
|
|
16
|
+
Scratch sessions: `.forge/sessions/` (14-day retention). Active pointer: `.forge/active.json`.
|
|
17
|
+
|
|
18
|
+
CLI: `forge new`, `forge status`, `forge prefs`, `forge models`, `forge phase`, `forge doctor`.
|
|
19
|
+
|
|
20
|
+
Do not edit vendor planning-engine skills — Forge orchestrates them. Workflow skills are bundled under the Forge skill's `skills/` folder.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
# Forge (thin rule)
|
|
2
|
-
|
|
3
|
-
Full workflow: `~/.codex/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.codex/skills/forge/SKILL.md` after `forge install`).
|
|
4
|
-
|
|
5
|
-
**Default:** triage before implementation. Substantial work → **Forge**
|
|
6
|
-
(brainstorm →
|
|
7
|
-
|
|
8
|
-
**
|
|
9
|
-
|
|
10
|
-
Scratch: `.forge/` · CLI: `forge new|status|prefs|models|phase|doctor`
|
|
1
|
+
# Forge (thin rule)
|
|
2
|
+
|
|
3
|
+
Full workflow: `~/.codex/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.codex/skills/forge/SKILL.md` after `forge install`).
|
|
4
|
+
|
|
5
|
+
**Default:** triage before implementation. Substantial work → **Forge**
|
|
6
|
+
(brainstorm → plan → subagent TDD implement → review).
|
|
7
|
+
|
|
8
|
+
**Planning engine:** recorded in `.forge/config.json` (`plan.engine`). After brainstorm, create the change directly — OpenSpec → `/opsx:propose`, built-in specs → `forge change new <slug>`. Skip with `/forge:skip` or when work is trivial.
|
|
9
|
+
|
|
10
|
+
Scratch: `.forge/` · CLI: `forge new|status|prefs|models|phase|doctor`
|
|
11
|
+
|
|
12
|
+
Do not edit vendor planning-engine skills — Forge orchestrates them.
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Forge triage and workflow (thin rule)
|
|
3
|
-
alwaysApply: true
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Forge (thin rule)
|
|
7
|
-
|
|
8
|
-
Full workflow: `~/.cursor/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.cursor/skills/forge/SKILL.md` after `forge install`).
|
|
9
|
-
|
|
10
|
-
**Default:** triage before implementation. Substantial work → **Forge**
|
|
11
|
-
(brainstorm →
|
|
12
|
-
|
|
13
|
-
**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
---
|
|
2
|
+
description: Forge triage and workflow (thin rule)
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Forge (thin rule)
|
|
7
|
+
|
|
8
|
+
Full workflow: `~/.cursor/skills/forge/docs/forge.md` · Skill: user-installed **Forge** (`~/.cursor/skills/forge/SKILL.md` after `forge install`).
|
|
9
|
+
|
|
10
|
+
**Default:** triage before implementation. Substantial work → **Forge**
|
|
11
|
+
(brainstorm → plan → subagent TDD implement → review).
|
|
12
|
+
|
|
13
|
+
**Planning engine:** this project's engine is recorded in `.forge/config.json` (`plan.engine`). After brainstorm, create the change spec directly — do not ask for a plan mode:
|
|
14
|
+
- OpenSpec → `/opsx:propose`
|
|
15
|
+
- built-in specs → `forge change new <slug>`
|
|
16
|
+
|
|
17
|
+
Work too small to spec should skip Forge (`/forge:skip` or direct execution).
|
|
18
|
+
|
|
19
|
+
**Skip Forge** only when work is trivial OR user sends **`/forge:skip`**.
|
|
20
|
+
|
|
21
|
+
Scratch sessions: `.forge/sessions/` (14-day retention). Active pointer: `.forge/active.json`.
|
|
22
|
+
|
|
23
|
+
CLI: `forge new`, `forge status`, `forge prefs`, `forge models`, `forge phase`, `forge doctor`.
|
|
24
|
+
|
|
25
|
+
Do not edit vendor planning-engine skills — Forge orchestrates them. Workflow skills are bundled under the Forge skill's `skills/` folder.
|