mindforge-cc 11.9.3 → 11.9.4
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/.mindforge/config.json +1 -1
- package/.mindforge/engine/autonomous/headless-adapter.md +8 -1
- package/CHANGELOG.md +168 -5
- package/MINDFORGE.md +2 -2
- package/README.md +46 -28
- package/RELEASENOTES.md +63 -0
- package/SECURITY.md +1 -1
- package/bin/dashboard/metrics-aggregator.js +6 -1
- package/bin/governance/approve.js +12 -1
- package/bin/governance/verify-approvals.js +13 -1
- package/bin/installer/hook-registration.js +54 -11
- package/bin/installer-core.js +31 -3
- package/changelogs/v11.9.3.md +14 -5
- package/changelogs/v11.9.4.md +155 -0
- package/docs/faq.md +3 -3
- package/docs/getting-started.md +9 -3
- package/docs/sdk-reference.md +3 -3
- package/docs/troubleshooting.md +56 -1
- package/docs/user-guide.md +3 -3
- package/package.json +2 -1
- package/.mindforge/memory/sync-manifest.json +0 -6
package/.mindforge/config.json
CHANGED
|
@@ -47,7 +47,14 @@ Typical GitHub Action setup:
|
|
|
47
47
|
steps:
|
|
48
48
|
- uses: actions/checkout@v4
|
|
49
49
|
- name: Run MindForge headless
|
|
50
|
-
|
|
50
|
+
# `npx --package=mindforge-cc` PINS the package. Bare `npx mindforge` resolves to an UNRELATED
|
|
51
|
+
# third-party package on the public registry (mindforge@1.0.21, maintainer william@mindforge.ai) —
|
|
52
|
+
# not this project, whose npm name is mindforge-cc. In a fresh runner there is no local bin to
|
|
53
|
+
# shadow it, so npx fetches and unpacks that package, runs any install scripts it has, and then
|
|
54
|
+
# fails with "could not determine executable to run" because it exposes no `mindforge` bin.
|
|
55
|
+
# Measured both forms: the pinned one exits 0 with mindforge-cc in the npx cache; the bare one
|
|
56
|
+
# exits 1 after downloading someone else's package into a job holding MINDFORGE_TOKEN.
|
|
57
|
+
run: npx --yes --package=mindforge-cc mindforge headless --phase 3
|
|
51
58
|
env:
|
|
52
59
|
MINDFORGE_TOKEN: ${{ secrets.MINDFORGE_TOKEN }}
|
|
53
60
|
AUTO_PUSH_ON_WAVE_COMPLETE: true
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,159 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [11.9.4] — 2026-08-22 — Delivery: the gates register, the tarball matches its tag, three packages attested
|
|
4
|
+
|
|
5
|
+
Patch release. 11.9.3 argued that an instrument must not report success while doing
|
|
6
|
+
nothing. 11.9.4 is what an adversarial audit of the **published** 11.9.3 artifact found
|
|
7
|
+
when that standard was applied to the delivery itself: **enforcement that installed and
|
|
8
|
+
then declined to register, a tarball that could not be reproduced from its own tag, and a
|
|
9
|
+
README that understated what shipped.**
|
|
10
|
+
|
|
11
|
+
Every finding here came from measuring the published package in a confined environment —
|
|
12
|
+
not from reading the repository. That distinction is the whole content of this release.
|
|
13
|
+
|
|
14
|
+
### BREAKING
|
|
15
|
+
|
|
16
|
+
- **The installer now registers hooks on projects where it previously declined.** If you
|
|
17
|
+
install into a project that has an ancestor directory containing a `.claude`, MindForge
|
|
18
|
+
now writes `.claude/settings.json` (merging append-only into any existing file) instead
|
|
19
|
+
of skipping. On a machine that has ever run Claude Code, `~/.claude` makes that
|
|
20
|
+
essentially every project — so most installs go from **0 registered hooks to 8**. Three
|
|
21
|
+
of them can block a tool call. If you were relying on the installer being inert here,
|
|
22
|
+
it no longer is; `.mindforge/hook-registration.json` records exactly what was written,
|
|
23
|
+
and the previous settings file is backed up under `.mindforge/backups/`. (#224)
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
**Hook registration — the gates shipped installed but inert**
|
|
28
|
+
|
|
29
|
+
- **`register()` skipped whenever any ancestor held a `.claude` directory.** Measured
|
|
30
|
+
against the published 11.9.3 tarball, confined HOME, `~/.claude` as the only ancestor:
|
|
31
|
+
**11 hook scripts installed, 0 registered, no settings file written.** The gates that
|
|
32
|
+
the shipped `CLAUDE.md` calls MANDATORY were copied in and left unreachable. Same
|
|
33
|
+
sandbox on 11.9.4: **8 registered, installer preflight executed 7 of 8 and verified all
|
|
34
|
+
3 deny-class hooks returning exit 2** before keeping the file. (#224)
|
|
35
|
+
|
|
36
|
+
The reason it printed — *"the harness will read `<ancestor>/.claude/settings.json`, not
|
|
37
|
+
this directory"* — was wrong three separate ways:
|
|
38
|
+
|
|
39
|
+
1. `~/.claude/settings.json` is the **user tier**, applied in addition to the project
|
|
40
|
+
tier. Its existence carries no information about whether a project file is read, so
|
|
41
|
+
the condition that suppressed the gates was satisfied by an ordinary laptop.
|
|
42
|
+
2. For a genuine project ancestor the claim is false too — that file is not read
|
|
43
|
+
either. Verified with a natural experiment: an ancestor two levels up carried a
|
|
44
|
+
`PreToolUse` Bash hook appending a marker to a log; across a dozen tool calls with
|
|
45
|
+
the inner directory as the project root, the log was never created. Skipping did not
|
|
46
|
+
deliver the gates elsewhere. It delivered them nowhere.
|
|
47
|
+
3. The git-boundary guard was **dead code**. `stop` was the git toplevel while the walk
|
|
48
|
+
began at `dirname(projectRoot)`, so when toplevel equalled projectRoot the stop
|
|
49
|
+
condition could never be true and the walk ran to the filesystem root every time.
|
|
50
|
+
The boundary meant to keep the check local is why it reached `$HOME`.
|
|
51
|
+
|
|
52
|
+
It now warns and registers anyway: a registration that turns out inert costs nothing and
|
|
53
|
+
becomes live when the harness is launched there, whereas a skip is guaranteed inert. The
|
|
54
|
+
check additionally requires a real `settings.json` **file** — the old one accepted any
|
|
55
|
+
directory named `.claude`, and the one it hit in practice held only markdown. (#224)
|
|
56
|
+
|
|
57
|
+
- **The installer's only failure-path pointer led nowhere.** It told anyone whose hooks
|
|
58
|
+
were not registered to "see `docs/troubleshooting.md`", where the word *hook* appeared
|
|
59
|
+
**0** times. That file now carries the section the message names, separating "not
|
|
60
|
+
registered" from "registered but not live", and including a copy-paste payload that
|
|
61
|
+
drives a hook directly so a broken hook can be told apart from an unwired one. (#224)
|
|
62
|
+
|
|
63
|
+
**Release artifacts**
|
|
64
|
+
|
|
65
|
+
- **The published tarball could not be reproduced from its tag.**
|
|
66
|
+
`.mindforge/memory/sync-manifest.json` — gitignored, written at runtime by
|
|
67
|
+
`bin/memory/semantic-hub.js` — was **1 of 1979** shipped files not tracked at
|
|
68
|
+
`v11.9.3`, so provenance attested to a tree containing a file the repository does not
|
|
69
|
+
contain. With a `files[]` allowlist, a **directory** entry ships its contents regardless
|
|
70
|
+
of `.gitignore`; `files[]` already carried a negation for `pattern-library.jsonl` for
|
|
71
|
+
exactly this reason, and the manifest's entire content is the sync record *for that
|
|
72
|
+
already-excluded file*. (#225)
|
|
73
|
+
|
|
74
|
+
- **`mindforge-sdk` is published again, with provenance.** It sat at **11.8.0** on npm
|
|
75
|
+
while `sync-version.js` kept `sdk/package.json` at canonical — seven releases of
|
|
76
|
+
disagreement (11.8.1 through 11.9.3, none published) that nothing detected, because
|
|
77
|
+
`version:check` verifies the tracked file and not what the registry serves. It was also
|
|
78
|
+
the only one of the three packages with **no attestation**. The release workflow now
|
|
79
|
+
publishes it with `--provenance`, after the two proven publishes and before the GitHub
|
|
80
|
+
Release, so the newest step cannot cost the others their artifacts.
|
|
81
|
+
|
|
82
|
+
- **The Homebrew formula carries the real 11.9.3 digest.** Verified against an independent
|
|
83
|
+
measurement rather than the tool's own output, and explicitly confirmed not to be the
|
|
84
|
+
SHA-256 of npm's 21-byte `{"error":"Not found"}` body — the constant #203 used to write
|
|
85
|
+
for every unpublished version. (#223)
|
|
86
|
+
|
|
87
|
+
**Honesty about what is enforced**
|
|
88
|
+
|
|
89
|
+
- **The README understated the product.** "What is actually enforced" still declared that
|
|
90
|
+
**no install channel registers hooks**, with a `No / No` table, and stated that the
|
|
91
|
+
plugin channel's dispatcher crashes on every fire. Measured: the plugin's
|
|
92
|
+
`scripts/lib/` exists, all **14** path tokens in `plugins/mindforge/hooks/hooks.json`
|
|
93
|
+
resolve under the plugin root, and driving the dispatcher by hand returns **exit 2** for
|
|
94
|
+
`mindforge-block-no-verify` and `mindforge-config-protection`. A document that
|
|
95
|
+
under-claims a security capability is the same defect as one that over-claims it —
|
|
96
|
+
either way it describes a system that is not the one shipped. Now stated per channel,
|
|
97
|
+
with the four cases that remain deliberately unenforced and the three liveness
|
|
98
|
+
preconditions outside MindForge's control. (#225)
|
|
99
|
+
|
|
100
|
+
**Defects the published-artifact audit found (#222)**
|
|
101
|
+
|
|
102
|
+
- The **v11.9.3 release page shipped empty**: `changelog-fetcher.js --latest` exits 0
|
|
103
|
+
while writing zero bytes, so the `||` fallback never fired and a 195-line changelog
|
|
104
|
+
reached nobody. The step now prefers the in-tree changelog and fails on an empty body.
|
|
105
|
+
- A **shipped CI snippet told users to `npx` a package we do not own**.
|
|
106
|
+
`npx mindforge …` resolves to an unrelated third-party package; in a fresh runner it is
|
|
107
|
+
fetched and unpacked, install scripts and all, inside a job holding `MINDFORGE_TOKEN`.
|
|
108
|
+
Now pinned with `--package=mindforge-cc`.
|
|
109
|
+
- The **version-source gate missed a live defect twice**. `mindforge health` printed
|
|
110
|
+
`RELEASE v0.4.2` and `Current : v11.9.3` twenty-six lines apart in a project declaring
|
|
111
|
+
0.4.2, and produced `Unexpected end of JSON input` with no manifest at all — the verb
|
|
112
|
+
whose job is verifying installation integrity misreporting the installation. Widening
|
|
113
|
+
the gate surfaced two more of the same shape, one of which bound the **wrong** version
|
|
114
|
+
silently into approval records, which is worse than no binding because the check still
|
|
115
|
+
returns a verdict.
|
|
116
|
+
- `mindforge approve` died with ENOENT on any non-Node project. Absent values are now
|
|
117
|
+
recorded as `null` rather than invented.
|
|
118
|
+
|
|
119
|
+
**Test infrastructure**
|
|
120
|
+
|
|
121
|
+
- `tests/production.test.js` carried the uncommitted diff into its clone with
|
|
122
|
+
`git diff HEAD` (which includes staged files) but committed it with `commit -a` (which
|
|
123
|
+
stages only modified and deleted **tracked** files). So any commit **adding** a file
|
|
124
|
+
under `bin/` or `tests/` left the clone dirty and failed the gate's own cleanliness
|
|
125
|
+
assertion — reintroducing precisely the `--no-verify` pressure that carry exists to
|
|
126
|
+
avoid, for the one case it did not cover.
|
|
127
|
+
|
|
128
|
+
### Added
|
|
129
|
+
|
|
130
|
+
New regression gates, each falsified by reinstating the exact defect and confirming RED,
|
|
131
|
+
with every touched file restored byte-exact afterwards:
|
|
132
|
+
|
|
133
|
+
- `tests/hook-registration-ancestor.test.js` — six properties, the first of which asserts
|
|
134
|
+
the ancestor detector fires at all, so the other five cannot pass by never triggering.
|
|
135
|
+
- `every shipped file is tracked in git` — property-based, no name list. It cannot fail on
|
|
136
|
+
a clean clone, which is how the real leak survived CI, so it is paired with a second
|
|
137
|
+
test that plants the runtime state in a throwaway clone and then packs.
|
|
138
|
+
- `all three published packages publish with provenance` — counts the `npm publish`
|
|
139
|
+
invocations rather than matching one, because a single-match regex was satisfied by
|
|
140
|
+
either of the two packages that already had an attestation while the SDK had none. Also
|
|
141
|
+
asserts the SDK step is idempotent and ordered after the proven publishes.
|
|
142
|
+
|
|
143
|
+
### Notes for operators
|
|
144
|
+
|
|
145
|
+
- **These fixes change installer behaviour on almost every project.** After upgrading,
|
|
146
|
+
check `.mindforge/hook-registration.json` to see what was registered, and restart the
|
|
147
|
+
harness — hooks are snapshotted at session start.
|
|
148
|
+
- A registered hook is only *live* if the harness has been restarted, the project is
|
|
149
|
+
trusted in the harness, and `CLAUDE_PROJECT_DIR` is set with `node` on the hook PATH.
|
|
150
|
+
None of those three are in MindForge's control; the last is a deliberate trade against a
|
|
151
|
+
fail-closed shell tail that was measured denying benign commands on a fresh clone.
|
|
152
|
+
- Two gaps remain that require repository settings rather than code, and are recorded
|
|
153
|
+
rather than claimed fixed: there is no `v*` **tag ruleset** restricting who may create
|
|
154
|
+
the ref that triggers publishing, and `NPM_TOKEN` is a long-lived repository secret with
|
|
155
|
+
no GitHub environment in front of it.
|
|
156
|
+
|
|
3
157
|
## [11.9.3] — 2026-08-21 — Honesty: gates that can fail, commands that run, a release path that is checked
|
|
4
158
|
|
|
5
159
|
Patch release. No new features. Twenty-one fixes, and they all turned out to be the
|
|
@@ -12,6 +166,14 @@ Contains behaviour changes under a patch bump — several of the things being fi
|
|
|
12
166
|
bugs that a consumer could have been relying on. Read BREAKING before upgrading if you
|
|
13
167
|
script against the CLI or the installer.
|
|
14
168
|
|
|
169
|
+
> **Corrected after release.** Three measured numbers in this entry were wrong and are fixed above:
|
|
170
|
+
> the count of places `--status`/`--stop` were documented (removed rather than re-guessed — it reads 4,
|
|
171
|
+
> 9 or 15 depending on how you count, which is the argument against stating it); the eslint total, which
|
|
172
|
+
> was 199 on the author's machine and **190** on a clean clone, because 9 problems came from an
|
|
173
|
+
> untracked local directory; and "four releases behind", which is **three** (11.8.3 → 11.9.0 → 11.9.1 →
|
|
174
|
+
> 11.9.2). Found by an adversarial audit of this changelog against the published artifact. A release
|
|
175
|
+
> arguing that measured numbers should be reproducible has to hold its own notes to that standard.
|
|
176
|
+
|
|
15
177
|
### BREAKING
|
|
16
178
|
|
|
17
179
|
Each of these is a bug fix whose correct behaviour differs from the shipped behaviour.
|
|
@@ -113,15 +275,16 @@ Each of these is a bug fix whose correct behaviour differs from the shipped beha
|
|
|
113
275
|
exactly one event — a `v*` tag push — and the repository's only ruleset targets
|
|
114
276
|
branches, so its six required checks applied to nothing on the path that ships. GitHub
|
|
115
277
|
cannot attach required status checks to a tag. A `preflight` job now gates it. (#216)
|
|
116
|
-
- The `stable` npm dist-tag was moved by hand, or not at all — it sat
|
|
117
|
-
behind `latest` (11.8.3 against 11.9.2), so `npm i mindforge-cc@stable` delivered a
|
|
278
|
+
- The `stable` npm dist-tag was moved by hand, or not at all — it sat three releases
|
|
279
|
+
behind `latest` (11.8.3 against 11.9.2, via 11.9.0 and 11.9.1), so `npm i mindforge-cc@stable` delivered a
|
|
118
280
|
build with none of the 11.9.x fixes. The release workflow now moves it as its final
|
|
119
281
|
step: forward-only, prereleases skipped, and verified against npm's uncached dist-tags
|
|
120
282
|
endpoint rather than the CDN-cached packument. (#216)
|
|
121
283
|
|
|
122
284
|
**Dashboard**
|
|
123
285
|
|
|
124
|
-
- `--status` and `--stop` were documented
|
|
286
|
+
- `--status` and `--stop` were documented across the harness roots and the docs and implemented
|
|
287
|
+
nowhere; both
|
|
125
288
|
printed nothing and exited 0. Now implemented, before `express` is required, so they
|
|
126
289
|
work without the dependency installed. (#206)
|
|
127
290
|
- `--stop` identified the target by the SHAPE of its command line, which matched any
|
|
@@ -141,8 +304,8 @@ Each of these is a bug fix whose correct behaviour differs from the shipped beha
|
|
|
141
304
|
**Verification**
|
|
142
305
|
|
|
143
306
|
- `mindforge verify`'s lint stage used `--max-warnings=0`, which made it impossible to
|
|
144
|
-
pass in the repository it ships from: `npx eslint .` reports
|
|
145
|
-
|
|
307
|
+
pass in the repository it ships from: on a clean clone `npx eslint .` reports 190 problems /
|
|
308
|
+
0 errors / 190 warnings, so `verify` reported a lint FAILURE on a tree that is green by the
|
|
146
309
|
project's own contract. Aligned with the project's definition; errors still fail. (#204)
|
|
147
310
|
- `temporal cleanup` printed "🧹 Cleaning up old temporal snapshots..." and
|
|
148
311
|
"✅ Cleanup complete." with no cleanup between them. Now wired to
|
package/MINDFORGE.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# MINDFORGE.md — Parameter Registry (v11.9.
|
|
1
|
+
# MINDFORGE.md — Parameter Registry (v11.9.4)
|
|
2
2
|
|
|
3
3
|
## 1. IDENTITY & VERSIONING
|
|
4
4
|
|
|
5
5
|
[NAME] = MindForge
|
|
6
|
-
[VERSION] = 11.9.
|
|
6
|
+
[VERSION] = 11.9.4
|
|
7
7
|
[STABLE] = true
|
|
8
8
|
[MODE] = "Platform Sovereign"
|
|
9
9
|
[REQUIRED_CORE_VERSION] = 11.9.1
|
package/README.md
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
## Latest release
|
|
8
8
|
|
|
9
|
-
**v11.9.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
**v11.9.3** (2026-08-21) — Honesty: gates that can fail, commands that run, a release path that is
|
|
10
|
+
checked. Twenty-one fixes sharing one defect — an instrument reporting success while doing nothing:
|
|
11
|
+
a self-install that printed "skipping" and overwrote 149 tracked files, 11 of 27 routed CLI verbs
|
|
12
|
+
dying on `MODULE_NOT_FOUND` in a real install, `--fetch-sha` hashing npm's 404 body into the Homebrew
|
|
13
|
+
formula, no version channel covering any document a user receives, and a publish path no check ever
|
|
14
|
+
touched. **Contains behaviour changes under a patch bump** — several fixed bugs whose correct
|
|
15
|
+
behaviour differs from what shipped. See the BREAKING section in
|
|
16
|
+
[CHANGELOG.md](./CHANGELOG.md), or [RELEASENOTES.md](./RELEASENOTES.md) for human-readable notes.
|
|
14
17
|
|
|
15
18
|
---
|
|
16
19
|
|
|
@@ -19,7 +22,8 @@ human-readable notes.
|
|
|
19
22
|
Read this before the install instructions. MindForge ships a large corpus of agent
|
|
20
23
|
instructions — commands, skills, personas, protocols — and those are advisory: they work by
|
|
21
24
|
being in the model's context, and a model can decline them. The parts that would *block* an
|
|
22
|
-
action are hooks
|
|
25
|
+
action are hooks. Through 11.9.2 **no channel registered them**; as of 11.9.3 both channels
|
|
26
|
+
register and execute them **on Claude Code**, and nowhere else.
|
|
23
27
|
|
|
24
28
|
| Capability | Plugin channel | `npx` channel |
|
|
25
29
|
|---|---|---|
|
|
@@ -27,34 +31,48 @@ action are hooks, and **no install channel currently registers them.**
|
|
|
27
31
|
| Skills / personas / protocol docs | Yes | Yes |
|
|
28
32
|
| Subagents | Yes | Yes |
|
|
29
33
|
| Audit hash-chain (`bin/verify-audit.js`) | Yes | Yes |
|
|
30
|
-
| **Hooks enforced (can block a tool call)** | **
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- **
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`plugins/mindforge/scripts/lib/`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
| **Hooks enforced (can block a tool call)** | **Claude Code only** | **Claude Code + `--local` only** |
|
|
35
|
+
|
|
36
|
+
What that means, measured rather than asserted:
|
|
37
|
+
|
|
38
|
+
- **The `npx` channel generates the config it never used to ship.** `files[]` has 49 entries and
|
|
39
|
+
none of them contains `settings`, so no settings file is *published* — instead
|
|
40
|
+
`bin/installer/hook-registration.js` writes one at install time, merging append-only into any
|
|
41
|
+
file you already have. Measured on a confined install: **8 hooks registered** into
|
|
42
|
+
`.claude/settings.json`, of which the installer's own preflight **executed 7 and verified all 3
|
|
43
|
+
deny-class hooks returning exit 2** before keeping the file. A preflight failure rolls the
|
|
44
|
+
registration back rather than leaving a config whose commands do not run.
|
|
45
|
+
- **The plugin channel's dispatcher runs.** It previously crashed on every fire —
|
|
46
|
+
`run-with-flags.js` requires `./lib/hook-flags` and `plugins/mindforge/scripts/lib/` was not
|
|
47
|
+
copied in. That directory now exists, all **14 path tokens** in
|
|
48
|
+
`plugins/mindforge/hooks/hooks.json` resolve under the plugin root, and driving the dispatcher by
|
|
49
|
+
hand returns **exit 2** for `mindforge-block-no-verify` and `mindforge-config-protection`.
|
|
50
|
+
|
|
51
|
+
Still **not** enforced, deliberately and with a printed reason for each: any runtime other than
|
|
52
|
+
Claude Code (Cursor, Copilot, Gemini/Antigravity, OpenCode), `--global` scope, a self-install
|
|
53
|
+
inside a MindForge checkout, and Windows. Writing a Claude-schema config into `.cursor/` without an
|
|
54
|
+
execution-verified hook contract would be decorative. Every outcome, including "not registered", is
|
|
55
|
+
printed by the installer and written to `.mindforge/hook-registration.json`.
|
|
56
|
+
|
|
57
|
+
Three things gate whether a registered hook is *live*, none of them in MindForge's control: the
|
|
58
|
+
harness must be **restarted** (hooks are snapshotted at session start), the project must be
|
|
59
|
+
**trusted** in the harness, and `CLAUDE_PROJECT_DIR` must be set with `node` on the hook PATH —
|
|
60
|
+
if it is not, the commands exit 1 and the gate is simply absent, which is a deliberate trade
|
|
61
|
+
against a fail-closed tail that was measured denying benign commands on a fresh clone. See
|
|
62
|
+
*Hooks are installed but nothing is blocked* in `docs/troubleshooting.md`.
|
|
63
|
+
|
|
64
|
+
So: on Claude Code, treat MindForge as a policy enforcement point for the 8 registered hooks plus
|
|
65
|
+
a tamper-evident audit log; on every other harness, as **governance-by-convention** plus that same
|
|
66
|
+
audit log. Installing it also expands your repository's trust boundary by a large volume of agent
|
|
67
|
+
instructions — review what you install. The audit chain is verifiable today
|
|
50
68
|
(`node bin/verify-audit.js`).
|
|
51
69
|
|
|
52
70
|
---
|
|
53
71
|
|
|
54
72
|
## Install
|
|
55
73
|
|
|
56
|
-
Claude Code plugin marketplace (no project files written).
|
|
57
|
-
|
|
74
|
+
Claude Code plugin marketplace (no project files written). The plugin's hooks now fire — see
|
|
75
|
+
*What is actually enforced* above for what that does and does not cover.
|
|
58
76
|
|
|
59
77
|
```bash
|
|
60
78
|
/plugin marketplace add sairam0424/MindForge
|
package/RELEASENOTES.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## v11.9.3 — 2026-08-21 — Honesty: gates that can fail, commands that run, a release path that is checked
|
|
4
|
+
|
|
5
|
+
### What's New
|
|
6
|
+
Nothing. Twenty-one fixes sharing a single defect: **an instrument reported success while doing
|
|
7
|
+
nothing.** Gates that could not fail, tests a comment satisfied, docs naming scripts that do not
|
|
8
|
+
exist, commands printing success while performing no action, and a publish path no check ever
|
|
9
|
+
touched.
|
|
10
|
+
|
|
11
|
+
### ⚠️ Breaking (under a patch bump)
|
|
12
|
+
Six behaviour changes, each a bug fix whose correct behaviour differs from what shipped. Read these
|
|
13
|
+
if you script against the CLI or the installer.
|
|
14
|
+
|
|
15
|
+
- **Routed CLI commands now act on YOUR project, not MindForge's checkout.** The router passed
|
|
16
|
+
`cwd: ROOT`, so `mindforge classify` diffed MindForge's repository instead of yours and
|
|
17
|
+
`mindforge health` inspected MindForge's `node_modules`. Of 27 routed commands, 7 changed
|
|
18
|
+
behaviour — all in the correct direction.
|
|
19
|
+
- **`npx mindforge-cc install`, and any other positional argument, now exits 1.** The installer
|
|
20
|
+
takes flags only and used to ignore stray words silently, so that command appeared to work while
|
|
21
|
+
configuring nothing. Use `npx mindforge-cc --claude --local`.
|
|
22
|
+
- **`mindforge verify` now SKIPS unavailable stages instead of failing them.** A project with no
|
|
23
|
+
ESLint config or no test script was reported as FAILING those stages rather than as not having
|
|
24
|
+
them. CI that relied on a non-zero exit there will now pass. A run where every stage skipped
|
|
25
|
+
prints a "NOTHING WAS VERIFIED" banner rather than a clean bill of health.
|
|
26
|
+
- **`scripts/sync-version.js` now exits non-zero when the plugin build artifacts are stale.** A bump
|
|
27
|
+
used to report success and exit 0 while leaving `npm test` red.
|
|
28
|
+
- **A self-install no longer writes over your tracked files.** Running the installer inside a
|
|
29
|
+
MindForge checkout printed that it was skipping and then overwrote 149 tracked files, including
|
|
30
|
+
`CLAUDE.md`, `.claude/**`, `.agent/**` and `.mindforge/**`.
|
|
31
|
+
- **Releases must be tagged on a commit reachable from `main`.**
|
|
32
|
+
|
|
33
|
+
### Fixes
|
|
34
|
+
- **11 of 27 routed CLI verbs died on `MODULE_NOT_FOUND` in a real install.** The router shipped;
|
|
35
|
+
six of the scripts it dispatches to did not.
|
|
36
|
+
- **Every `--global` install reported failure on a correct run.** Verification demanded six `bin/**`
|
|
37
|
+
paths regardless of scope, so a global install — which writes 389 files to `$HOME/.claude` and,
|
|
38
|
+
deliberately, zero to `bin/` — ended `6 of 12 required file(s) missing` and exit 1, with a
|
|
39
|
+
`--force` retry that could not help.
|
|
40
|
+
- **`--fetch-sha` hashed npm's 404 error body into the Homebrew formula.** For an unpublished
|
|
41
|
+
version the registry answers `{"error":"Not found"}` and `curl -sL` exits 0, so the digest written
|
|
42
|
+
was the SHA-256 of that error text — the same constant for every unpublished version — and
|
|
43
|
+
`--check` then passed. It now fails closed on both status and gzip magic bytes.
|
|
44
|
+
- **No version channel covered a document a user receives.** `SECURITY.md` — the security policy at
|
|
45
|
+
the root of the published package — said "Current version: 11.9.0", and five docs titled
|
|
46
|
+
themselves v11.9.0: three releases stale while every npm manifest was correct. A channel that does
|
|
47
|
+
not exist cannot drift, so `--check` was green the whole time.
|
|
48
|
+
- **The tag push that publishes was exempt from every gate.** Publishing is triggered by exactly one
|
|
49
|
+
event — a `v*` tag push — and the repository's only ruleset targets branches, so its six required
|
|
50
|
+
checks applied to nothing on the path that ships. GitHub cannot attach required status checks to a
|
|
51
|
+
tag, so this had to be fixed in the workflow itself.
|
|
52
|
+
- **The `stable` dist-tag sat three releases behind `latest`** (11.8.3 against 11.9.2), so
|
|
53
|
+
`npm i mindforge-cc@stable` delivered a build with none of the 11.9.x fixes. The release workflow
|
|
54
|
+
now moves it as its final step — forward-only, prereleases skipped.
|
|
55
|
+
- **`mindforge dashboard --status` and `--stop` were documented and implemented nowhere.** Both
|
|
56
|
+
printed nothing useful. `--stop` also identified its target by the SHAPE of a command line, which
|
|
57
|
+
matched any `node <anything>/dashboard/server.js` — verified against an unrelated app's dashboard.
|
|
58
|
+
- **`temporal cleanup` printed "Cleaning up…" and "Cleanup complete." with no cleanup between them.**
|
|
59
|
+
- **The protocol files instructed the agent to run scripts that do not exist** (`soul-engine.js`,
|
|
60
|
+
`shard-controller.js`), and 15 phantom `/mindforge:` slash commands appeared in shipped docs. A
|
|
61
|
+
reader following the user guide typed `/mindforge:personas --list` and got nothing.
|
|
62
|
+
- **Every abandoned exit left a full copy of the database on disk** — 1.8 GB of orphaned `.tmp` files.
|
|
63
|
+
|
|
64
|
+
Full detail, including the measured evidence for each: [changelogs/v11.9.3.md](./changelogs/v11.9.3.md).
|
|
65
|
+
|
|
3
66
|
## v11.9.2 — 2026-08-16 — Correctness: config gate, audit chain, retrieval, cost ledger
|
|
4
67
|
|
|
5
68
|
### What's New
|
package/SECURITY.md
CHANGED
|
@@ -210,7 +210,12 @@ function getApprovals() {
|
|
|
210
210
|
const { verifyRecord } = require('../governance/approval-record');
|
|
211
211
|
let currentVersion = null;
|
|
212
212
|
try {
|
|
213
|
-
|
|
213
|
+
// MindForge's version, resolved by package NAME. `path.join(__dirname, '..', '..',
|
|
214
|
+
// 'package.json')` reached <project>/package.json in an install — the CONSUMER's manifest — so
|
|
215
|
+
// verifyRecord() below compared an approval record against the host app's version (0.4.2, say)
|
|
216
|
+
// instead of MindForge's. The try/catch stopped it crashing, which is why it went unnoticed:
|
|
217
|
+
// a wrong binding is quieter than a missing one.
|
|
218
|
+
currentVersion = require('../utils/mindforge-version').resolveMindforgeVersion(process.cwd()).version;
|
|
214
219
|
} catch { /* version binding is skipped if the manifest is unreadable */ }
|
|
215
220
|
|
|
216
221
|
const now = Date.now();
|
|
@@ -80,7 +80,18 @@ function approve(opts = {}) {
|
|
|
80
80
|
const root = opts.root || ROOT;
|
|
81
81
|
const approvalsDir = opts.approvalsDir || APPROVALS_DIR;
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
// TOLERATES A PROJECT WITH NO package.json. This was an unguarded readFileSync, so `mindforge approve`
|
|
84
|
+
// died with `ENOENT: no such file or directory, open '<project>/package.json'` on any repo that is not
|
|
85
|
+
// Node — Python, Go, Rust, or any polyglot root. Measured on the published 11.9.3 tarball.
|
|
86
|
+
//
|
|
87
|
+
// The FIELDS stay the consumer's on purpose: this record documents a governance decision in the
|
|
88
|
+
// user's project, so `project` and `version` describing that project is correct. Only the crash was
|
|
89
|
+
// wrong. Absent values are recorded as null rather than invented — an approval record that guesses
|
|
90
|
+
// what it is approving is worse than one that admits it does not know.
|
|
91
|
+
const pkg = (() => {
|
|
92
|
+
try { return JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')); }
|
|
93
|
+
catch { return { name: path.basename(root) || null, version: null }; }
|
|
94
|
+
})();
|
|
84
95
|
|
|
85
96
|
const id = `MF-AUTH-${Date.now().toString(36).toUpperCase()}`;
|
|
86
97
|
const timestamp = new Date().toISOString();
|
|
@@ -72,7 +72,19 @@ function summary(lines) {
|
|
|
72
72
|
|
|
73
73
|
function main(argv = process.argv.slice(2)) {
|
|
74
74
|
const args = parseArgs(argv);
|
|
75
|
-
|
|
75
|
+
// MindForge's version, by package NAME. This read `path.join(ROOT, 'package.json')`, which in an
|
|
76
|
+
// install is the CONSUMER's manifest — so every approval record was verified against the host
|
|
77
|
+
// app's version rather than MindForge's, and the command died with ENOENT on any project without
|
|
78
|
+
// a package.json at all. Version binding is the point of the record; binding it to the wrong
|
|
79
|
+
// version is worse than not binding it, because the check still reports a verdict.
|
|
80
|
+
//
|
|
81
|
+
// Degrades to null rather than throwing: an unresolvable version should make the binding
|
|
82
|
+
// unverifiable, not make the whole verification unrunnable. verifyRecord treats a null
|
|
83
|
+
// currentVersion as "do not check the binding".
|
|
84
|
+
let currentVersion = null;
|
|
85
|
+
try {
|
|
86
|
+
currentVersion = require('../utils/mindforge-version').resolveMindforgeVersion(process.cwd()).version;
|
|
87
|
+
} catch { /* binding unverifiable, reported as such rather than crashing the run */ }
|
|
76
88
|
|
|
77
89
|
let files = [];
|
|
78
90
|
try {
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
*/
|
|
61
61
|
|
|
62
62
|
const fs = require('node:fs');
|
|
63
|
+
const os = require('node:os');
|
|
63
64
|
const path = require('node:path');
|
|
64
65
|
const { spawnSync } = require('node:child_process');
|
|
65
66
|
|
|
@@ -366,14 +367,48 @@ function probeInner(projectRoot, failures) {
|
|
|
366
367
|
|
|
367
368
|
// ── register ─────────────────────────────────────────────────────────────────
|
|
368
369
|
|
|
369
|
-
/**
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
370
|
+
/**
|
|
371
|
+
* An ancestor project whose OWN .claude/settings.json a harness launched there would read instead of
|
|
372
|
+
* ours. Advisory only — see the three corrections below. Returns the directory, or null.
|
|
373
|
+
*
|
|
374
|
+
* THIS USED TO SKIP REGISTRATION ENTIRELY, and the reason it printed was wrong in three ways:
|
|
375
|
+
*
|
|
376
|
+
* "the harness will read <ancestor>/.claude/settings.json, not this directory"
|
|
377
|
+
*
|
|
378
|
+
* 1. IT TRIPPED ON $HOME, so it tripped for essentially every project. ~/.claude/settings.json is the
|
|
379
|
+
* USER TIER: Claude Code applies it to every session IN ADDITION TO the project tier, not instead
|
|
380
|
+
* of it. Its existence says nothing about whether a project file is read. Measured on the author's
|
|
381
|
+
* machine: the user-tier hooks fire on every Bash call while a project settings.json sits below
|
|
382
|
+
* them. So the condition that suppressed the gates was satisfied by the normal state of a laptop.
|
|
383
|
+
*
|
|
384
|
+
* 2. FOR A REAL PROJECT ANCESTOR THE CLAIM IS ALSO FALSE — the ancestor's file is not read either.
|
|
385
|
+
* Measured with a natural experiment: an ancestor two levels up carried a PreToolUse Bash hook
|
|
386
|
+
* appending a marker to a log file. Across a dozen Bash calls with the inner directory as the
|
|
387
|
+
* project root, that log was never even created. Claude Code reads the project tier from the
|
|
388
|
+
* directory it treats as the project root; it does not walk up for settings. So skipping did not
|
|
389
|
+
* deliver the gates "over there", it delivered them nowhere.
|
|
390
|
+
*
|
|
391
|
+
* 3. THE GIT-BOUNDARY GUARD WAS DEAD CODE. `stop` was the git toplevel, but the walk started at
|
|
392
|
+
* path.dirname(projectRoot) — so when toplevel === projectRoot (the normal case) `dir === stop`
|
|
393
|
+
* could never be true and the walk ran to the filesystem root every time. The boundary that was
|
|
394
|
+
* supposed to keep this local is why it reached $HOME.
|
|
395
|
+
*
|
|
396
|
+
* So: WARN, NEVER SKIP. A registration that turns out to be inert costs nothing and becomes live the
|
|
397
|
+
* moment the harness is launched here; a skip is guaranteed inert. Two narrowings keep the warning
|
|
398
|
+
* meaningful rather than universal: $HOME is excluded because it is a tier and not a shadow, and an
|
|
399
|
+
* actual settings.json FILE must exist — the old check accepted any directory named .claude, of which
|
|
400
|
+
* a docs folder is a perfectly ordinary example.
|
|
401
|
+
*
|
|
402
|
+
* The git boundary is deliberately not repaired, just removed: a git toplevel ABOVE projectRoot means
|
|
403
|
+
* this project is nested inside another repo, which is exactly the case worth warning about, so
|
|
404
|
+
* stopping the walk there would suppress the one signal this function exists to produce.
|
|
405
|
+
*/
|
|
406
|
+
function shadowingProjectSettings(projectRoot) {
|
|
407
|
+
const home = os.homedir();
|
|
373
408
|
let dir = path.dirname(path.resolve(projectRoot));
|
|
374
409
|
for (let i = 0; i < 64; i++) {
|
|
375
|
-
if (fs.existsSync(path.join(dir,
|
|
376
|
-
if (dir ===
|
|
410
|
+
if (dir !== home && fs.existsSync(path.join(dir, SETTINGS_REL))) return dir;
|
|
411
|
+
if (dir === path.dirname(dir)) break;
|
|
377
412
|
dir = path.dirname(dir);
|
|
378
413
|
}
|
|
379
414
|
return null;
|
|
@@ -391,10 +426,15 @@ function register(options = {}) {
|
|
|
391
426
|
if (selfInstall) return skip('self-install: the repo maintains its own tracked .claude/settings.json');
|
|
392
427
|
if (process.platform === 'win32') return skip('win32 is unverified for the emitted command shape');
|
|
393
428
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
429
|
+
// Advisory, deliberately not a skip — see shadowingProjectSettings for the three measurements that
|
|
430
|
+
// demoted it from one. The operator is told what to do about it; the gates still get installed.
|
|
431
|
+
const shadow = shadowingProjectSettings(projectRoot);
|
|
432
|
+
const warnings = shadow
|
|
433
|
+
? [`${path.join(shadow, SETTINGS_REL)} exists in an ancestor project. These hooks are registered `
|
|
434
|
+
+ 'for THIS directory and are live when the harness runs with it as the project root. If you '
|
|
435
|
+
+ `launch the harness in ${shadow} instead, run the installer there too — its project settings `
|
|
436
|
+
+ 'are read from where it starts, not walked up from.']
|
|
437
|
+
: [];
|
|
398
438
|
|
|
399
439
|
const copy = applyCopyManifest(projectRoot, repoRoot);
|
|
400
440
|
if (!copy.ok) return skip(copy.reason);
|
|
@@ -424,7 +464,7 @@ function register(options = {}) {
|
|
|
424
464
|
|
|
425
465
|
const text = `${JSON.stringify(merged.next, null, 2)}\n`;
|
|
426
466
|
if (dryRun) {
|
|
427
|
-
return { status: 'dry-run', reason: `would write ${HOOK_SPEC.length} hooks to ${SETTINGS_REL}`, registered: false, preview: text };
|
|
467
|
+
return { status: 'dry-run', reason: `would write ${HOOK_SPEC.length} hooks to ${SETTINGS_REL}`, registered: false, preview: text, warnings };
|
|
428
468
|
}
|
|
429
469
|
|
|
430
470
|
const existedBefore = fs.existsSync(absSettings);
|
|
@@ -452,6 +492,7 @@ function register(options = {}) {
|
|
|
452
492
|
preflight_skipped: verified.skipped,
|
|
453
493
|
preflight_skip_reason: 'registered but not executed during preflight: spawns a background '
|
|
454
494
|
+ 'process and writes under $HOME. Advisory, so a failure there would not have blocked.',
|
|
495
|
+
warnings,
|
|
455
496
|
residual_risk: 'CLAUDE_PROJECT_DIR unset, or node off the hook PATH, yields exit 1 and the gate is '
|
|
456
497
|
+ 'absent (identical to not installing). No fail-closed shell tail is used: measured, it denies '
|
|
457
498
|
+ 'benign commands on a fresh clone.',
|
|
@@ -466,6 +507,7 @@ function register(options = {}) {
|
|
|
466
507
|
target: SETTINGS_REL,
|
|
467
508
|
backup: receipt.backup,
|
|
468
509
|
receipt: RECEIPT_REL,
|
|
510
|
+
warnings,
|
|
469
511
|
};
|
|
470
512
|
}
|
|
471
513
|
|
|
@@ -500,5 +542,6 @@ module.exports = {
|
|
|
500
542
|
DENY_CLASS, OWNED_RE, KNOWN_IDS,
|
|
501
543
|
commandFor, profilesFor, isOwned,
|
|
502
544
|
applyCopyManifest, mergeSettings, assertNoLoss, probe,
|
|
545
|
+
shadowingProjectSettings,
|
|
503
546
|
register, unregister,
|
|
504
547
|
};
|
package/bin/installer-core.js
CHANGED
|
@@ -1152,7 +1152,15 @@ async function install(runtime, scope, options = {}) {
|
|
|
1152
1152
|
} else {
|
|
1153
1153
|
Theme.printStatus(c.yellow(`Hooks NOT registered (${hookRegistration.status}): ${hookRegistration.reason}`), 'warn');
|
|
1154
1154
|
Theme.printStatus(c.dim('The hook scripts are installed but nothing invokes them, so no tool call '
|
|
1155
|
-
+ 'is gated. This is stated rather than implied — see
|
|
1155
|
+
+ 'is gated. This is stated rather than implied — see "Hooks are installed but nothing is '
|
|
1156
|
+
+ 'blocked" in docs/troubleshooting.md.'), 'info');
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
// Non-fatal advisories. Printed for BOTH outcomes, because the case that produces one today —
|
|
1160
|
+
// an ancestor project with its own settings.json — used to CANCEL registration outright, and the
|
|
1161
|
+
// whole point of demoting it to a warning is that the operator hears it without losing the gates.
|
|
1162
|
+
for (const w of hookRegistration.warnings || []) {
|
|
1163
|
+
Theme.printStatus(c.yellow(w), 'warn');
|
|
1156
1164
|
}
|
|
1157
1165
|
}
|
|
1158
1166
|
|
|
@@ -1297,11 +1305,31 @@ async function run(args) {
|
|
|
1297
1305
|
const options = { dryRun, force, verbose, withUtils, minimal };
|
|
1298
1306
|
|
|
1299
1307
|
// Get package.json for version
|
|
1300
|
-
|
|
1308
|
+
// MINDFORGE'S VERSION, NOT THE HOST PROJECT'S — and it must not crash when there is no manifest.
|
|
1309
|
+
//
|
|
1310
|
+
// This read was `JSON.parse(fsu.read(path.join(SOURCE_ROOT, 'package.json')))`, and SOURCE_ROOT is
|
|
1311
|
+
// path.resolve(__dirname, '..'). In an install that lands at <project>/bin/, so it read the CONSUMER's
|
|
1312
|
+
// package.json. Measured on the published 11.9.3 tarball: in a project declaring version 0.4.2,
|
|
1313
|
+
// `mindforge health` printed the banner `RELEASE v0.4.2` and then, 26 lines later, `Current : v11.9.3`
|
|
1314
|
+
// — one command, two contradictory versions, exit 0. In a project with NO package.json the whole
|
|
1315
|
+
// command was `Unexpected end of JSON input`, exit 1, no report at all: fsu.read returns empty for a
|
|
1316
|
+
// missing file and JSON.parse throws.
|
|
1317
|
+
//
|
|
1318
|
+
// This is the same defect 11.9.3 fixed for `--version`, in the one verb whose advertised job is
|
|
1319
|
+
// "verify project health and installation integrity". bin/utils/mindforge-version.js already resolves
|
|
1320
|
+
// correctly — by package NAME, which is what distinguishes our manifest from a consumer's — and it
|
|
1321
|
+
// shipped in the same release. It simply was not used here.
|
|
1322
|
+
//
|
|
1323
|
+
// It THROWS rather than guessing, which is right for a version check and wrong for a banner, so the
|
|
1324
|
+
// banner degrades to 'unknown' instead of taking the whole health report down with it.
|
|
1325
|
+
let bannerVersion = 'unknown';
|
|
1326
|
+
try {
|
|
1327
|
+
bannerVersion = require('./utils/mindforge-version').resolveMindforgeVersion(process.cwd()).version;
|
|
1328
|
+
} catch { /* a banner must never be the reason health cannot run */ }
|
|
1301
1329
|
|
|
1302
1330
|
// Print header and brand manifest
|
|
1303
1331
|
// Print header and brand manifest
|
|
1304
|
-
Theme.printHeader(
|
|
1332
|
+
Theme.printHeader(bannerVersion);
|
|
1305
1333
|
Theme.printBrandManifest();
|
|
1306
1334
|
// Check for updates only
|
|
1307
1335
|
if (isCheck) {
|
package/changelogs/v11.9.3.md
CHANGED
|
@@ -12,6 +12,14 @@ Contains behaviour changes under a patch bump — several of the things being fi
|
|
|
12
12
|
bugs that a consumer could have been relying on. Read BREAKING before upgrading if you
|
|
13
13
|
script against the CLI or the installer.
|
|
14
14
|
|
|
15
|
+
> **Corrected after release.** Three measured numbers in this entry were wrong and are fixed above:
|
|
16
|
+
> the count of places `--status`/`--stop` were documented (removed rather than re-guessed — it reads 4,
|
|
17
|
+
> 9 or 15 depending on how you count, which is the argument against stating it); the eslint total, which
|
|
18
|
+
> was 199 on the author's machine and **190** on a clean clone, because 9 problems came from an
|
|
19
|
+
> untracked local directory; and "four releases behind", which is **three** (11.8.3 → 11.9.0 → 11.9.1 →
|
|
20
|
+
> 11.9.2). Found by an adversarial audit of this changelog against the published artifact. A release
|
|
21
|
+
> arguing that measured numbers should be reproducible has to hold its own notes to that standard.
|
|
22
|
+
|
|
15
23
|
### BREAKING
|
|
16
24
|
|
|
17
25
|
Each of these is a bug fix whose correct behaviour differs from the shipped behaviour.
|
|
@@ -113,15 +121,16 @@ Each of these is a bug fix whose correct behaviour differs from the shipped beha
|
|
|
113
121
|
exactly one event — a `v*` tag push — and the repository's only ruleset targets
|
|
114
122
|
branches, so its six required checks applied to nothing on the path that ships. GitHub
|
|
115
123
|
cannot attach required status checks to a tag. A `preflight` job now gates it. (#216)
|
|
116
|
-
- The `stable` npm dist-tag was moved by hand, or not at all — it sat
|
|
117
|
-
behind `latest` (11.8.3 against 11.9.2), so `npm i mindforge-cc@stable` delivered a
|
|
124
|
+
- The `stable` npm dist-tag was moved by hand, or not at all — it sat three releases
|
|
125
|
+
behind `latest` (11.8.3 against 11.9.2, via 11.9.0 and 11.9.1), so `npm i mindforge-cc@stable` delivered a
|
|
118
126
|
build with none of the 11.9.x fixes. The release workflow now moves it as its final
|
|
119
127
|
step: forward-only, prereleases skipped, and verified against npm's uncached dist-tags
|
|
120
128
|
endpoint rather than the CDN-cached packument. (#216)
|
|
121
129
|
|
|
122
130
|
**Dashboard**
|
|
123
131
|
|
|
124
|
-
- `--status` and `--stop` were documented
|
|
132
|
+
- `--status` and `--stop` were documented across the harness roots and the docs and implemented
|
|
133
|
+
nowhere; both
|
|
125
134
|
printed nothing and exited 0. Now implemented, before `express` is required, so they
|
|
126
135
|
work without the dependency installed. (#206)
|
|
127
136
|
- `--stop` identified the target by the SHAPE of its command line, which matched any
|
|
@@ -141,8 +150,8 @@ Each of these is a bug fix whose correct behaviour differs from the shipped beha
|
|
|
141
150
|
**Verification**
|
|
142
151
|
|
|
143
152
|
- `mindforge verify`'s lint stage used `--max-warnings=0`, which made it impossible to
|
|
144
|
-
pass in the repository it ships from: `npx eslint .` reports
|
|
145
|
-
|
|
153
|
+
pass in the repository it ships from: on a clean clone `npx eslint .` reports 190 problems /
|
|
154
|
+
0 errors / 190 warnings, so `verify` reported a lint FAILURE on a tree that is green by the
|
|
146
155
|
project's own contract. Aligned with the project's definition; errors still fail. (#204)
|
|
147
156
|
- `temporal cleanup` printed "🧹 Cleaning up old temporal snapshots..." and
|
|
148
157
|
"✅ Cleanup complete." with no cleanup between them. Now wired to
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [11.9.4] — 2026-08-22 — Delivery: the gates register, the tarball matches its tag, three packages attested
|
|
4
|
+
|
|
5
|
+
Patch release. 11.9.3 argued that an instrument must not report success while doing
|
|
6
|
+
nothing. 11.9.4 is what an adversarial audit of the **published** 11.9.3 artifact found
|
|
7
|
+
when that standard was applied to the delivery itself: **enforcement that installed and
|
|
8
|
+
then declined to register, a tarball that could not be reproduced from its own tag, and a
|
|
9
|
+
README that understated what shipped.**
|
|
10
|
+
|
|
11
|
+
Every finding here came from measuring the published package in a confined environment —
|
|
12
|
+
not from reading the repository. That distinction is the whole content of this release.
|
|
13
|
+
|
|
14
|
+
### BREAKING
|
|
15
|
+
|
|
16
|
+
- **The installer now registers hooks on projects where it previously declined.** If you
|
|
17
|
+
install into a project that has an ancestor directory containing a `.claude`, MindForge
|
|
18
|
+
now writes `.claude/settings.json` (merging append-only into any existing file) instead
|
|
19
|
+
of skipping. On a machine that has ever run Claude Code, `~/.claude` makes that
|
|
20
|
+
essentially every project — so most installs go from **0 registered hooks to 8**. Three
|
|
21
|
+
of them can block a tool call. If you were relying on the installer being inert here,
|
|
22
|
+
it no longer is; `.mindforge/hook-registration.json` records exactly what was written,
|
|
23
|
+
and the previous settings file is backed up under `.mindforge/backups/`. (#224)
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
**Hook registration — the gates shipped installed but inert**
|
|
28
|
+
|
|
29
|
+
- **`register()` skipped whenever any ancestor held a `.claude` directory.** Measured
|
|
30
|
+
against the published 11.9.3 tarball, confined HOME, `~/.claude` as the only ancestor:
|
|
31
|
+
**11 hook scripts installed, 0 registered, no settings file written.** The gates that
|
|
32
|
+
the shipped `CLAUDE.md` calls MANDATORY were copied in and left unreachable. Same
|
|
33
|
+
sandbox on 11.9.4: **8 registered, installer preflight executed 7 of 8 and verified all
|
|
34
|
+
3 deny-class hooks returning exit 2** before keeping the file. (#224)
|
|
35
|
+
|
|
36
|
+
The reason it printed — *"the harness will read `<ancestor>/.claude/settings.json`, not
|
|
37
|
+
this directory"* — was wrong three separate ways:
|
|
38
|
+
|
|
39
|
+
1. `~/.claude/settings.json` is the **user tier**, applied in addition to the project
|
|
40
|
+
tier. Its existence carries no information about whether a project file is read, so
|
|
41
|
+
the condition that suppressed the gates was satisfied by an ordinary laptop.
|
|
42
|
+
2. For a genuine project ancestor the claim is false too — that file is not read
|
|
43
|
+
either. Verified with a natural experiment: an ancestor two levels up carried a
|
|
44
|
+
`PreToolUse` Bash hook appending a marker to a log; across a dozen tool calls with
|
|
45
|
+
the inner directory as the project root, the log was never created. Skipping did not
|
|
46
|
+
deliver the gates elsewhere. It delivered them nowhere.
|
|
47
|
+
3. The git-boundary guard was **dead code**. `stop` was the git toplevel while the walk
|
|
48
|
+
began at `dirname(projectRoot)`, so when toplevel equalled projectRoot the stop
|
|
49
|
+
condition could never be true and the walk ran to the filesystem root every time.
|
|
50
|
+
The boundary meant to keep the check local is why it reached `$HOME`.
|
|
51
|
+
|
|
52
|
+
It now warns and registers anyway: a registration that turns out inert costs nothing and
|
|
53
|
+
becomes live when the harness is launched there, whereas a skip is guaranteed inert. The
|
|
54
|
+
check additionally requires a real `settings.json` **file** — the old one accepted any
|
|
55
|
+
directory named `.claude`, and the one it hit in practice held only markdown. (#224)
|
|
56
|
+
|
|
57
|
+
- **The installer's only failure-path pointer led nowhere.** It told anyone whose hooks
|
|
58
|
+
were not registered to "see `docs/troubleshooting.md`", where the word *hook* appeared
|
|
59
|
+
**0** times. That file now carries the section the message names, separating "not
|
|
60
|
+
registered" from "registered but not live", and including a copy-paste payload that
|
|
61
|
+
drives a hook directly so a broken hook can be told apart from an unwired one. (#224)
|
|
62
|
+
|
|
63
|
+
**Release artifacts**
|
|
64
|
+
|
|
65
|
+
- **The published tarball could not be reproduced from its tag.**
|
|
66
|
+
`.mindforge/memory/sync-manifest.json` — gitignored, written at runtime by
|
|
67
|
+
`bin/memory/semantic-hub.js` — was **1 of 1979** shipped files not tracked at
|
|
68
|
+
`v11.9.3`, so provenance attested to a tree containing a file the repository does not
|
|
69
|
+
contain. With a `files[]` allowlist, a **directory** entry ships its contents regardless
|
|
70
|
+
of `.gitignore`; `files[]` already carried a negation for `pattern-library.jsonl` for
|
|
71
|
+
exactly this reason, and the manifest's entire content is the sync record *for that
|
|
72
|
+
already-excluded file*. (#225)
|
|
73
|
+
|
|
74
|
+
- **`mindforge-sdk` is published again, with provenance.** It sat at **11.8.0** on npm
|
|
75
|
+
while `sync-version.js` kept `sdk/package.json` at canonical — seven releases of
|
|
76
|
+
disagreement (11.8.1 through 11.9.3, none published) that nothing detected, because
|
|
77
|
+
`version:check` verifies the tracked file and not what the registry serves. It was also
|
|
78
|
+
the only one of the three packages with **no attestation**. The release workflow now
|
|
79
|
+
publishes it with `--provenance`, after the two proven publishes and before the GitHub
|
|
80
|
+
Release, so the newest step cannot cost the others their artifacts.
|
|
81
|
+
|
|
82
|
+
- **The Homebrew formula carries the real 11.9.3 digest.** Verified against an independent
|
|
83
|
+
measurement rather than the tool's own output, and explicitly confirmed not to be the
|
|
84
|
+
SHA-256 of npm's 21-byte `{"error":"Not found"}` body — the constant #203 used to write
|
|
85
|
+
for every unpublished version. (#223)
|
|
86
|
+
|
|
87
|
+
**Honesty about what is enforced**
|
|
88
|
+
|
|
89
|
+
- **The README understated the product.** "What is actually enforced" still declared that
|
|
90
|
+
**no install channel registers hooks**, with a `No / No` table, and stated that the
|
|
91
|
+
plugin channel's dispatcher crashes on every fire. Measured: the plugin's
|
|
92
|
+
`scripts/lib/` exists, all **14** path tokens in `plugins/mindforge/hooks/hooks.json`
|
|
93
|
+
resolve under the plugin root, and driving the dispatcher by hand returns **exit 2** for
|
|
94
|
+
`mindforge-block-no-verify` and `mindforge-config-protection`. A document that
|
|
95
|
+
under-claims a security capability is the same defect as one that over-claims it —
|
|
96
|
+
either way it describes a system that is not the one shipped. Now stated per channel,
|
|
97
|
+
with the four cases that remain deliberately unenforced and the three liveness
|
|
98
|
+
preconditions outside MindForge's control. (#225)
|
|
99
|
+
|
|
100
|
+
**Defects the published-artifact audit found (#222)**
|
|
101
|
+
|
|
102
|
+
- The **v11.9.3 release page shipped empty**: `changelog-fetcher.js --latest` exits 0
|
|
103
|
+
while writing zero bytes, so the `||` fallback never fired and a 195-line changelog
|
|
104
|
+
reached nobody. The step now prefers the in-tree changelog and fails on an empty body.
|
|
105
|
+
- A **shipped CI snippet told users to `npx` a package we do not own**.
|
|
106
|
+
`npx mindforge …` resolves to an unrelated third-party package; in a fresh runner it is
|
|
107
|
+
fetched and unpacked, install scripts and all, inside a job holding `MINDFORGE_TOKEN`.
|
|
108
|
+
Now pinned with `--package=mindforge-cc`.
|
|
109
|
+
- The **version-source gate missed a live defect twice**. `mindforge health` printed
|
|
110
|
+
`RELEASE v0.4.2` and `Current : v11.9.3` twenty-six lines apart in a project declaring
|
|
111
|
+
0.4.2, and produced `Unexpected end of JSON input` with no manifest at all — the verb
|
|
112
|
+
whose job is verifying installation integrity misreporting the installation. Widening
|
|
113
|
+
the gate surfaced two more of the same shape, one of which bound the **wrong** version
|
|
114
|
+
silently into approval records, which is worse than no binding because the check still
|
|
115
|
+
returns a verdict.
|
|
116
|
+
- `mindforge approve` died with ENOENT on any non-Node project. Absent values are now
|
|
117
|
+
recorded as `null` rather than invented.
|
|
118
|
+
|
|
119
|
+
**Test infrastructure**
|
|
120
|
+
|
|
121
|
+
- `tests/production.test.js` carried the uncommitted diff into its clone with
|
|
122
|
+
`git diff HEAD` (which includes staged files) but committed it with `commit -a` (which
|
|
123
|
+
stages only modified and deleted **tracked** files). So any commit **adding** a file
|
|
124
|
+
under `bin/` or `tests/` left the clone dirty and failed the gate's own cleanliness
|
|
125
|
+
assertion — reintroducing precisely the `--no-verify` pressure that carry exists to
|
|
126
|
+
avoid, for the one case it did not cover.
|
|
127
|
+
|
|
128
|
+
### Added
|
|
129
|
+
|
|
130
|
+
New regression gates, each falsified by reinstating the exact defect and confirming RED,
|
|
131
|
+
with every touched file restored byte-exact afterwards:
|
|
132
|
+
|
|
133
|
+
- `tests/hook-registration-ancestor.test.js` — six properties, the first of which asserts
|
|
134
|
+
the ancestor detector fires at all, so the other five cannot pass by never triggering.
|
|
135
|
+
- `every shipped file is tracked in git` — property-based, no name list. It cannot fail on
|
|
136
|
+
a clean clone, which is how the real leak survived CI, so it is paired with a second
|
|
137
|
+
test that plants the runtime state in a throwaway clone and then packs.
|
|
138
|
+
- `all three published packages publish with provenance` — counts the `npm publish`
|
|
139
|
+
invocations rather than matching one, because a single-match regex was satisfied by
|
|
140
|
+
either of the two packages that already had an attestation while the SDK had none. Also
|
|
141
|
+
asserts the SDK step is idempotent and ordered after the proven publishes.
|
|
142
|
+
|
|
143
|
+
### Notes for operators
|
|
144
|
+
|
|
145
|
+
- **These fixes change installer behaviour on almost every project.** After upgrading,
|
|
146
|
+
check `.mindforge/hook-registration.json` to see what was registered, and restart the
|
|
147
|
+
harness — hooks are snapshotted at session start.
|
|
148
|
+
- A registered hook is only *live* if the harness has been restarted, the project is
|
|
149
|
+
trusted in the harness, and `CLAUDE_PROJECT_DIR` is set with `node` on the hook PATH.
|
|
150
|
+
None of those three are in MindForge's control; the last is a deliberate trade against a
|
|
151
|
+
fail-closed shell tail that was measured denying benign commands on a fresh clone.
|
|
152
|
+
- Two gaps remain that require repository settings rather than code, and are recorded
|
|
153
|
+
rather than claimed fixed: there is no `v*` **tag ruleset** restricting who may create
|
|
154
|
+
the ref that triggers publishing, and `NPM_TOKEN` is a long-lived repository secret with
|
|
155
|
+
no GitHub environment in front of it.
|
package/docs/faq.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MindForge FAQ (v11.9.
|
|
1
|
+
# MindForge FAQ (v11.9.4)
|
|
2
2
|
|
|
3
3
|
## Is MindForge tied to Claude only?
|
|
4
4
|
No. MindForge supports Claude Code and Antigravity. Install with `--claude`,
|
|
@@ -55,7 +55,7 @@ The `deep-research` workflow was removed before the v11.8.0 release (the superpo
|
|
|
55
55
|
## Version & Stability
|
|
56
56
|
|
|
57
57
|
**Q: What version is current?**
|
|
58
|
-
v11.9.
|
|
58
|
+
v11.9.4 — verify with `node bin/mindforge-cli.js --version`
|
|
59
59
|
|
|
60
60
|
**Q: Is v11.9.0 production-stable?**
|
|
61
61
|
Yes. The IQ200 deep-audit (258 discrete checks across 14 dimensions) shows 258/258 passing. 0 CVEs, 0 test failures, 0 ESLint errors, 0 TypeScript errors.
|
|
@@ -80,7 +80,7 @@ Spawn dispatch is not yet implemented in v11.9.0. Use `/mindforge:auto` or `/min
|
|
|
80
80
|
Tier-3 trust uses in-process key simulation in v11.9.0 — this is intentional and safe. `SECURITY_TIER_3_SIMULATED = true` is the documented v11.x behavior. Hardware TPM/HSM is planned for v12.x.
|
|
81
81
|
|
|
82
82
|
**Q: What is the test coverage?**
|
|
83
|
-
|
|
83
|
+
134 test files: 132 pass, 0 failures, 2 env-dependent skips (`browser.test.js` needs a Chromium
|
|
84
84
|
daemon, `sre-integration.test.js` needs git worktree support and a clean tree).
|
|
85
85
|
|
|
86
86
|
The enforced floor is **30% lines**, gated in CI by the `mindforge-quality` job
|
package/docs/getting-started.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MindForge — Getting Started (v11.9.
|
|
1
|
+
# MindForge — Getting Started (v11.9.4)
|
|
2
2
|
|
|
3
3
|
This guide gets you from zero to a working MindForge project in under five minutes.
|
|
4
4
|
|
|
@@ -54,7 +54,13 @@ Run the MindForge MCP server (`mindforge-mcp-server`) over stdio — it exposes
|
|
|
54
54
|
claude mcp add mindforge -- npx -y mindforge-mcp-server
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
This server is also published to the [MCP Registry](https://registry.modelcontextprotocol.io) as
|
|
57
|
+
This server is also published to the [MCP Registry](https://registry.modelcontextprotocol.io) as
|
|
58
|
+
`io.github.sairam0424/mindforge`. **The registry entry lags this package** — it is republished
|
|
59
|
+
manually, so check what it actually serves before relying on it:
|
|
60
|
+
`curl -s 'https://registry.modelcontextprotocol.io/v0/servers?search=io.github.sairam0424/mindforge'`.
|
|
61
|
+
To pin a known version instead, install `mindforge-mcp-server` from npm directly. (The previous
|
|
62
|
+
wording named a specific version and marked it latest; both were wrong in both directions, which
|
|
63
|
+
is why this now describes how to check rather than asserting a number.)
|
|
58
64
|
|
|
59
65
|
### 4. Homebrew
|
|
60
66
|
|
|
@@ -108,7 +114,7 @@ Or use slash commands: `/mindforge:wf-code-audit`
|
|
|
108
114
|
## Your First 5 Minutes with MindForge
|
|
109
115
|
|
|
110
116
|
1. **Verify install:** `node bin/mindforge-cli.js health`
|
|
111
|
-
2. **Check version:** `node bin/mindforge-cli.js --version` (should print `11.9.
|
|
117
|
+
2. **Check version:** `node bin/mindforge-cli.js --version` (should print `11.9.4`)
|
|
112
118
|
3. **List workflows:** `node bin/mindforge-cli.js workflow list`
|
|
113
119
|
4. **Run first slash command:** Open Claude Code → `/mindforge:status`
|
|
114
120
|
5. **Onboard your codebase:** Open Claude Code → `/mindforge:wf-onboard-codebase`
|
package/docs/sdk-reference.md
CHANGED
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
} from 'mindforge-sdk';
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Current SDK version: `11.9.
|
|
17
|
+
Current SDK version: `11.9.4`
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## SDK Exports (v11.9.
|
|
21
|
+
## SDK Exports (v11.9.4)
|
|
22
22
|
|
|
23
23
|
```javascript
|
|
24
24
|
const {
|
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
commands, // Command registry
|
|
29
29
|
batch, // Batch execution
|
|
30
30
|
MindForgeMemory, // Memory interface
|
|
31
|
-
VERSION // '11.9.
|
|
31
|
+
VERSION // '11.9.4'
|
|
32
32
|
} = require('mindforge-sdk');
|
|
33
33
|
// or: import { MindForgeClient, VERSION } from 'mindforge-sdk';
|
|
34
34
|
```
|
package/docs/troubleshooting.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MindForge Troubleshooting (v11.9.
|
|
1
|
+
# MindForge Troubleshooting (v11.9.4)
|
|
2
2
|
|
|
3
3
|
This page lists common issues and fast fixes. If you get stuck, start with
|
|
4
4
|
`/mindforge:health`.
|
|
@@ -208,3 +208,58 @@ All tests must be run from the MindForge project root: `cd /path/to/MindForge &&
|
|
|
208
208
|
**Symptom:** `--version` flag reports "Unknown command" on installs older than v11.9.0.
|
|
209
209
|
|
|
210
210
|
**Fix:** Upgrade: `npx mindforge-cc@latest --claude --local`
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Hooks are installed but nothing is blocked
|
|
215
|
+
|
|
216
|
+
**Symptom:** The hook scripts are present under `.claude/hooks/`, but a command that should be denied
|
|
217
|
+
— say `git commit --no-verify` — runs normally.
|
|
218
|
+
|
|
219
|
+
Hooks have two separate failure modes: **not registered** (no config names them) and **registered but
|
|
220
|
+
not live** (the config exists, the harness has not applied it). Check them in that order.
|
|
221
|
+
|
|
222
|
+
**1. Was registration attempted, and what did it decide?** The installer prints one line for every
|
|
223
|
+
outcome, and writes a receipt:
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
cat .mindforge/hook-registration.json
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`registered: false` there carries the reason. Registration is deliberately narrow: Claude Code only,
|
|
230
|
+
`--local` only, non-Windows. A self-install inside a MindForge checkout also declines, because that
|
|
231
|
+
repo maintains its own tracked config.
|
|
232
|
+
|
|
233
|
+
**2. Restart the harness.** Claude Code snapshots hooks at session start, so a registration performed
|
|
234
|
+
during an open session is not live in it. This is the single most common cause.
|
|
235
|
+
|
|
236
|
+
**3. Confirm the project is trusted.** User-tier and project-tier settings are applied independently:
|
|
237
|
+
`~/.claude/settings.json` is the user tier and applies to every session, while
|
|
238
|
+
`<project>/.claude/settings.json` is the project tier and needs the project itself to be trusted.
|
|
239
|
+
Measured on one machine: the user-tier hooks fired on every tool call while the project-tier hooks in
|
|
240
|
+
the same session did not, and that project's entry in `~/.claude.json` had
|
|
241
|
+
`hasTrustDialogAccepted: false`. Accept the trust prompt for the directory, then use `/hooks` to
|
|
242
|
+
confirm the entries are listed.
|
|
243
|
+
|
|
244
|
+
**4. Drive the hook directly** to separate "the hook is broken" from "the hook is not wired". This
|
|
245
|
+
takes the harness out of the loop entirely — a deny-class hook must exit **2**:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
echo '{"hook_event_name":"PreToolUse","tool_name":"Bash","cwd":"'"$PWD"'","tool_input":{"command":"git commit --no-verify -m x"}}' \
|
|
249
|
+
| node .claude/hooks/run-with-flags.js mindforge-block-no-verify .claude/hooks/mindforge-block-no-verify.js minimal,standard,strict
|
|
250
|
+
echo "exit=$?"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Exit 2 with a `BLOCKED:` line on stderr means the hook works and the problem is registration or
|
|
254
|
+
trust. Exit 0 with the payload echoed back means the dispatcher could not load the script — check
|
|
255
|
+
that the second path exists under `.claude/hooks/`.
|
|
256
|
+
|
|
257
|
+
**5. If you launch the harness somewhere else, install there too.** Project settings are read from the
|
|
258
|
+
directory the harness starts in; they are **not** inherited from a parent directory. An ancestor
|
|
259
|
+
project having its own `.claude/settings.json` does not make its hooks apply here, and does not stop
|
|
260
|
+
these from applying — the installer warns when it sees one, and still registers.
|
|
261
|
+
|
|
262
|
+
**Known residual:** if `CLAUDE_PROJECT_DIR` is unset, or `node` is not on the hook PATH, the
|
|
263
|
+
registered commands exit 1 and the gate is simply absent — the same position as not installing. This
|
|
264
|
+
is a deliberate trade: a fail-closed shell tail was measured denying benign commands on a fresh
|
|
265
|
+
clone.
|
package/docs/user-guide.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# MindForge User Guide (v11.9.
|
|
1
|
+
# MindForge User Guide (v11.9.4)
|
|
2
2
|
|
|
3
3
|
This guide gets you from install to productive, with the minimum needed to run MindForge in a real project.
|
|
4
4
|
|
|
5
|
-
> **v11.9.
|
|
5
|
+
> **v11.9.4 Stats:** 35 workflows · 221 slash commands · 232 engine skills · 216 personas · 0 CVEs · 258/258 IQ200 checks passing
|
|
6
6
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
@@ -44,7 +44,7 @@ mindforge health # Verify project integrity
|
|
|
44
44
|
mindforge security-scan # Run security checks
|
|
45
45
|
mindforge headless # Run agent in non-interactive mode
|
|
46
46
|
mindforge --verbose ... # Enable verbose output for debugging
|
|
47
|
-
mindforge --version # Print installed version (e.g. 11.9.
|
|
47
|
+
mindforge --version # Print installed version (e.g. 11.9.4) and exit 0
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Use `--verbose` (or `-v`) on any command for detailed diagnostic output. Use `--version` (or `-V`) to print the installed version and exit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mindforge-cc",
|
|
3
|
-
"version": "11.9.
|
|
3
|
+
"version": "11.9.4",
|
|
4
4
|
"description": "MindForge — Sovereign Agentic Intelligence Framework. Sovereign Stability: Production-Hardened Agentic Intelligence (v11)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mindforge-cc": "bin/install.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
".mindforge/intelligence/",
|
|
30
30
|
".mindforge/memory/",
|
|
31
31
|
"!.mindforge/memory/pattern-library.jsonl",
|
|
32
|
+
"!.mindforge/memory/sync-manifest.json",
|
|
32
33
|
".mindforge/metrics/",
|
|
33
34
|
"!.mindforge/metrics/token-usage.jsonl",
|
|
34
35
|
".mindforge/models/",
|