@ijfw/install 1.3.0 → 1.3.1
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 +19 -0
- package/dist/ijfw.js +45 -24
- package/dist/install.js +6 -8
- package/docs/GUIDE.md +4 -4
- package/package.json +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.1] -- 2026-05-12
|
|
4
|
+
|
|
5
|
+
**Codex hook cleanup + release cadence hardening.** Tightens IJFW's Codex integration for Codex 0.130+, reduces the default dependency footprint, and moves more release drift into automated gates before it reaches users.
|
|
6
|
+
|
|
7
|
+
- Codex `SessionStart` now emits `additionalContext` inside `hookSpecificOutput` with `hookEventName: "SessionStart"`, matching Codex's strict hook response shape. This closes the `SessionStart hook (failed): hook returned invalid session start JSON output` error.
|
|
8
|
+
- Codex `PostToolUse` is now stdout-silent. IJFW still records local observations and failure signals, but it no longer re-injects cleaned tool output as `systemMessage`, which Codex renders as visible hook warning spam.
|
|
9
|
+
- Codex hook Node shims now pass user/tool text after `--`, so tool output beginning with `---` is treated as data instead of a Node CLI option. This closes the `node: bad option: ---` failure.
|
|
10
|
+
- Codex `UserPromptSubmit` and `PreToolUse` advisory output now use the same `hookSpecificOutput.additionalContext` shape when they do emit context.
|
|
11
|
+
- Codex `Stop` now stays stdout-silent on routine session saves. Normal receipts are written locally; only actionable compression notices can surface by default. This closes the `Stop hook (completed) warning: [ijfw] Session #... saved` noise.
|
|
12
|
+
- Codex bundle tests now cover strict `SessionStart` JSON and silent `PostToolUse` behavior for both routine output and failure-looking output.
|
|
13
|
+
- The shipped MCP server no longer installs `@xenova/transformers` by default. Cold semantic vectors are explicit opt-in and `IJFW_VECTORS` now defaults to `off`, keeping the production install smaller and quieter under package audits.
|
|
14
|
+
- The preflight audit gate now runs against both `installer` and `mcp-server`, so server-side dependency drift is covered by the same release gate as the installer.
|
|
15
|
+
- `ijfw preflight` now routes through the canonical 11-gate preflight entrypoint from both installer and MCP CLI paths instead of falling back to `scripts/check-all.sh`.
|
|
16
|
+
- Platform capability drift is now gated by `platform-capabilities.json` plus `scripts/check-platform-drift.js`, covering skill counts, hook-event counts, and marketplace/plugin manifest claims.
|
|
17
|
+
- Update-check changelog URLs now point at GitLab releases, matching the canonical repository.
|
|
18
|
+
- D2 graph-write lock timeout handling now throws the intended `EBUSY_GRAPH_WRITE` error instead of tripping an undeclared variable path under collision.
|
|
19
|
+
|
|
20
|
+
Files: `codex/.codex/hooks/session-start.sh`, `codex/.codex/hooks/post-tool-use.sh`, `codex/.codex/hooks/pre-prompt.sh`, `codex/.codex/hooks/pre-tool-use.sh`, `codex/.codex/hooks/session-end.sh`, `scripts/observation/test-envelope-invariant-codex.sh`, `mcp-server/test-codex-bundle.js`, `mcp-server/src/vectors.js`, `mcp-server/package.json`, `installer/src/preflight/gates/audit-ci.js`, `installer/src/preflight.js`, `mcp-server/src/cross-orchestrator-cli.js`, `mcp-server/src/compute/graph-lock.js`, `platform-capabilities.json`, `scripts/check-platform-drift.js`.
|
|
21
|
+
|
|
3
22
|
## [1.2.6] -- 2026-05-01
|
|
4
23
|
|
|
5
24
|
**Token sandbox + parallel workflow dispatch + DeepSeek frontier upgrade.** A new `ijfw_run` MCP tool keeps large command output out of your context window entirely -- builds, test suites, grep runs, and log tails are sandboxed to disk and summarized in a few lines instead of flooding thousands of tokens. The `ijfw-workflow` execution engine gains a formal Wave Table that makes parallel agent dispatch deterministic rather than inferred. DeepSeek moves to `deepseek-v4-pro` -- the actual frontier model -- so the Trident gets Frontier AI checking Frontier AI.
|
package/dist/ijfw.js
CHANGED
|
@@ -582,27 +582,35 @@ async function run7(ctx) {
|
|
|
582
582
|
const t0 = Date.now();
|
|
583
583
|
const ver = ctx.versions["audit-ci"] || "latest";
|
|
584
584
|
const configPath = join4(ctx.repoRoot, ".audit-ci.jsonc");
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
585
|
+
const packageDirs = ["installer", "mcp-server"];
|
|
586
|
+
const runs = packageDirs.map((dir) => {
|
|
587
|
+
const res = spawnSync7(
|
|
588
|
+
"npx",
|
|
589
|
+
["--yes", `audit-ci@${ver}`, "--config", configPath],
|
|
590
|
+
{
|
|
591
|
+
encoding: "utf8",
|
|
592
|
+
cwd: join4(ctx.repoRoot, dir),
|
|
593
|
+
timeout: 6e4
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
return { dir, status: res.status, output: (res.stdout || "") + (res.stderr || "") };
|
|
597
|
+
});
|
|
594
598
|
const durationMs = Date.now() - t0;
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
if (res.status === 0) {
|
|
599
|
+
const failed = runs.filter((r) => r.status !== 0);
|
|
600
|
+
if (failed.length === 0) {
|
|
598
601
|
return {
|
|
599
602
|
name: "audit-ci",
|
|
600
603
|
status: "PASS",
|
|
601
|
-
message: "audit-ci: no high/critical vulnerabilities",
|
|
602
|
-
details:
|
|
604
|
+
message: "audit-ci: no high/critical vulnerabilities in installer or mcp-server",
|
|
605
|
+
details: runs.map((r) => `${r.dir}: pass`),
|
|
603
606
|
durationMs
|
|
604
607
|
};
|
|
605
608
|
}
|
|
609
|
+
const lines = [];
|
|
610
|
+
for (const r of failed) {
|
|
611
|
+
lines.push(`${r.dir}: audit failed`);
|
|
612
|
+
lines.push(...r.output.split("\n").filter(Boolean).slice(0, 10));
|
|
613
|
+
}
|
|
606
614
|
return {
|
|
607
615
|
name: "audit-ci",
|
|
608
616
|
status: "FAIL",
|
|
@@ -1045,7 +1053,7 @@ __export(preflight_exports, {
|
|
|
1045
1053
|
runPreflightCommand: () => runPreflightCommand
|
|
1046
1054
|
});
|
|
1047
1055
|
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "node:fs";
|
|
1048
|
-
import { join as join8, dirname } from "node:path";
|
|
1056
|
+
import { join as join8, dirname, resolve as resolve3 } from "node:path";
|
|
1049
1057
|
import { fileURLToPath } from "node:url";
|
|
1050
1058
|
function printHelp() {
|
|
1051
1059
|
console.log(`
|
|
@@ -1144,11 +1152,24 @@ async function runPreflightCommand(argv, repoRoot2) {
|
|
|
1144
1152
|
const report = await runPreflight(gates, ctx);
|
|
1145
1153
|
process.exit(report.outcome === "pass" ? 0 : 1);
|
|
1146
1154
|
}
|
|
1155
|
+
function defaultRepoRoot() {
|
|
1156
|
+
let dir = __dirname;
|
|
1157
|
+
for (let i = 0; i < 8; i++) {
|
|
1158
|
+
if (existsSync3(join8(dir, "package.json")) && existsSync3(join8(dir, "mcp-server"))) return dir;
|
|
1159
|
+
const next = resolve3(dir, "..");
|
|
1160
|
+
if (next === dir) break;
|
|
1161
|
+
dir = next;
|
|
1162
|
+
}
|
|
1163
|
+
return process.cwd();
|
|
1164
|
+
}
|
|
1147
1165
|
var __dirname;
|
|
1148
1166
|
var init_preflight = __esm({
|
|
1149
|
-
"src/preflight.js"() {
|
|
1167
|
+
async "src/preflight.js"() {
|
|
1150
1168
|
init_runner();
|
|
1151
1169
|
__dirname = dirname(fileURLToPath(import.meta.url));
|
|
1170
|
+
if (process.argv[1] && resolve3(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
1171
|
+
await runPreflightCommand(process.argv, defaultRepoRoot());
|
|
1172
|
+
}
|
|
1152
1173
|
}
|
|
1153
1174
|
});
|
|
1154
1175
|
|
|
@@ -2412,7 +2433,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
2412
2433
|
});
|
|
2413
2434
|
|
|
2414
2435
|
// src/ijfw.js
|
|
2415
|
-
import { dirname as dirname2, join as join9, resolve as
|
|
2436
|
+
import { dirname as dirname2, join as join9, resolve as resolve4, basename } from "node:path";
|
|
2416
2437
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2417
2438
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, copyFileSync, readdirSync as readdirSync4, rmSync as rmSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2418
2439
|
import { homedir, platform as platform2 } from "node:os";
|
|
@@ -2422,7 +2443,7 @@ function repoRoot() {
|
|
|
2422
2443
|
let dir = __dirname2;
|
|
2423
2444
|
for (let i = 0; i < 6; i++) {
|
|
2424
2445
|
if (existsSync4(join9(dir, "package.json")) && existsSync4(join9(dir, ".git"))) return dir;
|
|
2425
|
-
dir =
|
|
2446
|
+
dir = resolve4(dir, "..");
|
|
2426
2447
|
}
|
|
2427
2448
|
return process.cwd();
|
|
2428
2449
|
}
|
|
@@ -2437,7 +2458,7 @@ COMMANDS
|
|
|
2437
2458
|
install Install IJFW into your AI coding agents
|
|
2438
2459
|
uninstall Remove IJFW from your AI coding agents
|
|
2439
2460
|
help Open the full IJFW guide (terminal, or --browser for rendered)
|
|
2440
|
-
preflight Run
|
|
2461
|
+
preflight Run 11-gate quality pipeline before publishing
|
|
2441
2462
|
dashboard Start / stop / check the local observability dashboard
|
|
2442
2463
|
design Manage the visual design companion
|
|
2443
2464
|
doctor Diagnose IJFW installation health
|
|
@@ -2494,19 +2515,19 @@ async function main() {
|
|
|
2494
2515
|
}
|
|
2495
2516
|
switch (sub) {
|
|
2496
2517
|
case "install": {
|
|
2497
|
-
const installBin =
|
|
2518
|
+
const installBin = resolve4(__dirname2, "..", "dist", "install.js");
|
|
2498
2519
|
const r = spawnSync12("node", [installBin, ...argv.slice(3)], { stdio: "inherit" });
|
|
2499
2520
|
process.exit(r.status ?? 1);
|
|
2500
2521
|
break;
|
|
2501
2522
|
}
|
|
2502
2523
|
case "uninstall": {
|
|
2503
|
-
const uninstallBin =
|
|
2524
|
+
const uninstallBin = resolve4(__dirname2, "..", "dist", "uninstall.js");
|
|
2504
2525
|
const r = spawnSync12("node", [uninstallBin, ...argv.slice(3)], { stdio: "inherit" });
|
|
2505
2526
|
process.exit(r.status ?? 1);
|
|
2506
2527
|
break;
|
|
2507
2528
|
}
|
|
2508
2529
|
case "preflight": {
|
|
2509
|
-
const { runPreflightCommand: runPreflightCommand2 } = await
|
|
2530
|
+
const { runPreflightCommand: runPreflightCommand2 } = await init_preflight().then(() => preflight_exports);
|
|
2510
2531
|
await runPreflightCommand2([argv[0], argv[1], ...argv.slice(3)], repoRoot());
|
|
2511
2532
|
break;
|
|
2512
2533
|
}
|
|
@@ -2563,7 +2584,7 @@ async function main() {
|
|
|
2563
2584
|
console.error("Usage: ijfw design push <file.html>");
|
|
2564
2585
|
process.exit(1);
|
|
2565
2586
|
}
|
|
2566
|
-
const abs =
|
|
2587
|
+
const abs = resolve4(filePath);
|
|
2567
2588
|
if (!existsSync4(abs)) {
|
|
2568
2589
|
console.error(`File not found: ${abs}`);
|
|
2569
2590
|
process.exit(1);
|
|
@@ -2587,7 +2608,7 @@ async function main() {
|
|
|
2587
2608
|
const wantsBrowser = argv.slice(3).includes("--browser");
|
|
2588
2609
|
const candidates = [
|
|
2589
2610
|
join9(repoRoot(), "docs", "GUIDE.md"),
|
|
2590
|
-
|
|
2611
|
+
resolve4(__dirname2, "..", "docs", "GUIDE.md"),
|
|
2591
2612
|
join9(homedir(), ".ijfw", "docs", "GUIDE.md")
|
|
2592
2613
|
];
|
|
2593
2614
|
const guidePath = candidates.find((p) => existsSync4(p));
|
package/dist/install.js
CHANGED
|
@@ -767,7 +767,7 @@ async function installCodex(ctx) {
|
|
|
767
767
|
copyDirIfAbsent(sd.path, join4(projSkills, sd.name));
|
|
768
768
|
}
|
|
769
769
|
}
|
|
770
|
-
ctx.log.ok("Installed Codex bundle: MCP + hooks +
|
|
770
|
+
ctx.log.ok("Installed Codex bundle: MCP + hooks + 19 skills + context");
|
|
771
771
|
return { status: "ok" };
|
|
772
772
|
}
|
|
773
773
|
async function installGemini(ctx) {
|
|
@@ -832,7 +832,7 @@ async function installGemini(ctx) {
|
|
|
832
832
|
for (const f of listFiles(agentSrc, ".md")) {
|
|
833
833
|
copyIfAbsent(f.path, join4(extDst, "agents", f.name));
|
|
834
834
|
}
|
|
835
|
-
ctx.log.ok("Installed Gemini bundle: MCP + extension +
|
|
835
|
+
ctx.log.ok("Installed Gemini bundle: MCP + extension + 19 skills + 11 hooks + policy");
|
|
836
836
|
return { status: "ok" };
|
|
837
837
|
}
|
|
838
838
|
async function installWayland(ctx) {
|
|
@@ -2048,14 +2048,12 @@ function cloneOrPull(dir, branch) {
|
|
|
2048
2048
|
else if (remoteSignal) console.warn(` git exited on signal ${remoteSignal}`);
|
|
2049
2049
|
else if (remoteStatus !== 0 && remoteStderr) console.warn(` git remote get-url: ${remoteStderr.slice(0, 120).trim()}`);
|
|
2050
2050
|
if (remoteStatus === 0) {
|
|
2051
|
-
const
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
"https://github.com/seandonahoe/ijfw/",
|
|
2055
|
-
"https://github.com/seandonahoe/ijfw.git/"
|
|
2051
|
+
const STALE_PATTERNS = [
|
|
2052
|
+
/^https:\/\/github\.com\/seandonahoe\/ijfw(\.git)?\/?$/i,
|
|
2053
|
+
/^https:\/\/github\.com\/therealseandonahoe\/ijfw(\.git)?\/?$/i
|
|
2056
2054
|
];
|
|
2057
2055
|
const currentOrigin = (stdout || "").trim();
|
|
2058
|
-
if (
|
|
2056
|
+
if (STALE_PATTERNS.some((re) => re.test(currentOrigin))) {
|
|
2059
2057
|
const setUrl = spawnSync2("git", ["-C", dir, "remote", "set-url", "origin", DEFAULT_REPO], { stdio: "inherit" });
|
|
2060
2058
|
if (setUrl.status !== 0) {
|
|
2061
2059
|
console.warn(` [!] origin migration failed -- could not repoint ${currentOrigin} to ${DEFAULT_REPO}`);
|
package/docs/GUIDE.md
CHANGED
|
@@ -172,7 +172,7 @@ Run `/team setup` in Claude Code, or `ijfw team` from the shell, to see your cur
|
|
|
172
172
|
|------|-------|--------------|
|
|
173
173
|
| Hot | Plain markdown in `.ijfw/memory/` | Always on. Instant reads. Git friendly. |
|
|
174
174
|
| Warm | BM25 ranked search | Always on. Scales to around 10,000 entries per project. |
|
|
175
|
-
| Cold | Optional semantic vectors |
|
|
175
|
+
| Cold | Optional semantic vectors | Off by default. Requires a user-installed embedding provider. |
|
|
176
176
|
|
|
177
177
|
Every session also ends with an optional "dream cycle". Run `/consolidate` or "run a dream cycle" to have IJFW sweep the day's memory: promote observed patterns into your knowledge base, prune stale entries, reconcile contradictions, optionally lift winners into global memory so every future project benefits. Memory that grows sharper over time instead of heavier.
|
|
178
178
|
|
|
@@ -359,9 +359,9 @@ IJFW configures six AI coding agents with native affordances on each, plus a uni
|
|
|
359
359
|
|
|
360
360
|
| Platform | What ships |
|
|
361
361
|
|----------|------------|
|
|
362
|
-
| Claude Code | Native plugin via marketplace, MCP auto-registered,
|
|
363
|
-
| Codex CLI | Native plugin (`.codex-plugin/plugin.json`),
|
|
364
|
-
| Gemini CLI | Native extension (`gemini-extension.json`),
|
|
362
|
+
| Claude Code | Native plugin via marketplace, MCP auto-registered, 6 hook events / 12 scripts, 22 on-demand skills, 22 slash commands |
|
|
363
|
+
| Codex CLI | Native plugin (`.codex-plugin/plugin.json`), 19 skills, 5 hook events, MCP registered, marketplace-ready |
|
|
364
|
+
| Gemini CLI | Native extension (`gemini-extension.json`), 19 skills, 11 hook events, 19 TOML slash commands, policy engine, BeforeModel injection, checkpointing |
|
|
365
365
|
| Cursor | `.cursor/mcp.json` plus `.cursor/rules/ijfw.mdc`. Dashboard view-only. |
|
|
366
366
|
| Windsurf | `~/.codeium/windsurf/mcp_config.json` plus `.windsurfrules`. Dashboard view-only. |
|
|
367
367
|
| Copilot (VS Code) | `.vscode/mcp.json` plus `.github/copilot-instructions.md`. Dashboard view-only. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ijfw/install",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "One-command installer for IJFW -- the AI efficiency layer. One install, every AI coding agent, zero config.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
"url": "git+https://gitlab.com/therealseandonahoe/ijfw.git"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
|
-
"access": "public"
|
|
59
|
-
"provenance": true
|
|
58
|
+
"access": "public"
|
|
60
59
|
}
|
|
61
60
|
}
|