@pushary/agent-hooks 1.9.2 → 1.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin/pushary-bell-hook.js +23 -23
  3. package/dist/bin/pushary-bell.js +9 -9
  4. package/dist/bin/pushary-claude.js +26 -26
  5. package/dist/bin/pushary-clean.js +28 -28
  6. package/dist/bin/pushary-codex-bridge.js +18 -18
  7. package/dist/bin/pushary-codex-hook.js +31 -31
  8. package/dist/bin/pushary-codex.js +13 -13
  9. package/dist/bin/pushary-connect.js +13 -13
  10. package/dist/bin/pushary-cowork.js +5 -5
  11. package/dist/bin/pushary-daemon.js +26 -26
  12. package/dist/bin/pushary-disconnect.js +18 -18
  13. package/dist/bin/pushary-doctor.js +30 -30
  14. package/dist/bin/pushary-elicitation-hook.js +25 -25
  15. package/dist/bin/pushary-gemini-bridge.js +13 -13
  16. package/dist/bin/pushary-gemini-hook.js +28 -28
  17. package/dist/bin/pushary-hook.js +32 -32
  18. package/dist/bin/pushary-login.js +12 -12
  19. package/dist/bin/pushary-logout.js +7 -7
  20. package/dist/bin/pushary-mcp.js +9 -9
  21. package/dist/bin/pushary-mode.js +9 -9
  22. package/dist/bin/pushary-notification-hook.js +28 -28
  23. package/dist/bin/pushary-opencode-hook.js +27 -27
  24. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  25. package/dist/bin/pushary-permission-hook.js +31 -31
  26. package/dist/bin/pushary-post-hook.js +28 -28
  27. package/dist/bin/pushary-prompt-hook.js +28 -28
  28. package/dist/bin/pushary-session-end-hook.js +28 -28
  29. package/dist/bin/pushary-session-start-hook.js +31 -31
  30. package/dist/bin/pushary-setup.js +36 -36
  31. package/dist/bin/pushary-stats.js +5 -5
  32. package/dist/bin/pushary-status.js +15 -15
  33. package/dist/bin/pushary-stop-hook.js +28 -28
  34. package/dist/bin/pushary-stopfailure-hook.js +28 -28
  35. package/dist/bin/pushary-suggestions.js +4 -4
  36. package/dist/bin/pushary-transcript-register.js +19 -19
  37. package/dist/bin/pushary-transcripts.js +7 -7
  38. package/dist/bin/pushary-upgrade.js +21 -21
  39. package/dist/bin/pushary-wait.js +9 -9
  40. package/dist/bin/pushary.js +6 -6
  41. package/dist/{chunk-ZSOFZDLY.js → chunk-2OPAES7P.js} +6 -6
  42. package/dist/{chunk-DKDZXJHZ.js → chunk-2UWD2WZC.js} +1 -1
  43. package/dist/{chunk-CTYCABBH.js → chunk-34JHGOYO.js} +1 -1
  44. package/dist/{chunk-L52OIZXV.js → chunk-4GTXFYQ7.js} +1 -1
  45. package/dist/{chunk-MZXXLIF6.js → chunk-552AGATI.js} +1 -1
  46. package/dist/{chunk-HZ57E6LS.js → chunk-5IIAUWEJ.js} +4 -4
  47. package/dist/{chunk-2E4SRGYD.js → chunk-7FVC3RGF.js} +6 -6
  48. package/dist/{chunk-Y6DSV2OS.js → chunk-7MO3CNBX.js} +3 -3
  49. package/dist/{chunk-HLNSTJND.js → chunk-AGW7PMMO.js} +2 -2
  50. package/dist/{chunk-PN3F7LOB.js → chunk-AMFNJPJ5.js} +8 -8
  51. package/dist/{chunk-SFKU5DXZ.js → chunk-AUS3LY4N.js} +2 -2
  52. package/dist/{chunk-UBNJYMTG.js → chunk-BPGATW2F.js} +4 -4
  53. package/dist/{chunk-35N53QLA.js → chunk-CJFVYYKM.js} +9 -9
  54. package/dist/{chunk-B6BLCHJW.js → chunk-CVVPUVBD.js} +3 -3
  55. package/dist/{chunk-73BH4SZY.js → chunk-DEWCUHOY.js} +2 -2
  56. package/dist/{chunk-ABIW72ST.js → chunk-EZFE4PC3.js} +1 -1
  57. package/dist/{chunk-2XK6D4WL.js → chunk-FANGHYW5.js} +1 -1
  58. package/dist/{chunk-BFVE3WPB.js → chunk-FLUECSUC.js} +2 -2
  59. package/dist/{chunk-3O4EBTR3.js → chunk-FSFI2PQL.js} +1 -1
  60. package/dist/{chunk-IH5NZMN4.js → chunk-G2YXIZZS.js} +2 -2
  61. package/dist/{chunk-KP45FGHD.js → chunk-GB2U4QVF.js} +4 -4
  62. package/dist/{chunk-COVPHB56.js → chunk-GOWCPJTP.js} +2 -2
  63. package/dist/{chunk-RTKPR4UA.js → chunk-HBUQ2EQD.js} +1 -1
  64. package/dist/{chunk-N2ATGXI4.js → chunk-HIQNUBWO.js} +2 -2
  65. package/dist/{chunk-JXLANQLV.js → chunk-HPXFPXW7.js} +1 -1
  66. package/dist/{chunk-ZFDGCEKO.js → chunk-JDUWMJDP.js} +104 -169
  67. package/dist/{chunk-IVPVCCFT.js → chunk-KA2GI53J.js} +1 -1
  68. package/dist/{chunk-QDCEEQUS.js → chunk-KO7UOTLD.js} +5 -5
  69. package/dist/{chunk-CEHDCHXK.js → chunk-MH6SJHUE.js} +1 -1
  70. package/dist/{chunk-4KMTRXNL.js → chunk-NGD7H3GZ.js} +2 -2
  71. package/dist/{chunk-BK3R5NRE.js → chunk-NP5RJL34.js} +1 -1
  72. package/dist/{chunk-VMGLXL74.js → chunk-NZJ5LFMX.js} +10 -10
  73. package/dist/{chunk-6S727YUV.js → chunk-OEMF3KJ3.js} +5 -5
  74. package/dist/{chunk-WM2MEFCA.js → chunk-OXJRUMZT.js} +1 -1
  75. package/dist/{chunk-Y4AUVOR7.js → chunk-P3REVSM5.js} +3 -3
  76. package/dist/{chunk-XXSAGQAV.js → chunk-PPC4FZKJ.js} +4 -4
  77. package/dist/{chunk-U4DLXAGD.js → chunk-Q4RF7EEP.js} +1 -1
  78. package/dist/{chunk-Y73RBCQD.js → chunk-Q7FLA4N3.js} +1 -1
  79. package/dist/{chunk-Q36G3P7I.js → chunk-Q7KSRRQ4.js} +1 -1
  80. package/dist/{chunk-SI327OZF.js → chunk-QVUOPB32.js} +2 -2
  81. package/dist/{chunk-XOXW4D6P.js → chunk-SJC5TXK7.js} +3 -3
  82. package/dist/{chunk-UBCTOE5X.js → chunk-U3DBAX7P.js} +2 -2
  83. package/dist/{chunk-HZYUDXIH.js → chunk-UWMEY4RS.js} +5 -5
  84. package/dist/{chunk-ESME4HN2.js → chunk-VRPNTJX3.js} +5 -5
  85. package/dist/{chunk-EUNYNLDU.js → chunk-VRYOALHQ.js} +3 -3
  86. package/dist/{chunk-FWQM6V7Z.js → chunk-WEK6US33.js} +1 -1
  87. package/dist/{chunk-WCHFDVCC.js → chunk-WL4YO6CO.js} +5 -5
  88. package/dist/{chunk-V3P2VSX7.js → chunk-WRDMCP4G.js} +3 -3
  89. package/dist/{chunk-AL4NHBZ6.js → chunk-ZDKGUHPW.js} +2 -2
  90. package/dist/{chunk-ZNUNWWCN.js → chunk-ZPTSEJMD.js} +2 -2
  91. package/dist/{chunk-FHLRRCUZ.js → chunk-ZUZKHTPJ.js} +3 -3
  92. package/dist/{chunk-UX2YSFKS.js → chunk-ZV32QRBR.js} +1 -1
  93. package/dist/{global-upgrade-N24WINE7.js → global-upgrade-VEQ4KQEW.js} +6 -6
  94. package/dist/{paths-53PCHAOJ.js → paths-QTOUBV2V.js} +2 -2
  95. package/dist/{reapply-2SU2ZHEK.js → reapply-T5PLCAGP.js} +8 -8
  96. package/dist/src/index.js +20 -20
  97. package/dist/{upgrade-lock-F6SM6IEZ.js → upgrade-lock-KFZBAPNU.js} +3 -3
  98. package/package.json +1 -1
@@ -10,10 +10,10 @@ import {
10
10
  resolvePackageVersionFromBinary,
11
11
  resolvePathBinary,
12
12
  resolvePathBinaryAsync
13
- } from "./chunk-HZ57E6LS.js";
13
+ } from "./chunk-5IIAUWEJ.js";
14
14
  import {
15
15
  MANAGED_PROVIDERS
16
- } from "./chunk-ZFDGCEKO.js";
16
+ } from "./chunk-JDUWMJDP.js";
17
17
 
18
18
  // src/setup/codex-install.ts
19
19
  var NATIVE_BINARY_MIN_BYTES = 20 * 1024 * 1024;
@@ -6,38 +6,38 @@ import {
6
6
  } from "./chunk-SGZJ5LYH.js";
7
7
  import {
8
8
  hookOwnerOf
9
- } from "./chunk-KP45FGHD.js";
9
+ } from "./chunk-GB2U4QVF.js";
10
10
  import {
11
11
  ensureDaemonRunning
12
- } from "./chunk-WCHFDVCC.js";
12
+ } from "./chunk-WL4YO6CO.js";
13
13
  import {
14
14
  buildTranscriptRecords,
15
15
  decodePublicKey,
16
16
  generateSessionKey,
17
17
  wrapSessionKey
18
- } from "./chunk-U4DLXAGD.js";
18
+ } from "./chunk-Q4RF7EEP.js";
19
19
  import {
20
20
  fetchTranscriptRecipients,
21
21
  uploadTranscriptRecords
22
- } from "./chunk-UX2YSFKS.js";
22
+ } from "./chunk-ZV32QRBR.js";
23
23
  import {
24
24
  transcriptEnvironmentPreference,
25
25
  transcriptsEnabled
26
- } from "./chunk-CTYCABBH.js";
26
+ } from "./chunk-34JHGOYO.js";
27
27
  import {
28
28
  readTranscriptPreference
29
- } from "./chunk-ZNUNWWCN.js";
29
+ } from "./chunk-ZPTSEJMD.js";
30
30
  import {
31
31
  codexHome,
32
32
  pusharyDir
33
- } from "./chunk-HZ57E6LS.js";
33
+ } from "./chunk-5IIAUWEJ.js";
34
34
  import {
35
35
  writeJsonAtomic
36
36
  } from "./chunk-T7E75EKA.js";
37
37
  import {
38
38
  getApiKey,
39
39
  getBaseUrl
40
- } from "./chunk-L52OIZXV.js";
40
+ } from "./chunk-4GTXFYQ7.js";
41
41
 
42
42
  // src/transcript-registration.ts
43
43
  import { createHash } from "crypto";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSseMessages
3
- } from "./chunk-XOXW4D6P.js";
3
+ } from "./chunk-SJC5TXK7.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-ABIW72ST.js";
6
+ } from "./chunk-EZFE4PC3.js";
7
7
 
8
8
  // src/mcp-stdio-bridge.ts
9
9
  var MCP_BRIDGE_BINARY = "pushary-mcp";
@@ -14,19 +14,19 @@ import {
14
14
  } from "./chunk-U4TMAANR.js";
15
15
  import {
16
16
  callMcpTool
17
- } from "./chunk-XOXW4D6P.js";
17
+ } from "./chunk-SJC5TXK7.js";
18
18
  import {
19
19
  reportedInstallSource
20
- } from "./chunk-UBCTOE5X.js";
20
+ } from "./chunk-U3DBAX7P.js";
21
21
  import {
22
22
  NPX_LATEST_COMMAND
23
- } from "./chunk-ABIW72ST.js";
23
+ } from "./chunk-EZFE4PC3.js";
24
24
  import {
25
25
  NO_PAIRING_COMPUTER,
26
26
  PAIR_TTL_SECONDS,
27
27
  classifyConfirmResponse,
28
28
  isAnswerSource
29
- } from "./chunk-ZFDGCEKO.js";
29
+ } from "./chunk-JDUWMJDP.js";
30
30
 
31
31
  // src/reach.ts
32
32
  var reachVerdict = (channels) => {
@@ -14,36 +14,36 @@ import {
14
14
  IDLE_PROMPT_NOTIFICATION,
15
15
  NOTIFICATION_PUSH_TYPES,
16
16
  POSTTOOLUSE_MIRROR_ONLY_TOOLS
17
- } from "./chunk-RTKPR4UA.js";
17
+ } from "./chunk-HBUQ2EQD.js";
18
18
  import {
19
19
  cancelQuestion,
20
20
  isPolicyConfig,
21
21
  sendNotification,
22
22
  waitForAnswer
23
- } from "./chunk-HZYUDXIH.js";
23
+ } from "./chunk-UWMEY4RS.js";
24
24
  import {
25
25
  clientErrorKindOf,
26
26
  reportClientError
27
- } from "./chunk-XXSAGQAV.js";
27
+ } from "./chunk-PPC4FZKJ.js";
28
28
  import {
29
29
  withRetry
30
- } from "./chunk-XOXW4D6P.js";
30
+ } from "./chunk-SJC5TXK7.js";
31
31
  import {
32
32
  getMachineId
33
- } from "./chunk-3O4EBTR3.js";
33
+ } from "./chunk-FSFI2PQL.js";
34
34
  import {
35
35
  reportedInstallSource
36
- } from "./chunk-UBCTOE5X.js";
36
+ } from "./chunk-U3DBAX7P.js";
37
37
  import {
38
38
  canonicalJson
39
- } from "./chunk-HZ57E6LS.js";
39
+ } from "./chunk-5IIAUWEJ.js";
40
40
  import {
41
41
  writeFileAtomic
42
42
  } from "./chunk-T7E75EKA.js";
43
43
  import {
44
44
  getApiKey,
45
45
  getBaseUrl
46
- } from "./chunk-L52OIZXV.js";
46
+ } from "./chunk-4GTXFYQ7.js";
47
47
  import {
48
48
  ACTION_BODY_MAX,
49
49
  AGENT_LABELS_BY_TYPE,
@@ -70,7 +70,7 @@ import {
70
70
  resolvePolicy,
71
71
  toToolLookup,
72
72
  truncateLine
73
- } from "./chunk-ZFDGCEKO.js";
73
+ } from "./chunk-JDUWMJDP.js";
74
74
 
75
75
  // src/policy.ts
76
76
  import { createHash } from "crypto";
@@ -5,16 +5,16 @@ import {
5
5
  import {
6
6
  NOTIFICATION_MATCHED_TYPES,
7
7
  POSTTOOLUSE_MIRRORED_TOOLS
8
- } from "./chunk-RTKPR4UA.js";
8
+ } from "./chunk-HBUQ2EQD.js";
9
9
  import {
10
10
  isProtectedByScope,
11
11
  registerHookEntry
12
- } from "./chunk-HZ57E6LS.js";
12
+ } from "./chunk-5IIAUWEJ.js";
13
13
  import {
14
14
  CLAUDE_PRETOOLUSE_MATCHER,
15
15
  HOOK_BUDGETS,
16
16
  HOOK_LOCATOR_BINARY
17
- } from "./chunk-ZFDGCEKO.js";
17
+ } from "./chunk-JDUWMJDP.js";
18
18
 
19
19
  // src/gemini-config.ts
20
20
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-KZERVKTD.js";
4
4
  import {
5
5
  renderCommandHelp
6
- } from "./chunk-ABIW72ST.js";
6
+ } from "./chunk-EZFE4PC3.js";
7
7
  import {
8
8
  getPackageVersion
9
- } from "./chunk-ZFDGCEKO.js";
9
+ } from "./chunk-JDUWMJDP.js";
10
10
 
11
11
  // src/cli/usage.ts
12
12
  var exitOnHelpFlag = (command) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SETUP_AGENT_CHOICES
3
- } from "./chunk-ZFDGCEKO.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/cli/commands.ts
6
6
  var NPX_LATEST_COMMAND = "npx pushary@latest";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HOOK_LOCATOR_BINARY
3
- } from "./chunk-ZFDGCEKO.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/diagnostics/bridge.ts
6
6
  import { execFileSync } from "child_process";
@@ -3,11 +3,11 @@ import {
3
3
  decodePublicKey,
4
4
  generateSessionKey,
5
5
  wrapSessionKey
6
- } from "./chunk-U4DLXAGD.js";
6
+ } from "./chunk-Q4RF7EEP.js";
7
7
  import {
8
8
  fetchTranscriptRecipients,
9
9
  uploadTranscriptRecords
10
- } from "./chunk-UX2YSFKS.js";
10
+ } from "./chunk-ZV32QRBR.js";
11
11
 
12
12
  // src/live-session.ts
13
13
  var MAX_TRANSCRIPT_QUEUE = 100;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-HZ57E6LS.js";
3
+ } from "./chunk-5IIAUWEJ.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-T7E75EKA.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  registerTranscript
3
- } from "./chunk-PN3F7LOB.js";
3
+ } from "./chunk-AMFNJPJ5.js";
4
4
  import {
5
5
  writeDegraded
6
- } from "./chunk-XXSAGQAV.js";
6
+ } from "./chunk-PPC4FZKJ.js";
7
7
 
8
8
  // src/tool-hook-input.ts
9
9
  var OPTIONAL_TEXT_FIELDS = ["hook_event_name", "session_id", "cwd", "transcript_path", "tool_use_id", "permission_mode"];
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  AGENT_CHOICES
3
- } from "./chunk-CEHDCHXK.js";
3
+ } from "./chunk-MH6SJHUE.js";
4
4
  import {
5
5
  isBridgeLocator
6
- } from "./chunk-2XK6D4WL.js";
6
+ } from "./chunk-FANGHYW5.js";
7
7
  import {
8
8
  pusharyHookExecutable
9
- } from "./chunk-EUNYNLDU.js";
9
+ } from "./chunk-VRYOALHQ.js";
10
10
  import {
11
11
  BELL_HOOK_BINARY
12
- } from "./chunk-DKDZXJHZ.js";
12
+ } from "./chunk-2UWD2WZC.js";
13
13
 
14
14
  // src/setup/hook-ownership.ts
15
15
  var commandsIn = (value) => {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-POFBE6ZY.js";
4
4
  import {
5
5
  autoUpdateState
6
- } from "./chunk-HZ57E6LS.js";
6
+ } from "./chunk-5IIAUWEJ.js";
7
7
  import {
8
8
  readJsonSafe,
9
9
  writeJsonAtomic
@@ -14,7 +14,7 @@ import {
14
14
  cliPackagePathSegments,
15
15
  globalUpgradeEntry,
16
16
  ownPackageRoot
17
- } from "./chunk-ZFDGCEKO.js";
17
+ } from "./chunk-JDUWMJDP.js";
18
18
 
19
19
  // src/auto-update.ts
20
20
  import { spawn } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PRETOOLUSE_GATED_TOOLS
3
- } from "./chunk-ZFDGCEKO.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/claude-tools.ts
6
6
  var POSTTOOLUSE_MIRROR_ONLY_TOOLS = ["TodoWrite", "Task", "WebFetch", "WebSearch"];
@@ -5,7 +5,7 @@ import {
5
5
  permissionDeniedAction,
6
6
  releaseThrottle,
7
7
  reportEvent
8
- } from "./chunk-35N53QLA.js";
8
+ } from "./chunk-CJFVYYKM.js";
9
9
  import {
10
10
  DEFAULT_SESSION
11
11
  } from "./chunk-N6IOSZOE.js";
@@ -13,7 +13,7 @@ import {
13
13
  machineDecisionFor,
14
14
  shouldDeferToNativeMode,
15
15
  wireVerdictFor
16
- } from "./chunk-ZFDGCEKO.js";
16
+ } from "./chunk-JDUWMJDP.js";
17
17
 
18
18
  // src/machine-decision-audit.ts
19
19
  import { basename } from "path";
@@ -2,7 +2,7 @@ import {
2
2
  autoUpdateLock,
3
3
  installPackageGlobally,
4
4
  npmErrorMessage
5
- } from "./chunk-HZ57E6LS.js";
5
+ } from "./chunk-5IIAUWEJ.js";
6
6
  import {
7
7
  writeJsonAtomic
8
8
  } from "./chunk-T7E75EKA.js";
@@ -518,6 +518,106 @@ var redactSecrets = (text) => applyRedactionRules(SECRET_REDACTION_RULES, text);
518
518
  var redactSecretsFromContent = (text) => applyRedactionRules(CUT_OFF_TEXT_REDACTION_RULES, text);
519
519
  var redactSecretsDeep = (text) => redactSecrets(text).replace(HIGH_ENTROPY_RULE.pattern, HIGH_ENTROPY_RULE.replacement);
520
520
 
521
+ // ../contracts/src/shell-analysis.ts
522
+ var SHELL_WORD_SEPARATOR = /[ \t\n]/;
523
+ var trimShellWhitespace = (command) => command.replace(/^[ \t\n]+|[ \t\n]+$/g, "");
524
+ var DOUBLE_QUOTE_ESCAPABLE = /* @__PURE__ */ new Set(['"', "\\", "$", "`"]);
525
+ var SEGMENT_SEPARATORS = /* @__PURE__ */ new Set([";", "\n", "&", "|"]);
526
+ var DOUBLED_SEPARATORS = /* @__PURE__ */ new Set(["&", "|"]);
527
+ var UNDECOMPOSABLE = /* @__PURE__ */ new Set(["`", "<", ">"]);
528
+ var LITERAL_IN_DOUBLE_QUOTES = /* @__PURE__ */ new Set([";", "|", "&", "<", ">", "*", "?", "[", "\\"]);
529
+ var scanShell = (command) => {
530
+ const lexemes = [];
531
+ let quote = null;
532
+ for (let index = 0; index < command.length; index += 1) {
533
+ const char = command.charAt(index);
534
+ const next = command.charAt(index + 1);
535
+ if (char === "\\" && next && quote !== "'" && (quote === null || DOUBLE_QUOTE_ESCAPABLE.has(next))) {
536
+ lexemes.push({ index, text: char + next, quote, kind: "escape" });
537
+ index += 1;
538
+ } else if ((char === "'" || char === '"') && (quote === null || quote === char)) {
539
+ lexemes.push({ index, text: char, quote, kind: "quote" });
540
+ quote = quote === null ? char : null;
541
+ } else {
542
+ lexemes.push({ index, text: char, quote, kind: "text" });
543
+ }
544
+ }
545
+ return quote === null ? lexemes : null;
546
+ };
547
+ var shellCommandSegments = (command) => {
548
+ const lexemes = scanShell(command);
549
+ if (lexemes === null) return null;
550
+ const segments = [];
551
+ let start = 0;
552
+ let consumed = -1;
553
+ for (const lexeme of lexemes) {
554
+ const { index, text, quote, kind } = lexeme;
555
+ if (index <= consumed || kind !== "text" || quote === "'") continue;
556
+ if (text === "`" || text === "$" && command[index + 1] === "(") return null;
557
+ if (quote !== null) continue;
558
+ if (UNDECOMPOSABLE.has(text)) return null;
559
+ if (!SEGMENT_SEPARATORS.has(text)) continue;
560
+ consumed = index + (DOUBLED_SEPARATORS.has(text) && command[index + 1] === text ? 1 : 0);
561
+ segments.push(trimShellWhitespace(command.slice(start, index)));
562
+ start = consumed + 1;
563
+ }
564
+ segments.push(trimShellWhitespace(command.slice(start)));
565
+ const present = segments.filter((segment) => segment.length > 0);
566
+ return present.length > 0 ? present : null;
567
+ };
568
+ var shellVisibleText = (command) => {
569
+ const lexemes = scanShell(command);
570
+ if (lexemes === null) return null;
571
+ let visible = "";
572
+ for (const { text, quote, kind } of lexemes) {
573
+ if (kind === "escape" && quote === '"') return null;
574
+ const literal = kind === "text" && (quote === "'" || quote === '"' && LITERAL_IN_DOUBLE_QUOTES.has(text));
575
+ visible += literal ? "_".repeat(text.length) : text;
576
+ }
577
+ return visible;
578
+ };
579
+ var shellWordsOf = (command) => {
580
+ const lexemes = scanShell(command);
581
+ if (lexemes === null) return null;
582
+ const words = [];
583
+ let text = "";
584
+ let plain = true;
585
+ let expands = false;
586
+ let comment = false;
587
+ let started = false;
588
+ const finishWord = () => {
589
+ if (started) words.push({ text, plain, expands, comment });
590
+ text = "";
591
+ plain = true;
592
+ expands = false;
593
+ comment = false;
594
+ started = false;
595
+ };
596
+ for (const lexeme of lexemes) {
597
+ if (lexeme.kind === "quote") {
598
+ plain = false;
599
+ started = true;
600
+ continue;
601
+ }
602
+ if (lexeme.kind === "escape") {
603
+ text += lexeme.text.slice(1);
604
+ plain = false;
605
+ started = true;
606
+ continue;
607
+ }
608
+ if (lexeme.quote === null && SHELL_WORD_SEPARATOR.test(lexeme.text)) {
609
+ finishWord();
610
+ continue;
611
+ }
612
+ comment ||= lexeme.quote === null && !started && lexeme.text === "#";
613
+ expands ||= lexeme.quote !== "'" && lexeme.text === "$";
614
+ text += lexeme.text;
615
+ started = true;
616
+ }
617
+ finishWord();
618
+ return words;
619
+ };
620
+
521
621
  // ../contracts/src/degraded.ts
522
622
  var DEGRADED_PREFIX = "[degraded]";
523
623
  var degradedPayload = (subsystem, report) => ({
@@ -857,57 +957,6 @@ var PATTERN_INTENT = {
857
957
  grant: "grant",
858
958
  restrict: "restrict"
859
959
  };
860
- var SHELL_ESCAPE = "\\";
861
- var SHELL_DOUBLE_QUOTE = '"';
862
- var SHELL_SUBSTITUTION_SIGIL = "$";
863
- var SHELL_GROUP_OPEN = "(";
864
- var SHELL_QUOTES = /* @__PURE__ */ new Set(["'", SHELL_DOUBLE_QUOTE]);
865
- var SHELL_SEGMENT_SEPARATORS = /* @__PURE__ */ new Set([";", "\n", "&", "|"]);
866
- var SHELL_DOUBLED_SEPARATORS = /* @__PURE__ */ new Set(["&", "|"]);
867
- var SHELL_UNDECOMPOSABLE = /* @__PURE__ */ new Set(["`", "<", ">"]);
868
- var shellCommandSegments = (command) => {
869
- const segments = [];
870
- let current = "";
871
- let quote = null;
872
- for (let index = 0; index < command.length; index += 1) {
873
- const char = command[index];
874
- const next = command[index + 1];
875
- if (quote !== null) {
876
- if (char === SHELL_ESCAPE && quote === SHELL_DOUBLE_QUOTE && next !== void 0) {
877
- current += char + next;
878
- index += 1;
879
- continue;
880
- }
881
- if (quote === SHELL_DOUBLE_QUOTE && (char === "`" || char === SHELL_SUBSTITUTION_SIGIL && next === SHELL_GROUP_OPEN)) return null;
882
- if (char === quote) quote = null;
883
- current += char;
884
- continue;
885
- }
886
- if (char === SHELL_ESCAPE && next !== void 0) {
887
- current += char + next;
888
- index += 1;
889
- continue;
890
- }
891
- if (SHELL_QUOTES.has(char)) {
892
- quote = char;
893
- current += char;
894
- continue;
895
- }
896
- if (SHELL_UNDECOMPOSABLE.has(char)) return null;
897
- if (char === SHELL_SUBSTITUTION_SIGIL && next === SHELL_GROUP_OPEN) return null;
898
- if (SHELL_SEGMENT_SEPARATORS.has(char)) {
899
- if (next === char && SHELL_DOUBLED_SEPARATORS.has(char)) index += 1;
900
- segments.push(current);
901
- current = "";
902
- continue;
903
- }
904
- current += char;
905
- }
906
- if (quote !== null) return null;
907
- segments.push(current);
908
- const present = segments.map((segment) => segment.trim()).filter((segment) => segment.length > 0);
909
- return present.length > 0 ? present : null;
910
- };
911
960
  var everySegmentMatches = (command, matches) => {
912
961
  const segments = shellCommandSegments(command);
913
962
  return segments !== null && segments.every(matches);
@@ -1147,40 +1196,8 @@ var isTrustedExecutable = (first) => {
1147
1196
  if (first.includes("..")) return false;
1148
1197
  return TRUSTED_EXE_PREFIXES.some((prefix) => first.startsWith(prefix));
1149
1198
  };
1150
- var tokenizeShellCommand = (command) => {
1151
- const tokens = [];
1152
- let current = "";
1153
- let quote = null;
1154
- let started = false;
1155
- for (const ch of command) {
1156
- if (quote) {
1157
- if (ch === quote) quote = null;
1158
- else current += ch;
1159
- started = true;
1160
- continue;
1161
- }
1162
- if (ch === '"' || ch === "'") {
1163
- quote = ch;
1164
- started = true;
1165
- continue;
1166
- }
1167
- if (ch === " " || ch === " ") {
1168
- if (started) {
1169
- tokens.push(current);
1170
- current = "";
1171
- started = false;
1172
- }
1173
- continue;
1174
- }
1175
- current += ch;
1176
- started = true;
1177
- }
1178
- if (quote) return null;
1179
- if (started) tokens.push(current);
1180
- return tokens;
1181
- };
1182
1199
  var isSafeSimpleCommand = (segment) => {
1183
- const tokens = tokenizeShellCommand(segment.trim());
1200
+ const tokens = shellWordsOf(segment)?.map((word) => word.text);
1184
1201
  if (!tokens || tokens.length === 0) return false;
1185
1202
  const first = tokens[0];
1186
1203
  if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(first) || first.includes("$")) return false;
@@ -1212,32 +1229,8 @@ var DATE_UTC_FLAG = "-u";
1212
1229
  var isFlagToken = (token) => token.startsWith("-");
1213
1230
  var isPrintOnlySed = (args) => args[0] === SED_QUIET_FLAG && SED_PRINT_ONLY_SCRIPT.test(args[1] ?? "") && !args.slice(2).some(isFlagToken);
1214
1231
  var isReadOnlyDate = (args) => args.every((arg) => arg.startsWith(DATE_FORMAT_PREFIX) || arg === DATE_UTC_FLAG);
1215
- var SINGLE_QUOTE = "'";
1216
- var QUOTED_LITERAL = "_";
1217
- var LITERAL_IN_DOUBLE_QUOTES = /* @__PURE__ */ new Set([";", "|", "&", "<", ">", "*", "?", "[", SHELL_ESCAPE]);
1218
1232
  var READ_ONLY_SEGMENT_SEPARATOR = /&&|\|\||[;|]/g;
1219
1233
  var PIPELINE_CHAIN_SEPARATOR = /&&|\|\||;/g;
1220
- var shellVisibleText = (command) => {
1221
- let visible = "";
1222
- let quote = null;
1223
- for (let index = 0; index < command.length; index += 1) {
1224
- const char = command[index];
1225
- if (quote === SINGLE_QUOTE) {
1226
- quote = char === SINGLE_QUOTE ? null : quote;
1227
- visible += quote === null ? char : QUOTED_LITERAL;
1228
- continue;
1229
- }
1230
- if (quote === SHELL_DOUBLE_QUOTE) {
1231
- if (char === SHELL_ESCAPE && DOUBLE_QUOTE_ESCAPABLE.has(command[index + 1] ?? "")) return null;
1232
- quote = char === SHELL_DOUBLE_QUOTE ? null : quote;
1233
- visible += quote !== null && LITERAL_IN_DOUBLE_QUOTES.has(char) ? QUOTED_LITERAL : char;
1234
- continue;
1235
- }
1236
- if (SHELL_QUOTES.has(char)) quote = char;
1237
- visible += char;
1238
- }
1239
- return quote === null ? visible : null;
1240
- };
1241
1234
  var EXPANSION_THAT_CAN_BECOME_A_FLAG = /\$|(?:^|\s)[*?[]/;
1242
1235
  var SHELL_QUOTE_CHARACTERS = /['"]/g;
1243
1236
  var INSPECTED_ARGUMENT_COMMANDS = /* @__PURE__ */ new Set(["git", "find", "sed", "date"]);
@@ -1257,7 +1250,7 @@ var segmentsSplitWhereVisible = (command, visible, separators) => {
1257
1250
  return segments;
1258
1251
  };
1259
1252
  var isSafeReadOnlyCommand = (command) => {
1260
- const trimmed = command.trim();
1253
+ const trimmed = trimShellWhitespace(command);
1261
1254
  if (!trimmed || trimmed.length > 2e3) return false;
1262
1255
  if (/[\n\r]/.test(trimmed)) return false;
1263
1256
  const visible = shellVisibleText(trimmed);
@@ -1267,7 +1260,7 @@ var isSafeReadOnlyCommand = (command) => {
1267
1260
  const visibleWithoutRedirection = blankedSafeRedirections(visible);
1268
1261
  if (/[<>]/.test(visibleWithoutRedirection)) return false;
1269
1262
  if (visibleWithoutRedirection.replace(/&&/g, " ").includes("&")) return false;
1270
- return segmentsSplitWhereVisible(blankedSafeRedirections(trimmed), visibleWithoutRedirection, READ_ONLY_SEGMENT_SEPARATOR).every((segment) => segment.trim().length > 0 && isSafeSimpleCommand(segment));
1263
+ return segmentsSplitWhereVisible(blankedSafeRedirections(trimmed), visibleWithoutRedirection, READ_ONLY_SEGMENT_SEPARATOR).every((segment) => trimShellWhitespace(segment).length > 0 && isSafeSimpleCommand(segment));
1271
1264
  };
1272
1265
  var isAutoApprove = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "approve";
1273
1266
  var isAutoDeny = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "deny";
@@ -1481,67 +1474,9 @@ var SHELL_RESERVED_WORDS = /* @__PURE__ */ new Set([
1481
1474
  var HARMLESS_GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--no-pager", "--version", "-v", "-V", "--help", "-h"]);
1482
1475
  var END_OF_OPTIONS = "--";
1483
1476
  var SUBCOMMAND_DEPTH = 3;
1484
- var SHELL_COMMENT_MARK = "#";
1485
1477
  var SHELL_LINE_CONTINUATION = /\\\n/g;
1486
- var SHELL_WORD_BREAK = /\s/;
1487
- var DOUBLE_QUOTE_ESCAPABLE = /* @__PURE__ */ new Set([SHELL_DOUBLE_QUOTE, SHELL_ESCAPE, SHELL_SUBSTITUTION_SIGIL, "`"]);
1488
- var shellWordsOf = (segment) => {
1489
- const words = [];
1490
- let text = "";
1491
- let plain = true;
1492
- let expands = false;
1493
- let comment = false;
1494
- let started = false;
1495
- let quote = null;
1496
- const finishWord = () => {
1497
- if (started) words.push({ text, plain, expands, comment });
1498
- text = "";
1499
- plain = true;
1500
- expands = false;
1501
- comment = false;
1502
- started = false;
1503
- };
1504
- for (let index = 0; index < segment.length; index += 1) {
1505
- const char = segment[index];
1506
- const next = segment[index + 1];
1507
- if (quote === "'") {
1508
- if (char === quote) quote = null;
1509
- else text += char;
1510
- continue;
1511
- }
1512
- if (char === SHELL_ESCAPE && next !== void 0 && (quote === null || DOUBLE_QUOTE_ESCAPABLE.has(next))) {
1513
- text += next;
1514
- plain = false;
1515
- started = true;
1516
- index += 1;
1517
- continue;
1518
- }
1519
- if (quote === SHELL_DOUBLE_QUOTE) {
1520
- if (char === quote) quote = null;
1521
- else text += char;
1522
- expands ||= char === SHELL_SUBSTITUTION_SIGIL;
1523
- continue;
1524
- }
1525
- if (SHELL_QUOTES.has(char)) {
1526
- quote = char;
1527
- plain = false;
1528
- started = true;
1529
- continue;
1530
- }
1531
- if (SHELL_WORD_BREAK.test(char)) {
1532
- finishWord();
1533
- continue;
1534
- }
1535
- comment ||= !started && char === SHELL_COMMENT_MARK;
1536
- expands ||= char === SHELL_SUBSTITUTION_SIGIL;
1537
- text += char;
1538
- started = true;
1539
- }
1540
- finishWord();
1541
- return words;
1542
- };
1543
1478
  var invocationOf = (segment) => {
1544
- const [program, ...args] = shellWordsOf(segment);
1479
+ const [program, ...args] = shellWordsOf(segment) ?? [];
1545
1480
  return { program, args };
1546
1481
  };
1547
1482
  var argsAfterHarmlessGlobalFlags = (args) => {
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  describeKeyCheck,
6
6
  keyCheckFromResponse
7
- } from "./chunk-Y6DSV2OS.js";
7
+ } from "./chunk-7MO3CNBX.js";
8
8
  import {
9
9
  EXIT
10
10
  } from "./chunk-KZERVKTD.js";