@entelligentsia/forgecli 0.11.2 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +324 -0
- package/README.md +2 -1
- package/dist/CHANGELOG-forge-plugin.md +210 -0
- package/dist/bin/forge.js +20 -1
- package/dist/bin/forge.js.map +1 -1
- package/dist/extensions/forgecli/ask-user-tool.js +32 -20
- package/dist/extensions/forgecli/ask-user-tool.js.map +1 -1
- package/dist/extensions/forgecli/config-layer.d.ts +15 -0
- package/dist/extensions/forgecli/config-layer.js +4 -1
- package/dist/extensions/forgecli/config-layer.js.map +1 -1
- package/dist/extensions/forgecli/config-writer.js +4 -1
- package/dist/extensions/forgecli/config-writer.js.map +1 -1
- package/dist/extensions/forgecli/enhance.js +1 -1
- package/dist/extensions/forgecli/enhance.js.map +1 -1
- package/dist/extensions/forgecli/fix-bug.js +31 -1
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-cli-schema.json +19 -0
- package/dist/extensions/forgecli/forge-tools.js +80 -0
- package/dist/extensions/forgecli/forge-tools.js.map +1 -1
- package/dist/extensions/forgecli/forge-update-command.js +24 -18
- package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
- package/dist/extensions/forgecli/friction-emit.d.ts +97 -0
- package/dist/extensions/forgecli/friction-emit.js +246 -0
- package/dist/extensions/forgecli/friction-emit.js.map +1 -0
- package/dist/extensions/forgecli/health-check.d.ts +10 -0
- package/dist/extensions/forgecli/health-check.js +160 -8
- package/dist/extensions/forgecli/health-check.js.map +1 -1
- package/dist/extensions/forgecli/hook-dispatcher.js +24 -2
- package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
- package/dist/extensions/forgecli/hooks/write-guard.js +5 -1
- package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -1
- package/dist/extensions/forgecli/index.js +29 -5
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/lib/store-error-remediation.d.ts +65 -0
- package/dist/extensions/forgecli/lib/store-error-remediation.js +298 -0
- package/dist/extensions/forgecli/lib/store-error-remediation.js.map +1 -0
- package/dist/extensions/forgecli/regenerate.d.ts +22 -0
- package/dist/extensions/forgecli/regenerate.js +133 -3
- package/dist/extensions/forgecli/regenerate.js.map +1 -1
- package/dist/extensions/forgecli/run-sprint.js +16 -1
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.js +30 -8
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/skill-curation-flag.d.ts +21 -0
- package/dist/extensions/forgecli/skill-curation-flag.js +71 -0
- package/dist/extensions/forgecli/skill-curation-flag.js.map +1 -0
- package/dist/extensions/forgecli/skill-curator-subagent.d.ts +101 -0
- package/dist/extensions/forgecli/skill-curator-subagent.js +342 -0
- package/dist/extensions/forgecli/skill-curator-subagent.js.map +1 -0
- package/dist/extensions/forgecli/skill-retriever.d.ts +84 -0
- package/dist/extensions/forgecli/skill-retriever.js +246 -0
- package/dist/extensions/forgecli/skill-retriever.js.map +1 -0
- package/dist/extensions/forgecli/skill-usage-tracker.d.ts +91 -0
- package/dist/extensions/forgecli/skill-usage-tracker.js +224 -0
- package/dist/extensions/forgecli/skill-usage-tracker.js.map +1 -0
- package/dist/extensions/forgecli/store-resolver.d.ts +18 -0
- package/dist/extensions/forgecli/store-resolver.js +44 -4
- package/dist/extensions/forgecli/store-resolver.js.map +1 -1
- package/dist/extensions/forgecli/store-validator.d.ts +3 -0
- package/dist/extensions/forgecli/store-validator.js +4 -2
- package/dist/extensions/forgecli/store-validator.js.map +1 -1
- package/dist/forge-payload/.base-pack/personas/supervisor.md +9 -0
- package/dist/forge-payload/.base-pack/workflows/enhance.md +344 -18
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/event.schema.json +20 -2
- package/dist/forge-payload/.schemas/migrations.json +112 -0
- package/dist/forge-payload/.schemas/proposal.schema.json +40 -0
- package/dist/forge-payload/agents/store-query-validator.md +103 -0
- package/dist/forge-payload/agents/tomoshibi.md +185 -0
- package/dist/forge-payload/commands/regenerate.md +109 -20
- package/dist/forge-payload/hooks/check-update.js +378 -0
- package/dist/forge-payload/hooks/forge-permissions.js +158 -0
- package/dist/forge-payload/hooks/triage-error.js +71 -0
- package/dist/forge-payload/hooks/validate-write.js +236 -0
- package/dist/forge-payload/integrity.json +32 -0
- package/dist/forge-payload/meta/workflows/meta-enhance.md +344 -18
- package/dist/forge-payload/schemas/structure-manifest.json +511 -0
- package/dist/forge-payload/tools/build-persona-pack.cjs +120 -11
- package/dist/forge-payload/tools/compression-gate.cjs +192 -0
- package/dist/forge-payload/tools/delete-candidate-detector.cjs +114 -0
- package/dist/forge-payload/tools/judge-proposal.cjs +177 -0
- package/dist/forge-payload/tools/manage-versions.cjs +132 -4
- package/dist/forge-payload/tools/queue-drain.cjs +152 -0
- package/dist/forge-payload/tools/replay-scoring.cjs +117 -0
- package/node_modules/@mariozechner/clipboard/package.json +2 -1
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +3 -0
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/clipboard.linux-x64-musl.node +0 -0
- package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +25 -0
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,330 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.0] — 2026-05-22
|
|
11
|
+
|
|
12
|
+
> **The SkillOS release.** Forge now treats its own skill library as a
|
|
13
|
+
> living, signal-driven asset. The model's actual frictions — what it
|
|
14
|
+
> reached for, what worked, what didn't — feed back into the project
|
|
15
|
+
> through a five-subkind taxonomy, an LLM-judge rubric, a compression
|
|
16
|
+
> gate, and a per-task curator queue drained as one batched review at
|
|
17
|
+
> sprint close. The result: your `.forge/skills/` tracks the codebase as
|
|
18
|
+
> it evolves, instead of calcifying into a directory of well-intentioned
|
|
19
|
+
> instructions nobody opens.
|
|
20
|
+
>
|
|
21
|
+
> This release also closes the packaging gaps that were silently
|
|
22
|
+
> shipping every Forge install: missing structural checks, missing
|
|
23
|
+
> SkillOS tools in the payload, a `/forge:update` that upgraded the
|
|
24
|
+
> CLI but skipped project migrations, a version banner that lied about
|
|
25
|
+
> the bundled plugin. The deterministic-check infrastructure
|
|
26
|
+
> (`check-structure.cjs`, `verify-integrity.cjs`) is finally live
|
|
27
|
+
> end-to-end and would now flag a missing skill file the moment it
|
|
28
|
+
> happens. The plugin payload is now coherent enough to drive its own
|
|
29
|
+
> auditing.
|
|
30
|
+
|
|
31
|
+
### Added — SkillOS curation pipeline (FORGE-S24)
|
|
32
|
+
|
|
33
|
+
- **`skill-retriever.ts`** (T08, ac90659). New BM25 retriever using
|
|
34
|
+
`lunr.js` (pinned exact) over skill frontmatter + description fields.
|
|
35
|
+
Returns deterministic top-k for a known corpus and emits a
|
|
36
|
+
`skill_usage` event with `retrieved: true` and a populated
|
|
37
|
+
`retrieval_score` for every hit. The signal that tells Phase 2 which
|
|
38
|
+
skills the model actually saw.
|
|
39
|
+
- **`skill-usage-tracker.ts`** (T09, 394125c). Diffs tool-call trajectories
|
|
40
|
+
against retrieved skills; emits `skill_usage` events with `used: true`
|
|
41
|
+
and `tool_call_success_rate` populated. Three discriminator cases
|
|
42
|
+
(overlap → used, no-overlap → unused, reasoning-only → used) covered
|
|
43
|
+
by failing-first tests. Telemetry-actor split: the orchestrator owns
|
|
44
|
+
emission; subagents never call this module directly.
|
|
45
|
+
- **`skill-curator-subagent.ts`** (T10, ea29079). Per-task curator —
|
|
46
|
+
takes retrieval + usage signals, dispatches a `runForgeSubagent` with
|
|
47
|
+
the composed task body, parses proposals out, and writes them to the
|
|
48
|
+
append-only queue at
|
|
49
|
+
`.forge/enhancement-proposals/queue/<sprint>/<task>-<ts>.json`. One
|
|
50
|
+
curator run per task; Phase 2 collects them at sprint close.
|
|
51
|
+
- **`friction-emit.ts`** (T11, b4d3526). Auto-emits friction events with
|
|
52
|
+
five skill subkinds — `skill_unused` (retrieved but not used on success),
|
|
53
|
+
`skill_failed` (used on failure), `skill_missing` (not retrieved on
|
|
54
|
+
success with ≥2 tool errors), `skill_stale` (unused 3 consecutive
|
|
55
|
+
sprints), `skill_redundant` (>0.8 overlap pair). The diagnostic
|
|
56
|
+
vocabulary that lets a project tell you which of its skills are
|
|
57
|
+
carrying weight and which aren't.
|
|
58
|
+
- **`forgeCli.skillCuration.enabled` flag** (T12, 7904c4b). Gated rollout
|
|
59
|
+
— default OFF. Layered resolution: env override
|
|
60
|
+
`FORGE_CLI_SKILL_CURATION_ENABLED` → project
|
|
61
|
+
`<cwd>/.pi/forge-cli/config.json` → global
|
|
62
|
+
`~/.pi/forge-cli/config.json` → `false`. All four emission modules
|
|
63
|
+
no-op silently when the flag is off, so a flag-off install is
|
|
64
|
+
byte-identical to pre-FORGE-S24 behaviour. The pure classifier helpers
|
|
65
|
+
(`computeFrictionSignals`, `classifySkillUsage`, `buildSkillIndex`,
|
|
66
|
+
`retrieveTopK`, `composeCuratorTask`, `parseProposalsFromOutput`) are
|
|
67
|
+
**not** gated — they have no side effects and remain callable for
|
|
68
|
+
downstream consumers.
|
|
69
|
+
|
|
70
|
+
### Added — bundled forge-plugin pipeline (paired with v0.46.1)
|
|
71
|
+
|
|
72
|
+
Forge-cli now bundles `forge-plugin@0.46.1` with the full FORGE-S24
|
|
73
|
+
machinery, regenerated into the installable base-pack:
|
|
74
|
+
|
|
75
|
+
- **`queue-drain.cjs`** (T07). Append-only queue under
|
|
76
|
+
`.forge/enhancement-proposals/queue/<sprint>/`; dedupe key is
|
|
77
|
+
`{op, target_path, sha256(diff_body)}`; drain at sprint close produces
|
|
78
|
+
a single batched review prompt instead of one prompt per task — the
|
|
79
|
+
SkillOS §3.2.1 grouped-reward pattern.
|
|
80
|
+
- **`compression-gate.cjs`** (T06). Rejects `update_skill` proposals that
|
|
81
|
+
grow a target skill by >20% unless backed by ≥3 supporting friction
|
|
82
|
+
events. Closes the unbounded-growth failure mode where every friction
|
|
83
|
+
pastes another paragraph of trajectory copy into a skill file. Strict
|
|
84
|
+
byte-wise (UTF-8) growth check; insert/delete pass through;
|
|
85
|
+
recurrence-supported growth is allowed.
|
|
86
|
+
- **`judge-proposal.cjs`** (T03). Sonnet-class LLM-judge rubric applied
|
|
87
|
+
to every surviving proposal; drops `<3/5`. Rejections persist to
|
|
88
|
+
`.forge/enhancement-proposals/queue/<sprint>/phase2-<ts>-rejections.json`
|
|
89
|
+
so every drop stays traceable.
|
|
90
|
+
- **`delete-candidate-detector.cjs`** (T05). Scans trailing 3 sprints
|
|
91
|
+
of `skill_usage` events. Any skill with zero retrieval AND zero
|
|
92
|
+
invocation across the window emits a `delete_skill` proposal at
|
|
93
|
+
Phase 2 entry. The only mechanism by which the skill repo shrinks.
|
|
94
|
+
- **`replay-scoring.cjs`** (T04). Cross-task recurrence — same
|
|
95
|
+
`{subkind, skillId}` across tasks t..N gets a `recurrence_count` boost
|
|
96
|
+
that the judge consumes as a specificity score. "This friction
|
|
97
|
+
happened three times" beats "this friction happened once."
|
|
98
|
+
- **Proposal schema with op classification** (T02). `proposal.schema.json`
|
|
99
|
+
enforces `op ∈ {insert_skill, update_skill, delete_skill}` with
|
|
100
|
+
required `target_path` and `diff_body`. Legacy inserts back-compat
|
|
101
|
+
via `proposal-normalize.cjs`. Strict `additionalProperties: false`.
|
|
102
|
+
- **`skill_usage` event variant** (T01). `event.schema.json` gained a
|
|
103
|
+
conditional `allOf` branch for `type: "skill_usage"` requiring
|
|
104
|
+
`{eventId, sprintId, taskId, skillId, retrieved, used,
|
|
105
|
+
tool_call_success_rate, retrieval_score}`. Strict.
|
|
106
|
+
|
|
107
|
+
### Fixed — packaging gaps that broke deterministic checks
|
|
108
|
+
|
|
109
|
+
- **`/forge:update` skipped the migration step entirely** (fc40f4a,
|
|
110
|
+
closes forge-cli#32). The handler implemented the full 5-step guided
|
|
111
|
+
upgrade — detect install → fetch changelog → confirm → npm install →
|
|
112
|
+
apply migrations — but the registration in `index.ts` omitted the
|
|
113
|
+
migration-side options, so the handler returned early before reaching
|
|
114
|
+
the migration block. Projects upgrading the CLI never received
|
|
115
|
+
schema/workflow/template migrations. Fixed by wiring
|
|
116
|
+
`currentBundledForgeVersion` + `migrationProjectRoot` at registration.
|
|
117
|
+
- **`/forge:update` migration block unreachable when CLI was already at
|
|
118
|
+
latest** (31796d5, follow-up on #32). The "already at latest" branch
|
|
119
|
+
early-returned BEFORE the migration check at line 373. Decoupled the
|
|
120
|
+
two orthogonal gates — npm-upgrade and project-migration — so a
|
|
121
|
+
locally-built CLI ahead of npm's published version (or a fresh clone
|
|
122
|
+
with a stale drift cache) still fires the migration prompt when
|
|
123
|
+
`fromVersion !== toVersion`.
|
|
124
|
+
- **`structure-manifest.json` + `integrity.json` not bundled** (cd732d2).
|
|
125
|
+
Both files exist in plugin source (`forge/forge/schemas/`,
|
|
126
|
+
`forge/forge/integrity.json`) and the consuming tools
|
|
127
|
+
(`check-structure.cjs`, `verify-integrity.cjs`) shipped in
|
|
128
|
+
`TOOLS_TO_COPY`, but `build-payload.cjs` never copied the artifacts.
|
|
129
|
+
Result: `/forge:health`'s structural-check and integrity-verify
|
|
130
|
+
gates silently passed on every install ("× not found" → exit 0).
|
|
131
|
+
Bundle now ships `dist/forge-payload/schemas/structure-manifest.json`
|
|
132
|
+
(non-dot path matching what `check-structure.cjs` resolves) and
|
|
133
|
+
`dist/forge-payload/integrity.json` at bundle root. After install,
|
|
134
|
+
`verify-integrity.cjs` correctly reports `〇 Plugin integrity — all
|
|
135
|
+
25 files unmodified`, and `check-structure.cjs` flags any missing
|
|
136
|
+
expected file in the user's `.forge/` tree.
|
|
137
|
+
- **`hooks/` and `agents/` not bundled** (625fbb1, continuation of
|
|
138
|
+
cd732d2). `integrity.json` tracks 25 files including 4 hooks
|
|
139
|
+
(`check-update.js`, `forge-permissions.js`, `triage-error.js`,
|
|
140
|
+
`validate-write.js`) and 2 agents (`tomoshibi.md`,
|
|
141
|
+
`store-query-validator.md`). None were copied. The TS ports
|
|
142
|
+
(`hook-dispatcher.ts`, `hooks/*.ts`) are the actual runtime path —
|
|
143
|
+
the `.js`/`.cjs` files are integrity ballast that satisfy plugin
|
|
144
|
+
tampering detection. Bundled to satisfy
|
|
145
|
+
`verify-integrity.cjs`. Hooks intentionally bundle only top-level
|
|
146
|
+
`*.js` (4 files); `lib/`, `__tests__/`, and `*.cjs` (post-init,
|
|
147
|
+
post-sprint) are excluded — none are integrity-tracked and the TS
|
|
148
|
+
ports own the runtime channel.
|
|
149
|
+
- **5 FORGE-S24 plugin tools missing from `TOOLS_TO_COPY`** (commit
|
|
150
|
+
in the build-payload cluster). `queue-drain.cjs`,
|
|
151
|
+
`compression-gate.cjs`, `judge-proposal.cjs`,
|
|
152
|
+
`delete-candidate-detector.cjs`, `replay-scoring.cjs` — the new Phase 2
|
|
153
|
+
workflow `require()`s them from `$FORGE_ROOT/tools/`. Without them
|
|
154
|
+
bundled, `/forge:enhance` would fail with
|
|
155
|
+
`Cannot find module './forge/tools/queue-drain.cjs'` (and four more).
|
|
156
|
+
Added to the allowlist with a comment block flagging the dependency.
|
|
157
|
+
- **Version banner reported stale `bundledVersion`** (ae520f8). Both
|
|
158
|
+
readers (`src/bin/forge.ts printVersion`, `src/extensions/forgecli/
|
|
159
|
+
index.ts readPkgVersions`) sourced the value from `package.json`
|
|
160
|
+
`forge.bundledVersion` — a hand-maintained mirror that nobody
|
|
161
|
+
updated when the plugin moved 0.45.0 → 0.46.0 → 0.46.1. Both readers
|
|
162
|
+
now prefer `dist/forge-payload/.claude-plugin/plugin.json` as the
|
|
163
|
+
single source of truth. After fix:
|
|
164
|
+
`@entelligentsia/forgecli@0.15.0 (forge-plugin@0.46.1, pi@…)` reads
|
|
165
|
+
the truth. The mirror in package.json is now informational only.
|
|
166
|
+
|
|
167
|
+
### Changed
|
|
168
|
+
|
|
169
|
+
- **Bundled forge-plugin: v0.44.5 → v0.46.1.** Two minor bumps. v0.45.x
|
|
170
|
+
shipped the FORGE-S24 SKILL-CURATION machinery (event variant,
|
|
171
|
+
proposal schema, queue drain, compression gate, judge, recurrence,
|
|
172
|
+
delete-candidate); v0.46.0 was the sprint-completion marker; v0.46.1
|
|
173
|
+
is the build fix that regenerated `init/base-pack/workflows/
|
|
174
|
+
enhance.md` from the meta source so projects migrating to 0.46.x
|
|
175
|
+
actually receive the new Phase 2 algorithm.
|
|
176
|
+
- **`forge_verify_apply` MCP tool ships in the bundle** (b971596,
|
|
177
|
+
closes forge-cli#31). Detects hallucinated `Edit` calls — when an
|
|
178
|
+
assistant proposes an edit that doesn't match any file on disk, the
|
|
179
|
+
tool flags it at apply time instead of silently no-op'ing.
|
|
180
|
+
|
|
181
|
+
### Documented
|
|
182
|
+
|
|
183
|
+
- **`hook-dispatcher.ts` scope clarification** (7d513ca). New header
|
|
184
|
+
comment block stating the write-guard is a soft fence for honest
|
|
185
|
+
mistakes, not a security boundary against adversarial bash escape.
|
|
186
|
+
See `doc/analysis/write-guard-scope-and-model-behavior.md` in the
|
|
187
|
+
forge-engineering repo for the testbench evidence (two pi-session
|
|
188
|
+
recordings of the same rogue-write prompt — one model surrendered on
|
|
189
|
+
the first block, another escalated three times until succeeding via
|
|
190
|
+
`echo > file`).
|
|
191
|
+
|
|
192
|
+
### Migration notes
|
|
193
|
+
|
|
194
|
+
After upgrading via `npm i -g @entelligentsia/forgecli@0.15.0`:
|
|
195
|
+
|
|
196
|
+
1. `4ge` from your project root.
|
|
197
|
+
2. `/forge:update` will now actually apply project migrations (the
|
|
198
|
+
wire-up + decoupling fixes above). Accept the migration prompt.
|
|
199
|
+
3. To enable SkillOS curation, set
|
|
200
|
+
`forgeCli.skillCuration.enabled: true` in
|
|
201
|
+
`<cwd>/.pi/forge-cli/config.json` (or
|
|
202
|
+
`FORGE_CLI_SKILL_CURATION_ENABLED=1` for one-shot use). Until you
|
|
203
|
+
enable it, the four emission modules no-op — the install is
|
|
204
|
+
byte-identical to pre-FORGE-S24 behaviour.
|
|
205
|
+
4. `/forge:health` now reports through the bundled
|
|
206
|
+
`verify-integrity.cjs` and `check-structure.cjs` — expect cleaner
|
|
207
|
+
output than prior releases, and real signal if your `.forge/` tree
|
|
208
|
+
diverges from the manifest's expectations.
|
|
209
|
+
|
|
210
|
+
## [0.14.0] — 2026-05-22
|
|
211
|
+
|
|
212
|
+
### Added
|
|
213
|
+
|
|
214
|
+
- **`forgeCli.skillCuration.enabled` config flag — gated rollout for SKILL-CURATION pipeline (FORGE-S24-T12).** Adds `forgeCli.skillCuration.enabled` (boolean, **default `false`**) to `forge-cli-schema.json` under a new top-level `forgeCli` object (`additionalProperties: false` preserved). New module `src/extensions/forgecli/skill-curation-flag.ts` exporting `isSkillCurationEnabled(cwd?)` resolves the flag in priority order: env override `FORGE_CLI_SKILL_CURATION_ENABLED` (accepts `1`/`true`/`0`/`false` case-insensitive; unrecognised values fall through) → project config (`<cwd>/.pi/forge-cli/config.json`) → global config (`~/.pi/forge-cli/config.json`) → `false`. The four SKILL-CURATION modules from T08–T11 now check the flag at the top of their public emission/dispatch entry points and no-op when off — `emitSkillUsageEvents` (T08), `emitSkillUsageTrackingEvents` (T09), `emitFrictionEvents` (T11) return `{emitted: 0, failed: 0, stderrs: []}` and make **zero** `spawnSync` calls; `runSkillCurator` (T10) returns `{exitCode: 0, written: 0}` and dispatches **no** subagent, writes **no** queue file. The gate runs BEFORE TypeBox `Value.Parse`, so a flag-off run with malformed runtime input is also a silent no-op (matches the "default OFF ⇒ byte-identical to pre-FORGE-S24 behaviour" acceptance criterion). The orchestrator-side friction channel (non-skill subkinds emitted via `forge/tools/friction-emit.cjs`) is **not** gated by this flag — only the auto-emit module landed in T11 (the five skill subkinds: `skill_unused`, `skill_failed`, `skill_missing`, `skill_stale`, `skill_redundant`). Pure classifier helpers (`computeFrictionSignals`, `classifySkillUsage`, `buildSkillIndex`, `retrieveTopK`, `clampRetrievalScore`, `composeCuratorTask`, `parseProposalsFromOutput`) are **not** gated — they have no side effects and remain callable for downstream consumers that want to compute signals without emitting. Test-first per Iron Law 2: `skill-curation-flag.test.ts` (14 cases — `parseEnvFlag` accepts on/off variants and rejects unrecognised, `isSkillCurationEnabled` defaults to false with all layers empty (AC2), env override wins over both disk layers in both directions, project config wins over global, global used when project absent, malformed env falls through to disk; flag-off no-op guarantee for all four modules — zero `spawnSync` for emit modules, no `runForgeSubagent` dispatch for curator, no queue directory created (AC3); flag-on smoke for `emitSkillUsageEvents` — exactly one argv-array spawn per hit with `["emit", sprintId, json]` shape (IL6)). Pre-existing skill-pipeline tests (`skill-retriever.test.ts`, `skill-usage-tracker.test.ts`, `friction-emit.test.ts`, `skill-curator-subagent.test.ts`) now set `FORGE_CLI_SKILL_CURATION_ENABLED=1` in their `beforeEach` to exercise the flag-on path; the default-off contract is covered by the dedicated gate suite. Full forge-cli test surface unchanged in count: 1733 passed / 7 skipped (3 pre-existing failures in `test/bin/doctor.test.ts` are environmental and unrelated to T12). `npm run typecheck` green. **Operator action required** to enable: upgrade to ≥ 0.14.0 AND set `forgeCli.skillCuration.enabled: true` in `<cwd>/.pi/forge-cli/config.json` (or `FORGE_CLI_SKILL_CURATION_ENABLED=1` for one-shot use). Until both conditions hold, the pipeline is silent — `skill_usage` events are not emitted, friction events for the five skill subkinds are not emitted, and the per-task curator subagent is not dispatched. Pairs with plugin v0.46.0 (convergent sprint marker; no plugin source change in that bump). Closes FORGE-S24-T12 and the SKILL-CURATION sprint.
|
|
215
|
+
|
|
216
|
+
### Changed
|
|
217
|
+
|
|
218
|
+
- **`config-layer.ts`** — `GlobalConfig` and `ProjectConfig` interfaces gain an optional `forgeCli?: ForgeCliFeatureFlags` field carrying the `skillCuration` sub-object. Schema-level addition (`additionalProperties: false` was already in force on the root); existing configs continue to validate unchanged.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## [0.13.4] — 2026-05-22
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
|
|
226
|
+
- **`friction-emit.ts` — auto-emit friction events with 5 skill subkinds (FORGE-S24-T11).** New module under `src/extensions/forgecli/` that, at task close, classifies the orchestrator's per-task signals (retrieved skills with T08 retrieval verdicts + T09 usage verdicts, task success outcome, observed tool-error count, per-skill historical "consecutive unused sprints" counter, optional pairwise retrieval-overlap measurements) and emits one `friction` event per matching gate via `node <storeCli> emit <sprintId> <json>` (argv-array, Iron Law 6). Public surface: `computeFrictionSignals(inputs)` → pure `FrictionSignal[]` (no IO, no subprocess); `emitFrictionEvents(signals, runtime)` → `FrictionEmitResult` (`emitted`, `failed`, `stderrs`). Five gating rules per FORGE-S24-T11 acceptance criteria: `skill_unused` (retrieved && !used && task.success), `skill_failed` (retrieved && used && !task.success), `skill_missing` (!retrieved && task.success && tool_errors ≥ 2 — one signal per task, no skillId attribution), `skill_stale` (retrieved && !used across ≥ 3 consecutive sprints, per-skill history supplied by caller), `skill_redundant` (pairwise retrieval overlap strictly > 0.8, attributed to skillA, paired-with skillB recorded in evidence). Each emitted event carries the schema's required `{type: "friction", workflow, persona, issue}` trio plus `subkind`, `skillId` (when applicable), and an `evidence` blob (retrievalScore, toolErrorCount, consecutiveUnusedSprints, or `{pairedWith, overlap}` as appropriate per subkind). Telemetry-actor split (IL10) honoured — runtime attribution (`model`, `provider`, `startTimestamp`, `endTimestamp`, `durationMinutes`) is caller-supplied, never fabricated inside the module; subagents never invoke this emitter directly. Non-zero `store-cli emit` exits increment `failed` and capture stderr without throwing (IL7). Subkind enum matches the plugin event schema (forge v0.45.0+) — no plugin schema change required for this task. Wiring into `run-task.ts` / `fix-bug.ts` is gated on FORGE-S24-T12 feature flag.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## [0.13.3] — 2026-05-22
|
|
231
|
+
|
|
232
|
+
### Added
|
|
233
|
+
|
|
234
|
+
- **`skill-curator-subagent.ts` — per-task curator dispatch (FORGE-S24-T10).** New module under `src/extensions/forgecli/` that, at task close, hands the task trajectory summary, the retrieved-skill bodies (from T08), and the task outcome verdict to a curator subagent, then writes the curator's enhancement proposals to the project-local enhancement-proposals queue at `.forge/enhancement-proposals/queue/<sprintId>/<taskId>-<ts>.json` (T07 layout — the sprint-close queue-drain consumes this path). Public surface: `runSkillCurator(input)` → typed `CuratorResult` (`exitCode`, `written`, `queueFile?`, `errorMessage?`); `parseProposalsFromOutput(text)` → `Proposal[]` (preferred: fenced ```json``` block, fallback: bare JSON array, items that fail TypeBox validation are dropped); `composeCuratorTask(input)` → first-user-message string carrying sprint/task header, trajectory summary, retrieved-skill bodies, task outcome, and the proposal schema. Dispatch goes through `runForgeSubagent({persona: defaultCuratorPersona(), task, cwd, exportTag})` — fresh in-process pi session, isolated context (Iron Law 10). The curator persona is **inline** (no new file under `forge/forge/meta/personas/` — Iron Law 1 forge-cli boundary respected, no plugin version bump, no security-scan trigger). Proposals are deduped by `{op, target_path, sha256(diff_body)}` (mirrors T07's `dedupeKey`) before write; the empty-array case writes NO file (zero-noise invariant); if the canonical path already exists, the curator retries with a `-N` suffix on the ts (append-only invariant — T07's queue-drain is read-only and never deletes). The subagent NEVER calls `store-cli emit`, writes to `forge/forge/meta/skills/`, or invokes write-mutating tools — these are forbidden in the persona system prompt and enforced by Slice 2 contract (orchestrator emits the canonical phase event AFTER `runSkillCurator` returns, using its own runtime telemetry). Failures (subagent `exitCode !== 0`, parse errors) surface as a typed result with `written: 0` and a non-empty `errorMessage` — no throw, no silent continuation (IL7). Wiring into `run-task.ts` / `fix-bug.ts` is gated on FORGE-S24-T12 feature flag.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## [0.13.2] — 2026-05-22
|
|
239
|
+
|
|
240
|
+
### Added
|
|
241
|
+
|
|
242
|
+
- **`skill-usage-tracker.ts` — post-task usage classification + emission (FORGE-S24-T09).** New module under `src/extensions/forgecli/` that, after a task closes, diffs the observed tool-call trajectory against each retrieved skill's declared workflow steps and emits a follow-up `skill_usage` event per skill with `used: true | false` and a populated `tool_call_success_rate`. Public surface: `classifySkillUsage(skill, trajectory)` → pure `UsageVerdict` (`used`, `signal: "overlap" | "reasoning" | "none"`, `tool_call_success_rate ∈ [0,1]`); `emitSkillUsageTrackingEvents(retrieved, trajectory, runtime)` writes one event per retrieved skill via `node <storeCli> emit <sprintId> <json>` (argv-array, Iron Law 6). Heuristic per FORGE-S24-T09 acceptance criteria: skill name appears in agent reasoning → `used: true` (signal `reasoning`); ≥2 distinct workflow steps overlap with executed tool calls → `used: true` (signal `overlap`); otherwise → `used: false`. `tool_call_success_rate` is the fraction of declared steps observed in the trajectory (distinct overlaps / total steps), clamped to `[0,1]`. Step matching is case-insensitive substring against tool call names to tolerate qualified MCP-style names (e.g. `mcp__store__store-cli-query` matches workflow step `"store-cli query"`). Emitted events conform to the `skill_usage` schema variant landed in forge plugin v0.45.0 (FORGE-S24-T01) with `retrieval_score: 0` — the populated retrieval score was already emitted at retrieval time by T08; this is a tracking-time follow-up. Runs in **orchestrator context** (telemetry-actor split honoured — subagent never invokes the tracker; runtime attribution `model/provider/timestamps/durationMinutes` is caller-supplied, never fabricated). Module owns classification + emission only — assembling the retrieved-skill list, trajectory, and runtime attribution is the orchestrator handler's responsibility (wiring into `run-task.ts`/`fix-bug.ts` is gated on FORGE-S24-T12 feature flag).
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## [0.13.1] — 2026-05-22
|
|
247
|
+
|
|
248
|
+
### Added
|
|
249
|
+
|
|
250
|
+
- **`skill-retriever.ts` — BM25 skill retrieval (FORGE-S24-T08).** New module under `src/extensions/forgecli/` that ranks the project skill corpus by relevance to a task description using `lunr.js` Okapi-BM25 scoring. Public surface: `buildSkillIndex(corpus)` → opaque `SkillIndex` handle; `retrieveTopK(index, query, k)` → deterministic `RetrievalHit[]`; `emitSkillUsageEvents(hits, runtime)` writes one `skill_usage` event per hit via `node <storeCli> emit <sprintId> <json>` (argv-array, Iron Law 6). Indexed fields: skill `name` (boost 4), `description` (boost 2), and selected frontmatter (`name`, `tags`, `aliases`, boost 1). Raw BM25 scores are squashed via `s / (1 + s)` before being written to `retrieval_score` (schema constraint `[0,1]`). Emitted events conform to the `skill_usage` variant landed in forge plugin v0.45.0 (FORGE-S24-T01): required `eventId, sprintId, taskId, skillId, retrieved=true, used=false, tool_call_success_rate=0, retrieval_score`, plus the canonical attribution fields supplied by the orchestrator (`role, action, startTimestamp, endTimestamp, durationMinutes, model, provider`). Module owns ranking + emission only — corpus construction (parsing `SKILL.md` frontmatter) remains the caller's responsibility and is delegated to `loaders/persona-skill-loader.ts`. Behaviour is gated downstream by `forgeCli.skillCuration.enabled` (FORGE-S24-T12).
|
|
251
|
+
|
|
252
|
+
### Dependencies
|
|
253
|
+
|
|
254
|
+
- **`lunr@2.3.9`** added as a runtime dependency, pinned exact (no `^`/`~`) per Iron Law 3 dependency discipline. Pure-JS, MIT-licensed, zero runtime dependencies — SBOM impact is a single direct entry. `@types/lunr@2.3.7` added as dev dependency.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## [0.13.0] — 2026-05-21
|
|
259
|
+
|
|
260
|
+
### Added
|
|
261
|
+
|
|
262
|
+
- **`forge_verify_apply` MCP tool** detects hallucinated Edit calls. The agent is instructed to call it AFTER applying Phase 2 enhancement edits and BEFORE invoking `manage-versions add-snapshot`. The tool runs `generation-manifest.cjs check` on each claimed file path and returns structured buckets: `modified` (verified ✓), `unchanged` (Edit silently no-op'd — usually `old_string` mismatch), `untracked` (no manifest entry), `missing` (file gone). If `unchanged.length > 0`, the agent MUST re-apply via Edit/Write and re-verify before snapshotting. Closes [forge-cli#31](https://github.com/Entelligentsia/forge-cli/issues/31).
|
|
263
|
+
|
|
264
|
+
Background: hello testbench session 17:48 UTC showed the agent's UI claimed 5 file modifications; the snap-4 archive captured by add-snapshot afterwards contained pristine content for 4 of 5 files. The Edit tool had failed silently and the agent reported success regardless. The verification logic is now in forge-cli code (deterministic, testable) rather than relying on agent self-inspection.
|
|
265
|
+
|
|
266
|
+
### Changed
|
|
267
|
+
|
|
268
|
+
- **`enhance.ts` Phase 2 kickoff** restructured: previous Step 5 (snapshot) split into Step 5 (VERIFY via `forge_verify_apply`) and Step 6 (snapshot after verify). Snapshot is now explicitly gated on verification completing with no `unchanged` files.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## [0.12.1] — 2026-05-21
|
|
273
|
+
|
|
274
|
+
### Fixed
|
|
275
|
+
|
|
276
|
+
- **`enhance.ts` — explicit `add-snapshot` instruction in Phase 2 kickoff.** Previously the kickoff said nothing about snapshots; agents had to discover the requirement buried in `meta-enhance.md` step 8. In practice many agents applied edits but skipped the snapshot call, breaking the entire durability story — replay (v0.12.0) had nothing to restore from. Kickoff now explicitly instructs: after applying any approved edits, MUST call `node "$FORGE_ROOT/tools/manage-versions.cjs" add-snapshot --source post-sprint:<SPRINT_ID> --enhanced-elements <paths>`. Discovered via hello testbench transcript: `currentSnapshot` stayed at 3 after a Phase 2 apply session, leading to silent data loss on the next regenerate. Closes part 1 of [forge-cli#30](https://github.com/Entelligentsia/forge-cli/issues/30).
|
|
277
|
+
- **`regenerate.ts` — modification guard now fires on untracked files.** Previously only fired on `generation-manifest check` exit 1 (modified hash mismatch); exit 2 (untracked — no manifest entry) was ignored. After a prior regenerate ran `clear-namespace` without re-recording, files end up in untracked state — and the next regenerate silently overwrote them. Guard now surfaces both "modified" and "untracked" states with state-aware prompt text. `ModifiedFile` interface extended with a `state: "modified" | "untracked"` field. Closes part 2 of [forge-cli#30](https://github.com/Entelligentsia/forge-cli/issues/30).
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## [0.12.0] — 2026-05-21
|
|
282
|
+
|
|
283
|
+
### Added
|
|
284
|
+
|
|
285
|
+
- **`regenerate.ts` — snapshot replay (Approach A layer 3).** Mirrors the new plugin behaviour in forge v0.45.0. After `substitute-placeholders.cjs` writes fresh base-pack content over `.forge/{personas,skills,workflows,templates}/`, the handler now invokes `manage-versions replay --target <category>` for each of the four structural-element categories. Restores user-enhanced files captured by `/forge:enhance` Phase 2 snapshots from `.forge/archive/snap-N/`. Pure additive — no-op when no snapshots match. Skipped when `--force` is used (force == "I want pristine base-pack content, no overlay"). Closes [forge-cli#27](https://github.com/Entelligentsia/forge-cli/issues/27).
|
|
286
|
+
|
|
287
|
+
### Changed
|
|
288
|
+
|
|
289
|
+
- **Modification guard text softened** to reflect the new replay behaviour. The pre-write prompt now states that snapshot-captured edits will be restored automatically post-regenerate, and only manual edits NOT captured in any snapshot are at risk. Guard remains as defence-in-depth.
|
|
290
|
+
|
|
291
|
+
- Bundled forge-plugin advanced to **0.45.0** (replay subcommand + regenerate replay step).
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## [0.11.6] — 2026-05-21
|
|
296
|
+
|
|
297
|
+
### Fixed
|
|
298
|
+
|
|
299
|
+
- **`enhance.ts` — Phase 2 kickoff no longer over-restricts friction discovery to `forge_store_query`.** The kickoff previously instructed agents to discover friction events "ONLY via the `forge_store_query` tool — do NOT raw-read `.forge/store/events/`". But the underlying NLP engine matches by keyword-on-title heuristics, not by `type === 'friction'` exactly — a testbench with 10 friction events on disk returned only 6 via NLP and zero in one agent's path, producing `frictionCount: 0` Phase 2 outputs despite events being present. Kickoff now: (a) keeps `forge_store_query` as **preferred** path, (b) explicitly instructs the agent to **fall back to the workflow body's filesystem walk** (`meta-enhance.md` Step 1's `e.type === 'friction'` filter) when MCP returns suspiciously low / zero, (c) zero-friction guard fires only when **both paths** are empty. Closes [forge-cli#29](https://github.com/Entelligentsia/forge-cli/issues/29).
|
|
300
|
+
- Bundled forge-plugin advanced to **0.44.10**, which includes the fix for `manage-versions add-snapshot` silently failing to archive files ([forge#108](https://github.com/Entelligentsia/forge/issues/108)) — layer 2 of the composition contract is now functional. Unblocks future Approach A work (forge#107 / forge-cli#27).
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## [0.11.5] — 2026-05-21
|
|
305
|
+
|
|
306
|
+
### Fixed
|
|
307
|
+
|
|
308
|
+
- **`index.ts` — `process.env.FORGE_ROOT` now exported on main-thread activation.** When forge-cli activates inside a Forge project, `process.env.FORGE_ROOT` is set to the absolute path resolved from `.forge/config.json`'s `paths.forgeRoot`, alongside the existing `before_agent_start` orientation injection. Subagent dispatch via `runForgeSubagent` already set this (forge-subagent.ts:200), but kickoff handlers (`/forge:enhance`, `/forge:health`, `/forge:calibrate`, etc.) bypass the subagent path — so `$FORGE_ROOT/...` in their workflow bodies' bash command literals previously substituted to an empty string, producing the symptom "Snapshot: not written (Forge manage-versions not available in this context)" during `/forge:enhance` Phase 2. Closes [forge-cli#28](https://github.com/Entelligentsia/forge-cli/issues/28). Phase 1 of the snapshot-replay durability story tracked in forge#107 / forge-cli#27.
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## [0.11.4] — 2026-05-21
|
|
313
|
+
|
|
314
|
+
### Fixed
|
|
315
|
+
|
|
316
|
+
- **`regenerate.ts` — pre-write modification guard for `/forge:regenerate`.** Companion to [forge#106](https://github.com/Entelligentsia/forge/issues/106) (FORGE-BUG-037) and the forge plugin v0.44.9 markdown fix. Before invoking `substitute-placeholders.cjs`, the handler now enumerates files in `.forge/{personas,skills,workflows,templates}/` and runs `generation-manifest.cjs check` on each. Any file whose hash no longer matches the recorded manifest — typically applied by `/forge:enhance` Phase 2 — triggers a `ctx.ui.confirm` prompt listing the modifications. On decline, regenerate is cancelled and the edits are preserved. New `--force` flag bypasses the prompt for CI / dogfood reset.
|
|
317
|
+
|
|
318
|
+
The plugin-level markdown fix (forge v0.44.9) covered the Claude Code plugin flow which executes the command markdown body. forge-cli has a self-contained TypeScript handler that bypasses the markdown body entirely; this commit closes that vector. See [forge-cli#26](https://github.com/Entelligentsia/forge-cli/issues/26).
|
|
319
|
+
|
|
320
|
+
- Bundled forge-plugin advanced to **0.44.9** (was 0.44.6 / 0.44.8 in 0.11.3 builds depending on rebuild timing).
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## [0.11.3] — 2026-05-21
|
|
325
|
+
|
|
326
|
+
### Fixed
|
|
327
|
+
|
|
328
|
+
- **`ask-user-tool.ts` — chip strip no longer steals arrow keys from `forge_ask_user` dialogs.** `ctx.ui.confirm`/`select`/`input` are pi's built-in overlay dialogs but `forge_ask_user` never called `pushOverlay`/`popOverlay` on the `ForgeInputRouter`. The thread-switcher's arrow-key handler (registered with `skipWhenOverlayActive`) was never suppressed because `overlayDepth` stayed at 0. All three dialog calls are now wrapped in `router.pushOverlay()` / `router.popOverlay()` (try/finally), matching the pattern in `config-command.ts`.
|
|
329
|
+
|
|
330
|
+
- **`run-task.ts` — chip strip no longer appears before task ID is resolved.** `registry.startSession(taskId)` was called with the raw user arg (e.g. `"T01"`) before `resolveToCanonicalId` had a chance to disambiguate ambiguous matches. The chip strip appeared showing `T01` before the user answered the `ctx.ui.select` choice dialog — and arrow keys were stolen by the strip. `startSession` is now deferred to after `resolveToCanonicalId` and all resume-detection `ctx.ui.confirm` prompts, right before pipeline delegation.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
10
334
|
## [0.11.2] — 2026-05-20
|
|
11
335
|
|
|
12
336
|
### Fixed
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://www.npmjs.com/package/@entelligentsia/forgecli)
|
|
9
9
|
[](#)
|
|
10
10
|
[](#)
|
|
11
|
-
[](https://github.com/Entelligentsia/forge)
|
|
12
12
|
[](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)
|
|
13
13
|
|
|
14
14
|
</div>
|
|
@@ -22,6 +22,7 @@ forge-cli generates a project-specific engineering knowledge base, sprint workfl
|
|
|
22
22
|
|
|
23
23
|
- **Structured SDLC, in any terminal.** Plan → implement → review → validate → commit chains, gated by your own personas and audience rules.
|
|
24
24
|
- **Project memory that compounds.** Every sprint sharpens the knowledge base; the next one starts smarter.
|
|
25
|
+
- **Skills that stay relevant.** Forge ships a SkillOS-style curation loop (FORGE-S24). Five friction subkinds — `skill_unused`, `skill_failed`, `skill_missing`, `skill_stale`, `skill_redundant` — surface what the model actually reached for, what worked, and what didn't. Phase 2 enhancement classifies proposals as `insert_skill` / `update_skill` / `delete_skill`, scores them through an LLM-judge rubric, gates oversize edits behind a compression check, and drains a per-task curator queue into one batched review at sprint close. The result: your skill library tracks your codebase as it evolves, instead of calcifying.
|
|
25
26
|
- **Bring your own model.** Anthropic, OpenAI, ollama, openrouter — anything pi resolves.
|
|
26
27
|
|
|
27
28
|
## Install
|
|
@@ -5,6 +5,216 @@ Format: newest first. Breaking changes are marked **△ Breaking**.
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [0.46.1] — 2026-05-22
|
|
9
|
+
|
|
10
|
+
**Build fix: ship the FORGE-S24 SKILL-CURATION Phase 2 pipeline that 0.46.0 was supposed to.**
|
|
11
|
+
|
|
12
|
+
The 0.45.1–0.45.7 migration entries declared `workflows:enhance` in their `regenerate` lists, but `node tools/build-base-pack.cjs` was not re-run during the sprint. As a result the installable `init/base-pack/workflows/enhance.md` stayed at the pre-S24 algorithm, and projects migrating to 0.46.0 received a stale workflow that lacked queue-drain (step 1a), recurrence scoring, delete-candidate detection (step 5b), compression gate (step 5b.5), and the LLM-judge step (step 5c).
|
|
13
|
+
|
|
14
|
+
This patch regenerates the base-pack copy from `meta/workflows/meta-enhance.md` (280 → 600 lines, 20 S24 markers landed) and forces a re-copy on any project sitting at 0.46.0 by declaring `workflows:enhance` in this entry's regenerate list. No plugin source change beyond the regenerated workflow file. Additive, non-breaking.
|
|
15
|
+
|
|
16
|
+
Discovered during cartographer testbench smoke-test of `/forge:enhance` — Phase 2 ran the legacy algorithm (no op classification, no queue path, no judge rejections sidecar) because the workflow the migration copied into the project lacked the new steps.
|
|
17
|
+
|
|
18
|
+
**Regenerate:** `workflows:enhance`
|
|
19
|
+
|
|
20
|
+
> Manual: Run `/forge:update` to refresh `.forge/workflows/enhance.md` with the SKILL-CURATION Phase 2 pipeline.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## [0.46.0] — 2026-05-22
|
|
25
|
+
|
|
26
|
+
**FORGE-S24 SKILL-CURATION sprint completion — gated rollout marker (FORGE-S24-T12).**
|
|
27
|
+
|
|
28
|
+
No plugin source change in this bump. The seven preceding migration entries (0.45.1 → 0.45.7) carry the actual SKILL-CURATION machinery:
|
|
29
|
+
|
|
30
|
+
| Bump | Task | Adds |
|
|
31
|
+
|------|------|------|
|
|
32
|
+
| 0.45.0 → 0.45.1 | T01 | `skill_usage` event variant in `forge/schemas/event.schema.json` |
|
|
33
|
+
| 0.45.1 → 0.45.2 | T02 | Proposal op classification (`insert_skill`/`update_skill`/`delete_skill`) — `forge/schemas/proposal.schema.json` + `forge/tools/proposal-normalize.cjs` |
|
|
34
|
+
| 0.45.2 → 0.45.3 | T04 | Cross-task recurrence scoring — `forge/tools/replay-scoring.cjs` |
|
|
35
|
+
| 0.45.3 → 0.45.4 | T05 | Delete-candidate detection (3-sprint zero-use) — `forge/tools/delete-candidate-detector.cjs` |
|
|
36
|
+
| 0.45.4 → 0.45.5 | T03 | LLM-judge rubric (Sonnet, drop <3/5) — `forge/tools/judge-proposal.cjs` |
|
|
37
|
+
| 0.45.5 → 0.45.6 | T06 | Compression gate (reject >20% growth without 3+ frictions) — `forge/tools/compression-gate.cjs` |
|
|
38
|
+
| 0.45.6 → 0.45.7 | T07 | Queue drain at sprint close — `forge/tools/queue-drain.cjs` |
|
|
39
|
+
|
|
40
|
+
T12 lands the **gated-rollout contract on the forge-cli side** via the new `forgeCli.skillCuration.enabled` config flag (default OFF). The four forge-cli modules (T08 skill-retriever, T09 skill-usage-tracker, T10 skill-curator-subagent, T11 friction-emit) no-op at entry when the flag is off, so a flag-off run is byte-identical to pre-FORGE-S24 behaviour. This plugin-side minor bump (0.45.7 → 0.46.0) is the convergent terminal marker for the sprint: it signals to operators running `/forge:update` that the full SKILL-CURATION pipeline has shipped end-to-end, and pairs with the forge-cli 0.13.4 → 0.14.0 bump that lands the rollout flag.
|
|
41
|
+
|
|
42
|
+
**No regeneration required** (no manifest entry change, no workflow change, no schema change in this bump alone — those landed in 0.45.1–0.45.7).
|
|
43
|
+
|
|
44
|
+
**Operator action required to enable:** upgrade forge-cli to ≥ 0.14.0 **and** set `forgeCli.skillCuration.enabled: true` in `<cwd>/.pi/forge-cli/config.json` (or the env override `FORGE_CLI_SKILL_CURATION_ENABLED=1` for one-shot use). Until both conditions hold, the new event variants and friction subkinds remain emitter-silent — the plugin schema continues to accept them on receipt, so a delayed forge-cli upgrade is non-blocking.
|
|
45
|
+
|
|
46
|
+
Additive, non-breaking.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## [0.45.3] — 2026-05-22
|
|
51
|
+
|
|
52
|
+
Feature: **Cross-task replay scoring — recurrence boost** (FORGE-S24-T04 — SKILL-CURATION).
|
|
53
|
+
|
|
54
|
+
For each Phase 2 enrichment proposal synthesised from a friction event at
|
|
55
|
+
task `t`, the new `forge/tools/replay-scoring.cjs` helper scans friction
|
|
56
|
+
events in tasks `t+1..N` of the same sprint for matching
|
|
57
|
+
`(subkind, evidence.skillId)` pairs and stamps `recurrence_count` (>= 1,
|
|
58
|
+
includes the origin task) plus `recurrence_task_ids` (taskOrder-sorted)
|
|
59
|
+
onto the proposal. The downstream T03 judge can now boost specificity
|
|
60
|
+
when a friction signal recurred across multiple tasks instead of treating
|
|
61
|
+
every observation as a singleton.
|
|
62
|
+
|
|
63
|
+
`forge/meta/workflows/meta-enhance.md` Phase 2 gains step 5a invoking
|
|
64
|
+
`annotateProposals(proposals, frictionEvents, taskOrder)` between the
|
|
65
|
+
synthesis step (5) and the artifact write (6); step 5 now requires
|
|
66
|
+
`sourceFrictionIds` to carry every contributing `eventId` so the
|
|
67
|
+
recurrence scan can resolve provenance. `forge/schemas/proposal.schema.json`
|
|
68
|
+
gains two optional fields — `recurrence_count` (integer, minimum 1) and
|
|
69
|
+
`recurrence_task_ids` (array of strings) — both additive;
|
|
70
|
+
`additionalProperties: false` continues to reject unknown keys.
|
|
71
|
+
|
|
72
|
+
Forward-only scan: earlier tasks (before `fromTaskId` in `taskOrder`) are
|
|
73
|
+
excluded. Proposals without resolvable provenance receive a neutral
|
|
74
|
+
`recurrence_count: 1` and empty `recurrence_task_ids: []` — neutral
|
|
75
|
+
signal, not silent failure.
|
|
76
|
+
|
|
77
|
+
Test-first per Iron Law 2: `replay-scoring.test.cjs` (11 cases including
|
|
78
|
+
the AC3 three-task fixture, forward-only-direction guard,
|
|
79
|
+
subkind/skillId mismatch rejection, and the no-mutation invariant)
|
|
80
|
+
landed before the helper. Full suite 1364/1364 (was 1353; +11).
|
|
81
|
+
|
|
82
|
+
Additive, non-breaking. Users running an older version receive the
|
|
83
|
+
recurrence-augmented proposal schema on `/forge:update` and re-run
|
|
84
|
+
`/forge:enhance --phase 2` to take advantage of the new fields.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## [0.45.2] — 2026-05-22
|
|
89
|
+
|
|
90
|
+
Feature: **Phase 2 proposal op classification** (FORGE-S24-T02 — SKILL-CURATION).
|
|
91
|
+
|
|
92
|
+
Replaces the insert-biased Phase 2 enrichment-proposal vocabulary with an
|
|
93
|
+
explicit three-op classification. New `forge/schemas/proposal.schema.json`
|
|
94
|
+
enumerates `op` ∈ `{insert_skill, update_skill, delete_skill}` and requires
|
|
95
|
+
`target_path` + `diff_body` per record; `additionalProperties: false` rejects
|
|
96
|
+
unknown fields.
|
|
97
|
+
|
|
98
|
+
`meta/workflows/meta-enhance.md` Phase 2 (steps 5–6) now:
|
|
99
|
+
|
|
100
|
+
- Routes every friction event through the three-op classifier when synthesising proposals.
|
|
101
|
+
- Emits a machine-readable `phase2-<timestamp>.json` artifact alongside the existing markdown — each entry conforms to `proposal.schema.json`.
|
|
102
|
+
- References `proposal-normalize.cjs:normaliseProposal()` as the **explicit** read-side back-compat path for legacy (pre-0.45.2) proposals lacking `op`; missing `op` defaults to `insert_skill` — never silently coerced.
|
|
103
|
+
|
|
104
|
+
This is the foundation for the remaining S24 work: T03 (judge), T05
|
|
105
|
+
(delete-candidate detection), T06 (compression gate), T07 (queue drain).
|
|
106
|
+
|
|
107
|
+
Test-first per Iron Law 2: `proposal-schema.test.cjs` (6 cases — missing op,
|
|
108
|
+
unknown op, missing `target_path`, `additionalProperties:false`, and the legacy
|
|
109
|
+
normalisation contract) landed before the schema. Full suite 1353/1353.
|
|
110
|
+
|
|
111
|
+
Additive, non-breaking: existing proposals continue to validate via the
|
|
112
|
+
normaliser, and no existing schema or tool changes.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## [0.45.1] — 2026-05-22
|
|
117
|
+
|
|
118
|
+
Feature: **`skill_usage` event variant** (FORGE-S24-T01, plan 08 Phase B — SKILL-CURATION).
|
|
119
|
+
|
|
120
|
+
`event.schema.json` gains a new event type `skill_usage` with an `allOf`
|
|
121
|
+
branch requiring `{eventId, sprintId, taskId, skillId, retrieved, used,
|
|
122
|
+
tool_call_success_rate, retrieval_score}`. The numeric properties
|
|
123
|
+
`tool_call_success_rate` and `retrieval_score` carry declarative `[0, 1]`
|
|
124
|
+
bounds; `skillId` is `minLength: 1`. The root `additionalProperties: false`
|
|
125
|
+
gate continues to reject unknown fields on every variant.
|
|
126
|
+
|
|
127
|
+
This is the data foundation for Sprint S24 SKILL-CURATION:
|
|
128
|
+
|
|
129
|
+
- **T02** emits `skill_usage` records when a skill is retrieved into context or invoked.
|
|
130
|
+
- **T04** correlates the `retrieval_score` against tool-call outcomes.
|
|
131
|
+
- **T05** detects delete-candidate skills using rolling-window aggregates of `used` × `tool_call_success_rate`.
|
|
132
|
+
- **T08** replays historic events for retrospective scoring.
|
|
133
|
+
|
|
134
|
+
No `validate-store.cjs` code-path change — the existing `validateRecord()`
|
|
135
|
+
machinery handles the new `allOf` branch identically to the `friction`,
|
|
136
|
+
`sprint-complete`, and `sprint-halted` variants. Additive and non-breaking:
|
|
137
|
+
existing event records remain valid.
|
|
138
|
+
|
|
139
|
+
**Note on target version.** TASK_PROMPT requested `v0.45.0`, but that tag
|
|
140
|
+
already shipped (snapshot-replay, forge#107). Bumping to `0.45.1` is the
|
|
141
|
+
minimum forward step.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## [0.45.0] — 2026-05-21
|
|
146
|
+
|
|
147
|
+
Feature: **Approach A — snapshot replay** ([forge#107](https://github.com/Entelligentsia/forge/issues/107)). `manage-versions` gains a new `replay` subcommand that fulfills **layer 3** of the composition contract declared at `manage-versions.cjs:13` (`Working Artifact = base@pluginVersion + snapshot@currentSnapshot + user_enhancements`).
|
|
148
|
+
|
|
149
|
+
After `/forge:regenerate` writes fresh base-pack content over `.forge/{personas,skills,workflows,templates}/`, the replay step walks all snapshots in `.forge/structure-versions.json`, finds enhanced elements matching the target prefix, and restores them from the archive over the freshly-generated content. Later snapshots win on file collision; files not captured by any snapshot remain at the fresh base-pack version.
|
|
150
|
+
|
|
151
|
+
This closes the loop opened by the v0.44.9 modification guard (forge#106) and the v0.44.10 archive-path fix (forge#108): user enhancements applied by `/forge:enhance` Phase 2 now survive `/forge:regenerate` automatically. The pre-write modification guard remains as defence-in-depth for manual edits not captured in any snapshot.
|
|
152
|
+
|
|
153
|
+
**v1 semantics (overlay).** A user-enhanced file retains its captured content even when the base-pack version of that file has changed in a plugin update. Trade-off accepted for v1; future v2 may layer 3-way merge for richer plugin-update propagation.
|
|
154
|
+
|
|
155
|
+
New CLI:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
node "$FORGE_ROOT/tools/manage-versions.cjs" replay --target personas # restore all personas/* enhancements
|
|
159
|
+
node "$FORGE_ROOT/tools/manage-versions.cjs" replay --target personas/engineer.md # restore one file
|
|
160
|
+
node "$FORGE_ROOT/tools/manage-versions.cjs" replay --target skills [--dry-run]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`regenerate.md` updated: each of personas, skills, workflows, templates fans out generation → calls `replay` → re-records manifest hashes so subsequent `check` operations reflect the restored content.
|
|
164
|
+
|
|
165
|
+
**Regenerate:** commands:regenerate, tools:manage-versions
|
|
166
|
+
|
|
167
|
+
> Closes [forge#107](https://github.com/Entelligentsia/forge/issues/107). Companion forge-cli mirror tracked in [forge-cli#27](https://github.com/Entelligentsia/forge-cli/issues/27).
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## [0.44.10] — 2026-05-21
|
|
172
|
+
|
|
173
|
+
Fix `manage-versions add-snapshot` silently failing to archive files. The tool previously did `path.join(projectRoot, ".forge", relPath)` to locate source files. Workflow callers (`meta-enhance.md`, `base-pack/workflows/enhance.md`) have always passed `--enhanced-elements` with the full `.forge/` prefix (e.g. `.forge/personas/architect.md`), producing a double-prefixed source path `projectRoot/.forge/.forge/...` that never exists — `fs.existsSync` then silently skipped every file. Every archive directory created since basePackVersion 0.43.3 has been empty. Layer 2 of the composition contract declared at `manage-versions.cjs:13` (`Working Artifact = base + snapshot + user_enhancements`) was a no-op. Tool now strips a leading `.forge/` from each element path; both `.forge/-relative` and project-root-relative forms accepted. New test `forge#108 — tolerates leading ".forge/" prefix in --enhanced-elements`. Unblocks [forge#107](https://github.com/Entelligentsia/forge/issues/107) (Approach A — snapshot replay).
|
|
174
|
+
|
|
175
|
+
**Regenerate:** tools:manage-versions
|
|
176
|
+
|
|
177
|
+
> Closes [forge#108](https://github.com/Entelligentsia/forge/issues/108).
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## [0.44.9] — 2026-05-21
|
|
182
|
+
|
|
183
|
+
Fix `/forge:regenerate personas` and `/forge:regenerate skills` silently overwriting manual modifications (typically applied by `/forge:enhance` Phase 2). Pre-write `generation-manifest check` + `△ ...has been manually modified. Overwriting will discard your changes. Proceed? (yes / no / show diff)` prompt added to both single-file and full-rebuild paths in `commands/regenerate.md`, mirroring the workflows and templates pattern. Closes the asymmetric modification-detection across the four structural-element categories. Markdown-only fix — no `.cjs` changes.
|
|
184
|
+
|
|
185
|
+
**Regenerate:** commands:regenerate
|
|
186
|
+
|
|
187
|
+
> Closes [forge#106](https://github.com/Entelligentsia/forge/issues/106) (FORGE-BUG-037).
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## [0.44.8] — 2026-05-21
|
|
192
|
+
|
|
193
|
+
**#104 fix — /forge:enhance UX gaps.** Two workflow enhancements:
|
|
194
|
+
|
|
195
|
+
1. **Phase-routing guidance** — the `--phase` flag table in both `commands/enhance.md` and the bundled `workflows/enhance.md` now includes a "when to run" one-liner for each phase: `--phase 1` (post-init placeholder fill), `--phase 2` (post-sprint friction scan), `--phase 3` (on-demand drift detection).
|
|
196
|
+
|
|
197
|
+
2. **Zero-friction guard for Phase 2** — meta-enhance.md now guards Step 1: if the friction event list is empty, the workflow prints `No friction events queued for the active sprint — nothing to enhance.` and exits Phase 2 immediately (skips steps 3–10; emits the enhancement event with `frictionCount: 0`). Prevents silent no-op Phase 2 runs. Steps 2–9 in Phase 2 are renumbered 3–10 accordingly.
|
|
198
|
+
|
|
199
|
+
**Regenerate:** workflows:enhance
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## [0.44.7] — 2026-05-21
|
|
204
|
+
|
|
205
|
+
**#105 fix — build-persona-pack.cjs schema mismatch.** Tool now accepts both:
|
|
206
|
+
|
|
207
|
+
- **Base-pack format** (no frontmatter, `init/base-pack/personas/`): derives `id`, `role`, `summary`, `responsibilities`, `outputs`, `file_ref` from content and filename. Previously threw "no frontmatter block found".
|
|
208
|
+
- **Meta format** (YAML frontmatter, `meta/personas/`): existing behavior preserved; `file_ref` must be in frontmatter.
|
|
209
|
+
|
|
210
|
+
Skills: `file_ref` is now derived from the file path when absent from frontmatter (base-pack skills). Previously threw "frontmatter missing required field 'file_ref'".
|
|
211
|
+
|
|
212
|
+
Guard: `buildPack()` throws when both dirs are empty, preventing silent empty-pack writes that caused `/forge:health` to report persona-pack permanently stale.
|
|
213
|
+
|
|
214
|
+
**Regenerate:** tools:build-persona-pack
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
8
218
|
## [0.44.6] — 2026-05-20
|
|
9
219
|
|
|
10
220
|
**P1 bug-fix batch (forge-cli#25 — defects C, D, E).** Three tool fixes to address defects discovered in the forge-cli 0.11.0 dogfooding session.
|
package/dist/bin/forge.js
CHANGED
|
@@ -44,10 +44,29 @@ async function readPiVersion() {
|
|
|
44
44
|
return "unknown";
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
function readBundledPluginVersion() {
|
|
48
|
+
// Authoritative source: dist/forge-payload/.claude-plugin/plugin.json,
|
|
49
|
+
// regenerated by scripts/build-payload.cjs from forge/forge/.claude-plugin/
|
|
50
|
+
// plugin.json on every build. The package.json forge.bundledVersion mirror
|
|
51
|
+
// (used as fallback below) is hand-maintained and tends to drift — until
|
|
52
|
+
// FORGE-S24 it sat at 0.45.0 across the entire 0.46.x line.
|
|
53
|
+
try {
|
|
54
|
+
const pluginJsonPath = path.resolve(__dirname, "..", "forge-payload", ".claude-plugin", "plugin.json");
|
|
55
|
+
const pluginPkg = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8"));
|
|
56
|
+
if (typeof pluginPkg.version === "string" && pluginPkg.version.length > 0) {
|
|
57
|
+
return pluginPkg.version;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Fall through to package.json mirror.
|
|
62
|
+
}
|
|
63
|
+
const pkg = readForgeCliPkg();
|
|
64
|
+
return pkg.forge?.bundledVersion ?? "unknown";
|
|
65
|
+
}
|
|
47
66
|
async function printVersion() {
|
|
48
67
|
const pkg = readForgeCliPkg();
|
|
49
68
|
const forgeCliVersion = pkg.version ?? "unknown";
|
|
50
|
-
const bundledVersion =
|
|
69
|
+
const bundledVersion = readBundledPluginVersion();
|
|
51
70
|
const piVersion = await readPiVersion();
|
|
52
71
|
process.stdout.write(`@entelligentsia/forgecli@${forgeCliVersion} (forge-plugin@${bundledVersion}, pi@${piVersion})\n`);
|
|
53
72
|
}
|