javi-forge 1.38.3 → 1.38.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.
@@ -19,7 +19,7 @@ export declare const CI_HELP_TEXT = "\n Usage\n $ javi-forge ci [subcommand]
19
19
  * Per-command help for `hooks`, shown by `javi-forge hooks --help` (or when
20
20
  * `hooks` is given an unknown subcommand). Whitespace is significant.
21
21
  */
22
- export declare const HOOKS_HELP_TEXT = "\n Usage\n $ javi-forge hooks run <pre-commit|pre-push>\n $ javi-forge hooks <install|doctor|repair> claude [--force]\n\n Run the sections enabled under hooks: in .javi-forge/ci.yaml, in a fixed\n cheap\u2192expensive order, fail-fast. With no hooks: config the default is the\n quick native CI gate (setup + lint + compile + gates \u2014 no tests, no coverage).\n\n Subcommands\n run pre-commit Run the composed pre-commit sections\n run pre-push Run the composed pre-push sections\n install claude Install the managed Claude PreToolUse guard (.claude/)\n doctor claude Report Claude PreToolUse guard health (informational)\n repair claude Repair the managed guard; --force overwrites edited assets\n\n Notes\n A blocking section failure exits non-zero and blocks the commit/push.\n A broken .javi-forge/ci.yaml exits 1 (fail-closed \u2014 never skips a gate).\n To skip: git commit --no-verify (pre-push: git push --no-verify)\n doctor claude is informational (always exits 0); install/repair exit 0 on\n success, non-zero on refusal/failure. Use repair claude --force to overwrite\n a locally edited managed asset.\n Linux: install/repair claude need the acl package (getfacl) to prove the\n parent chain \u2014 apt install acl / apk add acl / dnf install acl. Without it\n they refuse fail-closed; an already-installed guard keeps firing, and\n doctor claude reports the acl capability as its own row.\n Claude Code spawns the guard with node from ITS path, so node must resolve\n there, not only inside javi-forge.\n\n Examples\n $ javi-forge hooks run pre-commit\n $ javi-forge hooks run pre-push\n $ javi-forge hooks install claude\n $ javi-forge hooks doctor claude\n $ javi-forge hooks repair claude --force\n";
22
+ export declare const HOOKS_HELP_TEXT = "\n Usage\n $ javi-forge hooks run <pre-commit|pre-push>\n $ javi-forge hooks <install|doctor|repair> <claude|codex> [--force]\n\n Run the sections enabled under hooks: in .javi-forge/ci.yaml, in a fixed\n cheap\u2192expensive order, fail-fast. With no hooks: config the default is the\n quick native CI gate (setup + lint + compile + gates \u2014 no tests, no coverage).\n\n Subcommands\n run pre-commit Run the composed pre-commit sections\n run pre-push Run the composed pre-push sections\n install claude Install the managed Claude PreToolUse guard (.claude/)\n doctor claude Report Claude PreToolUse guard health (informational)\n repair claude Repair the managed guard; --force overwrites edited assets\n install codex Install the managed Codex PreToolUse guard (~/.codex/)\n doctor codex Report Codex hook execution readiness and trust boundary\n repair codex Repair the managed Codex guard; --force overwrites edits\n\n Notes\n A blocking section failure exits non-zero and blocks the commit/push.\n A broken .javi-forge/ci.yaml exits 1 (fail-closed \u2014 never skips a gate).\n To skip: git commit --no-verify (pre-push: git push --no-verify)\n doctor claude is informational (always exits 0); install/repair exit 0 on\n success, non-zero on refusal/failure. Use repair claude --force to overwrite\n a locally edited managed asset.\n doctor codex exits 0 when runnable, 1 when blocked, and 2 when inconclusive;\n it does not prove provider trust or runtime execution. Use repair codex\n --force only to overwrite an edited managed asset.\n Linux: install/repair claude need the acl package (getfacl) to prove the\n parent chain \u2014 apt install acl / apk add acl / dnf install acl. Without it\n they refuse fail-closed; an already-installed guard keeps firing, and\n doctor claude reports the acl capability as its own row.\n Claude Code spawns the guard with node from ITS path, so node must resolve\n there, not only inside javi-forge.\n\n Examples\n $ javi-forge hooks run pre-commit\n $ javi-forge hooks run pre-push\n $ javi-forge hooks install claude\n $ javi-forge hooks doctor claude\n $ javi-forge hooks repair claude --force\n $ javi-forge hooks install codex\n $ javi-forge hooks doctor codex\n $ javi-forge hooks repair codex --force\n";
23
23
  export declare const FLAGS_SCHEMA: {
24
24
  readonly help: {
25
25
  readonly type: "boolean";
package/dist/cli/help.js CHANGED
@@ -166,7 +166,7 @@ export const CI_HELP_TEXT = `
166
166
  export const HOOKS_HELP_TEXT = `
167
167
  Usage
168
168
  $ javi-forge hooks run <pre-commit|pre-push>
169
- $ javi-forge hooks <install|doctor|repair> claude [--force]
169
+ $ javi-forge hooks <install|doctor|repair> <claude|codex> [--force]
170
170
 
171
171
  Run the sections enabled under hooks: in .javi-forge/ci.yaml, in a fixed
172
172
  cheap→expensive order, fail-fast. With no hooks: config the default is the
@@ -178,6 +178,9 @@ export const HOOKS_HELP_TEXT = `
178
178
  install claude Install the managed Claude PreToolUse guard (.claude/)
179
179
  doctor claude Report Claude PreToolUse guard health (informational)
180
180
  repair claude Repair the managed guard; --force overwrites edited assets
181
+ install codex Install the managed Codex PreToolUse guard (~/.codex/)
182
+ doctor codex Report Codex hook execution readiness and trust boundary
183
+ repair codex Repair the managed Codex guard; --force overwrites edits
181
184
 
182
185
  Notes
183
186
  A blocking section failure exits non-zero and blocks the commit/push.
@@ -186,6 +189,9 @@ export const HOOKS_HELP_TEXT = `
186
189
  doctor claude is informational (always exits 0); install/repair exit 0 on
187
190
  success, non-zero on refusal/failure. Use repair claude --force to overwrite
188
191
  a locally edited managed asset.
192
+ doctor codex exits 0 when runnable, 1 when blocked, and 2 when inconclusive;
193
+ it does not prove provider trust or runtime execution. Use repair codex
194
+ --force only to overwrite an edited managed asset.
189
195
  Linux: install/repair claude need the acl package (getfacl) to prove the
190
196
  parent chain — apt install acl / apk add acl / dnf install acl. Without it
191
197
  they refuse fail-closed; an already-installed guard keeps firing, and
@@ -199,6 +205,9 @@ export const HOOKS_HELP_TEXT = `
199
205
  $ javi-forge hooks install claude
200
206
  $ javi-forge hooks doctor claude
201
207
  $ javi-forge hooks repair claude --force
208
+ $ javi-forge hooks install codex
209
+ $ javi-forge hooks doctor codex
210
+ $ javi-forge hooks repair codex --force
202
211
  `;
203
212
  export const FLAGS_SCHEMA = {
204
213
  // `--help` is handled manually (autoHelp is disabled at the entrypoint so
@@ -254,9 +254,10 @@ function buildCodexHooksContainer(assetPath) {
254
254
  };
255
255
  }
256
256
  /**
257
- * Merge our managed group into an existing container: drop any prior managed
258
- * groups (ours, by command regex) and append a fresh one, preserving every
259
- * foreign group. A fresh install (no container) yields the clean container.
257
+ * Merge our managed group into an existing container: remove only prior managed
258
+ * handlers (ours, by command regex), preserve foreign handlers in their groups,
259
+ * and append one fresh canonical managed group. A fresh install (no container)
260
+ * yields the clean container.
260
261
  */
261
262
  function mergeCodexHooks(existing, assetPath) {
262
263
  if (!isPlainObject(existing))
@@ -266,14 +267,24 @@ function mergeCodexHooks(existing, assetPath) {
266
267
  container.hooks = {};
267
268
  const hooks = container.hooks;
268
269
  const groups = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
269
- const kept = groups.filter((group) => {
270
- const list = isPlainObject(group) && Array.isArray(group.hooks) ? group.hooks : [];
271
- const isOurs = list.some((h) => isPlainObject(h) &&
270
+ const kept = [];
271
+ for (const group of groups) {
272
+ if (!isPlainObject(group) || !Array.isArray(group.hooks)) {
273
+ kept.push(group);
274
+ continue;
275
+ }
276
+ const foreign = group.hooks.filter((h) => !(isPlainObject(h) &&
272
277
  h.type === "command" &&
273
278
  typeof h.command === "string" &&
274
- CODEX_CMD_RE.test(h.command));
275
- return !isOurs;
276
- });
279
+ CODEX_CMD_RE.test(h.command)));
280
+ if (foreign.length === 0)
281
+ continue;
282
+ if (foreign.length === group.hooks.length) {
283
+ kept.push(group);
284
+ continue;
285
+ }
286
+ kept.push({ ...group, hooks: foreign });
287
+ }
277
288
  const fresh = buildCodexHooksContainer(assetPath).hooks;
278
289
  hooks.PreToolUse = [...kept, ...fresh.PreToolUse];
279
290
  return container;
@@ -372,7 +383,9 @@ export async function doctorCodexPreToolUse(homeDir, options = {}) {
372
383
  ? "inconclusive"
373
384
  : "runnable";
374
385
  const remediation = [];
375
- if (hooksJson.state === "absent" || asset.state !== "managed-current") {
386
+ if (hooksJson.state === "absent" ||
387
+ hooksJson.state === "released-outdated" ||
388
+ asset.state !== "managed-current") {
376
389
  remediation.push("install the codex guard with: javi-forge hooks install codex");
377
390
  }
378
391
  if (!trusted)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javi-forge",
3
- "version": "1.38.3",
3
+ "version": "1.38.4",
4
4
  "description": "Project scaffolding and AI-ready CI bootstrap",
5
5
  "type": "module",
6
6
  "bin": {