pushary 1.9.94 → 1.9.97

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 (126) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/{api-QBIRIMGU.js → api-WH3DLHJB.js} +10 -10
  3. package/dist/bin/pushary-bell-hook.js +26 -26
  4. package/dist/bin/pushary-bell.js +10 -10
  5. package/dist/bin/pushary-claude.js +27 -27
  6. package/dist/bin/pushary-clean.js +34 -34
  7. package/dist/bin/pushary-codex-bridge.js +21 -21
  8. package/dist/bin/pushary-codex-hook.js +32 -34
  9. package/dist/bin/pushary-codex-session.js +8 -8
  10. package/dist/bin/pushary-codex.js +14 -14
  11. package/dist/bin/pushary-connect.js +27 -27
  12. package/dist/bin/pushary-cowork.js +5 -5
  13. package/dist/bin/pushary-daemon.js +39 -39
  14. package/dist/bin/pushary-disconnect.js +26 -26
  15. package/dist/bin/pushary-display-hook.js +17 -17
  16. package/dist/bin/pushary-doctor.js +42 -42
  17. package/dist/bin/pushary-elicitation-hook.js +26 -26
  18. package/dist/bin/pushary-gemini-bridge.js +15 -15
  19. package/dist/bin/pushary-gemini-hook.js +28 -28
  20. package/dist/bin/pushary-hook.js +30 -30
  21. package/dist/bin/pushary-login.js +20 -20
  22. package/dist/bin/pushary-logout.js +25 -25
  23. package/dist/bin/pushary-mcp.js +11 -11
  24. package/dist/bin/pushary-mode.js +15 -15
  25. package/dist/bin/pushary-notification-hook.js +25 -25
  26. package/dist/bin/pushary-opencode-hook.js +27 -27
  27. package/dist/bin/pushary-permission-denied-hook.js +30 -30
  28. package/dist/bin/pushary-permission-hook.js +30 -30
  29. package/dist/bin/pushary-post-hook.js +25 -25
  30. package/dist/bin/pushary-prompt-hook.js +25 -25
  31. package/dist/bin/pushary-session-end-hook.js +27 -27
  32. package/dist/bin/pushary-session-start-hook.js +35 -35
  33. package/dist/bin/pushary-setup.js +48 -48
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +32 -32
  36. package/dist/bin/pushary-stop-hook.js +25 -25
  37. package/dist/bin/pushary-stopfailure-hook.js +25 -25
  38. package/dist/bin/pushary-suggestions.js +15 -15
  39. package/dist/bin/pushary-transcript-register.js +18 -18
  40. package/dist/bin/pushary-transcripts.js +26 -26
  41. package/dist/bin/pushary-upgrade.js +40 -40
  42. package/dist/bin/pushary-wait.js +15 -15
  43. package/dist/bin/pushary.js +7 -7
  44. package/dist/{chunk-ANZECRZO.js → chunk-2ZAFA3XI.js} +3 -3
  45. package/dist/{chunk-AMPF5FAS.js → chunk-32577NGL.js} +1 -1
  46. package/dist/{chunk-K3E3NFTT.js → chunk-4D4USO5K.js} +6 -6
  47. package/dist/{chunk-EFCHGKAD.js → chunk-5OLBO5EB.js} +1 -1
  48. package/dist/{chunk-KXCSF2IK.js → chunk-5RNZP53C.js} +6 -6
  49. package/dist/{chunk-ZZ5QZ24I.js → chunk-5U63KUP3.js} +1 -1
  50. package/dist/{chunk-HHKBWPXA.js → chunk-5WOO44TA.js} +5 -5
  51. package/dist/{chunk-4YSFD4RY.js → chunk-5WYXFKZV.js} +1 -1
  52. package/dist/{chunk-5ZBYW7IO.js → chunk-5YRDZE5F.js} +1 -1
  53. package/dist/{chunk-GPGLRSGY.js → chunk-6CDA4R5L.js} +3 -3
  54. package/dist/{chunk-YQCRX4T6.js → chunk-6RGQIKAC.js} +3 -3
  55. package/dist/{chunk-CA2V7TKX.js → chunk-APFQBVQW.js} +6 -6
  56. package/dist/{chunk-4GNFBBE6.js → chunk-AUZITE2H.js} +6 -6
  57. package/dist/{chunk-Z4JULPCS.js → chunk-CB2RYMAO.js} +1 -1
  58. package/dist/{chunk-6SN6L5YT.js → chunk-CG3C2WL7.js} +11 -11
  59. package/dist/{chunk-FQZSKWWL.js → chunk-CMDIKFVL.js} +1 -1
  60. package/dist/{chunk-JLWI2HZF.js → chunk-CP72YEEA.js} +1 -1
  61. package/dist/{chunk-OWCWJBGW.js → chunk-E5WUBHVH.js} +4 -4
  62. package/dist/{chunk-ERQD5UVH.js → chunk-EAJT6RYP.js} +7 -7
  63. package/dist/{chunk-BE4KMA7N.js → chunk-FZQSUS3R.js} +21 -19
  64. package/dist/{chunk-QR7RXGNF.js → chunk-GEA6ZV2P.js} +2 -2
  65. package/dist/{chunk-RGMS5EDS.js → chunk-GN2L5CYF.js} +1 -1
  66. package/dist/{chunk-HRFOVTCQ.js → chunk-GNFUPHPZ.js} +10 -10
  67. package/dist/{chunk-REV2QMUD.js → chunk-HD7AURL6.js} +4 -4
  68. package/dist/{chunk-K56A3LSA.js → chunk-HWEEBVS7.js} +4 -4
  69. package/dist/{chunk-X7GKDLW7.js → chunk-HXUE6IIP.js} +5 -5
  70. package/dist/{chunk-E2WYLZIL.js → chunk-IED5CTYP.js} +3 -3
  71. package/dist/{chunk-KH3QOWTE.js → chunk-IFQKSIID.js} +3 -3
  72. package/dist/{chunk-JCZ7WE5G.js → chunk-JA6GCOW2.js} +7 -7
  73. package/dist/{chunk-AEKTC2DX.js → chunk-JR6FCHAQ.js} +3 -3
  74. package/dist/{chunk-LFIFIIMK.js → chunk-KNVTKFDP.js} +2 -2
  75. package/dist/{chunk-4N6MND55.js → chunk-KYX7VBEE.js} +2 -2
  76. package/dist/{chunk-F74RBPJY.js → chunk-KZTN6OXM.js} +6 -6
  77. package/dist/{chunk-SSXMA23D.js → chunk-LKDAMWTZ.js} +4 -4
  78. package/dist/{chunk-PGCDYBKG.js → chunk-MFJFN4DA.js} +3 -3
  79. package/dist/{chunk-TYHOBIDF.js → chunk-MGYGWHG5.js} +1 -1
  80. package/dist/{chunk-XASOD3XX.js → chunk-MYKZPTAL.js} +1 -1
  81. package/dist/{chunk-MC7I3SZW.js → chunk-NDJ7H2WF.js} +1 -1
  82. package/dist/{chunk-QVCDU4NT.js → chunk-NI3NSURQ.js} +1 -1
  83. package/dist/{chunk-X5DCL36E.js → chunk-NTCVGJFC.js} +4 -4
  84. package/dist/{chunk-JJ2AA3N6.js → chunk-OBB6VTSG.js} +5 -5
  85. package/dist/{chunk-4YPTEVZD.js → chunk-ORVMA5KJ.js} +3 -3
  86. package/dist/{chunk-RCDCFFG4.js → chunk-OW4WEO56.js} +3 -3
  87. package/dist/{chunk-AUIRBCYE.js → chunk-QCEY7TSX.js} +3 -3
  88. package/dist/{chunk-CS2C7S5L.js → chunk-QP3OSLKU.js} +5 -5
  89. package/dist/{chunk-OSDL6OND.js → chunk-R7D3PH2M.js} +6 -6
  90. package/dist/{chunk-QU2G6MM7.js → chunk-R7TVELKF.js} +1 -1
  91. package/dist/{chunk-FSMR6GJT.js → chunk-RILJLDKG.js} +5 -5
  92. package/dist/{chunk-SV6WE5QB.js → chunk-RPY5XCGA.js} +2 -2
  93. package/dist/{chunk-5QSPRDUO.js → chunk-RRA6POT5.js} +1 -1
  94. package/dist/{chunk-BOHUB5VP.js → chunk-RSITUL2U.js} +2 -2
  95. package/dist/{chunk-IB5MLSE3.js → chunk-RZD7ULBJ.js} +1 -1
  96. package/dist/{chunk-6YX4VASU.js → chunk-SXX47FHL.js} +2 -2
  97. package/dist/{chunk-7Y3AQNHV.js → chunk-T35RHO3X.js} +5 -5
  98. package/dist/{chunk-QYP4EEDA.js → chunk-TKOL7DJH.js} +2 -2
  99. package/dist/{chunk-Z5QJONDX.js → chunk-TSSV3NBD.js} +2 -2
  100. package/dist/{chunk-3GZCHFYV.js → chunk-TZE2S3XP.js} +3 -3
  101. package/dist/{chunk-CDIVGMBR.js → chunk-UAUADSJX.js} +2 -2
  102. package/dist/{chunk-HHE7ONVT.js → chunk-VAY5AJ6N.js} +4 -4
  103. package/dist/{chunk-UFT4R4V7.js → chunk-VHOGSWUF.js} +3 -3
  104. package/dist/{chunk-VDBRLNW7.js → chunk-VPT3RDTO.js} +1 -1
  105. package/dist/{chunk-HZQIC3DG.js → chunk-VVHNHETX.js} +2 -2
  106. package/dist/{chunk-2TA5UKNE.js → chunk-VVP4CP4O.js} +10 -10
  107. package/dist/{chunk-UC6IZRXP.js → chunk-W3OTAHLV.js} +4 -4
  108. package/dist/{chunk-5M6ASRLB.js → chunk-W5IW7NZE.js} +1 -1
  109. package/dist/{chunk-XERTD7VZ.js → chunk-WOFHN2IZ.js} +370 -44
  110. package/dist/{chunk-3DASOC3M.js → chunk-X22LLKBY.js} +3 -3
  111. package/dist/{chunk-SKYDYDGX.js → chunk-Z6O6CDTP.js} +5 -5
  112. package/dist/{chunk-QNFDU72D.js → chunk-ZDIQPYM2.js} +1 -1
  113. package/dist/{chunk-IMNXYNBJ.js → chunk-ZFUSWR2P.js} +2 -2
  114. package/dist/{codex-app-cards-switch-QEMMPNK3.js → codex-app-cards-switch-DFZK6GPW.js} +11 -11
  115. package/dist/{codex-desktop-launch-LNIZPXSJ.js → codex-desktop-launch-7QGN7SL7.js} +1 -1
  116. package/dist/{codex-session-launch-IZ4IQDS7.js → codex-session-launch-OWMNCYAH.js} +18 -18
  117. package/dist/{config-3J5OOY3O.js → config-ITPE5M6M.js} +3 -3
  118. package/dist/{global-upgrade-LQM7IFAP.js → global-upgrade-PYEFLMJA.js} +10 -10
  119. package/dist/{identity-IQ3JVAIM.js → identity-WTYTOLG3.js} +4 -4
  120. package/dist/{live-capabilities-3AWVBJSK.js → live-capabilities-HZ42KLZS.js} +5 -5
  121. package/dist/{paths-TAAVCO2D.js → paths-6JUJIM74.js} +3 -3
  122. package/dist/{reapply-37FCVQCJ.js → reapply-5WV6IS5V.js} +28 -28
  123. package/dist/src/index.js +29 -29
  124. package/dist/{upgrade-lock-GWB57A36.js → upgrade-lock-ENAQL63D.js} +4 -4
  125. package/dist/{usage-QJYVQ3GS.js → usage-BO7LGOA3.js} +3 -3
  126. package/package.json +1 -1
@@ -1942,6 +1942,8 @@ var POWERSHELL_FILE_WRITERS = /* @__PURE__ */ new Set([
1942
1942
  "start-bitstransfer"
1943
1943
  ]);
1944
1944
  var POWERSHELL_FETCHERS = /* @__PURE__ */ new Set(["invoke-webrequest", "invoke-restmethod", "start-bitstransfer"]);
1945
+ var POWERSHELL_WEB_REQUESTS = /* @__PURE__ */ new Set(["invoke-webrequest", "invoke-restmethod"]);
1946
+ var WEB_READ_METHODS = /* @__PURE__ */ new Set(["get", "head", "options"]);
1945
1947
  var DISK_ERASERS = /* @__PURE__ */ new Set(["format-volume", "clear-disk", "initialize-disk", "remove-partition", "format"]);
1946
1948
  var WINDOWS_SERVICE_CHANGERS = /* @__PURE__ */ new Set([
1947
1949
  "start-service",
@@ -2140,9 +2142,29 @@ var stageIsDestructive = (stage, judge) => {
2140
2142
  const command = powerShellCommandOf(stage);
2141
2143
  return DOTNET_RECURSIVE_DELETE.test(stage.source) || command !== null && (removesRecursively(command) || !onlyReads(command, judge) && judge.namesADestructiveAction(keywordTextOf(command)));
2142
2144
  };
2145
+ var LOOKS_LIKE_AN_ADDRESS = /^(?:[a-z][a-z\d+.-]*:\/\/|localhost\b|127\.|\[::1\])/i;
2146
+ var namesAWebRequestBody = (command) => command.args.some((arg) => {
2147
+ const parameter = parameterOf(arg);
2148
+ return namesTheParameter(parameter, "body", 1) || namesTheParameter(parameter, "infile", 2) || namesTheParameter(parameter, "form", 3);
2149
+ });
2150
+ var webRequestMethodOf = (command) => parameterValueOf(command, "method", 2) ?? parameterValueOf(command, "custommethod", 2);
2151
+ var SPLATTED_PARAMETERS = /^@\w+$/;
2152
+ var splatsItsParameters = (command) => command.args.some((arg) => !arg.quoted && SPLATTED_PARAMETERS.test(arg.text));
2153
+ var goesThroughAProxy = (command) => command.args.some((arg) => namesTheParameter(parameterOf(arg), "proxy", 5));
2154
+ var webRequestSendsData = (command) => {
2155
+ const method = webRequestMethodOf(command);
2156
+ if (splatsItsParameters(command)) return true;
2157
+ return method === void 0 ? namesAWebRequestBody(command) : method.includes("$") || !WEB_READ_METHODS.has(method.toLowerCase());
2158
+ };
2159
+ var webRequestAddressesOf = (command) => {
2160
+ if (splatsItsParameters(command) || goesThroughAProxy(command)) return [];
2161
+ const uri = parameterValueOf(command, "uri", 2);
2162
+ return uri === void 0 ? positionalTextsOf(command).filter((text3) => LOOKS_LIKE_AN_ADDRESS.test(text3)) : [uri];
2163
+ };
2164
+ var sendsAWebRequestThatNeedsAPerson = (command, judge) => POWERSHELL_WEB_REQUESTS.has(command.cmdlet) && judge.webRequestNeedsAPerson({ sendsData: webRequestSendsData(command), addresses: webRequestAddressesOf(command) });
2143
2165
  var stageHasAVisibleConsequence = (stage, judge) => {
2144
2166
  const command = powerShellCommandOf(stage);
2145
- return stage.redirectTargets.some((target) => namesAPathThatNeedsAPerson(target.text, judge)) || command !== null && !onlyReads(command, judge) && powerShellCommandChangesSomething(command, judge);
2167
+ return stage.redirectTargets.some((target) => namesAPathThatNeedsAPerson(target.text, judge)) || command !== null && sendsAWebRequestThatNeedsAPerson(command, judge) || command !== null && !onlyReads(command, judge) && powerShellCommandChangesSomething(command, judge);
2146
2168
  };
2147
2169
  var fetchesWithPowerShell = (stage, judge) => {
2148
2170
  const command = powerShellCommandOf(stage);
@@ -4538,12 +4560,14 @@ var sqlClientChangesData = (invocation) => {
4538
4560
  var PULL_REQUEST_CLIS = /* @__PURE__ */ new Set(["gh", "glab"]);
4539
4561
  var PULL_REQUEST_NOUNS = /* @__PURE__ */ new Set(["pr", "mr"]);
4540
4562
  var MERGE_SUBCOMMAND = "merge";
4541
- var PULL_REQUEST_MERGE_PATH = /(?:^|\/)pulls\/[^/\s]+\/merge(?:[?#]|$)/;
4563
+ var PULL_REQUEST_MERGE_PATH = /(?:^|\/)pulls\/\d+\/merge$/;
4564
+ var PULL_REQUEST_MERGE_PATH_SPELLED_ANY_WAY = /(?:^|\/)pulls\/[^/\s]+\/merge(?:[?#]|$)/;
4542
4565
  var mergesAPullRequest = ({ program, args }) => {
4543
4566
  if (program === void 0 || !PULL_REQUEST_CLIS.has(basenameOf(program.text))) return false;
4544
4567
  const words = args.filter((arg) => !arg.text.startsWith("-"));
4545
4568
  return words.some((word, index) => PULL_REQUEST_NOUNS.has(word.text) && words[index + 1]?.text === MERGE_SUBCOMMAND) || args.some((arg) => PULL_REQUEST_MERGE_PATH.test(arg.text));
4546
4569
  };
4570
+ var mergesAPullRequestByAnyPath = ({ program, args }) => program !== void 0 && PULL_REQUEST_CLIS.has(basenameOf(program.text)) && args.some((arg) => PULL_REQUEST_MERGE_PATH_SPELLED_ANY_WAY.test(arg.text));
4547
4571
  var DEPLOY_AND_SCHEMA_COMMAND_PATTERNS = [
4548
4572
  "Bash(kubectl apply:*)",
4549
4573
  "Bash(kubectl replace:*)",
@@ -4622,12 +4646,15 @@ var PUSHES_EVERY_TAG = /* @__PURE__ */ new Set(["--tags", "--follow-tags"]);
4622
4646
  var NAMES_A_TAG = /(?:^|:)\+?refs\/tags\/|^tag$|(?:^|:)v?\d+(?:\.\d+){1,3}$|(?:^|:)v?\d+\.\d+\.\d+[-+][\w.]+$|\/v\d+\.\d+\.\d+(?:\.\d+)?(?:[-+][\w.]+)?$|^v\$/;
4623
4647
  var TAG_HELD_IN_A_VARIABLE = /^v?\$\{?(?:\w+_)?(?:tag|version)(?:_name)?\}?$/i;
4624
4648
  var GIT_PUSH = "push";
4649
+ var NAMES_A_MAJOR_VERSION_TAG = /(?:^|:)v\d+$/;
4650
+ var SETS_THE_UPSTREAM_BRANCH = /* @__PURE__ */ new Set(["-u", "--set-upstream"]);
4625
4651
  var pushesATag = ({ program, args }) => {
4626
4652
  if (program === void 0 || basenameOf(program.text) !== GIT) return false;
4627
4653
  const [subcommand, ...rest] = argsAfterHarmlessGlobalFlags(args);
4628
4654
  if (subcommand?.text !== GIT_PUSH) return false;
4629
4655
  const operands = rest.filter((arg) => !FLAG.test(arg.text));
4630
- return rest.some((arg) => PUSHES_EVERY_TAG.has(arg.text)) || operands.slice(1).some((operand) => NAMES_A_TAG.test(operand.text) || TAG_HELD_IN_A_VARIABLE.test(operand.text));
4656
+ const pushesABranch = rest.some((arg) => SETS_THE_UPSTREAM_BRANCH.has(arg.text));
4657
+ return rest.some((arg) => PUSHES_EVERY_TAG.has(arg.text)) || operands.slice(1).some((operand) => NAMES_A_TAG.test(operand.text) || TAG_HELD_IN_A_VARIABLE.test(operand.text) || !pushesABranch && NAMES_A_MAJOR_VERSION_TAG.test(operand.text));
4631
4658
  };
4632
4659
  var SECRET_FILE_NAME = /^(?:\.env(?:\.(?!example$|sample$|template$)[\w.-]+)?|(?:secrets?|credentials)\.(?:json|ya?ml|env|toml|ini)|credentials)$/i;
4633
4660
  var CI_WORKFLOW_FILE = /(?:^|\/)\.github\/workflows\/[^/]+$/i;
@@ -4643,7 +4670,24 @@ var AGENT_SETTINGS_FILE = new RegExp(String.raw`(?:^|/)(?:${[
4643
4670
  String.raw`\.config/opencode/(?:opencode\.jsonc?|plugins?/.+)`,
4644
4671
  String.raw`\.pushary(?:/.+)?`,
4645
4672
  String.raw`\.git/hooks(?:/.+)?`,
4646
- String.raw`\.ssh(?:/(?!known_hosts(?:\.old)?$).+)?`
4673
+ String.raw`\.git/config`,
4674
+ String.raw`\.ssh(?:/(?!known_hosts(?:\.old)?$).+)?`,
4675
+ String.raw`\.mcp\.json`,
4676
+ String.raw`\.cursor/mcp\.json`,
4677
+ String.raw`\.claude/hooks/.+`,
4678
+ String.raw`pushary-(?:policy|mode)-[^/]*\.json`
4679
+ ].join("|")})$`, "i");
4680
+ var HOME_DIRECTORY = String.raw`(?:~|\$HOME|\$\{HOME\}|(?:[A-Za-z]:)?/Users/[^/]+|/home/[^/]+|/root|/var/root)`;
4681
+ var FILE_THE_MACHINE_RUNS_LATER = new RegExp(String.raw`^(?:${[
4682
+ String.raw`${HOME_DIRECTORY}/\.(?:zshrc|zshenv|zprofile|zlogin|zlogout|bashrc|bash_profile|bash_login|bash_logout|bash_aliases|profile)(?:\.[\w-]+)?`,
4683
+ String.raw`${HOME_DIRECTORY}/\.gitconfig(?:[-._][\w.-]+)?`,
4684
+ String.raw`${HOME_DIRECTORY}/\.p10k\.zsh`,
4685
+ String.raw`${HOME_DIRECTORY}/\.(?:zsh|zshrc\.d|oh-my-zsh)/.+`,
4686
+ String.raw`${HOME_DIRECTORY}/\.config/(?:fish/config\.fish|fish/conf\.d/.+|git/config|zsh/.+|systemd/user/.+)`,
4687
+ String.raw`(?:.*/)?Library/Launch(?:Agents|Daemons)/[^/]+`,
4688
+ String.raw`(?:.*/)?(?:Windows)?PowerShell/(?:Microsoft\.[\w.]+_)?profile\.ps1`,
4689
+ String.raw`\$profile(?:\.\w+)?`,
4690
+ String.raw`/(?:private/)?etc/.+`
4647
4691
  ].join("|")})$`, "i");
4648
4692
  var withoutDotSegments = (path) => {
4649
4693
  const kept = [];
@@ -4655,12 +4699,15 @@ var withoutDotSegments = (path) => {
4655
4699
  };
4656
4700
  var pathNeedsAPersonToChange = (path) => {
4657
4701
  const written = withoutDotSegments(normalizeSeparators(path));
4658
- return SECRET_FILE_NAME.test(basenameOf(written)) || CI_WORKFLOW_FILE.test(written) || AGENT_SETTINGS_FILE.test(written);
4702
+ return SECRET_FILE_NAME.test(basenameOf(written)) || CI_WORKFLOW_FILE.test(written) || AGENT_SETTINGS_FILE.test(written) || FILE_THE_MACHINE_RUNS_LATER.test(written);
4659
4703
  };
4660
4704
  var REDIRECTS_INTO_A_SECRET_FILE = />>?\s*(?:[^\s;|&<>]*\/)?\.env(?:\.[\w-]+)?(?=$|[\s;|&)])/;
4661
4705
  var COPIES_ONTO_ITS_LAST_OPERAND = /* @__PURE__ */ new Set(["cp", "install", "ln", "rsync", "scp"]);
4662
- var WRITES_EVERY_OPERAND = /* @__PURE__ */ new Set(["mv", "tee", "rm", "unlink", "shred", "truncate", "sponge"]);
4663
- var EDITS_IN_PLACE = /* @__PURE__ */ new Set(["sed", "gsed", "perl", "yq"]);
4706
+ var WRITES_EVERY_OPERAND = /* @__PURE__ */ new Set(["mv", "tee", "rm", "unlink", "shred", "truncate"]);
4707
+ var EDITS_IN_PLACE = /* @__PURE__ */ new Set(["sed", "gsed", "perl"]);
4708
+ var IN_PLACE_FLAG = /^(?:-[A-Za-z]*i|--in-place(?:=.*)?)$/;
4709
+ var PERMISSIONS_OFF_WRITES_EVERY_OPERAND = /* @__PURE__ */ new Set([...WRITES_EVERY_OPERAND, "sponge"]);
4710
+ var PERMISSIONS_OFF_EDITS_IN_PLACE = /* @__PURE__ */ new Set([...EDITS_IN_PLACE, "yq"]);
4664
4711
  var IN_PLACE_LONG_FLAG = /^--in-?place(?:=|$)/;
4665
4712
  var IN_PLACE_LETTER = "i";
4666
4713
  var SED_FLAGS_THAT_TAKE_THE_REST = /* @__PURE__ */ new Set(["e", "f", "l"]);
@@ -4698,6 +4745,7 @@ var spellingsOfAWord = (word) => {
4698
4745
  }
4699
4746
  return spellings.map((text3) => ({ ...word, text: text3 }));
4700
4747
  };
4748
+ var namesASecretFile = (word) => word !== void 0 && SECRET_FILE_NAME.test(basenameOf(word.text));
4701
4749
  var namesAFileThatNeedsAPerson = (word) => word !== void 0 && pathNeedsAPersonToChange(word.text);
4702
4750
  var RECURSIVE_COPY_FLAG = /^(?:-[A-Za-z]*[rRa][A-Za-z]*|--recursive|--archive)$/;
4703
4751
  var FOLDER_THAT_NEEDS_A_PERSON = new RegExp(String.raw`(?:^|/)(?:${[
@@ -4712,7 +4760,8 @@ var FOLDER_THAT_NEEDS_A_PERSON = new RegExp(String.raw`(?:^|/)(?:${[
4712
4760
  String.raw`\.pushary`,
4713
4761
  String.raw`\.git/hooks`,
4714
4762
  String.raw`\.ssh`,
4715
- String.raw`\.config/opencode(?:/plugins?)?`
4763
+ String.raw`\.config/opencode(?:/plugins?)?`,
4764
+ String.raw`Library/Launch(?:Agents|Daemons)`
4716
4765
  ].join("|")})$`, "i");
4717
4766
  var folderNeedsAPersonToChange = (path) => FOLDER_THAT_NEEDS_A_PERSON.test(withoutDotSegments(normalizeSeparators(path)));
4718
4767
  var NETWORK_SENDERS = /* @__PURE__ */ new Set([
@@ -4732,6 +4781,17 @@ var NETWORK_SENDERS = /* @__PURE__ */ new Set([
4732
4781
  "rclone"
4733
4782
  ]);
4734
4783
  var FILE_REFERENCE_PREFIX = /^(?:[\w.-]+=)?@|^[\w.-]+:/;
4784
+ var namesASecretFileReference = (word) => SECRET_FILE_NAME.test(basenameOf(word.text.replace(FILE_REFERENCE_PREFIX, "")));
4785
+ var sendsASecretFile = ({ program, args }) => program !== void 0 && NETWORK_SENDERS.has(basenameOf(program.text)) && args.some(namesASecretFileReference);
4786
+ var writesASecretFile = ({ program, args }) => {
4787
+ if (program === void 0) return false;
4788
+ if (sendsASecretFile({ program, args })) return true;
4789
+ const name = basenameOf(program.text);
4790
+ const operands = args.filter((arg) => !FLAG.test(arg.text));
4791
+ if (COPIES_ONTO_ITS_LAST_OPERAND.has(name)) return namesASecretFile(operands.at(-1));
4792
+ if (WRITES_EVERY_OPERAND.has(name)) return operands.some(namesASecretFile);
4793
+ return EDITS_IN_PLACE.has(name) && args.some((arg) => IN_PLACE_FLAG.test(arg.text)) && operands.some(namesASecretFile);
4794
+ };
4735
4795
  var referencesAFileThatNeedsAPerson = (word) => pathNeedsAPersonToChange(word.text.replace(FILE_REFERENCE_PREFIX, ""));
4736
4796
  var sendsAFileThatNeedsAPerson = ({ program, args }) => program !== void 0 && NETWORK_SENDERS.has(basenameOf(program.text)) && args.some(referencesAFileThatNeedsAPerson);
4737
4797
  var targetDirectoryOf = (args) => {
@@ -4758,17 +4818,52 @@ var changesWhereGitLooksForHooks = ({ program, args }) => {
4758
4818
  if (args[setting - 1]?.text === GIT_ONE_COMMAND_SETTING_FLAG) return true;
4759
4819
  return args.some((arg) => arg.text === GIT_CONFIG_SUBCOMMAND) && (args[setting + 1] !== void 0 || args.some((arg) => GIT_CONFIG_UNSET_FLAGS.has(arg.text)));
4760
4820
  };
4821
+ var GIT_SETTING_THAT_RUNS_A_PROGRAM = new RegExp(`^(?:${[
4822
+ String.raw`core\.(?:fsmonitor|sshcommand|pager|editor|askpass|gitproxy|alternaterefscommand|hookspath)`,
4823
+ String.raw`pager\..+`,
4824
+ String.raw`sequence\.editor`,
4825
+ String.raw`diff\.external`,
4826
+ String.raw`diff\..+\.(?:textconv|command)`,
4827
+ String.raw`merge\..+\.driver`,
4828
+ String.raw`(?:diff|merge)tool\..+\.(?:cmd|path)`,
4829
+ String.raw`interactive\.difffilter`,
4830
+ String.raw`gpg\.ssh\.defaultkeycommand`,
4831
+ String.raw`uploadpack\.packobjectshook`,
4832
+ String.raw`credential\.(?:.+\.)?helper`,
4833
+ String.raw`gpg(?:\.[\w-]+)?\.program`,
4834
+ String.raw`filter\..+\.(?:clean|smudge|process)`,
4835
+ String.raw`remote\..+\.(?:uploadpack|receivepack)`,
4836
+ String.raw`protocol\.(?:.+\.)?allow`,
4837
+ String.raw`include\.path`,
4838
+ String.raw`includeif\..+\.path`
4839
+ ].join("|")})$`, "i");
4840
+ var SWITCHES_A_SETTING_ON_OR_OFF = /^(?:true|false|yes|no|on|off|0|1|never|)$/i;
4841
+ var GIT_INCLUDE_SETTING = /^include(?:if\..+)?\.path$/i;
4842
+ var GIT_CREDENTIAL_HELPER_SETTING = /^credential\.(?:.+\.)?helper$/i;
4843
+ var NAMES_A_KNOWN_CREDENTIAL_HELPER = /^(?:osxkeychain|store|cache|manager|manager-core|libsecret|wincred|gnome-keyring)(?:\s+--[\w-]+(?:=[\w./~:@%+,-]+)?)*$/i;
4844
+ var namesNoNewProgram = (setting, value) => !value.expands && !GIT_INCLUDE_SETTING.test(setting) && (SWITCHES_A_SETTING_ON_OR_OFF.test(value.text) || GIT_CREDENTIAL_HELPER_SETTING.test(setting) && NAMES_A_KNOWN_CREDENTIAL_HELPER.test(value.text));
4845
+ var GIT_SETTING_THAT_RUNS_A_COMMAND_AFTER_A_BANG = /^(?:alias\..+|submodule\..+\.update)$/i;
4846
+ var RUNS_A_SHELL_COMMAND = /^!/;
4847
+ var setsAGitSettingThatRunsAProgram = ({ program, args }) => {
4848
+ if (program === void 0 || basenameOf(program.text) !== GIT || !args.some((arg) => arg.text === GIT_CONFIG_SUBCOMMAND)) return false;
4849
+ const operands = args.filter((arg) => !FLAG.test(arg.text));
4850
+ const setting = operands.findIndex((arg) => GIT_SETTING_THAT_RUNS_A_PROGRAM.test(arg.text) || GIT_SETTING_THAT_RUNS_A_COMMAND_AFTER_A_BANG.test(arg.text));
4851
+ const value = setting === -1 ? void 0 : operands[setting + 1];
4852
+ const name = operands[setting]?.text ?? "";
4853
+ if (value === void 0 || namesNoNewProgram(name, value)) return false;
4854
+ return !GIT_SETTING_THAT_RUNS_A_COMMAND_AFTER_A_BANG.test(name) || value.expands || RUNS_A_SHELL_COMMAND.test(value.text);
4855
+ };
4761
4856
  var writesAFileThatNeedsAPerson = ({ program, args }) => {
4762
4857
  if (program === void 0) return false;
4763
4858
  if (sendsAFileThatNeedsAPerson({ program, args })) return true;
4764
4859
  const name = basenameOf(program.text);
4765
- const editsInPlace = EDITS_IN_PLACE.has(name) && args.some((arg) => flagEditsInPlace(name, arg.text));
4766
- if (!COPIES_ONTO_ITS_LAST_OPERAND.has(name) && !WRITES_EVERY_OPERAND.has(name) && !editsInPlace) return false;
4860
+ const editsInPlace = PERMISSIONS_OFF_EDITS_IN_PLACE.has(name) && args.some((arg) => flagEditsInPlace(name, arg.text));
4861
+ if (!COPIES_ONTO_ITS_LAST_OPERAND.has(name) && !PERMISSIONS_OFF_WRITES_EVERY_OPERAND.has(name) && !editsInPlace) return false;
4767
4862
  const spelled = args.filter((arg) => !FLAG.test(arg.text)).map(spellingsOfAWord);
4768
4863
  if (spelled.includes(null)) return true;
4769
4864
  const operands = spelled.flatMap((words) => words ?? []);
4770
4865
  if (COPIES_ONTO_ITS_LAST_OPERAND.has(name)) return copiesOntoAFileThatNeedsAPerson(args, operands);
4771
- if (WRITES_EVERY_OPERAND.has(name)) {
4866
+ if (PERMISSIONS_OFF_WRITES_EVERY_OPERAND.has(name)) {
4772
4867
  return operands.some((operand) => namesAFileThatNeedsAPerson(operand) || folderNeedsAPersonToChange(operand.text)) || name === MOVE && copiesOntoAFileThatNeedsAPerson(args, operands);
4773
4868
  }
4774
4869
  return operands.some(namesAFileThatNeedsAPerson);
@@ -4877,7 +4972,8 @@ var AWS_OPTIONS_WITH_VALUES = /* @__PURE__ */ new Set([
4877
4972
  "--cli-binary-format"
4878
4973
  ]);
4879
4974
  var AWS_LOCAL_COMMANDS = /* @__PURE__ */ new Set(["configure", "help", "history", "sso", "login", "logout"]);
4880
- var AWS_READ_OPERATION = /^(?:describe|list|get|head|batch-get|lookup|search|filter|scan|query|select|wait|validate|estimate|simulate|tail|ls|presign|help|login|update-kubeconfig|start-query|stop-query|assume-role)(?:-|$)/;
4975
+ var AWS_READ_OPERATION = /^(?:describe|list|get|head|batch-get|lookup|search|filter|scan|query|select|wait|validate|estimate|simulate|tail|ls|presign|help)(?:-|$)/;
4976
+ var AWS_SIGN_IN_OR_QUERY_OPERATION = /^(?:login|update-kubeconfig|start-query|stop-query|assume-role)(?:-|$)/;
4881
4977
  var AWS_S3_SERVICE = "s3";
4882
4978
  var AWS_S3_COPIES = /* @__PURE__ */ new Set(["cp", "sync"]);
4883
4979
  var S3_URL_PREFIX = "s3://";
@@ -4976,10 +5072,15 @@ var twilioCliWrites = (args) => {
4976
5072
  return !TWILIO_READ_ACTIONS.has(topic.text.split(TWILIO_TOPIC_SEPARATOR).at(-1) ?? "");
4977
5073
  };
4978
5074
  var GITHUB_CLI = "gh";
5075
+ var AWS_CLI = "aws";
5076
+ var awsOnlySignsInOrQueries = (args) => {
5077
+ const [service, operation] = positionalWordsOf(args, AWS_OPTIONS_WITH_VALUES);
5078
+ return service !== void 0 && service.text !== AWS_S3_SERVICE && operation !== void 0 && AWS_SIGN_IN_OR_QUERY_OPERATION.test(operation.text);
5079
+ };
4979
5080
  var REMOTE_API_CLI_WRITES = /* @__PURE__ */ new Map([
4980
5081
  [GITHUB_CLI, githubCliWrites],
4981
5082
  ["stripe", stripeCliWrites],
4982
- ["aws", awsCliWrites],
5083
+ [AWS_CLI, awsCliWrites],
4983
5084
  ["twilio", twilioCliWrites]
4984
5085
  ]);
4985
5086
  var invocationWritesThroughARemoteApi = ({ program, args }) => {
@@ -4995,6 +5096,7 @@ var GITHUB_COMMANDS_WITH_A_CONSEQUENCE = /* @__PURE__ */ new Map([
4995
5096
  ["secret", /* @__PURE__ */ new Set(["set"])],
4996
5097
  ["variable", /* @__PURE__ */ new Set(["set"])],
4997
5098
  [GITHUB_REPO_NOUN, /* @__PURE__ */ new Set(["archive", "rename"])],
5099
+ ["workflow", /* @__PURE__ */ new Set(["run", "enable", "disable"])],
4998
5100
  ["ssh-key", /* @__PURE__ */ new Set(["add"])],
4999
5101
  ["gpg-key", /* @__PURE__ */ new Set(["add"])]
5000
5102
  ]);
@@ -5062,6 +5164,7 @@ var writesThroughAServiceApi = (invocation) => {
5062
5164
  const name = basenameOf(innermost.program?.text ?? "");
5063
5165
  if (name === GITHUB_CLI) return false;
5064
5166
  if (name === STRIPE_CLI && !stripeMayUseLiveData(wordsOfInvocation(invocation))) return false;
5167
+ if (name === AWS_CLI && awsOnlySignsInOrQueries(innermost.args)) return false;
5065
5168
  return invocationWritesThroughARemoteApi(innermost);
5066
5169
  };
5067
5170
  var NO_SHORT_OPTIONS = /* @__PURE__ */ new Set();
@@ -5164,13 +5267,210 @@ var sshRemoteCommandOf = (args) => {
5164
5267
  }
5165
5268
  return args.slice(index + 1);
5166
5269
  };
5270
+ var PLAIN_REMOTE_COMMAND = /^[\w ./:=,@%+-]+$/;
5271
+ var REMOTE_STATUS_COMMAND = new RegExp(`^(?:${[
5272
+ String.raw`(?:uptime|free|who|w|nproc|lscpu|lsblk|last|lsof|netstat)`,
5273
+ String.raw`docker (?:compose )?(?:ps|images|logs|inspect|stats|top|version|info)`,
5274
+ String.raw`systemctl (?:status|is-active|is-enabled|is-failed|list-units|list-timers|show|cat)`,
5275
+ String.raw`journalctl`
5276
+ ].join("|")})(?: |$)`);
5277
+ var JOURNAL_CHANGING_OPTIONS = [
5278
+ "vacuum-size",
5279
+ "vacuum-time",
5280
+ "vacuum-files",
5281
+ "rotate",
5282
+ "flush",
5283
+ "sync",
5284
+ "relinquish-var",
5285
+ "smart-relinquish-var",
5286
+ "setup-keys",
5287
+ "update-catalog",
5288
+ "cursor-file"
5289
+ ];
5290
+ var JOURNAL_READ_OPTIONS_SHARING_A_PREFIX = /* @__PURE__ */ new Set(["cursor"]);
5291
+ var LONG_OPTION_NAME = /^--([\w-]+)/;
5292
+ var namesAJournalChangingOption = (word) => {
5293
+ const name = LONG_OPTION_NAME.exec(word)?.[1];
5294
+ return name !== void 0 && !JOURNAL_READ_OPTIONS_SHARING_A_PREFIX.has(name) && JOURNAL_CHANGING_OPTIONS.some((option) => option.startsWith(name));
5295
+ };
5296
+ var onlyReadsTheRemoteStatus = (command) => PLAIN_REMOTE_COMMAND.test(command) && REMOTE_STATUS_COMMAND.test(command) && !command.split(" ").some(namesAJournalChangingOption);
5167
5297
  var sshRunsMoreThanAReadOnlyCommand = ({ program, args }) => {
5168
5298
  if (program === void 0 || basenameOf(program.text) !== SSH) return false;
5169
5299
  if (sshOptionRunsACommand(args)) return true;
5170
5300
  const command = sshRemoteCommandOf(args);
5171
- return command.length > 0 && (command.some((arg) => arg.expands) || !isSafeReadOnlyCommand(command.map((arg) => arg.text).join(" ")));
5301
+ const remote = command.map((arg) => arg.text).join(" ");
5302
+ return command.length > 0 && (command.some((arg) => arg.expands) || !isSafeReadOnlyCommand(remote) && !onlyReadsTheRemoteStatus(remote));
5303
+ };
5304
+ var REMOTE_COPY_OPTIONS_WITH_A_VALUE = /* @__PURE__ */ new Map([
5305
+ ["scp", /* @__PURE__ */ new Set(["-c", "-D", "-F", "-i", "-J", "-l", "-o", "-P", "-S", "-X"])],
5306
+ ["rsync", /* @__PURE__ */ new Set([
5307
+ "-e",
5308
+ "--rsh",
5309
+ "--rsync-path",
5310
+ "--exclude",
5311
+ "--include",
5312
+ "--filter",
5313
+ "-f",
5314
+ "--exclude-from",
5315
+ "--include-from",
5316
+ "--files-from",
5317
+ "--chmod",
5318
+ "--chown",
5319
+ "--log-file",
5320
+ "--password-file",
5321
+ "--port",
5322
+ "--timeout",
5323
+ "--contimeout",
5324
+ "--bwlimit",
5325
+ "--max-size",
5326
+ "--min-size",
5327
+ "--max-delete",
5328
+ "--backup-dir",
5329
+ "--link-dest",
5330
+ "--compare-dest",
5331
+ "--copy-dest",
5332
+ "--partial-dir",
5333
+ "--temp-dir",
5334
+ "-T",
5335
+ "--suffix",
5336
+ "--out-format",
5337
+ "--iconv",
5338
+ "--usermap",
5339
+ "--groupmap",
5340
+ "-M",
5341
+ "--remote-option",
5342
+ "--info",
5343
+ "--debug",
5344
+ "--skip-compress",
5345
+ "--compress-level",
5346
+ "--block-size",
5347
+ "-B",
5348
+ "--modify-window",
5349
+ "--sockopts",
5350
+ "--outbuf",
5351
+ "--copy-as",
5352
+ "--stop-at",
5353
+ "--stop-after",
5354
+ "--time-limit",
5355
+ "--checksum-seed",
5356
+ "--max-alloc",
5357
+ "--early-input",
5358
+ "--address",
5359
+ "--write-batch",
5360
+ "--read-batch",
5361
+ "--only-write-batch"
5362
+ ])]
5363
+ ]);
5364
+ var SSHPASS = "sshpass";
5365
+ var SSHPASS_OPTIONS_WITH_A_VALUE = /* @__PURE__ */ new Set(["-p", "-f", "-d", "-P"]);
5366
+ var NAMES_ANOTHER_MACHINE = /^(?:(?:rsync|scp|sftp):\/\/|(?:[^\s/:@]+@)?[^\s/:@]+:)/i;
5367
+ var SHORT_OPTION_CLUSTER2 = /^-[A-Za-z]+$/;
5368
+ var clusterEndsWithAnOptionThatTakesAValue = (text3, withAValue) => {
5369
+ const letters = text3.slice(1);
5370
+ const firstWithAValue = [...letters].findIndex((letter) => withAValue.has(`-${letter}`));
5371
+ return firstWithAValue === letters.length - 1;
5372
+ };
5373
+ var optionTakesTheNextWord = (text3, withAValue) => withAValue.has(text3) || SHORT_OPTION_CLUSTER2.test(text3) && clusterEndsWithAnOptionThatTakesAValue(text3, withAValue);
5374
+ var operandsAfterOptions = (args, withAValue) => {
5375
+ const operands = [];
5376
+ for (let index = 0; index < args.length; index += 1) {
5377
+ const text3 = args[index]?.text ?? "";
5378
+ if (text3 === END_OF_OPTIONS3) return [...operands, ...args.slice(index + 1)];
5379
+ if (!FLAG.test(text3)) operands.push(args[index]);
5380
+ else if (optionTakesTheNextWord(text3, withAValue)) index += 1;
5381
+ }
5382
+ return operands;
5383
+ };
5384
+ var optionWordsOf = (args, withAValue) => {
5385
+ const options = [];
5386
+ for (let index = 0; index < args.length; index += 1) {
5387
+ const text3 = args[index]?.text ?? "";
5388
+ if (text3 === END_OF_OPTIONS3) break;
5389
+ if (!FLAG.test(text3)) continue;
5390
+ options.push(text3);
5391
+ if (optionTakesTheNextWord(text3, withAValue)) index += 1;
5392
+ }
5393
+ return options;
5394
+ };
5395
+ var withoutSshpass = (invocation) => {
5396
+ if (invocation.program === void 0 || basenameOf(invocation.program.text) !== SSHPASS) return invocation;
5397
+ const [program, ...args] = operandsAfterOptions(invocation.args, SSHPASS_OPTIONS_WITH_A_VALUE);
5398
+ const start = program === void 0 ? -1 : invocation.args.indexOf(program);
5399
+ return { program, args: start === -1 ? [] : invocation.args.slice(start + 1) };
5400
+ };
5401
+ var RSYNC = "rsync";
5402
+ var RSYNC_DRY_RUN = "--dry-run";
5403
+ var RSYNC_DRY_RUN_LETTER = "n";
5404
+ var RSYNC_REMOTE_SHELL_LETTER = "e";
5405
+ var RSYNC_NAMES_A_PROGRAM = /^--(?:rsh|rsync-path)(?:=|$)/;
5406
+ var clusterTurnsOn = (text3, letter, withAValue) => {
5407
+ if (!SHORT_OPTION_CLUSTER2.test(text3)) return false;
5408
+ for (const each of text3.slice(1)) {
5409
+ if (each === letter) return true;
5410
+ if (withAValue.has(`-${each}`)) return false;
5411
+ }
5412
+ return false;
5413
+ };
5414
+ var rsyncOnlyPreviews = (args, withAValue) => {
5415
+ const options = optionWordsOf(args, withAValue);
5416
+ return options.some((text3) => text3 === RSYNC_DRY_RUN || clusterTurnsOn(text3, RSYNC_DRY_RUN_LETTER, withAValue)) && !options.some((text3) => RSYNC_NAMES_A_PROGRAM.test(text3) || clusterTurnsOn(text3, RSYNC_REMOTE_SHELL_LETTER, withAValue));
5417
+ };
5418
+ var copiesOntoAnotherMachine = (invocation) => {
5419
+ const { program, args } = withoutSshpass(invocation);
5420
+ const name = program === void 0 ? void 0 : basenameOf(program.text);
5421
+ const withAValue = name === void 0 ? void 0 : REMOTE_COPY_OPTIONS_WITH_A_VALUE.get(name);
5422
+ if (withAValue === void 0 || name === RSYNC && rsyncOnlyPreviews(args, withAValue)) return false;
5423
+ const operands = operandsAfterOptions(args, withAValue);
5424
+ const destination = operands.at(-1);
5425
+ return operands.length > 1 && destination !== void 0 && NAMES_ANOTHER_MACHINE.test(destination.text);
5426
+ };
5427
+ var HOSTED_SECRET_WRITES = /* @__PURE__ */ new Map([
5428
+ ["doppler", /(?:^| )secrets (?:set|delete|upload)(?: |$)/],
5429
+ ["vercel", /(?:^| )env (?:add|rm|remove|update)(?: |$)/],
5430
+ ["fly", /(?:^| )secrets (?:set|unset|import|deploy)(?: |$)/],
5431
+ ["flyctl", /(?:^| )secrets (?:set|unset|import|deploy)(?: |$)/],
5432
+ ["heroku", /(?:^| )config:(?:set|unset|add|remove)(?: |$)/],
5433
+ ["netlify", /(?:^| )env:(?:set|unset|import|clone)(?: |$)/],
5434
+ ["railway", /(?:^| )variables? (?:set|delete)(?: |$)/],
5435
+ ["supabase", /(?:^| )secrets (?:set|unset)(?: |$)/],
5436
+ ["wrangler", /(?:^| )secret (?:put|delete|bulk)(?: |$)/],
5437
+ ["firebase", /(?:^| )functions:secrets:(?:set|destroy|prune)(?: |$)/],
5438
+ ["gcloud", /(?:^| )secrets (?:create|delete|update|versions (?:add|destroy|disable|enable))(?: |$)/],
5439
+ ["az", /(?:^| )keyvault secret (?:set|set-attributes|delete|purge|recover|restore)(?: |$)/]
5440
+ ]);
5441
+ var RAILWAY_CLI = "railway";
5442
+ var RAILWAY_VARIABLES = /(?:^| )variables?(?: |$)/;
5443
+ var RAILWAY_SET_FLAG = /^(?:--set(?:=|$)|-s$)/;
5444
+ var PACKAGE_RUNNERS = /* @__PURE__ */ new Set(["npx", "bunx", "pnpx", "pnpm", "yarn", "npm", "bun"]);
5445
+ var CLI_OF_A_PACKAGE = /* @__PURE__ */ new Map([
5446
+ ["netlify-cli", "netlify"],
5447
+ ["firebase-tools", "firebase"],
5448
+ ["@railway/cli", "railway"],
5449
+ ["@doppler/cli", "doppler"]
5450
+ ]);
5451
+ var PACKAGE_VERSION = /(?<=.)@[^/@]*$/;
5452
+ var cliNameOf = (program) => {
5453
+ const unversioned = program.text.replace(PACKAGE_VERSION, "");
5454
+ return CLI_OF_A_PACKAGE.get(unversioned) ?? basenameOf(unversioned);
5455
+ };
5456
+ var namesAHostingCli = (word) => {
5457
+ const name = cliNameOf(word);
5458
+ return HOSTED_SECRET_WRITES.has(name) || name === RAILWAY_CLI;
5459
+ };
5460
+ var withoutAPackageRunner = (invocation) => {
5461
+ const { program, args } = invocation;
5462
+ if (program === void 0 || !PACKAGE_RUNNERS.has(basenameOf(program.text))) return invocation;
5463
+ const start = args.findIndex((arg) => !FLAG.test(arg.text) && namesAHostingCli(arg));
5464
+ return start === -1 ? invocation : { program: args[start], args: args.slice(start + 1) };
5465
+ };
5466
+ var writesAHostedSecret = (invocation) => {
5467
+ const { program, args } = withoutAPackageRunner(invocation);
5468
+ if (program === void 0) return false;
5469
+ const name = cliNameOf(program);
5470
+ const words = args.filter((arg) => !FLAG.test(arg.text)).map((arg) => arg.text.toLowerCase()).join(" ");
5471
+ return (HOSTED_SECRET_WRITES.get(name)?.test(words) ?? false) || name === RAILWAY_CLI && RAILWAY_VARIABLES.test(words) && args.some((arg) => RAILWAY_SET_FLAG.test(arg.text));
5172
5472
  };
5173
- var changesSomethingHostedElsewhere = (invocation) => githubCommandHasAConsequence(invocation) || writesThroughAServiceApi(invocation) || sendsDataOffThisMachine(invocation) || kubectlExecRunsMoreThanAReadOnlyCommand(invocation) || sshRunsMoreThanAReadOnlyCommand(invocation);
5473
+ var changesSomethingHostedElsewhere = (invocation) => githubCommandHasAConsequence(invocation) || writesThroughAServiceApi(invocation) || writesAHostedSecret(invocation) || sendsDataOffThisMachine(invocation) || copiesOntoAnotherMachine(invocation) || kubectlExecRunsMoreThanAReadOnlyCommand(invocation) || sshRunsMoreThanAReadOnlyCommand(invocation);
5174
5474
  var segmentWritesThroughARemoteApi = (segment, depth) => {
5175
5475
  const innermost = innermostInvocation(segment.invocation);
5176
5476
  return invocationWritesThroughARemoteApi(innermost) || commandsNestedIn(innermost, inlineScriptsOf(innermost, segment.heredocs)).some((nested) => commandWritesThroughARemoteApiAt(nested, depth + 1));
@@ -5188,7 +5488,6 @@ var commandNeedsAPerson = (toolName, command) => {
5188
5488
  const segments = readableCommandSegments(command);
5189
5489
  return segments === null || classifyDecisionRisk(readingTool, command) !== "standard" || segments.some((segment) => segmentNeedsAPerson(readingTool, segment)) || pipesIntoASqlClient(command) || shellDialectOf(toolName) === "powershell" && powerShellCommandHasAVisibleConsequence(command, posixShellJudgeFor(toolName));
5190
5490
  };
5191
- var sessionGrantMustAskAbout = (toolName, command) => commandNeedsAPerson(toolName, command) || SHELL_DIALECT_BY_TOOL.has(toolName) && commandHasAVisibleConsequence(toolName, command);
5192
5491
  var VISIBLE_DATA_LOSS_PATTERNS = [
5193
5492
  "Bash(git branch -D:*)",
5194
5493
  "Bash(git branch --delete:*)",
@@ -5300,12 +5599,12 @@ var FIND_RUNNERS = /* @__PURE__ */ new Set(["-exec", "-execdir", "-ok", "-okdir"
5300
5599
  var FIND_RUNNER_END = /* @__PURE__ */ new Set([";", "+"]);
5301
5600
  var FIND = "find";
5302
5601
  var commandsRunByFind = ({ program, args }) => program === void 0 || basenameOf(program.text) !== FIND ? [] : args.flatMap((arg, index) => FIND_RUNNERS.has(arg.text) ? [{ program: args[index + 1], args: args.slice(index + 2, findRunnerEnd(args, index + 2)) }] : []);
5303
- var losesDataVisibly = (toolName, invocation, normalized, depth) => {
5602
+ var losesDataVisibly = (toolName, invocation, normalized, depth, line) => {
5304
5603
  const { program, args } = invocation;
5305
5604
  if (program === void 0) return false;
5306
5605
  const name = basenameOf(program.text);
5307
5606
  if (name === FIND) {
5308
- return args.some((arg) => arg.text === FIND_DELETE) || commandsRunByFind(invocation).some((run) => invocationHasAVisibleConsequence(toolName, run, depth + 1));
5607
+ return args.some((arg) => arg.text === FIND_DELETE) || commandsRunByFind(invocation).some((run) => invocationHasAVisibleConsequence(toolName, run, depth + 1, line));
5309
5608
  }
5310
5609
  const destructiveArguments = destructiveArgumentsOf(name, args);
5311
5610
  return destructiveArguments !== void 0 && args.some((arg) => namesDestructiveArgument(arg.text, destructiveArguments)) || namesDestructiveWordInAnyCase(name, args.map((arg) => arg.text)) || gitDiscardsWork(invocation) || changesAService(invocation) || replacesTheCrontab(invocation) || isCoveredByPolicy(VISIBLE_DATA_LOSS_PATTERNS, toolName, normalized);
@@ -5471,13 +5770,14 @@ var honoursPreviewFlags = ({ program, args }) => {
5471
5770
  var onlyPreviews = (invocation) => invocation.program !== void 0 && honoursPreviewFlags(invocation) && invocation.args.some((arg) => !arg.expands && PREVIEW_FLAG.test(arg.text));
5472
5771
  var changesWhatIsDeployed = (toolName, invocation, normalized) => !onlyPreviews(invocation) && (changesProduction(invocation) || mergesAPullRequest(invocation) || isCoveredByPolicy(DEPLOY_AND_SCHEMA_COMMAND_PATTERNS, toolName, normalized));
5473
5772
  var releasesOrChangesACluster = (toolName, invocation, normalized) => !onlyPreviews(invocation) && (pushesATag(invocation) || publishesAnAppBuild(invocation) || RELEASE_AND_CLUSTER_PROGRAMS.has(basenameOf(invocation.program?.text ?? "")) && isCoveredByPolicy(RELEASE_AND_CLUSTER_COMMAND_PATTERNS, toolName, normalized));
5474
- var invocationHasAVisibleConsequence = (toolName, invocation, depth) => {
5773
+ var invocationHasAConsequenceOnlyPermissionsOffAsksAbout = (toolName, invocation, normalized) => releasesOrChangesACluster(toolName, invocation, normalized) || mergesAPullRequestByAnyPath(invocation) || writesAFileThatNeedsAPerson(invocation) || changesWhereGitLooksForHooks(invocation) || setsAGitSettingThatRunsAProgram(invocation) || changesSomethingHostedElsewhere(invocation);
5774
+ var invocationHasAVisibleConsequence = (toolName, invocation, depth, line) => {
5475
5775
  if (depth > MAX_CONSEQUENCE_DEPTH) return true;
5476
5776
  if (invocation.program === void 0) return false;
5477
5777
  const normalized = quotedInvocation(invocation);
5478
5778
  const innermost = innermostInvocation(invocation);
5479
5779
  const script = shellScriptOf(invocation);
5480
- return classifyDecisionRisk(toolName, normalized) === "destructive" || changesWhatIsDeployed(toolName, invocation, normalized) || releasesOrChangesACluster(toolName, invocation, normalized) || writesAFileThatNeedsAPerson(invocation) || changesWhereGitLooksForHooks(invocation) || changesSomethingHostedElsewhere(invocation) || losesDataVisibly(toolName, invocation, normalized, depth) || subcommandDestroysVisibly(invocation) || sqlClientChangesData(invocation) || innermost !== invocation && invocationHasAVisibleConsequence(toolName, innermost, depth) || script === null && passesAnInlineScript(invocation) || script !== null && commandHasAVisibleConsequenceAt(toolName, script, depth + 1) || readingsPastGlobalFlags(invocation).some((reading) => invocationHasAVisibleConsequence(toolName, reading, depth + 1));
5780
+ return classifyDecisionRisk(toolName, normalized) === "destructive" || changesWhatIsDeployed(toolName, invocation, normalized) || writesASecretFile(invocation) || line === "permissions_off" && invocationHasAConsequenceOnlyPermissionsOffAsksAbout(toolName, invocation, normalized) || losesDataVisibly(toolName, invocation, normalized, depth, line) || subcommandDestroysVisibly(invocation) || sqlClientChangesData(invocation) || innermost !== invocation && invocationHasAVisibleConsequence(toolName, innermost, depth, line) || script === null && passesAnInlineScript(invocation) || script !== null && commandHasAVisibleConsequenceAt(toolName, script, depth + 1, line) || readingsPastGlobalFlags(invocation).some((reading) => invocationHasAVisibleConsequence(toolName, reading, depth + 1, line));
5481
5781
  };
5482
5782
  var RUNS_FETCHED_CODE = /(?:\$\(|`|<\()\s*(?:curl|wget)\b/;
5483
5783
  var RUNS_DECODED_CODE = /(?:^|[;&|(\s])(?:bash|sh|zsh|source|\.|python3?|node|ruby|perl)\s+(?:-[A-Za-z]+\s+)*["']?(?:<\(|\$\()[^)]*\b(?:base64|xxd|openssl)\b/;
@@ -5511,7 +5811,7 @@ var decodes = (invocation) => {
5511
5811
  return decodingFlags !== void 0 && args.some((arg) => decodingFlags.test(arg.text));
5512
5812
  };
5513
5813
  var producesCodeTheCommandDoesNotShow = (invocation) => fetches(invocation) || decodes(invocation);
5514
- var pipesHiddenCodeIntoAnInterpreter = (command, invocations) => invocations.some(producesCodeTheCommandDoesNotShow) && pipedSegmentsOf(command).some(runsWhatItReads);
5814
+ var pipesCodeIntoAnInterpreter = (command, invocations, producesCode) => invocations.some(producesCode) && pipedSegmentsOf(command).some(runsWhatItReads);
5515
5815
  var CODE_THAT_DELETES_RECURSIVELY = /\b(?:rmtree|rimraf|rm_rf|rm_r|removedirs)\b|\b(?:rm|rmSync|remove|rmdir|rmdirSync)\s*\([^)]*recursive/;
5516
5816
  var CODE_THAT_DECODES = /\b(?:b64decode|atob|base64)\b/;
5517
5817
  var CODE_THAT_RUNS_CODE_IT_BUILDS = /(?<![.\w])(?:eval|exec)\s*\(/;
@@ -5571,7 +5871,7 @@ var interpreterCodeIn = (command, invocations) => {
5571
5871
  const heredocs = interpreters.some(runsWhatItReads) ? withHeredocBodiesSetAside(command).bodies : [];
5572
5872
  return [...interpreters.flatMap(inlineCodeOf), ...heredocs];
5573
5873
  };
5574
- var codeNeedsAPerson = (code, depth) => CODE_THAT_DELETES_RECURSIVELY.test(code) || CODE_THAT_RUNS_CODE_IT_BUILDS.test(code) && CODE_THAT_DECODES.test(code) || CODE_THAT_WRITES_A_FILE.test(code) && pathsSpelledIn(code).some(pathNeedsAPersonToChange) || CODE_THAT_RUNS_COMMANDS.test(code) && commandsSpelledIn(code).some((command) => commandHasAVisibleConsequenceAt(SHELL_TOOL, command, depth + 1));
5874
+ var codeNeedsAPerson = (code, depth) => CODE_THAT_DELETES_RECURSIVELY.test(code) || CODE_THAT_RUNS_CODE_IT_BUILDS.test(code) && CODE_THAT_DECODES.test(code) || CODE_THAT_WRITES_A_FILE.test(code) && pathsSpelledIn(code).some(pathNeedsAPersonToChange) || CODE_THAT_RUNS_COMMANDS.test(code) && commandsSpelledIn(code).some((command) => commandHasAVisibleConsequenceAt(SHELL_TOOL, command, depth + 1, "permissions_off"));
5575
5875
  var runsInterpreterCodeThatNeedsAPerson = (command, invocations, depth) => interpreterCodeIn(command, invocations).some((code) => codeNeedsAPerson(code, depth));
5576
5876
  var WORDS_THAT_OPEN_A_COMMAND = String.raw`if|then|elif|else|do|while|until|!`;
5577
5877
  var SHELL_GROUPING_PREFIX = new RegExp(String.raw`^\s*(?:(?:${WORDS_THAT_OPEN_A_COMMAND})\s+|[({]\s*)+`);
@@ -5717,26 +6017,29 @@ var evalRunsOneEnvironmentSetup = (pieces, index) => {
5717
6017
  const next = pieces[index + 3];
5718
6018
  return opening !== void 0 && EVAL_BEFORE_ITS_ARGUMENT.test(opening.text) && substitution !== void 0 && SUBSTITUTION_OPENERS.has(substitution.before) && SETS_UP_THE_ENVIRONMENT.test(substitution.text) && closing !== void 0 && SUBSTITUTION_CLOSERS.has(closing.before) && EVAL_AFTER_ITS_ARGUMENT.test(closing.text) && (next === void 0 || WHAT_MAY_FOLLOW_AN_EVAL.has(next.before));
5719
6019
  };
5720
- var roughSegmentHasAVisibleConsequence = (toolName, segment, producesHiddenCode, depth) => {
6020
+ var evalRunsHiddenCode = (segment, innermost) => segment.substitution !== null && basenameOf(innermost.program?.text ?? "") === EVAL && !segment.evalRunsOneEnvironmentSetup;
6021
+ var roughSegmentHasAVisibleConsequence = (toolName, segment, producesHiddenCode, depth, line) => {
5721
6022
  const innermost = innermostInvocation(segment.invocation);
5722
6023
  const runsAHeredocScript = innermost.program !== void 0 && POSIX_SHELL_PROGRAMS.has(basenameOf(innermost.program.text));
5723
- return invocationHasAVisibleConsequence(toolName, segment.invocation, depth) || sqlClientSyntaxOf(innermost) !== void 0 && (segment.readsInput || segment.feedsASubstitution) || segment.substitution !== null && basenameOf(innermost.program?.text ?? "") === EVAL && !segment.evalRunsOneEnvironmentSetup || segment.readsAPipe && producesHiddenCode && runsWhatItReads(innermost) || runsAHeredocScript && segment.heredocs.some((body) => commandHasAVisibleConsequenceAt(toolName, body, depth + 1));
6024
+ return invocationHasAVisibleConsequence(toolName, segment.invocation, depth, line) || sqlClientSyntaxOf(innermost) !== void 0 && (segment.readsInput || segment.feedsASubstitution) || line === "permissions_off" && evalRunsHiddenCode(segment, innermost) || segment.readsAPipe && producesHiddenCode && runsWhatItReads(innermost) || runsAHeredocScript && segment.heredocs.some((body) => commandHasAVisibleConsequenceAt(toolName, body, depth + 1, line));
5724
6025
  };
5725
- var roughReadingHasAVisibleConsequence = (toolName, command, depth) => {
6026
+ var producesCodeTheLineCannotSee = (line) => line === "permissions_off" ? producesCodeTheCommandDoesNotShow : fetches;
6027
+ var roughReadingHasAVisibleConsequence = (toolName, command, depth, line) => {
5726
6028
  const segments = roughSegmentsOf(command);
5727
6029
  const invocations = segments.map((segment) => segment.invocation);
5728
- const producesHiddenCode = invocations.some(producesCodeTheCommandDoesNotShow);
5729
- return segments.some((segment) => roughSegmentHasAVisibleConsequence(toolName, segment, producesHiddenCode, depth)) || runsADownloadedScript(invocations) || runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
6030
+ const producesHiddenCode = invocations.some(producesCodeTheLineCannotSee(line));
6031
+ return segments.some((segment) => roughSegmentHasAVisibleConsequence(toolName, segment, producesHiddenCode, depth, line)) || runsADownloadedScript(invocations) || line === "permissions_off" && runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
5730
6032
  };
5731
- var commandHasAVisibleConsequenceAt = (toolName, command, depth) => {
6033
+ var commandHidesWhatItWritesOrRuns = (command, readable) => RUNS_DECODED_CODE.test(readable) || redirectsIntoAFileThatNeedsAPerson(command);
6034
+ var commandHasAVisibleConsequenceAt = (toolName, command, depth, line) => {
5732
6035
  if (toolName === "Bash" && isSafeReadOnlyCommand(command)) return false;
5733
6036
  const readable = withHeredocSubstitutionsAsQuotedText(command);
5734
6037
  if (classifyDecisionRisk(toolName, readable) === "destructive" || RUNS_FETCHED_CODE.test(readable) || REDIRECTS_INTO_A_SECRET_FILE.test(readable)) return true;
5735
- if (RUNS_DECODED_CODE.test(readable) || redirectsIntoAFileThatNeedsAPerson(command)) return true;
6038
+ if (line === "permissions_off" && commandHidesWhatItWritesOrRuns(command, readable)) return true;
5736
6039
  const segments = readableCommandSegments(command);
5737
- if (segments === null) return roughReadingHasAVisibleConsequence(toolName, command, depth);
6040
+ if (segments === null) return roughReadingHasAVisibleConsequence(toolName, command, depth, line);
5738
6041
  const invocations = segments.map((segment) => invocationOf(withoutShellGrouping(segment)));
5739
- return invocations.some((invocation) => invocationHasAVisibleConsequence(toolName, invocation, depth)) || pipesIntoASqlClient(command) || pipesHiddenCodeIntoAnInterpreter(command, invocations) || runsADownloadedScript(invocations) || runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
6042
+ return invocations.some((invocation) => invocationHasAVisibleConsequence(toolName, invocation, depth, line)) || pipesIntoASqlClient(command) || pipesCodeIntoAnInterpreter(command, invocations, producesCodeTheLineCannotSee(line)) || runsADownloadedScript(invocations) || line === "permissions_off" && runsInterpreterCodeThatNeedsAPerson(command, invocations, depth);
5740
6043
  };
5741
6044
  var REDIRECTION_OPERATOR_CHARACTER = /[<>]/;
5742
6045
  var redirectsIntoAFileThatNeedsAPerson = (command) => {
@@ -5749,18 +6052,24 @@ var redirectsIntoAFileThatNeedsAPerson = (command) => {
5749
6052
  });
5750
6053
  };
5751
6054
  var posixCommandOf = (words) => words.map(asOneShellWord).join(" ");
5752
- var posixShellJudgeFor = (toolName) => ({
6055
+ var webRequestSendsDataOffThisMachine = ({ sendsData, addresses }) => sendsData && !(addresses.length > 0 && addresses.every((address) => THIS_MACHINE_ADDRESS.test(address)));
6056
+ var noWebRequestNeedsAPerson = () => false;
6057
+ var namesASecretPowerShellPath = (path) => SECRET_FILE_NAME.test(fileNameOf(path));
6058
+ var posixShellJudgeFor = (toolName, line = "standing_allow") => ({
5753
6059
  namesADestructiveAction: (text3) => classifyDecisionRisk(toolName, text3) === "destructive",
5754
- invocationShowsAConsequence: (invocation) => invocationHasAVisibleConsequence(SHELL_TOOL, invocation, 0),
5755
- commandShowsAConsequence: (words) => commandHasAVisibleConsequenceAt(SHELL_TOOL, posixCommandOf(words), 1),
6060
+ invocationShowsAConsequence: (invocation) => invocationHasAVisibleConsequence(SHELL_TOOL, invocation, 0, line),
6061
+ commandShowsAConsequence: (words) => commandHasAVisibleConsequenceAt(SHELL_TOOL, posixCommandOf(words), 1, line),
5756
6062
  onlyReads: (words) => isSafeReadOnlyCommand(posixCommandOf(words)),
5757
6063
  fetches,
5758
6064
  runsWhatItReads,
5759
6065
  runsScripts,
5760
- namesAFileThatNeedsAPerson: pathNeedsAPersonToChange
6066
+ namesAFileThatNeedsAPerson: line === "permissions_off" ? pathNeedsAPersonToChange : namesASecretPowerShellPath,
6067
+ webRequestNeedsAPerson: line === "permissions_off" ? webRequestSendsDataOffThisMachine : noWebRequestNeedsAPerson
5761
6068
  });
5762
6069
  var commandIsDestructive = (toolName, command) => shellDialectOf(toolName) === "powershell" ? powerShellCommandIsDestructive(command, posixShellJudgeFor(toolName)) : readingsThatCanAct(command).some((reading) => classifyDecisionRisk(toolNameForAPosixReading(toolName), reading) === "destructive");
5763
- var commandHasAVisibleConsequence = (toolName, command) => shellDialectOf(toolName) === "powershell" ? powerShellCommandHasAVisibleConsequence(command, posixShellJudgeFor(toolName)) : commandHasAVisibleConsequenceAt(toolNameForAPosixReading(toolName), command, 0);
6070
+ var commandHasAConsequenceOnTheLine = (toolName, command, line) => shellDialectOf(toolName) === "powershell" ? powerShellCommandHasAVisibleConsequence(command, posixShellJudgeFor(toolName, line)) : commandHasAVisibleConsequenceAt(toolNameForAPosixReading(toolName), command, 0, line);
6071
+ var commandHasAVisibleConsequence = (toolName, command) => commandHasAConsequenceOnTheLine(toolName, command, "standing_allow");
6072
+ var commandHasAConsequenceWithPermissionsOff = (toolName, command) => commandHasAConsequenceOnTheLine(toolName, command, "permissions_off");
5764
6073
  var MAX_SPELLING_DEPTH = 3;
5765
6074
  var GIT_GLOBAL_OPTIONS_WITH_A_VALUE = /* @__PURE__ */ new Set([
5766
6075
  "-C",
@@ -6961,7 +7270,7 @@ var unmatchedPolicyOf = (config, toolName) => ({
6961
7270
  mode: config.defaultMode ?? "push_first",
6962
7271
  pushFirstSeconds: config.defaultPushFirstSeconds ?? 20
6963
7272
  });
6964
- var sessionToolGrantCannotCover = (toolName, arg, toolInput) => typeof arg === "string" && sessionGrantMustAskAbout(toolName, arg) || parseMcpToolName(toolName) !== void 0 && (toolInput === void 0 || !mcpToolInputOnlyReads(toolName, toolInput));
7273
+ var sessionToolGrantCannotCover = (toolName, arg, toolInput) => typeof arg === "string" && commandNeedsAPerson(toolName, arg) || parseMcpToolName(toolName) !== void 0 && (toolInput === void 0 || !mcpToolInputOnlyReads(toolName, toolInput));
6965
7274
  var stricterOfTheReadings = (asWritten, asSpelled, unmatched) => comparePolicyStrictness(asWritten?.policy ?? unmatched, asSpelled?.policy ?? unmatched) > 0 ? asWritten : asSpelled;
6966
7275
  var resolvePolicy = (config, toolName, modeOverride, toolInput, cwd, repoKey, sessionId) => {
6967
7276
  const args = toolInput ? policyArgForms(toolName, toolInput, cwd) : [];
@@ -7038,6 +7347,10 @@ var strictestScopeVerdict = (scope, paths) => {
7038
7347
  var survivesDegraded = (config, toolName, toolInputs, cwd, repoKey, sessionId) => toolInputs.length === 1 && resolveAutoResolveOrigin(config, toolName, toolInputs[0], cwd, repoKey, sessionId) === "safe_readonly";
7039
7348
  var FULL_DEFER_MODES = /* @__PURE__ */ new Set(["plan", "auto", "dontAsk"]);
7040
7349
  var BYPASS_PERMISSION_MODE = "bypassPermissions";
7350
+ var BYPASS_STOPS = ["consequences", "nothing"];
7351
+ var DEFAULT_BYPASS_STOPS = "consequences";
7352
+ var isBypassStops = (value) => typeof value === "string" && BYPASS_STOPS.includes(value);
7353
+ var bypassStopsOf = (config) => isBypassStops(config.bypassStops) ? config.bypassStops : DEFAULT_BYPASS_STOPS;
7041
7354
  var isBypassPermissionMode = (permissionMode) => permissionMode === BYPASS_PERMISSION_MODE;
7042
7355
  var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set([
7043
7356
  "Write",
@@ -7134,13 +7447,19 @@ var LINE_BREAK = /[\r\n]/;
7134
7447
  var bypassModeCovers = (toolName, toolInput) => {
7135
7448
  const arg = extractPolicyArg(toolName, toolInput);
7136
7449
  if (SHELL_DIALECT_BY_TOOL.has(toolName)) {
7137
- return arg !== void 0 && !commandIsDestructive(toolName, arg) && !commandHasAVisibleConsequence(toolName, arg);
7450
+ return arg !== void 0 && !commandIsDestructive(toolName, arg) && !commandHasAConsequenceWithPermissionsOff(toolName, arg);
7138
7451
  }
7139
- if (FILE_EDIT_TOOLS.has(toolName)) return arg !== void 0 && !LINE_BREAK.test(arg) && !fileEditNeedsAPerson(toolName, arg);
7452
+ if (FILE_EDIT_TOOLS.has(toolName)) return arg !== void 0 && !LINE_BREAK.test(arg) && !fileEditNeedsAPersonWithPermissionsOff(toolName, arg);
7140
7453
  return mcpToolOnlyReads(toolName) && mcpToolInputOnlyReads(toolName, toolInput);
7141
7454
  };
7142
- var aChosenRuleGovernsInEitherRepository = (input) => aChosenRuleGoverns(input) || input.sharedRepoKey !== void 0 && input.sharedRepoKey !== input.repoKey && aChosenRuleGoverns({ ...input, repoKey: input.sharedRepoKey });
7143
- var bypassModeAllows = (input) => isBypassPermissionMode(input.permissionMode) && !isModeStateDegraded(input.modeState) && noModeOverrideIsActive(input) && input.deletesFiles !== true && input.toolInputs.length > 0 && input.toolInputs.every((toolInput) => bypassModeCovers(input.toolName, toolInput)) && !aChosenRuleGovernsInEitherRepository(input);
7455
+ var aChosenRuleGovernsInEitherRepository = (input, counts = everyRule) => aChosenRuleGoverns(input, counts) || input.sharedRepoKey !== void 0 && input.sharedRepoKey !== input.repoKey && aChosenRuleGoverns({ ...input, repoKey: input.sharedRepoKey }, counts);
7456
+ var ruleAsksOrRefuses = (rule) => !isAutoApprove(rule);
7457
+ var bypassModeCoversEveryInput = (input) => input.deletesFiles !== true && input.toolInputs.every((toolInput) => bypassModeCovers(input.toolName, toolInput)) && !aChosenRuleGovernsInEitherRepository(input);
7458
+ var bypassModeApplies = (input) => isBypassPermissionMode(input.permissionMode) && !isModeStateDegraded(input.modeState) && noModeOverrideIsActive(input) && input.toolInputs.length > 0;
7459
+ var bypassModeAllows = (input) => bypassModeApplies(input) && (bypassStopsOf(input.config) === "nothing" ? !aChosenRuleGovernsInEitherRepository(input, ruleAsksOrRefuses) : bypassModeCoversEveryInput(input));
7460
+ var PERMISSIONS_OFF_ASK_REASON = "Permissions are off in your agent, so Pushary only stops for risky steps like this one. You can change this in Settings on pushary.com.";
7461
+ var permissionsOffLineAppliesTo = (agentType) => agentType === CLAUDE_CODE_AGENT_TYPE;
7462
+ var permissionsOffAskReason = (input, verdict) => verdict.kind === "gate" && !verdict.scopeReason && !isAskedInEveryMode(input.toolName) && bypassModeApplies(input) && bypassStopsOf(input.config) === "consequences" && !aChosenRuleGovernsInEitherRepository(input) ? PERMISSIONS_OFF_ASK_REASON : void 0;
7144
7463
  var resolveGate = (input) => {
7145
7464
  const { modeState, config, toolName, toolInputs, cwd, sessionId } = input;
7146
7465
  const repoKey = input.sharedRepoKey ?? input.repoKey;
@@ -7225,7 +7544,9 @@ var runsACommandThatNeedsAPerson = ({ toolName, toolInputs }) => SHELL_DIALECT_B
7225
7544
  const command = extractPolicyArg(toolName, toolInput);
7226
7545
  return command !== void 0 && (commandNeedsAPerson(toolName, command) || commandWritesThroughARemoteApi(command));
7227
7546
  });
7228
- var fileEditNeedsAPerson = (toolName, path) => FILE_EDIT_TOOLS.has(toolName) && pathNeedsAPersonToChange(path);
7547
+ var namesASecretOrWorkflowFile = (path) => SECRET_FILE_NAME.test(basenameOf(path)) || CI_WORKFLOW_FILE.test(normalizeSeparators(path));
7548
+ var fileEditNeedsAPerson = (toolName, path) => FILE_EDIT_TOOLS.has(toolName) && namesASecretOrWorkflowFile(path);
7549
+ var fileEditNeedsAPersonWithPermissionsOff = (toolName, path) => FILE_EDIT_TOOLS.has(toolName) && pathNeedsAPersonToChange(path);
7229
7550
  var editsAFileThatNeedsAPerson = ({ toolName, toolInputs }) => toolInputs.some((toolInput) => {
7230
7551
  const path = extractPolicyArg(toolName, toolInput);
7231
7552
  return path !== void 0 && fileEditNeedsAPerson(toolName, path);
@@ -7294,14 +7615,16 @@ var approvalRoutesOf = (config) => {
7294
7615
  const routes = config.approvalRoutes ?? [];
7295
7616
  return Array.isArray(routes) && routes.every(isApprovalRoutePattern) ? routes : null;
7296
7617
  };
7297
- var aChosenRuleGoverns = (input) => {
7618
+ var everyRule = () => true;
7619
+ var aChosenRuleGoverns = (input, counts = everyRule) => {
7298
7620
  const chosen = input.config.policies.filter((policy) => !isDefaultRule(policy));
7299
7621
  const routes = approvalRoutesOf(input.config);
7300
7622
  if (routes === null) return true;
7301
7623
  return input.toolInputs.some((toolInput) => {
7302
7624
  const args = policyArgForms(input.toolName, toolInput, input.cwd);
7303
7625
  const reading = policyReadingOf(chosen, input.toolName, args);
7304
- return governingRuleForReading(chosen, input.toolName, args, reading, input.repoKey, input.sessionId) !== void 0 || findBestRoute(routes, input.toolName, args, input.repoKey) !== void 0;
7626
+ const governing = governingRuleForReading(chosen, input.toolName, args, reading, input.repoKey, input.sessionId);
7627
+ return governing !== void 0 && counts(governing.policy) || findBestRoute(routes, input.toolName, args, input.repoKey) !== void 0;
7305
7628
  });
7306
7629
  };
7307
7630
  var claudeAllowlistOwnsCall = (input, verdict, permissionMode, rules) => rules !== null && verdict.kind === "gate" && !verdict.scopeReason && !aChosenRuleGoverns(input) && !isAskedInEveryMode(input.toolName) && claudeConsultsItsAllowlist(permissionMode) && agentRulesAllowEveryInput(rules, input.toolName, input.toolInputs, input.cwd);
@@ -7493,6 +7816,7 @@ var PLAN_DECLINED_REASON = "Plan declined from the phone. Ask what to change bef
7493
7816
  var claudeStoppedPreToolUseOutput = (reason) => stoppedOutput(claudePreToolUseOutput("deny", reason), reason);
7494
7817
  var claudeStoppedPermissionRequestOutput = (reason) => stoppedOutput(claudePermissionRequestOutput("deny", reason), reason);
7495
7818
  var UNANSWERED_ASKS_BEFORE_PAUSE = 3;
7819
+ var CLAUDE_CODE_AGENT_TYPE = "claude_code";
7496
7820
  var SESSION_PAUSED_REASON = `Phone approvals for this session are paused because ${UNANSWERED_ASKS_BEFORE_PAUSE} of them went unanswered, so this was refused without asking anyone. A notification was sent to your phone: tap Approve on it to resume, then run this again.`;
7497
7821
  var unansweredRefusalReason = (paused) => paused ? SESSION_PAUSED_REASON : NO_RESPONSE_REASON;
7498
7822
  var UNHEARD_PUSH_WINDOW_DAYS = 14;
@@ -7840,6 +8164,8 @@ export {
7840
8164
  PRETOOLUSE_HANDLED_TOOLS,
7841
8165
  isPermissionRequestOwnedByPreToolUse,
7842
8166
  CLAUDE_PRETOOLUSE_MATCHER,
8167
+ permissionsOffLineAppliesTo,
8168
+ permissionsOffAskReason,
7843
8169
  resolveGate,
7844
8170
  editGoesToTheAgentsPrompt,
7845
8171
  SCOPE_BATCH_REASON,