pushary 1.9.139 → 1.9.141

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 (135) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/data/vscode-plugin/README.md +2 -0
  3. package/dist/{api-JY6EQT7A.js → api-JWLCKSWR.js} +11 -11
  4. package/dist/bin/pushary-audit.js +3 -3
  5. package/dist/bin/pushary-bell-hook.js +28 -28
  6. package/dist/bin/pushary-bell.js +10 -10
  7. package/dist/bin/pushary-claude.js +27 -27
  8. package/dist/bin/pushary-clean.js +36 -36
  9. package/dist/bin/pushary-codex-bridge.js +23 -23
  10. package/dist/bin/pushary-codex-hook.js +35 -35
  11. package/dist/bin/pushary-codex-session.js +9 -9
  12. package/dist/bin/pushary-codex.js +16 -16
  13. package/dist/bin/pushary-connect.js +29 -29
  14. package/dist/bin/pushary-cowork.js +5 -5
  15. package/dist/bin/pushary-daemon.js +93 -95
  16. package/dist/bin/pushary-disconnect.js +28 -28
  17. package/dist/bin/pushary-display-hook.js +93 -5
  18. package/dist/bin/pushary-doctor.js +43 -43
  19. package/dist/bin/pushary-elicitation-hook.js +28 -28
  20. package/dist/bin/pushary-gemini-bridge.js +19 -18
  21. package/dist/bin/pushary-gemini-hook.js +32 -32
  22. package/dist/bin/pushary-hook.js +35 -35
  23. package/dist/bin/pushary-login.js +21 -21
  24. package/dist/bin/pushary-logout.js +27 -27
  25. package/dist/bin/pushary-mcp.js +12 -12
  26. package/dist/bin/pushary-mode.js +15 -15
  27. package/dist/bin/pushary-notification-hook.js +27 -27
  28. package/dist/bin/pushary-opencode-hook.js +31 -31
  29. package/dist/bin/pushary-permission-denied-hook.js +35 -35
  30. package/dist/bin/pushary-permission-hook.js +35 -35
  31. package/dist/bin/pushary-post-hook.js +28 -28
  32. package/dist/bin/pushary-prompt-hook.js +27 -27
  33. package/dist/bin/pushary-session-end-hook.js +27 -27
  34. package/dist/bin/pushary-session-start-hook.js +36 -36
  35. package/dist/bin/pushary-setup.js +51 -51
  36. package/dist/bin/pushary-stats.js +5 -5
  37. package/dist/bin/pushary-status.js +33 -33
  38. package/dist/bin/pushary-stop-hook.js +27 -27
  39. package/dist/bin/pushary-stopfailure-hook.js +27 -27
  40. package/dist/bin/pushary-suggestions.js +15 -15
  41. package/dist/bin/pushary-transcript-register.js +17 -17
  42. package/dist/bin/pushary-transcripts.js +25 -25
  43. package/dist/bin/pushary-upgrade.js +41 -41
  44. package/dist/bin/pushary-wait.js +15 -15
  45. package/dist/bin/pushary.js +7 -7
  46. package/dist/{chunk-SVKZKLEP.js → chunk-24BLJAQN.js} +1 -1
  47. package/dist/{chunk-SKVPWXNK.js → chunk-3MFJDZ2L.js} +10 -10
  48. package/dist/{chunk-UTUR6WEA.js → chunk-3MMOB5TM.js} +3 -3
  49. package/dist/{chunk-BURSH6SW.js → chunk-3PALTBFX.js} +4 -4
  50. package/dist/{chunk-P3UCAWUP.js → chunk-3RBUCAO7.js} +6 -6
  51. package/dist/{chunk-KYWH4XUR.js → chunk-3YV26XPH.js} +3 -3
  52. package/dist/{chunk-GGTLV67J.js → chunk-4JR6PPIY.js} +4 -4
  53. package/dist/{chunk-RBPAUX6C.js → chunk-4KHBN7LI.js} +5 -5
  54. package/dist/{chunk-4NLZUCPG.js → chunk-4Y2LO2WB.js} +2 -2
  55. package/dist/{chunk-U7Z53YWH.js → chunk-4ZTPPMLM.js} +4 -4
  56. package/dist/{chunk-J5SMCRIT.js → chunk-5DMGHDOT.js} +5 -5
  57. package/dist/{chunk-LHUA6ADC.js → chunk-62V26PAL.js} +3 -3
  58. package/dist/{chunk-IAWFSD4Q.js → chunk-6DAXKHVX.js} +1 -1
  59. package/dist/{chunk-KDQSPNPH.js → chunk-7EYUDJQ6.js} +16 -16
  60. package/dist/{chunk-KXHGEJVW.js → chunk-7TKF7IFS.js} +2 -2
  61. package/dist/{chunk-KQVURVAP.js → chunk-A6KNDKO5.js} +597 -116
  62. package/dist/{chunk-IDXCVT6W.js → chunk-ACG7RC7N.js} +3 -3
  63. package/dist/{chunk-4RKB6X4S.js → chunk-AIZ5KC2N.js} +2 -2
  64. package/dist/{chunk-BRXKVYTV.js → chunk-ALJL6GDD.js} +1 -1
  65. package/dist/{chunk-M6TJWXST.js → chunk-ARIJUXCG.js} +8 -8
  66. package/dist/{chunk-QTR6KQEU.js → chunk-BFXIQGWS.js} +1 -1
  67. package/dist/{chunk-ZYLZCNOJ.js → chunk-BKWDG5QV.js} +1 -1
  68. package/dist/{chunk-2MJMKM6D.js → chunk-C4VTURGH.js} +1 -1
  69. package/dist/{chunk-IOWB43KY.js → chunk-CAUSBRTJ.js} +1 -1
  70. package/dist/{chunk-DTJZK3MN.js → chunk-CL3OIICA.js} +6 -6
  71. package/dist/{chunk-LHYBHWCK.js → chunk-CUJ2MGG5.js} +2 -2
  72. package/dist/{chunk-H4O4IPWY.js → chunk-CVGVWUNE.js} +5 -5
  73. package/dist/{chunk-3FNBN4JQ.js → chunk-CWCJFCAY.js} +1 -1
  74. package/dist/{chunk-LYLADUYE.js → chunk-D35XQMWO.js} +2 -2
  75. package/dist/{chunk-UZZRSCFR.js → chunk-EADQYNLU.js} +5 -5
  76. package/dist/{chunk-M4G4VWW6.js → chunk-F335PCA4.js} +1 -1
  77. package/dist/{chunk-CQLQFN6B.js → chunk-FKKS4ZC5.js} +3 -12
  78. package/dist/{chunk-2X2JHX77.js → chunk-FOPV3VQD.js} +4 -4
  79. package/dist/{chunk-FSTSLVZJ.js → chunk-GA72NGS7.js} +1 -1
  80. package/dist/{chunk-CZH3JDVB.js → chunk-GGXAZTSW.js} +2 -2
  81. package/dist/{chunk-7MPKMLE3.js → chunk-GX46NBAE.js} +11 -11
  82. package/dist/{chunk-IHUXZGHB.js → chunk-HEXX52SX.js} +1 -1
  83. package/dist/{chunk-S63DCSH4.js → chunk-I547BHSE.js} +4 -4
  84. package/dist/{chunk-OBPBT6RG.js → chunk-I72H3AWD.js} +3 -3
  85. package/dist/{chunk-T5FPA2JO.js → chunk-IR7J5WY4.js} +3 -3
  86. package/dist/{chunk-3PQEUSPK.js → chunk-J2ELAXGI.js} +1 -1
  87. package/dist/{chunk-6RAHONLG.js → chunk-J3NMHMG7.js} +2 -2
  88. package/dist/{chunk-6A6OSNC2.js → chunk-JBQFVXDK.js} +1 -1
  89. package/dist/{chunk-INGRSQVC.js → chunk-KAYK66B3.js} +3 -3
  90. package/dist/{chunk-FIQ7ND7P.js → chunk-LCYHJQGQ.js} +5 -5
  91. package/dist/{chunk-2YMVIBFT.js → chunk-ME2ZKG6Y.js} +12 -12
  92. package/dist/{chunk-LKSFQTGQ.js → chunk-MQJEDVTH.js} +1 -1
  93. package/dist/{chunk-C4F5RUJL.js → chunk-MW6MPOQZ.js} +6 -6
  94. package/dist/{chunk-XQYBTRVW.js → chunk-NDAJSNIZ.js} +1 -1
  95. package/dist/{chunk-DF2CUKN4.js → chunk-NFXWQDZ6.js} +2 -2
  96. package/dist/{chunk-ZAZQHOBS.js → chunk-O2CW5IFD.js} +11 -11
  97. package/dist/{chunk-GVJWHTN2.js → chunk-OR47JOLE.js} +2 -2
  98. package/dist/{chunk-422KDIO5.js → chunk-PD5LSNEK.js} +2 -2
  99. package/dist/{chunk-IEHI64ZN.js → chunk-PDES33BK.js} +1 -1
  100. package/dist/{chunk-AOAIYHAP.js → chunk-PHSPXFAY.js} +5 -5
  101. package/dist/{chunk-AEC72YC3.js → chunk-PNKFGNJF.js} +6 -6
  102. package/dist/{chunk-OBKHLKKB.js → chunk-PY2JHBNC.js} +4 -4
  103. package/dist/{chunk-LSABM2ES.js → chunk-Q4XW5FWF.js} +2 -2
  104. package/dist/{chunk-WES6E62H.js → chunk-Q6EK2GDR.js} +4 -4
  105. package/dist/{chunk-ZNMLL2WN.js → chunk-QNEF5JII.js} +2 -2
  106. package/dist/{chunk-XKXOT2ZU.js → chunk-QVXNSVBS.js} +3 -3
  107. package/dist/{chunk-LVL7XAXK.js → chunk-RO36S2KY.js} +5 -5
  108. package/dist/{chunk-QMKI5RGT.js → chunk-RQCKUCWK.js} +4 -5
  109. package/dist/{chunk-Q5H5AFS7.js → chunk-TIX4DZ2J.js} +3 -3
  110. package/dist/{chunk-E46NE7FB.js → chunk-U4P4NDVB.js} +2 -0
  111. package/dist/{chunk-GCOOOIBX.js → chunk-UJ2WT54H.js} +43 -31
  112. package/dist/{chunk-LGIB72D7.js → chunk-UOKA4ENY.js} +3 -3
  113. package/dist/{chunk-OLJTUTD2.js → chunk-UQ352C7S.js} +37 -33
  114. package/dist/{chunk-7Q6YKZY2.js → chunk-VBYWBGIJ.js} +3 -3
  115. package/dist/{chunk-QG5MJ6NW.js → chunk-VR6VWNLQ.js} +6 -6
  116. package/dist/{chunk-ISDMTGZ3.js → chunk-VTT3WV4C.js} +1 -1
  117. package/dist/{chunk-MAPC5KKZ.js → chunk-XBPBYSNM.js} +2 -2
  118. package/dist/{chunk-FMQBG2TD.js → chunk-XYFKYZCQ.js} +6 -6
  119. package/dist/{chunk-J6CNQ5UK.js → chunk-XYRPLFMD.js} +1 -1
  120. package/dist/{chunk-P6S4CALA.js → chunk-YKL7VBKJ.js} +5 -5
  121. package/dist/{chunk-MNVBO6UO.js → chunk-ZE56WMFL.js} +4 -4
  122. package/dist/{codex-app-cards-switch-TOHSGS5T.js → codex-app-cards-switch-NRAMENRL.js} +12 -12
  123. package/dist/{codex-card-routing-BPCOKSBO.js → codex-card-routing-D7ARIQKL.js} +2 -2
  124. package/dist/{codex-desktop-launch-6LD5GETH.js → codex-desktop-launch-2X4UEMRL.js} +2 -2
  125. package/dist/{codex-session-launch-ZVFPD4ON.js → codex-session-launch-FY5QIZSI.js} +20 -20
  126. package/dist/{config-3AFJSGM2.js → config-NDOIVL6S.js} +3 -3
  127. package/dist/{global-upgrade-6SWFRW5G.js → global-upgrade-MS3WGHEP.js} +9 -9
  128. package/dist/{identity-K2VBL5PB.js → identity-VXA3TZ7U.js} +4 -4
  129. package/dist/{live-capabilities-VQEG7TCE.js → live-capabilities-2LCBHUWN.js} +14 -11
  130. package/dist/{paths-ZAVMBGAQ.js → paths-HOCSWOBY.js} +3 -3
  131. package/dist/{reapply-BXMMOQXK.js → reapply-VYMO3QM6.js} +29 -29
  132. package/dist/src/index.js +34 -34
  133. package/dist/{upgrade-lock-UZN332AO.js → upgrade-lock-XH5AQIOD.js} +4 -4
  134. package/dist/{usage-EDDIN5YZ.js → usage-EVX6CH5H.js} +3 -3
  135. package/package.json +1 -1
@@ -118,9 +118,9 @@ var isAgentQuestionSet = (value) => {
118
118
  const labels = /* @__PURE__ */ new Set();
119
119
  for (const option of question.options) {
120
120
  if (!option || typeof option !== "object" || Array.isArray(option)) return false;
121
- const record4 = option;
122
- const label = record4.label;
123
- if (typeof label !== "string" || label.length === 0 || labels.has(label) || record4.description !== void 0 && typeof record4.description !== "string") return false;
121
+ const record5 = option;
122
+ const label = record5.label;
123
+ if (typeof label !== "string" || label.length === 0 || labels.has(label) || record5.description !== void 0 && typeof record5.description !== "string") return false;
124
124
  labels.add(label);
125
125
  }
126
126
  questions.add(question.question);
@@ -191,6 +191,42 @@ var codexQuestionAnswerReason = (answers) => {
191
191
  return `${CODEX_QUESTION_ANSWERED_IN_PUSHARY}. ${answered}. ${CODEX_QUESTION_CONTINUE}`;
192
192
  };
193
193
 
194
+ // ../contracts/src/session-runtime.ts
195
+ var SPAWN_CAPABILITY = "spawn";
196
+ var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
197
+ var CLAUDE_RESUME_CAPABILITY = "claude-resume";
198
+ var CODEX_BRIDGE_CAPABILITY = "codex-bridge";
199
+ var CODEX_RESUME_CAPABILITY = "codex-resume";
200
+ var GEMINI_BRIDGE_CAPABILITY = "gemini-bridge";
201
+ var GEMINI_RESUME_CAPABILITY = "gemini-resume";
202
+ var SESSION_RUNTIMES = {
203
+ claude: {
204
+ provider: "claude",
205
+ label: "Claude",
206
+ protocol: "claude-stream-json",
207
+ bridgeCapability: CLAUDE_BRIDGE_CAPABILITY,
208
+ resumeCapability: CLAUDE_RESUME_CAPABILITY,
209
+ phoneResume: false
210
+ },
211
+ codex: {
212
+ provider: "codex",
213
+ label: "Codex",
214
+ protocol: "codex-app-server",
215
+ bridgeCapability: CODEX_BRIDGE_CAPABILITY,
216
+ resumeCapability: CODEX_RESUME_CAPABILITY,
217
+ phoneResume: true
218
+ },
219
+ gemini: {
220
+ provider: "gemini",
221
+ label: "Gemini",
222
+ protocol: "gemini-stream-json",
223
+ bridgeCapability: GEMINI_BRIDGE_CAPABILITY,
224
+ resumeCapability: GEMINI_RESUME_CAPABILITY,
225
+ phoneResume: true
226
+ }
227
+ };
228
+ var sessionProvidersAdvertisedBy = (capabilities) => Object.values(SESSION_RUNTIMES).filter((runtime) => capabilities.includes(runtime.bridgeCapability)).map((runtime) => runtime.provider);
229
+
194
230
  // ../contracts/src/claude-connector.ts
195
231
  var CLAUDE_DIRECTORY_URL = "https://claude.ai/directory/pushary";
196
232
  var CLAUDE_CONNECTOR_URL = "https://pushary.com/api/mcp/mcp";
@@ -236,7 +272,7 @@ var defaults = {
236
272
  policyAgent: null,
237
273
  repoAware: false,
238
274
  disconnectable: false,
239
- managedProvider: false,
275
+ sessionRuntime: null,
240
276
  bridged: false,
241
277
  enforcement: "cooperative",
242
278
  connectVia: "Plain MCP",
@@ -259,7 +295,7 @@ var AGENTS = {
259
295
  policyAgent: "claude_code",
260
296
  repoAware: true,
261
297
  disconnectable: true,
262
- managedProvider: true,
298
+ sessionRuntime: SESSION_RUNTIMES.claude,
263
299
  enforcement: "enforced",
264
300
  connectVia: "Native hooks + MCP",
265
301
  setupCommand: PUSHARY_SETUP_COMMAND,
@@ -287,7 +323,7 @@ var AGENTS = {
287
323
  policyAgent: "codex",
288
324
  repoAware: true,
289
325
  disconnectable: true,
290
- managedProvider: true,
326
+ sessionRuntime: SESSION_RUNTIMES.codex,
291
327
  enforcement: "enforced",
292
328
  connectVia: "Native hooks + MCP",
293
329
  setupCommand: PUSHARY_SETUP_COMMAND,
@@ -308,7 +344,7 @@ var AGENTS = {
308
344
  policyAgent: "gemini_cli",
309
345
  repoAware: true,
310
346
  disconnectable: true,
311
- managedProvider: true,
347
+ sessionRuntime: SESSION_RUNTIMES.gemini,
312
348
  enforcement: "enforced",
313
349
  connectVia: "Native hooks + MCP",
314
350
  setupCommand: PUSHARY_SETUP_COMMAND,
@@ -524,7 +560,7 @@ var SESSION_HISTORY_AGENT_TYPES = Object.freeze(
524
560
  );
525
561
  var DISCONNECTABLE_AGENTS = Object.freeze(Object.values(AGENTS).flatMap((agent) => agent.disconnectable && agent.hookSource !== null ? [agent.hookSource] : []));
526
562
  var REPO_AWARE_AGENTS = Object.freeze(Object.values(AGENTS).flatMap((agent) => agent.repoAware ? [agent.policyAgent] : []));
527
- var MANAGED_PROVIDERS = Object.freeze(Object.values(AGENTS).flatMap((agent) => agent.managedProvider ? [agent.hookSource] : []));
563
+ var MANAGED_PROVIDERS = Object.freeze(Object.values(AGENTS).flatMap((agent) => agent.sessionRuntime ? [agent.sessionRuntime.provider] : []));
528
564
  var BRIDGE_HOOK_SOURCES = Object.freeze(Object.values(AGENTS).flatMap((agent) => agent.bridged ? [agent.hookSource] : []));
529
565
  var isAgentId = (value) => Object.keys(AGENTS).includes(value);
530
566
  var isHooklessDisconnectableAgent = (value) => isAgentId(value) && AGENTS[value].disconnectable && AGENTS[value].hookSource === null;
@@ -616,18 +652,18 @@ var CANONICAL_COMMAND_KEYS = ["command"];
616
652
  var SHELL_TOOLS = /* @__PURE__ */ new Set([SHELL_TOOL, POWERSHELL_TOOL]);
617
653
  var PATH_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit", "Read"]);
618
654
  var PHONE_ANSWERED_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
619
- var firstString = (record4, keys2) => {
620
- for (const key of keys2) {
621
- const value = record4[key];
655
+ var firstString = (record5, keys3) => {
656
+ for (const key of keys3) {
657
+ const value = record5[key];
622
658
  if (typeof value === "string" && value.length > 0) return value;
623
659
  }
624
660
  return void 0;
625
661
  };
626
- var pathsNamedIn = (record4, keys2) => keys2.flatMap((key) => {
627
- const value = record4[key];
662
+ var pathsNamedIn = (record5, keys3) => keys3.flatMap((key) => {
663
+ const value = record5[key];
628
664
  return typeof value === "string" && value.length > 0 ? [value] : [];
629
665
  });
630
- var namesOneFile = (paths, resolvePath) => new Set(paths.map(resolvePath)).size === 1;
666
+ var namesOneFile = (paths2, resolvePath) => new Set(paths2.map(resolvePath)).size === 1;
631
667
  var filePathKeysOf = (profile) => [...profile.pathInputKeys, ...CANONICAL_PATH_KEYS];
632
668
  var namesAFilePath = (profile, toolInput) => pathsNamedIn(toolInput, filePathKeysOf(profile)).length > 0;
633
669
  var withCanonicalInputKeys = (profile, toolInput) => {
@@ -673,9 +709,9 @@ var toToolLookup = (profile, toolName, toolInput, resolvePath = (path) => path)
673
709
  return { tool, input: { command, ...context }, unreadable: false };
674
710
  }
675
711
  if (!PATH_TOOLS.has(tool)) return { tool, input: toolInput, unreadable: false };
676
- const paths = pathsNamedIn(toolInput, filePathKeysOf(profile));
677
- const [filePath] = paths;
678
- if (!filePath || !namesOneFile(paths, resolvePath)) return { tool, input: toolInput, unreadable: true };
712
+ const paths2 = pathsNamedIn(toolInput, filePathKeysOf(profile));
713
+ const [filePath] = paths2;
714
+ if (!filePath || !namesOneFile(paths2, resolvePath)) return { tool, input: toolInput, unreadable: true };
679
715
  return { tool, input: { ...withCanonicalInputKeys(profile, toolInput), file_path: resolvePath(filePath) }, unreadable: false };
680
716
  };
681
717
  var NO_AGENT_PROMPT_REASON = "Pushary needs an answer from the phone before this can run, and this agent has no approval prompt of its own here, so nothing ran. Ask the user, then try again.";
@@ -1148,7 +1184,7 @@ var readNullableText = (value, field) => {
1148
1184
  var ASKED_TEXT_FIELDS = ["id", "siteId", "type", "content", "createdAt"];
1149
1185
  var ASKED_NULLABLE_FIELDS = ["questionType", "context", "contextPayloadSha256", "correlationId", "externalId", "sessionId", "agentType", "agentName", "machineId", "toolName", "toolTarget", "requestedByUserId"];
1150
1186
  var DECISION_NULLABLE_FIELDS = ["response", "responseSource", "note", "decisionOutcome", "decisionOrigin", "decidedByUserId", "decidedByActor", "riskClass", "answeredAt"];
1151
- var isComplete = (record4, fields) => fields.every((field) => field in record4);
1187
+ var isComplete = (record5, fields) => fields.every((field) => field in record5);
1152
1188
  var readFields = (value, fields, read) => {
1153
1189
  const result = {};
1154
1190
  for (const field of fields) {
@@ -1160,7 +1196,7 @@ var readFields = (value, fields, read) => {
1160
1196
  };
1161
1197
  var ASKED_PAYLOAD_KEYS = /* @__PURE__ */ new Set(["event", ...ASKED_TEXT_FIELDS, ...ASKED_NULLABLE_FIELDS]);
1162
1198
  var DECISION_PAYLOAD_KEYS = /* @__PURE__ */ new Set(["event", "id", "autoResolved", "decisionLatencyMs", ...DECISION_NULLABLE_FIELDS]);
1163
- var hasOnlyKeys = (value, keys2) => Object.keys(value).every((key) => keys2.has(key));
1199
+ var hasOnlyKeys = (value, keys3) => Object.keys(value).every((key) => keys3.has(key));
1164
1200
  var parseAskedPayload = (value) => {
1165
1201
  const text3 = readFields(value, ASKED_TEXT_FIELDS, readText);
1166
1202
  const nullable = readFields(value, ASKED_NULLABLE_FIELDS, readNullableText);
@@ -1205,7 +1241,7 @@ var parseAllOrNothing = (values, parse) => {
1205
1241
  }
1206
1242
  return parsed;
1207
1243
  };
1208
- var entriesFitPage = (entries, beforeSeq) => beforeSeq === null || entries.every((entry) => entry.seq < beforeSeq);
1244
+ var entriesFitPage = (entries, beforeSeq) => beforeSeq === null || entries.every((entry2) => entry2.seq < beforeSeq);
1209
1245
  var parseSite = (value) => {
1210
1246
  if (!isPlainObject(value)) return null;
1211
1247
  const { siteId, siteName, beforeSeq, retentionFloor } = value;
@@ -1230,68 +1266,68 @@ var boundaryGapFindings = (entries, beforeSeq) => {
1230
1266
  };
1231
1267
  var linkFindings = (entries) => {
1232
1268
  const findings = [];
1233
- entries.forEach((entry, index) => {
1269
+ entries.forEach((entry2, index) => {
1234
1270
  const previous = entries[index - 1];
1235
1271
  if (!previous) {
1236
- if (entry.seq === 1 && entry.prevHash !== AUDIT_CHAIN_GENESIS_HASH) findings.push({ kind: "genesis_mismatch", seq: entry.seq });
1272
+ if (entry2.seq === 1 && entry2.prevHash !== AUDIT_CHAIN_GENESIS_HASH) findings.push({ kind: "genesis_mismatch", seq: entry2.seq });
1237
1273
  return;
1238
1274
  }
1239
- if (entry.seq !== previous.seq + 1) findings.push({ kind: "sequence_gap", afterSeq: previous.seq, seq: entry.seq });
1240
- if (entry.prevHash !== previous.entryHash) findings.push({ kind: "broken_link", seq: entry.seq });
1275
+ if (entry2.seq !== previous.seq + 1) findings.push({ kind: "sequence_gap", afterSeq: previous.seq, seq: entry2.seq });
1276
+ if (entry2.prevHash !== previous.entryHash) findings.push({ kind: "broken_link", seq: entry2.seq });
1241
1277
  });
1242
1278
  return findings;
1243
1279
  };
1244
- var entryHashFindings = (entries, crypto) => entries.flatMap((entry) => crypto.sha256Hex(auditEntryMessage(entry)) === entry.entryHash ? [] : [{ kind: "entry_altered", seq: entry.seq }]);
1245
- var payloadMatchesEntry = (payload, entry, siteId, crypto) => {
1246
- if (payload.id !== entry.interactionId || auditPayloadHash(payload, crypto.sha256Hex) !== entry.payloadHash) return false;
1247
- return payload.event === "asked" ? payload.siteId === siteId && payload.createdAt === entry.interactionCreatedAt : isFinalAuditDecision(payload) === entry.decisionFinal;
1280
+ var entryHashFindings = (entries, crypto) => entries.flatMap((entry2) => crypto.sha256Hex(auditEntryMessage(entry2)) === entry2.entryHash ? [] : [{ kind: "entry_altered", seq: entry2.seq }]);
1281
+ var payloadMatchesEntry = (payload, entry2, siteId, crypto) => {
1282
+ if (payload.id !== entry2.interactionId || auditPayloadHash(payload, crypto.sha256Hex) !== entry2.payloadHash) return false;
1283
+ return payload.event === "asked" ? payload.siteId === siteId && payload.createdAt === entry2.interactionCreatedAt : isFinalAuditDecision(payload) === entry2.decisionFinal;
1248
1284
  };
1249
1285
  var lastDecisionSeqByInteraction = (entries) => {
1250
1286
  const lastSeq = /* @__PURE__ */ new Map();
1251
- for (const entry of entries) {
1252
- if (entry.event === "decision") lastSeq.set(entry.interactionId, Math.max(entry.seq, lastSeq.get(entry.interactionId) ?? 0));
1287
+ for (const entry2 of entries) {
1288
+ if (entry2.event === "decision") lastSeq.set(entry2.interactionId, Math.max(entry2.seq, lastSeq.get(entry2.interactionId) ?? 0));
1253
1289
  }
1254
1290
  return lastSeq;
1255
1291
  };
1256
- var goneBeforeRetentionEnded = (entry, retentionFloor) => retentionFloor === null || entry.interactionCreatedAt >= retentionFloor;
1292
+ var goneBeforeRetentionEnded = (entry2, retentionFloor) => retentionFloor === null || entry2.interactionCreatedAt >= retentionFloor;
1257
1293
  var payloadFindings = (site, entries, crypto) => {
1258
1294
  const lastDecisionSeq = lastDecisionSeqByInteraction(entries);
1259
- return entries.flatMap((entry) => {
1260
- const invalid = { kind: "invalid_status", seq: entry.seq, status: entry.payloadStatus };
1261
- const hasLaterDecision = entry.event === "decision" && (lastDecisionSeq.get(entry.interactionId) ?? 0) > entry.seq;
1262
- switch (entry.payloadStatus) {
1295
+ return entries.flatMap((entry2) => {
1296
+ const invalid = { kind: "invalid_status", seq: entry2.seq, status: entry2.payloadStatus };
1297
+ const hasLaterDecision = entry2.event === "decision" && (lastDecisionSeq.get(entry2.interactionId) ?? 0) > entry2.seq;
1298
+ switch (entry2.payloadStatus) {
1263
1299
  case "included":
1264
1300
  if (hasLaterDecision) return [invalid];
1265
- return entry.payload && payloadMatchesEntry(entry.payload, entry, site.siteId, crypto) ? [] : [{ kind: "entry_changed", seq: entry.seq }];
1301
+ return entry2.payload && payloadMatchesEntry(entry2.payload, entry2, site.siteId, crypto) ? [] : [{ kind: "entry_changed", seq: entry2.seq }];
1266
1302
  case "changed_since_recorded":
1267
- if (entry.event === "asked" || hasLaterDecision) return [invalid];
1268
- return [{ kind: entry.decisionFinal ? "entry_changed" : "unrecorded_change", seq: entry.seq }];
1303
+ if (entry2.event === "asked" || hasLaterDecision) return [invalid];
1304
+ return [{ kind: entry2.decisionFinal ? "entry_changed" : "unrecorded_change", seq: entry2.seq }];
1269
1305
  case "superseded":
1270
- return entry.event === "asked" || entry.decisionFinal || !hasLaterDecision && site.beforeSeq === null ? [invalid] : [];
1306
+ return entry2.event === "asked" || entry2.decisionFinal || !hasLaterDecision && site.beforeSeq === null ? [invalid] : [];
1271
1307
  case "aged_out":
1272
- return goneBeforeRetentionEnded(entry, site.retentionFloor) ? [{ kind: "row_missing", seq: entry.seq }] : [];
1308
+ return goneBeforeRetentionEnded(entry2, site.retentionFloor) ? [{ kind: "row_missing", seq: entry2.seq }] : [];
1273
1309
  }
1274
1310
  });
1275
1311
  };
1276
1312
  var decisionSequenceFindings = (entries) => {
1277
1313
  const asked = /* @__PURE__ */ new Set();
1278
1314
  const decidedFinally = /* @__PURE__ */ new Set();
1279
- return entries.flatMap((entry) => {
1280
- if (entry.event === "asked") {
1281
- const repeated = asked.has(entry.interactionId);
1282
- asked.add(entry.interactionId);
1283
- return repeated ? [{ kind: "asked_twice", seq: entry.seq }] : [];
1315
+ return entries.flatMap((entry2) => {
1316
+ if (entry2.event === "asked") {
1317
+ const repeated = asked.has(entry2.interactionId);
1318
+ asked.add(entry2.interactionId);
1319
+ return repeated ? [{ kind: "asked_twice", seq: entry2.seq }] : [];
1284
1320
  }
1285
- const afterFinal = decidedFinally.has(entry.interactionId);
1286
- if (entry.decisionFinal) decidedFinally.add(entry.interactionId);
1287
- return afterFinal ? [{ kind: "decision_rewritten", seq: entry.seq }] : [];
1321
+ const afterFinal = decidedFinally.has(entry2.interactionId);
1322
+ if (entry2.decisionFinal) decidedFinally.add(entry2.interactionId);
1323
+ return afterFinal ? [{ kind: "decision_rewritten", seq: entry2.seq }] : [];
1288
1324
  });
1289
1325
  };
1290
1326
  var payloadCountsOf = (entries) => ({
1291
- included: entries.filter((entry) => entry.payloadStatus === "included").length,
1292
- aged_out: entries.filter((entry) => entry.payloadStatus === "aged_out").length,
1293
- superseded: entries.filter((entry) => entry.payloadStatus === "superseded").length,
1294
- changed_since_recorded: entries.filter((entry) => entry.payloadStatus === "changed_since_recorded").length
1327
+ included: entries.filter((entry2) => entry2.payloadStatus === "included").length,
1328
+ aged_out: entries.filter((entry2) => entry2.payloadStatus === "aged_out").length,
1329
+ superseded: entries.filter((entry2) => entry2.payloadStatus === "superseded").length,
1330
+ changed_since_recorded: entries.filter((entry2) => entry2.payloadStatus === "changed_since_recorded").length
1295
1331
  });
1296
1332
  var findingsForCheckpoint = (checkpoint, siteId, hashBySeq, crypto, pinnedKeyIds) => {
1297
1333
  const findings = [];
@@ -1338,7 +1374,7 @@ var knownHeadFindings = (site, hashBySeq, lastSeq, exportedAt, known) => {
1338
1374
  };
1339
1375
  var verifyAuditChainSite = (site, crypto, options) => {
1340
1376
  const entries = [...site.entries].sort((left, right) => left.seq - right.seq);
1341
- const hashBySeq = new Map(entries.map((entry) => [entry.seq, entry.entryHash]));
1377
+ const hashBySeq = new Map(entries.map((entry2) => [entry2.seq, entry2.entryHash]));
1342
1378
  const firstSeq = entries[0]?.seq ?? null;
1343
1379
  const lastSeq = entries[entries.length - 1]?.seq ?? null;
1344
1380
  const checkpointResults = site.checkpoints.map((checkpoint) => ({
@@ -1889,9 +1925,9 @@ var scriptOfAnEvalEndingAt = (text3, end) => {
1889
1925
  return [(firstComment === -1 ? words : words.slice(0, firstComment)).map((word) => word.text).join(" ")];
1890
1926
  };
1891
1927
  var scriptsOfEvalsIn = (text3) => [...text3.matchAll(AN_EVAL_THAT_RUNS)].slice(0, MOST_SCRIPTS_READ_FROM_ONE_COMMAND + 1).flatMap((match) => scriptOfAnEvalEndingAt(text3, match.index + match[0].length));
1892
- var scriptsDirectlyInside = (text3) => [...scriptsOfEvalsIn(text3), ...scriptsOfShellsIn(text3)];
1928
+ var scriptsWrittenForAShellOrAnEval = (text3) => [...scriptsOfEvalsIn(text3), ...scriptsOfShellsIn(text3)];
1893
1929
  var READING_OF_SCRIPTS_TOO_MANY_TO_READ = ": | sh";
1894
- var readingsOfScriptsPassedToAShell = (text3) => {
1930
+ var readingsOfNestedShellScripts = (text3, scriptsDirectlyInside) => {
1895
1931
  const readings = [];
1896
1932
  let scriptsRead = 0;
1897
1933
  let level = [text3];
@@ -3860,16 +3896,345 @@ var scriptACodexShellCommandRuns = (command) => {
3860
3896
  return script.trim().length === 0 ? null : script;
3861
3897
  };
3862
3898
 
3899
+ // ../contracts/src/codex-permission-profile.ts
3900
+ var CODEX_PERMISSION_PROFILE_METHOD = "item/permissions/requestApproval";
3901
+ var CODEX_PERMISSION_PROFILE_CHOICES = { turn: "Allow this turn", session: "Allow this session", deny: "Deny" };
3902
+ var record2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
3903
+ var keys = (value, allowed) => Object.keys(value).every((key) => allowed.includes(key));
3904
+ var literalAbsolutePath = (value) => typeof value === "string" && value.length > 0 && value.length <= 4096 && /^(\/|[a-z]:[\\/])/i.test(value) && !/[\u0000-\u001f*?\[\]{}]/.test(value) && !value.split(/[\\/]/).some((part) => part === ".." || part === ".");
3905
+ var paths = (value) => value == null || Array.isArray(value) && value.length <= 32 && value.every(literalAbsolutePath);
3906
+ var entry = (value) => record2(value) && keys(value, ["path", "access"]) && (value.access === "read" || value.access === "write" || value.access === "deny") && record2(value.path) && keys(value.path, ["type", "path"]) && value.path.type === "path" && literalAbsolutePath(value.path.path);
3907
+ var isCodexPermissionProfile = (value) => {
3908
+ if (!record2(value) || !keys(value, ["network", "fileSystem"])) return false;
3909
+ const network = value.network;
3910
+ if (network != null && (!record2(network) || !keys(network, ["enabled"]) || network.enabled != null && typeof network.enabled !== "boolean")) return false;
3911
+ const files = value.fileSystem;
3912
+ if (files == null) return true;
3913
+ return record2(files) && keys(files, ["read", "write", "entries", "globScanMaxDepth"]) && paths(files.read) && paths(files.write) && (files.globScanMaxDepth == null || typeof files.globScanMaxDepth === "number" && Number.isSafeInteger(files.globScanMaxDepth) && files.globScanMaxDepth > 0) && (files.entries == null || Array.isArray(files.entries) && files.entries.length <= 32 && files.entries.every(entry));
3914
+ };
3915
+ var codexPermissionPaths = (profile, access) => [
3916
+ ...profile.fileSystem?.[access] ?? [],
3917
+ ...(profile.fileSystem?.entries ?? []).filter((entry2) => entry2.access === access).map((entry2) => entry2.path.path)
3918
+ ];
3919
+ var CODEX_PERMISSION_QUESTION_MAX_UNITS = 180;
3920
+ var CODEX_PERMISSION_QUESTION_WITHOUT_A_GRANT = "Allow a Codex permission request that names no network access and no file paths?";
3921
+ var BROAD_ROOT_LABELS = {
3922
+ computer: "the whole computer",
3923
+ drive: "the whole drive",
3924
+ volume: "a whole volume",
3925
+ share: "a network share",
3926
+ everyHome: "every home folder",
3927
+ home: "a home folder",
3928
+ topLevel: "a top-level folder"
3929
+ };
3930
+ var BROAD_ROOTS_IN_NAMING_ORDER = ["computer", "drive", "volume", "share", "everyHome", "home", "topLevel"];
3931
+ var RANK_IN_A_SENSITIVE_PLACE = BROAD_ROOTS_IN_NAMING_ORDER.length;
3932
+ var RANK_OUTSIDE_THE_WORKING_DIRECTORY = RANK_IN_A_SENSITIVE_PLACE + 1;
3933
+ var RANK_INSIDE_THE_WORKING_DIRECTORY = RANK_OUTSIDE_THE_WORKING_DIRECTORY + 1;
3934
+ var DRIVE_PREFIX = /^[a-z]:/i;
3935
+ var PATH_SEPARATOR = /[\\/]/;
3936
+ var TWO_SEPARATORS_THEN_A_NAME = /^[\\/]{2}[^\\/]/;
3937
+ var DOTS_AND_SPACES_WINDOWS_DROPS = /[. ]+$/;
3938
+ var PROCESS_WHOSE_ROOT_IS_LINKED = /^(?:self|thread-self|\d+)$/;
3939
+ var MACOS_DATA_VOLUME_FOLDERS = ["system", "volumes", "data"];
3940
+ var PROCESS_FOLDER = "proc";
3941
+ var PROCESS_ROOT_LINK = "root";
3942
+ var PROCESS_ROOT_FOLDERS = 3;
3943
+ var MOUNT_PARENT_FOLDERS = ["volumes", "mnt"];
3944
+ var MOUNT_FOLDERS = 2;
3945
+ var MACOS_PRIVATE_FOLDER = "private";
3946
+ var MACOS_PRIVATE_FOLDERS = 1;
3947
+ var FOLDERS_MACOS_KEEPS_UNDER_PRIVATE = ["etc", "var", "tmp"];
3948
+ var HOME_PARENT_FOLDERS = ["users", "home"];
3949
+ var FOLDERS_EVERY_HOME_SHARES = ["shared", "public"];
3950
+ var SUPERUSER_HOME_FOLDER = "root";
3951
+ var MACOS_SUPERUSER_HOME_PARENT = "var";
3952
+ var HIDDEN_ENTRY_PREFIX = ".";
3953
+ var HOME_APP_DATA_FOLDERS = ["library", "appdata"];
3954
+ var HOME_APP_DATA_FOLDERS_HOLDING_NOTHING_KEPT = ["caches", "logs"];
3955
+ var SYSTEM_FOLDERS_OF_A_COMPUTER = ["etc", "library", "system", "usr", "bin", "sbin", "dev", "boot", "lib", "lib64", "var", "applications", "opt", "proc", "sys"];
3956
+ var ENTRIES_OF_A_SYSTEM_FOLDER_HOLDING_NOTHING_KEPT = {
3957
+ dev: ["null", "zero", "tty", "stdin", "stdout", "stderr", "fd", "random", "urandom"],
3958
+ var: ["folders", "tmp", "log"]
3959
+ };
3960
+ var SYSTEM_FOLDERS_OF_A_DRIVE = ["windows", "program files", "program files (x86)", "programdata"];
3961
+ var SENSITIVE_PLACE_LABELS = {
3962
+ hiddenInAHome: "hidden in a home folder",
3963
+ appDataOfAHome: "app data in a home folder",
3964
+ system: "a system folder"
3965
+ };
3966
+ var SEPARATOR_RUN = /[\\/]{2,}/g;
3967
+ var NETWORK_GRANT = "use the network";
3968
+ var WRITABLE_LEAD = "read and write ";
3969
+ var READ_ONLY_LEAD = "read ";
3970
+ var LIST_SEPARATOR = ", ";
3971
+ var QUOTE_UNITS = 2;
3972
+ var DETAILS_NOTE = " The details list every path.";
3973
+ var PERMISSIONS_HEADING = "Requested permissions:";
3974
+ var ELISION_MARK = "\u2026";
3975
+ var PATH_NO_REDACTION_SETTLES = "[redacted]";
3976
+ var SETTLING_PASSES = 4;
3977
+ var NAMED_PATH_FLOOR_UNITS = 32;
3978
+ var ONLY_NAMED_PATH_FLOOR_UNITS = 12;
3979
+ var NEVER_DRAWN_OR_BLANK = /^(?:[\p{C}\p{Zl}\p{Zp}\p{Default_Ignorable_Code_Point}\u2800]|(?! )\p{Zs})$/u;
3980
+ var COMBINING_MARK = /^\p{M}$/u;
3981
+ var LETTER_OR_DIGIT = /^[\p{L}\p{N}]$/u;
3982
+ var DISPLAY_UNIT = /\\ud[89ab][0-9a-f]{2}\\ud[c-f][0-9a-f]{2}|\\u[0-9a-f]{4}|\\["\\]|\[redacted(?: key)?\]|[\s\S]/gu;
3983
+ var PATH_IN_A_QUESTION = { backslashed: '"\\', reserved: ELISION_MARK };
3984
+ var PROSE_IN_QUOTES = { backslashed: '"\\', reserved: "" };
3985
+ var TEXT_ALREADY_ESCAPED = { backslashed: "", reserved: "" };
3986
+ var unitEscapes = (text3) => Array.from({ length: text3.length }, (_, index) => `\\u${text3.charCodeAt(index).toString(16).padStart(4, "0")}`).join("");
3987
+ var withCodePointVisible = (rules) => (shown, codePoint) => {
3988
+ if (rules.backslashed.includes(codePoint)) return { text: `${shown.text}\\${codePoint}`, marksHaveABase: false };
3989
+ if (rules.reserved.includes(codePoint) || NEVER_DRAWN_OR_BLANK.test(codePoint)) return { text: `${shown.text}${unitEscapes(codePoint)}`, marksHaveABase: false };
3990
+ if (COMBINING_MARK.test(codePoint)) return { text: `${shown.text}${shown.marksHaveABase ? codePoint : unitEscapes(codePoint)}`, marksHaveABase: shown.marksHaveABase };
3991
+ return { text: `${shown.text}${codePoint}`, marksHaveABase: LETTER_OR_DIGIT.test(codePoint) };
3992
+ };
3993
+ var visibleText = (text3, rules) => Array.from(text3).reduce(withCodePointVisible(rules), { text: "", marksHaveABase: false }).text;
3994
+ var inQuotes = (inside) => `"${inside}"`;
3995
+ var leadingUnitsWithin = (displayUnits, maxUnits) => {
3996
+ const kept = [];
3997
+ let units = 0;
3998
+ for (const displayUnit of displayUnits) {
3999
+ if (units + displayUnit.length > maxUnits) break;
4000
+ kept.push(displayUnit);
4001
+ units += displayUnit.length;
4002
+ }
4003
+ return kept;
4004
+ };
4005
+ var shortenedInTheMiddle = (text3, maxUnits) => {
4006
+ if (text3.length <= maxUnits) return text3;
4007
+ const displayUnits = text3.match(DISPLAY_UNIT) ?? [];
4008
+ const keptUnits = maxUnits - ELISION_MARK.length;
4009
+ const headUnits = Math.ceil(keptUnits / 2);
4010
+ const head = leadingUnitsWithin(displayUnits, headUnits);
4011
+ const tail = [...leadingUnitsWithin([...displayUnits].reverse(), keptUnits - headUnits)].reverse();
4012
+ return `${head.join("")}${ELISION_MARK}${tail.join("")}`;
4013
+ };
4014
+ var isStillInQuotes = (text3) => text3.length >= QUOTE_UNITS && text3.startsWith('"') && text3.endsWith('"');
4015
+ var settledWithin = (inside, maxUnits, passesLeft = SETTLING_PASSES) => {
4016
+ const shortened = shortenedInTheMiddle(inside, maxUnits);
4017
+ const redacted = redactSecrets(inQuotes(shortened));
4018
+ if (redacted === inQuotes(shortened)) return shortened;
4019
+ if (passesLeft === 0 || !isStillInQuotes(redacted)) return PATH_NO_REDACTION_SETTLES;
4020
+ return settledWithin(visibleText(redacted.slice(1, -1), TEXT_ALREADY_ESCAPED), maxUnits, passesLeft - 1);
4021
+ };
4022
+ var isNamedSegment = (segment) => segment.length > 0;
4023
+ var withoutWhatWindowsDrops = (segment) => segment.replace(DOTS_AND_SPACES_WINDOWS_DROPS, "");
4024
+ var pathShape = (path) => {
4025
+ const drive = DRIVE_PREFIX.exec(path)?.[0].toLowerCase() ?? null;
4026
+ const segments = path.slice(drive?.length ?? 0).split(PATH_SEPARATOR);
4027
+ return {
4028
+ drive,
4029
+ doubleSlashed: drive === null && TWO_SEPARATORS_THEN_A_NAME.test(path),
4030
+ segments: (drive === null ? segments : segments.map(withoutWhatWindowsDrops)).filter(isNamedSegment)
4031
+ };
4032
+ };
4033
+ var spellingOf = ({ drive, doubleSlashed, segments }) => `${drive ?? ""}${doubleSlashed ? "//" : "/"}${segments.join("/")}`;
4034
+ var startsWithTheDataVolume = (folders) => MACOS_DATA_VOLUME_FOLDERS.every((folder, index) => folders[index] === folder);
4035
+ var startsWithAProcessRoot = ([first, second, third]) => first === PROCESS_FOLDER && second !== void 0 && PROCESS_WHOSE_ROOT_IS_LINKED.test(second) && third === PROCESS_ROOT_LINK;
4036
+ var startsWithAMount = ([first, second]) => first !== void 0 && second !== void 0 && MOUNT_PARENT_FOLDERS.includes(first);
4037
+ var startsWithAFolderMacosKeepsUnderPrivate = ([first, second]) => first === MACOS_PRIVATE_FOLDER && second !== void 0 && FOLDERS_MACOS_KEEPS_UNDER_PRIVATE.includes(second);
4038
+ var beyondRootAliases = ({ root, folders }) => {
4039
+ if (startsWithTheDataVolume(folders)) return beyondRootAliases({ root: "volume", folders: folders.slice(MACOS_DATA_VOLUME_FOLDERS.length) });
4040
+ if (startsWithAProcessRoot(folders)) return beyondRootAliases({ root: "computer", folders: folders.slice(PROCESS_ROOT_FOLDERS) });
4041
+ if (startsWithAMount(folders)) return beyondRootAliases({ root: "volume", folders: folders.slice(MOUNT_FOLDERS) });
4042
+ if (startsWithAFolderMacosKeepsUnderPrivate(folders)) return beyondRootAliases({ root, folders: folders.slice(MACOS_PRIVATE_FOLDERS) });
4043
+ return { root, folders };
4044
+ };
4045
+ var placeOf = ({ drive, segments }) => {
4046
+ const folders = segments.map((segment) => segment.toLowerCase());
4047
+ return drive === null ? beyondRootAliases({ root: "computer", folders }) : { root: "drive", folders };
4048
+ };
4049
+ var namesAHome = (parent, folder) => HOME_PARENT_FOLDERS.includes(parent) && !FOLDERS_EVERY_HOME_SHARES.includes(folder) || parent === MACOS_SUPERUSER_HOME_PARENT && folder === SUPERUSER_HOME_FOLDER;
4050
+ var homeRelativePlace = ({ root, folders }) => {
4051
+ const [first, second] = folders;
4052
+ if (first === SUPERUSER_HOME_FOLDER) return { home: `${root}/${first}`, inside: folders.slice(1) };
4053
+ if (first === void 0 || second === void 0 || !namesAHome(first, second)) return null;
4054
+ return { home: `${root}/${first}/${second}`, inside: folders.slice(2) };
4055
+ };
4056
+ var sensitivePlaceInAHome = ({ home, inside }) => {
4057
+ const [entry2, kept] = inside;
4058
+ if (entry2 === void 0) return null;
4059
+ if (entry2.startsWith(HIDDEN_ENTRY_PREFIX)) return { kind: "hiddenInAHome", folder: `${home}/${entry2}`, isTheFolderItself: kept === void 0 };
4060
+ if (!HOME_APP_DATA_FOLDERS.includes(entry2) || kept !== void 0 && HOME_APP_DATA_FOLDERS_HOLDING_NOTHING_KEPT.includes(kept)) return null;
4061
+ return { kind: "appDataOfAHome", folder: `${home}/${entry2}`, isTheFolderItself: kept === void 0 };
4062
+ };
4063
+ var holdsNothingKept = (systemFolder, entry2) => entry2 !== void 0 && (ENTRIES_OF_A_SYSTEM_FOLDER_HOLDING_NOTHING_KEPT[systemFolder] ?? []).includes(entry2);
4064
+ var systemFoldersOf = (root) => root === "drive" ? SYSTEM_FOLDERS_OF_A_DRIVE : SYSTEM_FOLDERS_OF_A_COMPUTER;
4065
+ var sensitivePlaceOf = (place) => {
4066
+ const home = homeRelativePlace(place);
4067
+ if (home !== null) return sensitivePlaceInAHome(home);
4068
+ const [first, entry2] = place.folders;
4069
+ if (first === void 0 || !systemFoldersOf(place.root).includes(first) || holdsNothingKept(first, entry2)) return null;
4070
+ return { kind: "system", folder: `${place.root}/${first}`, isTheFolderItself: entry2 === void 0 };
4071
+ };
4072
+ var broadRootOf = (shape, place, sensitivePlace) => {
4073
+ const [first, second] = place.folders;
4074
+ if (first === void 0) return place.root;
4075
+ if (homeRelativePlace(place)?.inside.length === 0) return "home";
4076
+ if (second === void 0) return HOME_PARENT_FOLDERS.includes(first) ? "everyHome" : "topLevel";
4077
+ return shape.doubleSlashed && shape.segments.length === 2 && sensitivePlace === null ? "share" : null;
4078
+ };
4079
+ var isInside = (path, folder) => folder.segments.length > 0 && path.drive === folder.drive && path.doubleSlashed === folder.doubleSlashed && folder.segments.every((segment, index) => path.segments[index] === segment);
4080
+ var FITTING_PLANS = [
4081
+ { pointsToTheDetails: false, onlyWhenNothingIsLeftOut: true },
4082
+ { pointsToTheDetails: true, onlyWhenNothingIsLeftOut: false },
4083
+ { pointsToTheDetails: false, onlyWhenNothingIsLeftOut: false }
4084
+ ];
4085
+ var workingDirectory = (cwd) => {
4086
+ const shape = pathShape(cwd);
4087
+ const placed = sensitivePlaceOf(placeOf(shape));
4088
+ return { shape, sensitiveFolder: placed === null || placed.isTheFolderItself ? null : placed.folder };
4089
+ };
4090
+ var namingRank = (broadRoot, sensitivePlace, insideTheWorkingDirectory) => {
4091
+ if (broadRoot !== null) return BROAD_ROOTS_IN_NAMING_ORDER.indexOf(broadRoot);
4092
+ if (sensitivePlace !== null) return RANK_IN_A_SENSITIVE_PLACE;
4093
+ return insideTheWorkingDirectory ? RANK_INSIDE_THE_WORKING_DIRECTORY : RANK_OUTSIDE_THE_WORKING_DIRECTORY;
4094
+ };
4095
+ var firstSeparatorOfARun = (run) => run.slice(0, 1);
4096
+ var withSeparatorRunsCollapsed = (path, { doubleSlashed }) => {
4097
+ const collapsed = path.replace(SEPARATOR_RUN, firstSeparatorOfARun);
4098
+ return doubleSlashed ? `${collapsed.slice(0, 1)}${collapsed}` : collapsed;
4099
+ };
4100
+ var isAWholeSystemFolder = (broadRoot, sensitivePlace) => broadRoot === "topLevel" && sensitivePlace?.kind === "system";
4101
+ var placeLabel = (broadRoot, sensitivePlace) => {
4102
+ if (broadRoot !== null && !isAWholeSystemFolder(broadRoot, sensitivePlace)) return ` (${BROAD_ROOT_LABELS[broadRoot]})`;
4103
+ return sensitivePlace === null ? "" : ` (${SENSITIVE_PLACE_LABELS[sensitivePlace.kind]})`;
4104
+ };
4105
+ var grantedPath = (path, cwd) => {
4106
+ const shape = pathShape(path);
4107
+ const place = placeOf(shape);
4108
+ const placed = sensitivePlaceOf(place);
4109
+ const insideTheWorkingDirectory = isInside(shape, cwd.shape);
4110
+ const sensitivePlace = placed !== null && insideTheWorkingDirectory && placed.folder === cwd.sensitiveFolder ? null : placed;
4111
+ const broadRoot = broadRootOf(shape, place, sensitivePlace);
4112
+ return {
4113
+ shown: settledWithin(visibleText(redactSecrets(withSeparatorRunsCollapsed(path, shape)), PATH_IN_A_QUESTION), Number.POSITIVE_INFINITY),
4114
+ label: placeLabel(broadRoot, sensitivePlace),
4115
+ sensitive: broadRoot !== null || sensitivePlace !== null,
4116
+ rank: namingRank(broadRoot, sensitivePlace, insideTheWorkingDirectory)
4117
+ };
4118
+ };
4119
+ var firstSpellings = (paths2) => {
4120
+ const spelled = /* @__PURE__ */ new Map();
4121
+ for (const path of paths2) {
4122
+ const spelling = spellingOf(pathShape(path));
4123
+ if (!spelled.has(spelling)) spelled.set(spelling, path);
4124
+ }
4125
+ return spelled;
4126
+ };
4127
+ var mostImportantFirst = (first, second) => first.rank - second.rank;
4128
+ var hasPaths = (list) => list.paths.length > 0;
4129
+ var permissionGrant = (profile, cwd) => {
4130
+ const from = workingDirectory(cwd);
4131
+ const writable = firstSpellings(codexPermissionPaths(profile, "write"));
4132
+ const isNotAlsoWritable = ([spelling]) => !writable.has(spelling);
4133
+ const readOnly = [...firstSpellings(codexPermissionPaths(profile, "read"))].filter(isNotAlsoWritable).map(([, path]) => path);
4134
+ const listOf = (lead, listed) => ({ lead, paths: listed.map((path) => grantedPath(path, from)).sort(mostImportantFirst) });
4135
+ return { network: profile.network?.enabled === true, lists: [listOf(WRITABLE_LEAD, [...writable.values()]), listOf(READ_ONLY_LEAD, readOnly)].filter(hasPaths) };
4136
+ };
4137
+ var isSensitive = (path) => path.sensitive;
4138
+ var sensitiveNote = (counted) => {
4139
+ const sensitive = counted.filter(isSensitive).length;
4140
+ if (sensitive === 0) return "";
4141
+ return sensitive === counted.length ? ", all sensitive" : `, ${sensitive} of them sensitive`;
4142
+ };
4143
+ var restOf = (unnamed) => unnamed.length === 0 ? "" : ` and ${unnamed.length} more${sensitiveNote(unnamed)}`;
4144
+ var countedOnly = ({ lead, paths: paths2 }) => ({
4145
+ text: `${lead}${paths2.length} ${paths2.length === 1 ? "path" : "paths"}${sensitiveNote(paths2)}`,
4146
+ named: 0,
4147
+ complete: false
4148
+ });
4149
+ var leastNamedUnits = ({ lead, paths: paths2 }) => {
4150
+ const [first, ...rest] = paths2;
4151
+ if (first === void 0) return 0;
4152
+ return lead.length + QUOTE_UNITS + Math.min(first.shown.length, ONLY_NAMED_PATH_FLOOR_UNITS) + first.label.length + restOf(rest).length;
4153
+ };
4154
+ var fairShareOf = (lengths, units) => {
4155
+ const shortestFirst = [...lengths].sort((first, second) => first - second);
4156
+ let unitsLeft = units;
4157
+ for (const [position, length] of shortestFirst.entries()) {
4158
+ const share = Math.floor(unitsLeft / (shortestFirst.length - position));
4159
+ if (length > share) return share;
4160
+ unitsLeft -= length;
4161
+ }
4162
+ return Number.POSITIVE_INFINITY;
4163
+ };
4164
+ var namingTheFirst = ({ lead, paths: paths2 }, count, units) => {
4165
+ const named = paths2.slice(0, count);
4166
+ const rest = restOf(paths2.slice(count));
4167
+ const lengths = named.map((path) => path.shown.length);
4168
+ const floor = count === 1 ? ONLY_NAMED_PATH_FLOOR_UNITS : NAMED_PATH_FLOOR_UNITS;
4169
+ const pathUnits = units - lead.length - rest.length - LIST_SEPARATOR.length * (count - 1) - named.reduce((sum, path) => sum + QUOTE_UNITS + path.label.length, 0);
4170
+ if (pathUnits < lengths.reduce((sum, length) => sum + Math.min(length, floor), 0)) return null;
4171
+ const share = fairShareOf(lengths, pathUnits);
4172
+ const fitted = named.map((path) => ({ path, shown: settledWithin(path.shown, share) }));
4173
+ return {
4174
+ text: `${lead}${fitted.map(({ path, shown }) => `${inQuotes(shown)}${path.label}`).join(LIST_SEPARATOR)}${rest}`,
4175
+ named: count,
4176
+ complete: count === paths2.length && fitted.every(({ path, shown }) => shown === path.shown)
4177
+ };
4178
+ };
4179
+ var namedWithin = (list, units) => {
4180
+ for (let count = list.paths.length; count > 0; count -= 1) {
4181
+ const fitted = namingTheFirst(list, count, units);
4182
+ if (fitted !== null) return fitted;
4183
+ }
4184
+ return null;
4185
+ };
4186
+ var namesAsMany = (shared, unshared) => shared !== null && shared.named === unshared.named;
4187
+ var fittedAlone = (list, units) => {
4188
+ const named = namedWithin(list, units);
4189
+ return named === null ? null : [named];
4190
+ };
4191
+ var fittedLists = ([first, second], units) => {
4192
+ if (first === void 0) return [];
4193
+ if (second === void 0) return fittedAlone(first, units);
4194
+ const counted = countedOnly(second);
4195
+ const unshared = namedWithin(first, units - counted.text.length);
4196
+ if (unshared === null) return null;
4197
+ const shared = namedWithin(first, units - leastNamedUnits(second));
4198
+ const leading = namesAsMany(shared, unshared) ? shared : unshared;
4199
+ return [leading, namedWithin(second, units - leading.text.length) ?? counted];
4200
+ };
4201
+ var asAQuestion = (network, lists, pointsToTheDetails) => {
4202
+ const grants = [...network ? [NETWORK_GRANT] : [], ...lists];
4203
+ const inAList = grants.length < 2 ? grants.join("") : `${grants.slice(0, -1).join(", ")}, and ${grants.slice(-1).join("")}`;
4204
+ return `Allow Codex to ${inAList}?${pointsToTheDetails ? DETAILS_NOTE : ""}`;
4205
+ };
4206
+ var questionUnder = ({ network, lists }, plan) => {
4207
+ const frameUnits = asAQuestion(network, lists.map(() => ""), plan.pointsToTheDetails).length;
4208
+ const fitted = fittedLists(lists, CODEX_PERMISSION_QUESTION_MAX_UNITS - frameUnits);
4209
+ if (fitted === null) return null;
4210
+ const nothingIsLeftOut = fitted.every((list) => list.complete);
4211
+ if (plan.onlyWhenNothingIsLeftOut && !nothingIsLeftOut) return null;
4212
+ return asAQuestion(network, fitted.map((list) => list.text), plan.pointsToTheDetails && !nothingIsLeftOut);
4213
+ };
4214
+ var isAskable = (question) => question !== null && question.length <= CODEX_PERMISSION_QUESTION_MAX_UNITS && redactSecrets(question) === question;
4215
+ var codexPermissionProfileQuestion = (profile, cwd) => {
4216
+ const grant = permissionGrant(profile, cwd);
4217
+ if (!grant.network && grant.lists.length === 0) return CODEX_PERMISSION_QUESTION_WITHOUT_A_GRANT;
4218
+ return FITTING_PLANS.map((plan) => questionUnder(grant, plan)).find(isAskable) ?? asAQuestion(grant.network, grant.lists.map((list) => countedOnly(list).text), true);
4219
+ };
4220
+ var codexPermissionProfileDetail = (profile) => `${PERMISSIONS_HEADING}
4221
+ ${JSON.stringify(profile, null, 2).split("\n").map((line) => visibleText(line, TEXT_ALREADY_ESCAPED)).join("\n")}`;
4222
+ var codexProseOnOneQuotedLine = (prose) => inQuotes(visibleText(prose, PROSE_IN_QUOTES));
4223
+ var codexPermissionProfileResponse = (permissions, answer) => ({
4224
+ permissions: answer === CODEX_PERMISSION_PROFILE_CHOICES.turn || answer === CODEX_PERMISSION_PROFILE_CHOICES.session ? permissions : {},
4225
+ scope: answer === CODEX_PERMISSION_PROFILE_CHOICES.session ? "session" : "turn"
4226
+ });
4227
+
3863
4228
  // ../contracts/src/codex-native-approval.ts
3864
4229
  var CODEX_NATIVE_APPROVAL_CAPABILITY = "codex-native-approval-v1";
3865
- var CODEX_NATIVE_APPROVAL_METHODS = ["item/commandExecution/requestApproval", "item/fileChange/requestApproval", "mcpServer/elicitation/request"];
4230
+ var CODEX_NATIVE_APPROVAL_METHODS = ["item/commandExecution/requestApproval", "item/fileChange/requestApproval", "mcpServer/elicitation/request", CODEX_PERMISSION_PROFILE_METHOD];
3866
4231
  var CODEX_NATIVE_APPROVAL_CHOICES = { once: "Allow once", session: "Allow this conversation", deny: "Deny" };
3867
4232
  var CODEX_NATIVE_APPROVAL_REPLIES = { ask: "ask", deny: "deny", native: "native", allow: "allow" };
3868
- var record2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
4233
+ var record3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
3869
4234
  var identifier2 = (v) => typeof v === "string" && v.length > 0 && v.length <= 200;
3870
4235
  var text = (v) => typeof v === "string" && v.trim().length > 0 && v.length <= 16384;
3871
4236
  var optionalIdentifier = (v) => v == null || identifier2(v);
3872
- var keys = (v, allowed) => Object.keys(v).every((key) => allowed.includes(key));
4237
+ var keys2 = (v, allowed) => Object.keys(v).every((key) => allowed.includes(key));
3873
4238
  var isMethod = (v) => typeof v === "string" && CODEX_NATIVE_APPROVAL_METHODS.some((method) => method === v);
3874
4239
  var boundedJson = (value) => {
3875
4240
  try {
@@ -3882,12 +4247,12 @@ var BASE_KEYS = ["threadId", "turnId", "itemId", "startedAtMs", "reason"];
3882
4247
  var MCP_META_KEYS = ["codex_approval_kind", "codex_requires_user_input", "codex_request_type", "codex_strict_auto_review", "codex_sensitive_action", "approvals_reviewer", "persist", "source", "connector_id", "connector_name", "connector_description", "tool_name", "tool_title", "tool_description", "tool_params", "tool_params_display"];
3883
4248
  var MCP_FLAGS_THAT_ASK_FOR_A_PERSON = ["codex_requires_user_input", "codex_strict_auto_review", "codex_sensitive_action"];
3884
4249
  var COMPUTER_USE_META_KEYS = [...MCP_META_KEYS, "riskLevel", "subtitle", "tool_call_id"];
3885
- var computerUseDisplay = (value) => Array.isArray(value) && value.length <= 16 && value.every((item) => record2(item) && keys(item, ["name", "display_name", "value"]) && text(item.name) && text(item.display_name) && text(item.value));
4250
+ var computerUseDisplay = (value) => Array.isArray(value) && value.length <= 16 && value.every((item) => record3(item) && keys2(item, ["name", "display_name", "value"]) && text(item.name) && text(item.display_name) && text(item.value));
3886
4251
  var isExecpolicyAmendment = (value) => Array.isArray(value) && value.length > 0 && value.length <= 128 && value.every((token) => typeof token === "string" && token.length <= 16384);
3887
4252
  var isCommandDecision = (value) => {
3888
4253
  if (typeof value === "string") return ["accept", "acceptForSession", "decline", "cancel"].includes(value);
3889
- if (!record2(value) || !keys(value, ["acceptWithExecpolicyAmendment"]) || !record2(value.acceptWithExecpolicyAmendment)) return false;
3890
- return keys(value.acceptWithExecpolicyAmendment, ["execpolicy_amendment"]) && isExecpolicyAmendment(value.acceptWithExecpolicyAmendment.execpolicy_amendment);
4254
+ if (!record3(value) || !keys2(value, ["acceptWithExecpolicyAmendment"]) || !record3(value.acceptWithExecpolicyAmendment)) return false;
4255
+ return keys2(value.acceptWithExecpolicyAmendment, ["execpolicy_amendment"]) && isExecpolicyAmendment(value.acceptWithExecpolicyAmendment.execpolicy_amendment);
3891
4256
  };
3892
4257
  var FILE_CHANGE_KINDS = ["add", "delete", "update"];
3893
4258
  var FILE_CHANGE_VERB = { add: "adding", delete: "deleting", update: "editing" };
@@ -3903,11 +4268,11 @@ var fileChangeQuestion = (changes) => {
3903
4268
  return `Allow these ${changes.length} file changes once? ${named}${unnamed > 0 ? ` and ${unnamed} more` : ""}`;
3904
4269
  };
3905
4270
  var codexElicitationToolName = (serverName, toolName) => `mcp__${serverName}__${toolName}`;
3906
- var withCodexReason = (detail, reason) => text(reason) ? `${detail}
3907
-
3908
- Codex's reason: ${redactSecrets(reason)}` : detail;
4271
+ var CODEX_REASON_LEAD = "\n\nCodex's reason: ";
4272
+ var withCodexReason = (detail, reason) => text(reason) ? `${detail}${CODEX_REASON_LEAD}${redactSecrets(reason)}` : detail;
4273
+ var withCodexReasonOnOneQuotedLine = (detail, reason) => text(reason) ? `${detail}${CODEX_REASON_LEAD}${codexProseOnOneQuotedLine(redactSecrets(reason))}` : detail;
3909
4274
  var parseCodexNativeApproval = (value) => {
3910
- if (!record2(value) || !keys(value, ["method", "params", "changes"]) || !isMethod(value.method) || !record2(value.params) || !boundedJson(value)) return null;
4275
+ if (!record3(value) || !keys2(value, ["method", "params", "changes"]) || !isMethod(value.method) || !record3(value.params) || !boundedJson(value)) return null;
3911
4276
  const p = value.params;
3912
4277
  if (!identifier2(p.threadId) || !optionalIdentifier(p.turnId) || !optionalIdentifier(p.itemId)) return null;
3913
4278
  const request = { method: value.method, params: p, ...Array.isArray(value.changes) ? { changes: value.changes } : {} };
@@ -3922,9 +4287,9 @@ var parseCodexNativeApproval = (value) => {
3922
4287
  };
3923
4288
  if (value.method === "mcpServer/elicitation/request") {
3924
4289
  const meta = p._meta;
3925
- const computerUse = record2(meta) && meta.connector_id === "computer-use";
3926
- if (value.changes !== void 0 || !keys(p, ["threadId", "turnId", "serverName", "mode", "message", "requestedSchema", "_meta"]) || !(p.mode === "form" || computerUse && (p.mode === "openai/form" || p.mode === "openaiForm")) || !identifier2(p.serverName) || !text(p.message) || p.message.length > 500 || !record2(p.requestedSchema) || !keys(p.requestedSchema, ["type", "properties", "required", "$schema"]) || p.requestedSchema.type !== "object" || !record2(p.requestedSchema.properties) || Object.keys(p.requestedSchema.properties).length !== 0 || p.requestedSchema.required != null && (!Array.isArray(p.requestedSchema.required) || p.requestedSchema.required.length !== 0)) return null;
3927
- if (!record2(meta) || !keys(meta, computerUse ? COMPUTER_USE_META_KEYS : MCP_META_KEYS) || meta.codex_approval_kind !== "mcp_tool_call" || !identifier2(meta.tool_name) || !record2(meta.tool_params) || meta.tool_params_display != null && !(computerUse ? computerUseDisplay(meta.tool_params_display) : record2(meta.tool_params_display))) return null;
4290
+ const computerUse = record3(meta) && meta.connector_id === "computer-use";
4291
+ if (value.changes !== void 0 || !keys2(p, ["threadId", "turnId", "serverName", "mode", "message", "requestedSchema", "_meta"]) || !(p.mode === "form" || computerUse && (p.mode === "openai/form" || p.mode === "openaiForm")) || !identifier2(p.serverName) || !text(p.message) || p.message.length > 500 || !record3(p.requestedSchema) || !keys2(p.requestedSchema, ["type", "properties", "required", "$schema"]) || p.requestedSchema.type !== "object" || !record3(p.requestedSchema.properties) || Object.keys(p.requestedSchema.properties).length !== 0 || p.requestedSchema.required != null && (!Array.isArray(p.requestedSchema.required) || p.requestedSchema.required.length !== 0)) return null;
4292
+ if (!record3(meta) || !keys2(meta, computerUse ? COMPUTER_USE_META_KEYS : MCP_META_KEYS) || meta.codex_approval_kind !== "mcp_tool_call" || !identifier2(meta.tool_name) || !record3(meta.tool_params) || meta.tool_params_display != null && !(computerUse ? computerUseDisplay(meta.tool_params_display) : record3(meta.tool_params_display))) return null;
3928
4293
  if (computerUse && (meta.riskLevel !== "low" && meta.riskLevel !== "high" || meta.subtitle != null && !text(meta.subtitle) || !optionalIdentifier(meta.tool_call_id))) return null;
3929
4294
  if (MCP_FLAGS_THAT_ASK_FOR_A_PERSON.some((key) => meta[key] != null && typeof meta[key] !== "boolean")) return null;
3930
4295
  if (meta.approvals_reviewer != null && meta.approvals_reviewer !== "user") return null;
@@ -3956,8 +4321,23 @@ var parseCodexNativeApproval = (value) => {
3956
4321
  };
3957
4322
  }
3958
4323
  if (!identifier2(p.turnId) || !identifier2(p.itemId) || !Number.isSafeInteger(p.startedAtMs) || p.reason != null && !text(p.reason)) return null;
4324
+ if (value.method === CODEX_PERMISSION_PROFILE_METHOD) {
4325
+ if (value.changes !== void 0 || !keys2(p, [...BASE_KEYS, "cwd", "environmentId", "permissions"]) || !text(p.cwd) || p.environmentId != null && p.environmentId !== "local" || !isCodexPermissionProfile(p.permissions)) return null;
4326
+ return {
4327
+ ...base,
4328
+ permissionProfile: p.permissions,
4329
+ codexAsksForAPerson: true,
4330
+ cwd: p.cwd,
4331
+ toolName: "request_permissions",
4332
+ toolInputs: [{ permissions: p.permissions }],
4333
+ scopePaths: [...codexPermissionPaths(p.permissions, "read"), ...codexPermissionPaths(p.permissions, "write")],
4334
+ question: codexPermissionProfileQuestion(p.permissions, p.cwd),
4335
+ detail: withCodexReasonOnOneQuotedLine(codexPermissionProfileDetail(p.permissions), p.reason),
4336
+ options: [CODEX_PERMISSION_PROFILE_CHOICES.turn, CODEX_PERMISSION_PROFILE_CHOICES.session, CODEX_PERMISSION_PROFILE_CHOICES.deny]
4337
+ };
4338
+ }
3959
4339
  if (value.method === "item/commandExecution/requestApproval") {
3960
- if (value.changes !== void 0 || !keys(p, [...BASE_KEYS, "approvalId", "kind", "environmentId", "command", "cwd", "commandActions", "networkApprovalContext", "proposedExecpolicyAmendment", "proposedNetworkPolicyAmendments", "availableDecisions"]) || !optionalIdentifier(p.approvalId) || p.kind != null && p.kind !== "command" || p.environmentId != null && p.environmentId !== "local" || p.networkApprovalContext != null || p.proposedNetworkPolicyAmendments != null || p.proposedExecpolicyAmendment != null && !isExecpolicyAmendment(p.proposedExecpolicyAmendment) || !text(p.command) || !text(p.cwd)) return null;
4340
+ if (value.changes !== void 0 || !keys2(p, [...BASE_KEYS, "approvalId", "kind", "environmentId", "command", "cwd", "commandActions", "networkApprovalContext", "proposedExecpolicyAmendment", "proposedNetworkPolicyAmendments", "availableDecisions"]) || !optionalIdentifier(p.approvalId) || p.kind != null && p.kind !== "command" || p.environmentId != null && p.environmentId !== "local" || p.networkApprovalContext != null || p.proposedNetworkPolicyAmendments != null || p.proposedExecpolicyAmendment != null && !isExecpolicyAmendment(p.proposedExecpolicyAmendment) || !text(p.command) || !text(p.cwd)) return null;
3961
4341
  const decisions = p.availableDecisions ?? ["accept", "decline", "cancel"];
3962
4342
  if (!Array.isArray(decisions) || !decisions.includes("accept") || !decisions.some((v) => v === "decline" || v === "cancel") || !decisions.every(isCommandDecision)) return null;
3963
4343
  const command = scriptACodexShellCommandRuns(p.command) ?? p.command;
@@ -3973,24 +4353,25 @@ Directory: ${redactSecrets(p.cwd)}`, p.reason),
3973
4353
  negativeDecision: decisions.includes("decline") ? "decline" : "cancel"
3974
4354
  };
3975
4355
  }
3976
- if (!keys(p, [...BASE_KEYS, "grantRoot"]) || p.grantRoot != null || !Array.isArray(value.changes) || value.changes.length === 0 || value.changes.length > 32) return null;
4356
+ if (!keys2(p, [...BASE_KEYS, "grantRoot"]) || p.grantRoot != null || !Array.isArray(value.changes) || value.changes.length === 0 || value.changes.length > 32) return null;
3977
4357
  const changes = [];
3978
4358
  for (const change of value.changes) {
3979
- if (!record2(change) || !keys(change, ["path", "kind", "diff"]) || !text(change.path) || typeof change.diff !== "string" || !record2(change.kind) || !keys(change.kind, ["type", "move_path"]) || !isFileChangeKind(change.kind.type) || change.kind.move_path != null) return null;
4359
+ if (!record3(change) || !keys2(change, ["path", "kind", "diff"]) || !text(change.path) || typeof change.diff !== "string" || !record3(change.kind) || !keys2(change.kind, ["type", "move_path"]) || !isFileChangeKind(change.kind.type) || change.kind.move_path != null) return null;
3980
4360
  changes.push({ kind: change.kind.type, path: change.path, diff: change.diff });
3981
4361
  }
3982
- const paths = changes.map((change) => change.path);
4362
+ const paths2 = changes.map((change) => change.path);
3983
4363
  return {
3984
4364
  ...base,
3985
4365
  toolName: "Edit",
3986
- toolInputs: paths.map((file_path) => ({ file_path })),
3987
- scopePaths: paths,
4366
+ toolInputs: paths2.map((file_path) => ({ file_path })),
4367
+ scopePaths: paths2,
3988
4368
  question: fileChangeQuestion(changes),
3989
4369
  detail: withCodexReason(changes.map((change) => `${redactSecrets(labelledFileChange(change))}
3990
4370
  ${redactSecretsDeep(change.diff)}`).join("\n\n"), p.reason)
3991
4371
  };
3992
4372
  };
3993
4373
  var codexNativeApprovalResponse = (approval, answer) => {
4374
+ if (approval.permissionProfile) return codexPermissionProfileResponse(approval.permissionProfile, answer);
3994
4375
  const accepted = approval.options.includes(answer) && (answer === CODEX_NATIVE_APPROVAL_CHOICES.once || answer === CODEX_NATIVE_APPROVAL_CHOICES.session);
3995
4376
  if (approval.request.method === "mcpServer/elicitation/request") return {
3996
4377
  action: accepted ? "accept" : "decline",
@@ -4014,10 +4395,22 @@ var compressTranscriptRecord = (raw, deflateRaw) => {
4014
4395
  if (raw.length > TRANSCRIPT_RECORD_MAX_INFLATED_BYTES) return raw;
4015
4396
  const deflated = deflateRaw(raw);
4016
4397
  if (!compressionShrinks(raw, deflated)) return raw;
4017
- const record4 = new Uint8Array(deflated.length + 1);
4018
- record4[0] = COMPRESSED_TRANSCRIPT_RECORD_MARKER;
4019
- record4.set(deflated, 1);
4020
- return record4;
4398
+ const record5 = new Uint8Array(deflated.length + 1);
4399
+ record5[0] = COMPRESSED_TRANSCRIPT_RECORD_MARKER;
4400
+ record5.set(deflated, 1);
4401
+ return record5;
4402
+ };
4403
+
4404
+ // ../contracts/src/spawn-delivery.ts
4405
+ var SPAWN_RECOVERY = {
4406
+ receiptRetentionMs: 7 * 24 * 60 * 60 * 1e3,
4407
+ retrySendWindowMs: 60 * 60 * 1e3
4408
+ };
4409
+ var SPAWN_LAUNCH_FAILED_CODE = "launch_failed";
4410
+ var SPAWN_UNCONFIRMED_ATTEMPT_FAILURE = {
4411
+ code: SPAWN_LAUNCH_FAILED_CODE,
4412
+ message: "The previous launch could not be confirmed. Check your sessions before starting another.",
4413
+ retryable: true
4021
4414
  };
4022
4415
 
4023
4416
  // ../contracts/src/claude-inbox.ts
@@ -4034,11 +4427,11 @@ var CLAUDE_INBOX = {
4034
4427
  sender: "pushary",
4035
4428
  carrier: "native"
4036
4429
  };
4037
- var record3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4430
+ var record4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4038
4431
  var text2 = (value) => typeof value === "string" && value.length > 0;
4039
4432
  var sessionIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4040
4433
  var parseClaudeInboxSession = (value, platform = "darwin") => {
4041
- if (!record3(value) || !Number.isSafeInteger(value.pid) || typeof value.pid !== "number" || value.pid <= 0 || !text2(value.sessionId) || !sessionIdPattern.test(value.sessionId) || !text2(value.cwd) || !text2(value.procStart) || platform === "linux" && !text2(value.pidDomain) || !text2(value.messagingSocketPath) || value.peerProtocol !== CLAUDE_INBOX.protocol || !text2(value.version) || !supportsClaudeInbox(value.version, platform))
4434
+ if (!record4(value) || !Number.isSafeInteger(value.pid) || typeof value.pid !== "number" || value.pid <= 0 || !text2(value.sessionId) || !sessionIdPattern.test(value.sessionId) || !text2(value.cwd) || !text2(value.procStart) || platform === "linux" && !text2(value.pidDomain) || !text2(value.messagingSocketPath) || value.peerProtocol !== CLAUDE_INBOX.protocol || !text2(value.version) || !supportsClaudeInbox(value.version, platform))
4042
4435
  return null;
4043
4436
  return {
4044
4437
  pid: value.pid,
@@ -4059,19 +4452,19 @@ var claudeInboxAction = (progress) => {
4059
4452
  }
4060
4453
  return progress.attempted ? "observe" /* observe */ : "submit" /* submit */;
4061
4454
  };
4062
- var isClaudeInboxReceipt = (value, sessionId, commandId) => record3(value) && value.type === "user" && value.sessionId === sessionId && value.uuid === commandId && record3(value.origin) && value.origin.kind === "peer" && value.origin.msg_id === commandId;
4455
+ var isClaudeInboxReceipt = (value, sessionId, commandId) => record4(value) && value.type === "user" && value.sessionId === sessionId && value.uuid === commandId && record4(value.origin) && value.origin.kind === "peer" && value.origin.msg_id === commandId;
4063
4456
  var CLAUDE_INBOX_MAX_SESSIONS = 128;
4064
4457
  var parseClaudeInboxCommand = (value) => {
4065
- if (!record3(value) || !text2(value.id) || !sessionIdPattern.test(value.id) || !text2(value.text) || typeof value.expiresAtMs !== "number" || !Number.isSafeInteger(value.expiresAtMs))
4458
+ if (!record4(value) || !text2(value.id) || !sessionIdPattern.test(value.id) || !text2(value.text) || typeof value.expiresAtMs !== "number" || !Number.isSafeInteger(value.expiresAtMs))
4066
4459
  return null;
4067
4460
  return { id: value.id, text: value.text, expiresAtMs: value.expiresAtMs };
4068
4461
  };
4069
4462
  var parseClaudeInboxPoll = (value) => {
4070
- if (!record3(value) || value.protocol !== CLAUDE_INBOX.protocol || !Array.isArray(value.sessionIds) || value.sessionIds.length > CLAUDE_INBOX_MAX_SESSIONS || !value.sessionIds.every((id) => nativeIdentifier(id)))
4463
+ if (!record4(value) || value.protocol !== CLAUDE_INBOX.protocol || !Array.isArray(value.sessionIds) || value.sessionIds.length > CLAUDE_INBOX_MAX_SESSIONS || !value.sessionIds.every((id) => nativeIdentifier(id)))
4071
4464
  return null;
4072
4465
  return value.sessionIds;
4073
4466
  };
4074
- var parseClaudeInboxClaim = (value) => record3(value) && value.protocol === CLAUDE_INBOX.protocol ? parseClaudeInboxCommand(value.command) : null;
4467
+ var parseClaudeInboxClaim = (value) => record4(value) && value.protocol === CLAUDE_INBOX.protocol ? parseClaudeInboxCommand(value.command) : null;
4075
4468
  var CLAUDE_INBOX_RECEIVER = {
4076
4469
  pollMs: 3e3,
4077
4470
  heartbeatMs: 6e4,
@@ -6903,9 +7296,38 @@ var substitutionFedTo = (pieces, index) => {
6903
7296
  const next = pieces[index + 1];
6904
7297
  return next !== void 0 && SUBSTITUTION_OPENERS.has(next.before) ? next.text : null;
6905
7298
  };
7299
+ var REDIRECTION_REMOVED = " ";
7300
+ var arrowReadingInForce = null;
7301
+ var anArrowWasReadAsText = false;
7302
+ var underEachArrowReading = (judge) => {
7303
+ if (arrowReadingInForce !== null) return [judge()];
7304
+ try {
7305
+ anArrowWasReadAsText = false;
7306
+ arrowReadingInForce = "arrows_the_shell_sees";
7307
+ const withArrowsTheShellSees = judge();
7308
+ if (!anArrowWasReadAsText) return [withArrowsTheShellSees];
7309
+ arrowReadingInForce = "every_arrow";
7310
+ return [withArrowsTheShellSees, judge()];
7311
+ } finally {
7312
+ arrowReadingInForce = null;
7313
+ }
7314
+ };
7315
+ var isTrue = (answer) => answer;
7316
+ var underEitherArrowReading = (judge) => underEachArrowReading(judge).some(isTrue);
7317
+ var withoutOutputRedirectionTargets = (text3) => {
7318
+ if (arrowReadingInForce === "every_arrow") return text3.replace(OUTPUT_REDIRECTION, REDIRECTION_REMOVED);
7319
+ const visible = shellVisibleText(text3);
7320
+ const removeVisibleRedirection = (match, _target, offset) => {
7321
+ const operator = offset + match.search(REDIRECTION_OPERATOR_CHARACTER);
7322
+ if (visible === null || REDIRECTION_OPERATOR_CHARACTER.test(visible.charAt(operator))) return REDIRECTION_REMOVED;
7323
+ anArrowWasReadAsText = true;
7324
+ return match;
7325
+ };
7326
+ return text3.replace(OUTPUT_REDIRECTION, removeVisibleRedirection);
7327
+ };
6906
7328
  var roughSegmentsOf = (command) => {
6907
7329
  const { text: text3, bodies } = withHeredocBodiesSetAside(commandForReading(command));
6908
- const pieces = roughPiecesOf(text3.replace(INPUT_REDIRECTION, ` ${REDIRECTED_INPUT_MARK} `).replace(OUTPUT_REDIRECTION, " "));
7330
+ const pieces = roughPiecesOf(withoutOutputRedirectionTargets(text3.replace(INPUT_REDIRECTION, ` ${REDIRECTED_INPUT_MARK} `)));
6909
7331
  let heredocsSeen = 0;
6910
7332
  return pieces.map((piece, index) => {
6911
7333
  const heredocCount = occurrencesOf(piece.text, HEREDOC_MARK);
@@ -7477,6 +7899,20 @@ var runnerReadingOf = (innermost) => {
7477
7899
  const commands = [.../* @__PURE__ */ new Set([...fromScript, ...named.map(verbatimInvocationText), ...afterEndOfOptions.map(verbatimInvocationText)])];
7478
7900
  return commands.length === 0 ? NO_INLINE_SCRIPT : { kind: "readable", scripts: commands };
7479
7901
  };
7902
+ var scriptsOfExecutablePiece = (piece) => {
7903
+ const invocation = innermostInvocation(invocationOfRoughPiece(piece.text));
7904
+ const scripts = inlineScriptsOf(invocation, []);
7905
+ const runner = runnerReadingOf(invocation);
7906
+ return [
7907
+ ...scripts.kind === "readable" ? scripts.scripts : [],
7908
+ ...runner.kind === "readable" ? runner.scripts : []
7909
+ ];
7910
+ };
7911
+ var scriptsExecutedBy = (command) => {
7912
+ const readable = readingWithoutCommentsOrAnsiEscapes(command) ?? command;
7913
+ return roughPiecesOf(withoutOutputRedirectionTargets(readable)).flatMap(scriptsOfExecutablePiece);
7914
+ };
7915
+ var readingsOfScriptsPassedToAShell = (command) => readingsOfNestedShellScripts(command, scriptsExecutedBy);
7480
7916
  var MAX_SPELLED_FORMS = 4096;
7481
7917
  var markTruncated = (accumulator) => {
7482
7918
  accumulator.hidesWhatItRuns = true;
@@ -8520,7 +8956,7 @@ var isScopeContract = (value) => {
8520
8956
  if (c.promises !== void 0 && !strings(c.promises)) return false;
8521
8957
  return strings(c.allowedPaths) && strings(c.offLimitsPaths) && typeof c.doneWhen === "string";
8522
8958
  };
8523
- var findBestRoute = (routes, toolName, args, repoKey) => {
8959
+ var routeMatchingBestUnderOneArrowReading = (routes, toolName, args, repoKey) => {
8524
8960
  let best;
8525
8961
  let bestWeight = 0;
8526
8962
  let bestScoped = -1;
@@ -8541,7 +8977,13 @@ var findBestRoute = (routes, toolName, args, repoKey) => {
8541
8977
  bestLength = length;
8542
8978
  }
8543
8979
  }
8544
- return best ?? routes.find((r) => r.toolPattern === "*");
8980
+ return best;
8981
+ };
8982
+ var isAMatchedRoute = (route) => route !== void 0;
8983
+ var routeWaitsForSomeoneElse = (route) => route.answeredBySomeoneElse === true;
8984
+ var findBestRoute = (routes, toolName, args, repoKey) => {
8985
+ const matched = underEachArrowReading(() => routeMatchingBestUnderOneArrowReading(routes, toolName, args, repoKey)).filter(isAMatchedRoute);
8986
+ return matched.find(routeWaitsForSomeoneElse) ?? matched[0] ?? routes.find((r) => r.toolPattern === "*");
8545
8987
  };
8546
8988
  var autoApprove = (tool) => ({
8547
8989
  tool,
@@ -8656,11 +9098,13 @@ var resolvePolicyReading = (reach, config, toolName, modeOverride, toolInput, cw
8656
9098
  }
8657
9099
  return base;
8658
9100
  };
8659
- var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
9101
+ var policyUnderOneArrowReading = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
8660
9102
  const withoutRunners = resolvePolicyReading(SPELLS_WITHOUT_COMMAND_RUNNERS, config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId);
8661
9103
  const withRunners = resolvePolicyReading(SPELLS_COMMAND_RUNNERS_TOO, config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId);
8662
9104
  return strictestReadingOf(withRunners, withoutRunners);
8663
9105
  };
9106
+ var keepingTheStrictestReading = (strictest, reading) => strictestReadingOf(reading, strictest);
9107
+ var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => underEachArrowReading(() => policyUnderOneArrowReading(config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId)).reduce(keepingTheStrictestReading);
8664
9108
  var VERDICT_RESTRAINT = { allow: 0, requires_human: 1, deny: 2 };
8665
9109
  var verdictRestraint = (policy) => VERDICT_RESTRAINT[verdictForPolicy(policy)];
8666
9110
  var asksAtLeastAsHard = (policy, than) => restraintRank(policy) >= restraintRank(than) && TIMEOUT_ACTION_STRICTNESS[policy.timeoutAction] >= TIMEOUT_ACTION_STRICTNESS[than.timeoutAction] && policy.timeoutSeconds >= than.timeoutSeconds && policy.pushFirstSeconds <= than.pushFirstSeconds;
@@ -8713,10 +9157,10 @@ var namesOneToolAfterPrefix = (toolName, prefix) => {
8713
9157
  return tool.length > 0 && !tool.includes(SERVER_AND_TOOL_SEPARATOR);
8714
9158
  };
8715
9159
  var isPusharyConnectorTool = (toolName) => PUSHARY_CONNECTOR_TOOL_PREFIXES.some((prefix) => namesOneToolAfterPrefix(toolName, prefix));
8716
- var strictestScopeVerdict = (scope, paths) => {
8717
- if (paths.length === 0) return evaluateScope(scope, void 0);
9160
+ var strictestScopeVerdict = (scope, paths2) => {
9161
+ if (paths2.length === 0) return evaluateScope(scope, void 0);
8718
9162
  let worst = { outcome: "in_scope" };
8719
- for (const path of paths) {
9163
+ for (const path of paths2) {
8720
9164
  const verdict = evaluateScope(scope, path);
8721
9165
  if (verdict.outcome === "off_limits") return verdict;
8722
9166
  if (verdict.outcome === "out_of_scope") worst = verdict;
@@ -8795,8 +9239,8 @@ var isBlockedActionRequest = (request) => isBlockedActionEvent(request) && block
8795
9239
  var canonicalJsonText = (value) => {
8796
9240
  if (Array.isArray(value)) return `[${value.map(canonicalJsonText).join(",")}]`;
8797
9241
  if (value !== null && typeof value === "object") {
8798
- const record4 = value;
8799
- return `{${Object.keys(record4).filter((key) => record4[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonText(record4[key])}`).join(",")}}`;
9242
+ const record5 = value;
9243
+ return `{${Object.keys(record5).filter((key) => record5[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonText(record5[key])}`).join(",")}}`;
8800
9244
  }
8801
9245
  return JSON.stringify(value) ?? "null";
8802
9246
  };
@@ -8885,15 +9329,18 @@ var policyForScopeQuestion = (policy) => policy.timeoutAction === "approve" ? {
8885
9329
  pushFirstSeconds: policy.pushFirstSeconds > 0 ? policy.pushFirstSeconds : SCOPE_QUESTION_FIRST_WAIT_SECONDS
8886
9330
  } : policy;
8887
9331
  var isAReading = (reading) => reading !== null && reading.trim() !== "";
9332
+ var readingsOfScriptsWrittenForAShell = (command) => readingsOfNestedShellScripts(command, scriptsWrittenForAShellOrAnEval);
8888
9333
  var extraReadingsOf = (toolInput) => {
8889
9334
  const { command } = toolInput;
8890
9335
  if (typeof command !== "string" || command.length > LONGEST_COMMAND_READ_FOR_A_PUSH) return [];
8891
9336
  const commentFree = readingWithoutCommentsOrAnsiEscapes(command);
8892
9337
  const spelledOut = [command, commentFree].filter(isAReading).map(readingWithShellFormsSpelledOut);
9338
+ const scanned = [command, commentFree, ...spelledOut].filter(isAReading);
8893
9339
  const readings = [
8894
9340
  commentFree,
8895
9341
  ...spelledOut,
8896
- ...[command, commentFree, ...spelledOut].filter(isAReading).flatMap(readingsOfScriptsPassedToAShell)
9342
+ ...scanned.flatMap(readingsOfScriptsPassedToAShell),
9343
+ ...scanned.flatMap(readingsOfScriptsWrittenForAShell)
8897
9344
  ];
8898
9345
  return readings.filter(isAReading).map((reading) => ({ ...toolInput, command: reading }));
8899
9346
  };
@@ -8906,7 +9353,16 @@ var readingsNotYetJudged = (toolInputs) => {
8906
9353
  });
8907
9354
  };
8908
9355
  var withExtraReadings = (input) => shellDialectOf(input.toolName) !== void 0 ? { ...input, toolInputs: [...input.toolInputs, ...readingsNotYetJudged(input.toolInputs)] } : input;
8909
- var resolveGate = (rawInput) => {
9356
+ var GATE_VERDICT_RESTRAINT = { allow: 0, defer: 1, gate: 2, deny: 3, kill: 4 };
9357
+ var strictestGateVerdictOf = (strictest, verdict) => {
9358
+ const restraint = GATE_VERDICT_RESTRAINT[verdict.kind] - GATE_VERDICT_RESTRAINT[strictest.kind];
9359
+ if (restraint !== 0) return restraint > 0 ? verdict : strictest;
9360
+ return strictest.kind === "gate" && verdict.kind === "gate" ? { ...strictest, policy: strictestReadingOf(verdict.policy, strictest.policy) } : strictest;
9361
+ };
9362
+ var policyOfReadings = (readings) => readings.policy;
9363
+ var toolInputsOfReadings = (readings) => readings.toolInputs;
9364
+ var readingsAreAllowed = (readings) => verdictForPolicy(readings.policy) === "allow";
9365
+ var gateVerdictUnderOneArrowReading = (rawInput) => {
8910
9366
  const input = withExtraReadings(rawInput);
8911
9367
  const { modeState, config, toolName, toolInputs, cwd, sessionId } = input;
8912
9368
  const repoKey = input.sharedRepoKey ?? input.repoKey;
@@ -8922,16 +9378,23 @@ var resolveGate = (rawInput) => {
8922
9378
  const legacyPolicy = (toolInputs.length ? toolInputs : [void 0]).map((toolInput) => resolvePolicy(config, toolName, modeState.mode, toolInput, cwd, input.repoKey, sessionId)).find((policy2) => policy2.repoKey === input.repoKey && verdictForPolicy(policy2) === "deny");
8923
9379
  if (legacyPolicy) return { kind: "deny", policy: legacyPolicy, reason: `Denied by policy for ${legacyPolicy.tool}` };
8924
9380
  }
8925
- const policy = toolInputs.slice(rawInput.toolInputs.length).map((reading) => resolvePolicy(config, toolName, modeState.mode, reading, cwd, repoKey, sessionId)).reduce(
8926
- (strictest, reading) => strictestReadingOf(reading, strictest),
8927
- resolvePolicyAcross(config, toolName, modeState.mode, rawInput.toolInputs, cwd, repoKey, sessionId)
8928
- );
9381
+ const written = {
9382
+ toolInputs: rawInput.toolInputs,
9383
+ policy: resolvePolicyAcross(config, toolName, modeState.mode, rawInput.toolInputs, cwd, repoKey, sessionId)
9384
+ };
9385
+ const extra = toolInputs.slice(rawInput.toolInputs.length).map((reading) => ({
9386
+ toolInputs: [reading],
9387
+ policy: resolvePolicy(config, toolName, modeState.mode, reading, cwd, repoKey, sessionId)
9388
+ }));
9389
+ const policy = extra.map(policyOfReadings).reduce(keepingTheStrictestReading, written.policy);
8929
9390
  const verdict = verdictForPolicy(policy);
8930
9391
  const autoDenies = verdict === "deny";
8931
9392
  const allowedByBypassMode = !autoDenies && verdict !== "allow" && bypassModeAllows(input);
8932
- const askBesideARoutedPush = verdict === "allow" ? askAtTheRouteOfAPush(input, repoKey, policy) : void 0;
9393
+ const allowed = [written, ...extra].filter(readingsAreAllowed);
9394
+ const allowedBy = allowed[0]?.policy;
9395
+ const askBesideARoutedPush = autoDenies || allowedBy === void 0 ? void 0 : askAtTheRouteOfAPush({ ...input, toolInputs: allowed.flatMap(toolInputsOfReadings) }, repoKey, allowedBy);
8933
9396
  const autoApproves = (verdict === "allow" || allowedByBypassMode) && askBesideARoutedPush === void 0;
8934
- const askedPolicy = askBesideARoutedPush ?? policy;
9397
+ const askedPolicy = askBesideARoutedPush === void 0 ? policy : strictestReadingOf(policy, askBesideARoutedPush);
8935
9398
  if (autoDenies) return { kind: "deny", policy, reason: `Denied by policy for ${policy.tool}` };
8936
9399
  if (isAskedInEveryMode(toolName)) return { kind: "gate", policy };
8937
9400
  if (isModeStateDegraded(modeState)) {
@@ -8961,6 +9424,7 @@ var resolveGate = (rawInput) => {
8961
9424
  scopePath: scopeReason && "path" in scopeVerdict ? widenablePath(scopeVerdict.path) : void 0
8962
9425
  };
8963
9426
  };
9427
+ var resolveGate = (rawInput) => underEachArrowReading(() => gateVerdictUnderOneArrowReading(rawInput)).reduce(strictestGateVerdictOf);
8964
9428
  var noModeOverrideIsActive = (input) => (input.modeState.mode ?? input.config.modeOverride ?? null) === null;
8965
9429
  var editAsksAtTheAgentsPrompt = (input, verdict) => verdict.kind === "gate" && !verdict.scopeReason && noModeOverrideIsActive(input) && !aChosenRuleGoverns(input) && verdict.policy.mode === "push_first" && FILE_EDIT_TOOLS.has(input.toolName);
8966
9430
  var claudePromptsBeforeAnEdit = (permissionMode) => permissionMode === "default";
@@ -8995,10 +9459,11 @@ var codexDeferredPreToolUse = () => ({ kind: "deny", reason: CODEX_PRE_TOOL_USE_
8995
9459
  var isScopeReason = (scopeReason) => typeof scopeReason === "string" && scopeReason.length > 0;
8996
9460
  var scopeBreachReasonOf = (verdict) => verdict.kind === "gate" && isScopeReason(verdict.scopeReason) ? verdict.scopeReason : void 0;
8997
9461
  var onlyCodexPreToolUseCanAsk = (verdict, permissionMode) => verdict.kind === "gate" && (scopeBreachReasonOf(verdict) !== void 0 || !codexRaisesItsOwnPrompts(permissionMode));
8998
- var runsACommandThatNeedsAPerson = ({ toolName, toolInputs }) => SHELL_DIALECT_BY_TOOL.has(toolName) && toolInputs.some((toolInput) => {
9462
+ var runsACommandThatNeedsAPersonUnderOneArrowReading = ({ toolName, toolInputs }) => SHELL_DIALECT_BY_TOOL.has(toolName) && toolInputs.some((toolInput) => {
8999
9463
  const command = extractPolicyArg(toolName, toolInput);
9000
9464
  return command !== void 0 && (commandNeedsAPerson(toolName, command) || commandWritesThroughARemoteApi(command));
9001
9465
  });
9466
+ var runsACommandThatNeedsAPerson = (input) => underEitherArrowReading(() => runsACommandThatNeedsAPersonUnderOneArrowReading(input));
9002
9467
  var namesASecretOrWorkflowFile = (path) => {
9003
9468
  const written = withoutDotSegments(normalizeSeparators(path));
9004
9469
  return SECRET_FILE_NAME.test(basenameOf(written)) || CI_WORKFLOW_FILE.test(written);
@@ -9009,10 +9474,11 @@ var editsAFileThatNeedsAPerson = ({ toolName, toolInputs }) => toolInputs.some((
9009
9474
  const path = extractPolicyArg(toolName, toolInput);
9010
9475
  return path !== void 0 && fileEditNeedsAPerson(toolName, path);
9011
9476
  });
9012
- var runsADestructiveCommand = ({ toolName, toolInputs }) => SHELL_DIALECT_BY_TOOL.has(toolName) && toolInputs.some((toolInput) => {
9477
+ var runsADestructiveCommandUnderOneArrowReading = ({ toolName, toolInputs }) => SHELL_DIALECT_BY_TOOL.has(toolName) && toolInputs.some((toolInput) => {
9013
9478
  const command = extractPolicyArg(toolName, toolInput);
9014
9479
  return command !== void 0 && commandIsDestructive(toolName, command);
9015
9480
  });
9481
+ var runsADestructiveCommand = (input) => underEitherArrowReading(() => runsADestructiveCommandUnderOneArrowReading(input));
9016
9482
  var codexCallIsDestructive = (input, call) => call.deletesFiles || runsADestructiveCommand(input);
9017
9483
  var connectorCallOnlyReads = ({ toolName, toolInputs }) => isCodexConnectorTool(toolName) && mcpToolOnlyReads(toolName) && !mcpToolAppNamesADatabase(toolName) && toolInputs.length > 0 && toolInputs.every((toolInput) => mcpToolInputOnlyReads(toolName, toolInput));
9018
9484
  var fullAccessRunsThisConnectorReadUnasked = (input, verdict, call) => !codexRaisesItsOwnPrompts(call.permissionMode) && scopeBreachReasonOf(verdict) === void 0 && noModeOverrideIsActive(input) && connectorCallOnlyReads(input);
@@ -9190,7 +9656,7 @@ var pushSpellingsBeyondTheWrittenOnesIn = (input, toolInput) => [...pushesOfTheC
9190
9656
  var writtenRouteArgumentsOf = (input, toolInput) => [...policyArgForms(input.toolName, toolInput, input.cwd), ...pushesOfTheCurrentBranchIn(input, toolInput)];
9191
9657
  var routeArgumentsOf = (input, toolInput) => [...writtenRouteArgumentsOf(input, toolInput), ...pushSpellingsBeyondTheWrittenOnesIn(input, toolInput)];
9192
9658
  var everyRule = () => true;
9193
- var aChosenRuleGoverns = (input, counts = everyRule) => {
9659
+ var aChosenRuleGovernsUnderOneArrowReading = (input, counts) => {
9194
9660
  const chosen = input.config.policies.filter((policy) => !isDefaultRule(policy));
9195
9661
  const routes = approvalRoutesOf(input.config);
9196
9662
  if (routes === null) return true;
@@ -9201,8 +9667,8 @@ var aChosenRuleGoverns = (input, counts = everyRule) => {
9201
9667
  return governing !== void 0 && counts(governing.policy) || findBestRoute(routes, input.toolName, routeArgumentsOf(input, toolInput), input.repoKey) !== void 0;
9202
9668
  });
9203
9669
  };
9670
+ var aChosenRuleGoverns = (input, counts = everyRule) => underEitherArrowReading(() => aChosenRuleGovernsUnderOneArrowReading(input, counts));
9204
9671
  var AUTO_PERMISSION_MODE = "auto";
9205
- var routeWaitsForSomeoneElse = (route) => route.answeredBySomeoneElse === true;
9206
9672
  var routeDeliveredFor = (input, routes, toolInput) => {
9207
9673
  const repoKey = input.sharedRepoKey ?? input.repoKey;
9208
9674
  const written = writtenRouteArgumentsOf(input, toolInput);
@@ -9214,12 +9680,13 @@ var routeDeliveredFor = (input, routes, toolInput) => {
9214
9680
  if (heldSpelledRoute !== void 0 && heldSpelledRoute.toolPattern.length > (writtenRoute?.toolPattern.length ?? -1)) return heldSpelledRoute;
9215
9681
  return writtenRoute ?? findBestRoute(routes, input.toolName, spelled, repoKey);
9216
9682
  };
9217
- var callWaitsForSomeoneElse = (input) => {
9683
+ var callWaitsForSomeoneElseUnderOneArrowReading = (input) => {
9218
9684
  const routes = approvalRoutesOf(input.config);
9219
9685
  if (routes === null) return false;
9220
9686
  return withExtraReadings(input).toolInputs.some((toolInput) => routeDeliveredFor(input, routes, toolInput)?.answeredBySomeoneElse === true);
9221
9687
  };
9222
- var namedRouteWaitsForSomeoneElse = (input) => {
9688
+ var callWaitsForSomeoneElse = (input) => underEitherArrowReading(() => callWaitsForSomeoneElseUnderOneArrowReading(input));
9689
+ var namedRouteWaitsForSomeoneElseUnderOneArrowReading = (input) => {
9223
9690
  const routes = approvalRoutesOf(input.config);
9224
9691
  if (routes === null) return false;
9225
9692
  return withExtraReadings(input).toolInputs.some((toolInput) => {
@@ -9227,11 +9694,15 @@ var namedRouteWaitsForSomeoneElse = (input) => {
9227
9694
  return route?.answeredBySomeoneElse === true && patternToolName(route.toolPattern) === input.toolName;
9228
9695
  });
9229
9696
  };
9230
- var matchedRouteOf = (input) => {
9697
+ var namedRouteWaitsForSomeoneElse = (input) => underEitherArrowReading(() => namedRouteWaitsForSomeoneElseUnderOneArrowReading(input));
9698
+ var firstRouteHeldForSomeoneElseOrFirstOf = (matched) => matched.find(routeWaitsForSomeoneElse) ?? matched[0];
9699
+ var routesMatchedUnderOneArrowReading = (input) => {
9231
9700
  const routes = approvalRoutesOf(input.config);
9232
- if (routes === null) return void 0;
9233
- const matched = withExtraReadings(input).toolInputs.flatMap((toolInput) => routeDeliveredFor(input, routes, toolInput) ?? []);
9234
- const route = matched.find((candidate) => candidate.answeredBySomeoneElse === true) ?? matched[0];
9701
+ if (routes === null) return [];
9702
+ return withExtraReadings(input).toolInputs.flatMap((toolInput) => routeDeliveredFor(input, routes, toolInput) ?? []);
9703
+ };
9704
+ var matchedRouteOf = (input) => {
9705
+ const route = firstRouteHeldForSomeoneElseOrFirstOf(underEachArrowReading(() => routesMatchedUnderOneArrowReading(input)).flat());
9235
9706
  if (route === void 0) return void 0;
9236
9707
  return route.repoKey ? { toolPattern: route.toolPattern, repoKey: route.repoKey } : { toolPattern: route.toolPattern };
9237
9708
  };
@@ -9448,11 +9919,11 @@ var elicitationEnum = (property) => {
9448
9919
  return members.length === property.enum.length && members.length >= ELICITATION_MIN_OPTIONS ? members : null;
9449
9920
  };
9450
9921
  var readElicitationFields = (schema) => {
9451
- const record4 = elicitationRecord(schema);
9452
- const properties = elicitationRecord(record4?.properties);
9453
- if (!properties || record4?.type !== "object") return null;
9454
- if (Object.keys(record4).some((key) => !["type", "properties", "required", "$schema"].includes(key))) return null;
9455
- if (record4.required !== void 0 && (!Array.isArray(record4.required) || !record4.required.every((name) => typeof name === "string" && Object.hasOwn(properties, name)))) return null;
9922
+ const record5 = elicitationRecord(schema);
9923
+ const properties = elicitationRecord(record5?.properties);
9924
+ if (!properties || record5?.type !== "object") return null;
9925
+ if (Object.keys(record5).some((key) => !["type", "properties", "required", "$schema"].includes(key))) return null;
9926
+ if (record5.required !== void 0 && (!Array.isArray(record5.required) || !record5.required.every((name) => typeof name === "string" && Object.hasOwn(properties, name)))) return null;
9456
9927
  const entries = Object.entries(properties);
9457
9928
  if (entries.length === 0) return null;
9458
9929
  const fields = [];
@@ -9622,6 +10093,14 @@ export {
9622
10093
  isCodexQuestionTool,
9623
10094
  parseCodexQuestions,
9624
10095
  codexQuestionAnswerReason,
10096
+ SPAWN_CAPABILITY,
10097
+ CLAUDE_BRIDGE_CAPABILITY,
10098
+ CLAUDE_RESUME_CAPABILITY,
10099
+ CODEX_BRIDGE_CAPABILITY,
10100
+ CODEX_RESUME_CAPABILITY,
10101
+ GEMINI_BRIDGE_CAPABILITY,
10102
+ GEMINI_RESUME_CAPABILITY,
10103
+ sessionProvidersAdvertisedBy,
9625
10104
  CLAUDE_CONNECTOR_URL,
9626
10105
  CLAUDE_CONNECTOR_GUIDE,
9627
10106
  COWORK_CONNECTOR_LIMIT,
@@ -9718,6 +10197,8 @@ export {
9718
10197
  codexNativeApprovalResponse,
9719
10198
  transcriptRecordPlaintext,
9720
10199
  compressTranscriptRecord,
10200
+ SPAWN_LAUNCH_FAILED_CODE,
10201
+ SPAWN_UNCONFIRMED_ATTEMPT_FAILURE,
9721
10202
  CLAUDE_INBOX,
9722
10203
  parseClaudeInboxSession,
9723
10204
  claudeInboxAction,