@pushary/agent-hooks 0.98.0 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/bin/pushary-bell-hook.js +15 -14
  3. package/dist/bin/pushary-bell.js +6 -5
  4. package/dist/bin/pushary-claude.js +15 -14
  5. package/dist/bin/pushary-clean.js +13 -12
  6. package/dist/bin/pushary-codex-bridge.js +8 -7
  7. package/dist/bin/pushary-codex-hook.js +25 -15
  8. package/dist/bin/pushary-codex.js +5 -4
  9. package/dist/bin/pushary-connect.js +4 -3
  10. package/dist/bin/pushary-daemon.js +19 -18
  11. package/dist/bin/pushary-disconnect.js +3 -3
  12. package/dist/bin/pushary-doctor.js +15 -14
  13. package/dist/bin/pushary-elicitation-hook.js +14 -13
  14. package/dist/bin/pushary-gemini-bridge.js +7 -6
  15. package/dist/bin/pushary-gemini-hook.js +15 -14
  16. package/dist/bin/pushary-hook.js +17 -16
  17. package/dist/bin/pushary-login.js +6 -5
  18. package/dist/bin/pushary-logout.js +4 -3
  19. package/dist/bin/pushary-notification-hook.js +15 -14
  20. package/dist/bin/pushary-opencode-hook.js +15 -14
  21. package/dist/bin/pushary-permission-denied-hook.js +17 -16
  22. package/dist/bin/pushary-permission-hook.js +17 -16
  23. package/dist/bin/pushary-post-hook.js +15 -14
  24. package/dist/bin/pushary-prompt-hook.js +15 -14
  25. package/dist/bin/pushary-session-end-hook.js +15 -14
  26. package/dist/bin/pushary-session-start-hook.js +18 -17
  27. package/dist/bin/pushary-setup.js +19 -18
  28. package/dist/bin/pushary-status.js +9 -8
  29. package/dist/bin/pushary-stop-hook.js +15 -14
  30. package/dist/bin/pushary-stopfailure-hook.js +15 -14
  31. package/dist/bin/pushary-transcript-register.js +13 -12
  32. package/dist/bin/pushary-transcripts.js +5 -4
  33. package/dist/bin/pushary-upgrade.js +13 -12
  34. package/dist/{chunk-FAJ4R7IB.js → chunk-3ZAEUPM4.js} +1 -1
  35. package/dist/{chunk-LX4NNYII.js → chunk-4C4XFAGJ.js} +1 -1
  36. package/dist/{chunk-VZD2GEKB.js → chunk-4LL6LG5X.js} +1 -43
  37. package/dist/{chunk-SJLGOVC6.js → chunk-4PBCNVI3.js} +4 -2
  38. package/dist/{chunk-WU6LSXJ6.js → chunk-562UJ2DA.js} +2 -2
  39. package/dist/{chunk-YJDRHQLG.js → chunk-64WARXGV.js} +2 -2
  40. package/dist/{chunk-J44RPHUZ.js → chunk-6IFUXNFX.js} +2 -2
  41. package/dist/{chunk-53QCTSWY.js → chunk-6KLCP7VF.js} +2 -2
  42. package/dist/{chunk-DOD3A6EU.js → chunk-CRFLU455.js} +4 -4
  43. package/dist/{chunk-2GLOHBYB.js → chunk-EXHXR2X5.js} +1 -1
  44. package/dist/chunk-GCD3SQSV.js +44 -0
  45. package/dist/{chunk-NQGYPTJQ.js → chunk-ID5FDKDZ.js} +1 -1
  46. package/dist/{chunk-XL3RKJYQ.js → chunk-JBJBVERL.js} +64 -29
  47. package/dist/{chunk-B35OCFXH.js → chunk-JL33EDN7.js} +4 -4
  48. package/dist/{chunk-6LRGZJFB.js → chunk-JXELRCU5.js} +9 -5
  49. package/dist/{chunk-K6CH5NVW.js → chunk-K4XFCEVI.js} +1 -1
  50. package/dist/{chunk-NIXVMMJM.js → chunk-K6BASBQJ.js} +1 -1
  51. package/dist/{chunk-JQU6PMH4.js → chunk-LWKPMSBB.js} +62 -45
  52. package/dist/{chunk-5B5QV3KC.js → chunk-NSFNEDCT.js} +7 -7
  53. package/dist/{chunk-M4TVEMLH.js → chunk-O3LZQEQP.js} +1 -1
  54. package/dist/{chunk-HFQ7WSHZ.js → chunk-PD6JY33P.js} +4 -2
  55. package/dist/{chunk-QXIF6R4P.js → chunk-QS55LDX4.js} +2 -2
  56. package/dist/{chunk-W2MG2P46.js → chunk-RALVI7OF.js} +2 -2
  57. package/dist/{chunk-6CYB77VD.js → chunk-T3JZZUAR.js} +3 -3
  58. package/dist/{chunk-V47GITZV.js → chunk-V262ATS5.js} +1 -1
  59. package/dist/{chunk-TZHDKRMG.js → chunk-WGV3VY7O.js} +1 -1
  60. package/dist/{chunk-OBYC6SN4.js → chunk-YKLCWWEI.js} +1 -1
  61. package/dist/reapply-HQ264ZTR.js +30 -0
  62. package/dist/src/index.js +7 -6
  63. package/package.json +1 -1
@@ -1,10 +1,3 @@
1
- import {
2
- configFilePath
3
- } from "./chunk-2UMNXADU.js";
4
- import {
5
- normalizeInstallSource
6
- } from "./chunk-OUAE3GKO.js";
7
-
8
1
  // src/cli/fsx.ts
9
2
  import { copyFileSync, existsSync, fsyncSync, mkdirSync, openSync, closeSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
10
3
  import { dirname, join } from "path";
@@ -64,45 +57,10 @@ var writeJsonAtomicDurable = (filePath, data, mode) => {
64
57
  }
65
58
  };
66
59
 
67
- // src/install-source.ts
68
- import { readFileSync as readFileSync2 } from "fs";
69
- var ENV_OVERRIDE = "PUSHARY_INSTALL_SOURCE";
70
- var PLUGIN_ROOT = "CLAUDE_PLUGIN_ROOT";
71
- var EDITOR_PLUGIN_MARKERS = ["cursor-plugin", "vscode-plugin"];
72
- var detectInstallSource = (env = process.env, argv = process.argv) => {
73
- const declared = env[ENV_OVERRIDE]?.trim();
74
- if (declared) return normalizeInstallSource(declared);
75
- const pluginRoot = env[PLUGIN_ROOT]?.trim();
76
- if (pluginRoot) {
77
- return EDITOR_PLUGIN_MARKERS.some((marker) => pluginRoot.includes(marker)) ? "editor_plugin" : "claude_plugin";
78
- }
79
- const entry = argv[1] ?? "";
80
- if (entry.includes("_npx")) return "npx";
81
- if (entry) return "npm";
82
- return "unknown";
83
- };
84
- var storedInstallSource = () => {
85
- try {
86
- const parsed = JSON.parse(readFileSync2(configFilePath(), "utf-8"));
87
- const stored = parsed.installSource;
88
- return typeof stored === "string" && stored ? normalizeInstallSource(stored) : void 0;
89
- } catch {
90
- return void 0;
91
- }
92
- };
93
- var resolveInstallSourceFor = (config) => {
94
- const stored = config.installSource;
95
- if (typeof stored === "string" && stored) return normalizeInstallSource(stored);
96
- return detectInstallSource();
97
- };
98
- var reportedInstallSource = () => storedInstallSource() ?? detectInstallSource();
99
-
100
60
  export {
101
61
  readJsonSafe,
102
62
  backupFile,
103
63
  writeFileAtomic,
104
64
  writeJsonAtomic,
105
- writeJsonAtomicDurable,
106
- resolveInstallSourceFor,
107
- reportedInstallSource
65
+ writeJsonAtomicDurable
108
66
  };
@@ -1,10 +1,12 @@
1
+ import {
2
+ resolveInstallSourceFor
3
+ } from "./chunk-GCD3SQSV.js";
1
4
  import {
2
5
  backupFile,
3
6
  readJsonSafe,
4
- resolveInstallSourceFor,
5
7
  writeFileAtomic,
6
8
  writeJsonAtomic
7
- } from "./chunk-VZD2GEKB.js";
9
+ } from "./chunk-4LL6LG5X.js";
8
10
  import {
9
11
  configFilePath
10
12
  } from "./chunk-2UMNXADU.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-XL3RKJYQ.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
  import {
5
5
  writeFileAtomic
6
- } from "./chunk-VZD2GEKB.js";
6
+ } from "./chunk-4LL6LG5X.js";
7
7
 
8
8
  // src/identity.ts
9
9
  import { randomUUID } from "crypto";
@@ -31,13 +31,13 @@ import {
31
31
  } from "./chunk-LGXUGYUH.js";
32
32
  import {
33
33
  getMachineId
34
- } from "./chunk-WU6LSXJ6.js";
34
+ } from "./chunk-562UJ2DA.js";
35
35
  import {
36
36
  withRetry
37
37
  } from "./chunk-EYRGBYZG.js";
38
38
  import {
39
39
  reportedInstallSource
40
- } from "./chunk-VZD2GEKB.js";
40
+ } from "./chunk-GCD3SQSV.js";
41
41
  import {
42
42
  getApiKey,
43
43
  getBaseUrl
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-XL3RKJYQ.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
  import {
5
5
  readJsonSafe
6
- } from "./chunk-VZD2GEKB.js";
6
+ } from "./chunk-4LL6LG5X.js";
7
7
 
8
8
  // src/process-ownership.ts
9
9
  import { createHash, randomUUID } from "crypto";
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-A76GNRIK.js";
4
4
  import {
5
5
  canonicalJson
6
- } from "./chunk-XL3RKJYQ.js";
6
+ } from "./chunk-JBJBVERL.js";
7
7
  import {
8
8
  writeFileAtomic
9
- } from "./chunk-VZD2GEKB.js";
9
+ } from "./chunk-4LL6LG5X.js";
10
10
  import {
11
11
  BLOCKED_ACTION_GRANT_TTL_SECONDS,
12
12
  blockedActionIdentity,
@@ -4,23 +4,23 @@ import {
4
4
  } from "./chunk-XHKBHWLX.js";
5
5
  import {
6
6
  getMachineId
7
- } from "./chunk-WU6LSXJ6.js";
7
+ } from "./chunk-562UJ2DA.js";
8
8
  import {
9
9
  pusharyDir,
10
10
  resolveGlobalBinary
11
- } from "./chunk-XL3RKJYQ.js";
11
+ } from "./chunk-JBJBVERL.js";
12
12
  import {
13
13
  getPackageVersion
14
14
  } from "./chunk-DINDL2CF.js";
15
15
  import {
16
16
  readControlMode
17
- } from "./chunk-SJLGOVC6.js";
17
+ } from "./chunk-4PBCNVI3.js";
18
18
  import {
19
19
  readJsonSafe,
20
20
  writeFileAtomic,
21
21
  writeJsonAtomic,
22
22
  writeJsonAtomicDurable
23
- } from "./chunk-VZD2GEKB.js";
23
+ } from "./chunk-4LL6LG5X.js";
24
24
  import {
25
25
  getApiKey
26
26
  } from "./chunk-2UMNXADU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-XL3RKJYQ.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -0,0 +1,44 @@
1
+ import {
2
+ configFilePath
3
+ } from "./chunk-2UMNXADU.js";
4
+ import {
5
+ normalizeInstallSource
6
+ } from "./chunk-OUAE3GKO.js";
7
+
8
+ // src/install-source.ts
9
+ import { readFileSync } from "fs";
10
+ var ENV_OVERRIDE = "PUSHARY_INSTALL_SOURCE";
11
+ var PLUGIN_ROOT = "CLAUDE_PLUGIN_ROOT";
12
+ var EDITOR_PLUGIN_MARKERS = ["cursor-plugin", "vscode-plugin"];
13
+ var detectInstallSource = (env = process.env, argv = process.argv) => {
14
+ const declared = env[ENV_OVERRIDE]?.trim();
15
+ if (declared) return normalizeInstallSource(declared);
16
+ const pluginRoot = env[PLUGIN_ROOT]?.trim();
17
+ if (pluginRoot) {
18
+ return EDITOR_PLUGIN_MARKERS.some((marker) => pluginRoot.includes(marker)) ? "editor_plugin" : "claude_plugin";
19
+ }
20
+ const entry = argv[1] ?? "";
21
+ if (entry.includes("_npx")) return "npx";
22
+ if (entry) return "npm";
23
+ return "unknown";
24
+ };
25
+ var storedInstallSource = () => {
26
+ try {
27
+ const parsed = JSON.parse(readFileSync(configFilePath(), "utf-8"));
28
+ const stored = parsed.installSource;
29
+ return typeof stored === "string" && stored ? normalizeInstallSource(stored) : void 0;
30
+ } catch {
31
+ return void 0;
32
+ }
33
+ };
34
+ var resolveInstallSourceFor = (config) => {
35
+ const stored = config.installSource;
36
+ if (typeof stored === "string" && stored) return normalizeInstallSource(stored);
37
+ return detectInstallSource();
38
+ };
39
+ var reportedInstallSource = () => storedInstallSource() ?? detectInstallSource();
40
+
41
+ export {
42
+ resolveInstallSourceFor,
43
+ reportedInstallSource
44
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readTranscriptPreference
3
- } from "./chunk-SJLGOVC6.js";
3
+ } from "./chunk-4PBCNVI3.js";
4
4
 
5
5
  // src/transcript-setting.ts
6
6
  var transcriptEnvironmentPreference = () => {
@@ -227,6 +227,35 @@ import { createHash } from "crypto";
227
227
  import { homedir } from "os";
228
228
  import { join as join2 } from "path";
229
229
 
230
+ // src/registration-holder.ts
231
+ var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
232
+ var registeredCommands = (document) => {
233
+ const hooks = asRecord(document?.hooks);
234
+ if (!hooks) return [];
235
+ const found = [];
236
+ for (const [event, value] of Object.entries(hooks)) {
237
+ if (!Array.isArray(value)) continue;
238
+ for (const item of value) {
239
+ const inner = asRecord(item)?.hooks;
240
+ if (!Array.isArray(inner)) continue;
241
+ for (const hook of inner) {
242
+ const command = asRecord(hook)?.command;
243
+ if (typeof command === "string") found.push({ event, command });
244
+ }
245
+ }
246
+ }
247
+ return found;
248
+ };
249
+ var wholeSegments = (command) => command.split(/[\s/\\"']+/).map((segment) => segment.replace(/\.(cmd|exe)$/i, ""));
250
+ var namesLocator = (command) => wholeSegments(command).includes(HOOK_LOCATOR_BINARY);
251
+ var namesCliBinary = (command, cliBinaries) => wholeSegments(command).some((segment) => cliBinaries.has(segment));
252
+ var namesOurBinary = (command, cliBinaries) => namesLocator(command) || namesCliBinary(command, cliBinaries);
253
+ var registrationHolderOf = (document, cliBinaries) => {
254
+ const commands = registeredCommands(document);
255
+ if (commands.some(({ command }) => namesLocator(command))) return "app";
256
+ return commands.some(({ command }) => namesCliBinary(command, cliBinaries)) ? "cli" : "none";
257
+ };
258
+
230
259
  // src/hook-entries.ts
231
260
  var registerHookEntry = (existing, isOurs, entry) => {
232
261
  const rewritten = [];
@@ -298,9 +327,9 @@ var CODEX_EVENT_KEY = {
298
327
  PostCompact: "post_compact"
299
328
  };
300
329
  var codexEventKeyOf = (event) => event.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
301
- var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
330
+ var asRecord2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
302
331
  var ensureRecord = (target, key) => {
303
- const existing = asRecord(target[key]);
332
+ const existing = asRecord2(target[key]);
304
333
  if (existing) return existing;
305
334
  const created = {};
306
335
  target[key] = created;
@@ -317,9 +346,9 @@ var addCodexMcpServer = (config, apiKey) => {
317
346
  delete pushary.tools;
318
347
  };
319
348
  var readCodexMcpAuth = (config) => {
320
- const pushary = asRecord(asRecord(config.mcp_servers)?.pushary);
349
+ const pushary = asRecord2(asRecord2(config.mcp_servers)?.pushary);
321
350
  if (!pushary) return void 0;
322
- const authorization = asRecord(pushary.http_headers)?.Authorization;
351
+ const authorization = asRecord2(pushary.http_headers)?.Authorization;
323
352
  if (typeof authorization === "string" && authorization.startsWith("Bearer ")) {
324
353
  return { method: "embedded", key: authorization.slice("Bearer ".length).trim() };
325
354
  }
@@ -330,14 +359,16 @@ var readCodexMcpAuth = (config) => {
330
359
  return void 0;
331
360
  };
332
361
  var isPusharyCommand = (hook, scope) => {
333
- const command = String(asRecord(hook)?.command ?? "");
362
+ const command = String(asRecord2(hook)?.command ?? "");
334
363
  if (isProtectedByScope(command, scope)) return false;
335
364
  return command.includes(CODEX_HOOK_BINARY) || command.includes(HOOK_LOCATOR_BINARY);
336
365
  };
337
366
  var isPusharyCodexHook = (entry, scope) => {
338
- const hooks = asRecord(entry)?.hooks;
367
+ const hooks = asRecord2(entry)?.hooks;
339
368
  return Array.isArray(hooks) && hooks.some((hook) => isPusharyCommand(hook, scope));
340
369
  };
370
+ var CODEX_CLI_BINARIES = /* @__PURE__ */ new Set([CODEX_HOOK_BINARY]);
371
+ var codexRegistrationHolder = (hooksConfig) => registrationHolderOf(hooksConfig, CODEX_CLI_BINARIES);
341
372
  var addCodexHooks = (config, command) => {
342
373
  const hooks = ensureRecord(config, "hooks");
343
374
  for (const definition of CODEX_HOOK_EVENTS) {
@@ -354,7 +385,7 @@ var addCodexHooks = (config, command) => {
354
385
  }
355
386
  };
356
387
  var removeCodexHooks = (config, scope) => {
357
- const hooks = asRecord(config.hooks);
388
+ const hooks = asRecord2(config.hooks);
358
389
  if (!hooks) return false;
359
390
  let changed = false;
360
391
  for (const definition of CODEX_HOOK_EVENTS) {
@@ -374,7 +405,7 @@ var removeCodexHooks = (config, scope) => {
374
405
  return changed;
375
406
  };
376
407
  var hasCodexHooks = (config) => {
377
- const hooks = asRecord(config.hooks);
408
+ const hooks = asRecord2(config.hooks);
378
409
  if (!hooks) return false;
379
410
  return CODEX_HOOK_EVENTS.some((definition) => {
380
411
  const entries = hooks[definition.event];
@@ -382,7 +413,7 @@ var hasCodexHooks = (config) => {
382
413
  });
383
414
  };
384
415
  var missingCodexHookEvents = (config) => {
385
- const hooks = asRecord(config.hooks);
416
+ const hooks = asRecord2(config.hooks);
386
417
  return CODEX_HOOK_EVENTS.filter((definition) => {
387
418
  const entries = hooks?.[definition.event];
388
419
  return !Array.isArray(entries) || !entries.some((entry) => isPusharyCodexHook(entry));
@@ -399,22 +430,22 @@ var codexEntryTrustHash = (eventKey, entry) => {
399
430
  const hooks = Array.isArray(entry.hooks) ? entry.hooks : [];
400
431
  const identity = {
401
432
  event_name: eventKey,
402
- hooks: hooks.map((hook) => ({ async: false, ...asRecord(hook) }))
433
+ hooks: hooks.map((hook) => ({ async: false, ...asRecord2(hook) }))
403
434
  };
404
435
  if (typeof entry.matcher === "string") identity.matcher = entry.matcher;
405
436
  return "sha256:" + createHash("sha256").update(canonicalJson(identity), "utf8").digest("hex");
406
437
  };
407
438
  var codexTrustSchemeAgrees = (hooksConfig, config, hooksJsonPath) => {
408
- const hooks = asRecord(hooksConfig?.hooks);
409
- const state = asRecord(asRecord(config.hooks)?.state);
439
+ const hooks = asRecord2(hooksConfig?.hooks);
440
+ const state = asRecord2(asRecord2(config.hooks)?.state);
410
441
  if (!hooks || !state) return false;
411
442
  for (const [event, entries] of Object.entries(hooks)) {
412
443
  if (!Array.isArray(entries)) continue;
413
444
  const eventKey = CODEX_EVENT_KEY[event] ?? codexEventKeyOf(event);
414
445
  for (const [index, entry] of entries.entries()) {
415
- const record = asRecord(entry);
446
+ const record = asRecord2(entry);
416
447
  if (!record) continue;
417
- const stored = asRecord(state[`${hooksJsonPath}:${eventKey}:${index}:0`])?.trusted_hash;
448
+ const stored = asRecord2(state[`${hooksJsonPath}:${eventKey}:${index}:0`])?.trusted_hash;
418
449
  if (typeof stored !== "string") continue;
419
450
  if (stored === codexEntryTrustHash(eventKey, record)) return true;
420
451
  }
@@ -422,14 +453,14 @@ var codexTrustSchemeAgrees = (hooksConfig, config, hooksJsonPath) => {
422
453
  return false;
423
454
  };
424
455
  var codexHookPositions = (hooksConfig) => {
425
- const hooks = asRecord(hooksConfig?.hooks);
456
+ const hooks = asRecord2(hooksConfig?.hooks);
426
457
  const positions = {};
427
458
  for (const definition of CODEX_HOOK_EVENTS) {
428
459
  const entries = hooks?.[definition.event];
429
460
  if (!Array.isArray(entries)) continue;
430
461
  const entryIndex = entries.findIndex((entry) => isPusharyCodexHook(entry));
431
462
  if (entryIndex < 0) continue;
432
- const inner = asRecord(entries[entryIndex])?.hooks;
463
+ const inner = asRecord2(entries[entryIndex])?.hooks;
433
464
  const hookIndex = Array.isArray(inner) ? inner.findIndex((hook) => isPusharyCommand(hook)) : -1;
434
465
  positions[definition.event] = [entryIndex, Math.max(hookIndex, 0)];
435
466
  }
@@ -437,7 +468,7 @@ var codexHookPositions = (hooksConfig) => {
437
468
  };
438
469
  var codexHookStateKey = (hooksJsonPath, event, position) => `${hooksJsonPath}:${CODEX_EVENT_KEY[event]}:${position[0]}:${position[1]}`;
439
470
  var codexVacatedIndexes = (hooksConfig) => {
440
- const hooks = asRecord(hooksConfig?.hooks);
471
+ const hooks = asRecord2(hooksConfig?.hooks);
441
472
  const vacated = {};
442
473
  for (const definition of CODEX_HOOK_EVENTS) {
443
474
  const entries = hooks?.[definition.event];
@@ -448,7 +479,7 @@ var codexVacatedIndexes = (hooksConfig) => {
448
479
  return vacated;
449
480
  };
450
481
  var dropVacatedCodexHookTrust = (config, hooksJsonPath, vacated) => {
451
- const state = asRecord(asRecord(config.hooks)?.state);
482
+ const state = asRecord2(asRecord2(config.hooks)?.state);
452
483
  if (!state) return false;
453
484
  let changed = false;
454
485
  for (const [event, from] of Object.entries(vacated)) {
@@ -464,7 +495,7 @@ var dropVacatedCodexHookTrust = (config, hooksJsonPath, vacated) => {
464
495
  return changed;
465
496
  };
466
497
  var captureCodexHookTrust = (config, hooksJsonPath, positions) => {
467
- const state = asRecord(asRecord(config.hooks)?.state);
498
+ const state = asRecord2(asRecord2(config.hooks)?.state);
468
499
  if (!state) return {};
469
500
  const snapshot = {};
470
501
  for (const [event, position] of Object.entries(positions)) {
@@ -483,16 +514,16 @@ var restoreCodexHookTrust = (config, hooksJsonPath, positions, snapshot) => {
483
514
  return true;
484
515
  };
485
516
  var codexTrustGaps = (config, hooksConfig, hooksJsonPath, command, positions) => {
486
- const state = asRecord(asRecord(config.hooks)?.state);
487
- const hooks = asRecord(hooksConfig?.hooks);
517
+ const state = asRecord2(asRecord2(config.hooks)?.state);
518
+ const hooks = asRecord2(hooksConfig?.hooks);
488
519
  const gaps = [];
489
520
  for (const definition of CODEX_HOOK_EVENTS) {
490
521
  const position = positions[definition.event];
491
522
  if (!position) continue;
492
- const stored = asRecord(state?.[codexHookStateKey(hooksJsonPath, definition.event, position)])?.trusted_hash;
523
+ const stored = asRecord2(state?.[codexHookStateKey(hooksJsonPath, definition.event, position)])?.trusted_hash;
493
524
  const eventKey = CODEX_EVENT_KEY[definition.event] ?? definition.event;
494
- const onDisk = asRecord(
495
- asRecord(hooks?.[definition.event]) ?? (Array.isArray(hooks?.[definition.event]) ? hooks[definition.event][position[0]] : void 0)
525
+ const onDisk = asRecord2(
526
+ asRecord2(hooks?.[definition.event]) ?? (Array.isArray(hooks?.[definition.event]) ? hooks[definition.event][position[0]] : void 0)
496
527
  );
497
528
  const diskHash = onDisk ? codexEntryTrustHash(eventKey, onDisk) : void 0;
498
529
  if (stored !== void 0 && diskHash !== void 0 && stored === diskHash) {
@@ -508,14 +539,14 @@ var codexTrustGaps = (config, hooksConfig, hooksJsonPath, command, positions) =>
508
539
  return gaps;
509
540
  };
510
541
  var removeCodexMcpServer = (config) => {
511
- const servers = asRecord(config.mcp_servers);
542
+ const servers = asRecord2(config.mcp_servers);
512
543
  if (!servers?.pushary) return false;
513
544
  delete servers.pushary;
514
545
  if (Object.keys(servers).length === 0) delete config.mcp_servers;
515
546
  return true;
516
547
  };
517
548
  var removeCodexHookTrust = (config, hooksJsonPath, positions) => {
518
- const state = asRecord(asRecord(config.hooks)?.state);
549
+ const state = asRecord2(asRecord2(config.hooks)?.state);
519
550
  if (!state) return false;
520
551
  let changed = false;
521
552
  for (const definition of CODEX_HOOK_EVENTS) {
@@ -528,7 +559,7 @@ var removeCodexHookTrust = (config, hooksJsonPath, positions) => {
528
559
  }
529
560
  }
530
561
  if (changed && Object.keys(state).length === 0) {
531
- const hooks = asRecord(config.hooks);
562
+ const hooks = asRecord2(config.hooks);
532
563
  if (hooks) {
533
564
  delete hooks.state;
534
565
  if (Object.keys(hooks).length === 0) delete config.hooks;
@@ -549,7 +580,7 @@ var addCodexHookTrust = (config, hooksJsonPath, command, positions) => {
549
580
  if (!position) continue;
550
581
  const key = codexHookStateKey(hooksJsonPath, definition.event, position);
551
582
  const ours = codexHookTrustHash(definition, command);
552
- const existing = asRecord(state[key]) ?? {};
583
+ const existing = asRecord2(state[key]) ?? {};
553
584
  state[key] = { ...existing, trusted_hash: ours };
554
585
  for (const stale of staleTrustKeys(state, hooksJsonPath, definition.event, key, ours)) {
555
586
  delete state[stale];
@@ -559,7 +590,7 @@ var addCodexHookTrust = (config, hooksJsonPath, command, positions) => {
559
590
  var staleTrustKeys = (state, hooksJsonPath, event, currentKey, ourHash) => {
560
591
  const prefix = `${hooksJsonPath}:${CODEX_EVENT_KEY[event]}:`;
561
592
  return Object.keys(state).filter(
562
- (key) => key !== currentKey && key.startsWith(prefix) && asRecord(state[key])?.trusted_hash === ourHash
593
+ (key) => key !== currentKey && key.startsWith(prefix) && asRecord2(state[key])?.trusted_hash === ourHash
563
594
  );
564
595
  };
565
596
 
@@ -588,6 +619,9 @@ var geminiMd = () => join3(homedir2(), ".gemini", "GEMINI.md");
588
619
  var pusharyConfigFile = () => join3(homedir2(), ".pushary", "config.json");
589
620
 
590
621
  export {
622
+ registeredCommands,
623
+ namesOurBinary,
624
+ registrationHolderOf,
591
625
  npmErrorMessage,
592
626
  execNpm,
593
627
  resolveGlobalBinary,
@@ -614,6 +648,7 @@ export {
614
648
  CODEX_HOOK_EVENTS,
615
649
  addCodexMcpServer,
616
650
  readCodexMcpAuth,
651
+ codexRegistrationHolder,
617
652
  addCodexHooks,
618
653
  removeCodexHooks,
619
654
  hasCodexHooks,
@@ -2,24 +2,24 @@ import {
2
2
  detectProviderLiveCapabilities,
3
3
  hasSpawnProvider,
4
4
  resolveControlPolicy
5
- } from "./chunk-TZHDKRMG.js";
5
+ } from "./chunk-WGV3VY7O.js";
6
6
  import {
7
7
  daemonHasRemoteProof,
8
8
  daemonServiceManagerAvailable,
9
9
  hasDaemonServiceDefinition,
10
10
  readDaemonNeedsLogin,
11
11
  readDaemonStatus
12
- } from "./chunk-DOD3A6EU.js";
12
+ } from "./chunk-CRFLU455.js";
13
13
  import {
14
14
  getMachineId
15
- } from "./chunk-WU6LSXJ6.js";
15
+ } from "./chunk-562UJ2DA.js";
16
16
  import {
17
17
  getPackageVersion
18
18
  } from "./chunk-DINDL2CF.js";
19
19
  import {
20
20
  readControlMode,
21
21
  readKeySource
22
- } from "./chunk-SJLGOVC6.js";
22
+ } from "./chunk-4PBCNVI3.js";
23
23
  import {
24
24
  getBaseUrl
25
25
  } from "./chunk-2UMNXADU.js";
@@ -2,11 +2,12 @@ import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  GEMINI_HOOK_EVENTS,
4
4
  hasGeminiHooks
5
- } from "./chunk-HFQ7WSHZ.js";
5
+ } from "./chunk-PD6JY33P.js";
6
6
  import {
7
7
  CODEX_HOOK_EVENTS,
8
- hasCodexHooks
9
- } from "./chunk-XL3RKJYQ.js";
8
+ hasCodexHooks,
9
+ holdBudgetOf
10
+ } from "./chunk-JBJBVERL.js";
10
11
  import {
11
12
  CURSOR_GATE_EVENTS,
12
13
  HOOK_LOCATOR_BINARY,
@@ -101,11 +102,14 @@ var claudeOtherHolders = (settings) => otherHolders(record(settings)?.hooks, CLA
101
102
  var codexOtherHolders = (hooks) => otherHolders(record(hooks)?.hooks, CODEX_GATE_EVENTS, "nested", "seconds");
102
103
  var geminiOtherHolders = (settings) => otherHolders(record(settings)?.hooks, GEMINI_GATE_EVENTS, "nested", "milliseconds");
103
104
  var cursorOtherHolders = (userHooks) => otherHolders(record(userHooks)?.hooks, CURSOR_GATE_EVENTS, "flat", "seconds");
104
- var holdEvents = (table) => table.filter((hook) => hook.holds).map((hook) => hook.event);
105
+ var holdEvents = (table) => table.flatMap((hook) => {
106
+ const seconds = holdBudgetOf(hook);
107
+ return seconds === void 0 ? [] : [{ event: hook.event, seconds }];
108
+ });
105
109
  var unprovenHolds = (hooks, events) => {
106
110
  const table = record(hooks);
107
111
  if (!table) return [];
108
- return events.filter((event) => registeredHooks(table[event], "nested", "seconds").some((hook) => pusharyHookExecutable(hook.command) !== null && hookCommandHoldBudget(hook.command) === void 0));
112
+ return events.filter(({ event, seconds }) => registeredHooks(table[event], "nested", "seconds").some((hook) => pusharyHookExecutable(hook.command) !== null && hookCommandHoldBudget(hook.command) !== seconds)).map(({ event }) => event);
109
113
  };
110
114
  var claudeUnprovenHolds = (settings) => unprovenHolds(record(settings)?.hooks, holdEvents(CLAUDE_HOOK_EVENTS));
111
115
  var codexUnprovenHolds = (hooks) => unprovenHolds(record(hooks)?.hooks, holdEvents(CODEX_HOOK_EVENTS));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseVersion
3
- } from "./chunk-HFQ7WSHZ.js";
3
+ } from "./chunk-PD6JY33P.js";
4
4
 
5
5
  // src/setup/agent-probe.ts
6
6
  import { execSync } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readConfigFileKey
3
- } from "./chunk-SJLGOVC6.js";
3
+ } from "./chunk-4PBCNVI3.js";
4
4
 
5
5
  // src/bell/fleet.ts
6
6
  import { closeSync, constants, futimesSync, lstatSync, mkdirSync, openSync, readdirSync, unlinkSync } from "fs";