@wrongstack/tools 0.320.1 → 1.0.1

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 (192) hide show
  1. package/dist/_danger-detect.d.ts +8 -0
  2. package/dist/_syntax-check.d.ts +1 -2
  3. package/dist/audit.d.ts +4 -5
  4. package/dist/audit.js +6 -6
  5. package/dist/auto-proceed-loop-guard.d.ts +1 -1
  6. package/dist/auto-proceed-loop-guard.js +9 -160
  7. package/dist/bash-kill-guard.d.ts +2 -3
  8. package/dist/bash.d.ts +2 -3
  9. package/dist/bash.js +4 -4
  10. package/dist/batch-tool-use.d.ts +2 -3
  11. package/dist/batch-tool-use.js +1 -1
  12. package/dist/browser/index.d.ts +1 -1
  13. package/dist/browser/index.js +1 -1
  14. package/dist/browser/tools.d.ts +56 -45
  15. package/dist/builtin.js +50 -50
  16. package/dist/{chunk-T77XOX7E.js → chunk-24T5XIJU.js} +1 -1
  17. package/dist/{chunk-DTQ75VBC.js → chunk-2CTZW6JQ.js} +2 -2
  18. package/dist/{chunk-KWXIKGE3.js → chunk-3D5DJWOE.js} +3 -3
  19. package/dist/{chunk-XSSFBS5I.js → chunk-4ERMPDHV.js} +11 -6
  20. package/dist/{chunk-QSNVDHOZ.js → chunk-4WPBS45A.js} +4 -5
  21. package/dist/{chunk-4CQWNZ62.js → chunk-5ITQPCLC.js} +2 -2
  22. package/dist/{chunk-B4HTSV6Z.js → chunk-5KS24LTS.js} +11 -11
  23. package/dist/{chunk-QPNYDH5B.js → chunk-62OAECEQ.js} +29 -7
  24. package/dist/{chunk-DFQDJT22.js → chunk-6GOZTS6F.js} +3 -3
  25. package/dist/{chunk-5UFVCIUB.js → chunk-6H4ERJP7.js} +140 -24
  26. package/dist/{chunk-34VLZ35Z.js → chunk-7HL23T3T.js} +63 -10
  27. package/dist/{chunk-HFXSNKCV.js → chunk-7JJFC6CT.js} +1 -1
  28. package/dist/{chunk-23EX5WDO.js → chunk-7LQCT3LT.js} +3 -3
  29. package/dist/{chunk-NDIT3SBZ.js → chunk-7N5U2RAU.js} +2 -2
  30. package/dist/{chunk-QBV725YG.js → chunk-7ODZTPCU.js} +2 -2
  31. package/dist/{chunk-6AAOT4PW.js → chunk-AQ5YBURX.js} +16 -4
  32. package/dist/{chunk-ZMW6WJFT.js → chunk-ASEXQRA7.js} +3 -3
  33. package/dist/{chunk-FRN7TIAA.js → chunk-B3MGJBFI.js} +1 -1
  34. package/dist/{chunk-JLYA4X7K.js → chunk-CGXTR34H.js} +21 -6
  35. package/dist/{chunk-IU4DV2PA.js → chunk-CHEK3ASV.js} +6 -3
  36. package/dist/{chunk-GOIZNNOA.js → chunk-DJYLI7EW.js} +1 -1
  37. package/dist/{chunk-Z6IHMJMC.js → chunk-DK4J2WMH.js} +11 -11
  38. package/dist/{chunk-OYP27E3I.js → chunk-DRRY6SCM.js} +47 -20
  39. package/dist/{chunk-JVRLTEO7.js → chunk-E7JE3UEX.js} +2 -2
  40. package/dist/{chunk-BK732J7I.js → chunk-FBUP524S.js} +4 -4
  41. package/dist/{chunk-NYRLWDT5.js → chunk-FVM3O4JQ.js} +1 -1
  42. package/dist/chunk-FYDBUVQD.js +244 -0
  43. package/dist/{chunk-PV6HIZQD.js → chunk-GDDXX27P.js} +50 -50
  44. package/dist/{chunk-3GIKYHLA.js → chunk-GKSG5CPH.js} +6 -6
  45. package/dist/{chunk-ESLPBT5A.js → chunk-HDYUBRMF.js} +4 -3
  46. package/dist/{chunk-4BABEJC2.js → chunk-IAYMTTR2.js} +236 -79
  47. package/dist/{chunk-ELRRTWNP.js → chunk-IXIS7RSG.js} +2 -2
  48. package/dist/{chunk-HR67OWEP.js → chunk-IYH4OHBP.js} +5 -5
  49. package/dist/{chunk-W232EFEM.js → chunk-JDOO4P6Z.js} +7 -4
  50. package/dist/{chunk-2OXHS3KZ.js → chunk-KLJZ4WV4.js} +4 -3
  51. package/dist/{chunk-3M7LLN7W.js → chunk-LQSOU63Z.js} +12 -11
  52. package/dist/{chunk-OTPTQBYE.js → chunk-MGPR7VG3.js} +279 -265
  53. package/dist/{chunk-C2DQKVLO.js → chunk-MJSJWXBF.js} +1 -1
  54. package/dist/{chunk-NSPNFOJ7.js → chunk-MK2JK35J.js} +25 -10
  55. package/dist/{chunk-JSNSMG5R.js → chunk-MSOAX3GC.js} +1 -1
  56. package/dist/{chunk-J43O3BOX.js → chunk-N3K2SFEI.js} +532 -492
  57. package/dist/{chunk-J74TMK4M.js → chunk-NJX2RXKJ.js} +50 -7
  58. package/dist/chunk-NL2S2CXD.js +171 -0
  59. package/dist/{chunk-WAQASTXB.js → chunk-O6BY43ZB.js} +29 -8
  60. package/dist/{chunk-QGF2C7TF.js → chunk-PVCB7RUZ.js} +2 -2
  61. package/dist/{chunk-YTKSNTT4.js → chunk-QA6IASYX.js} +8 -8
  62. package/dist/{chunk-VPALDFYM.js → chunk-RV7BVTDG.js} +1 -1
  63. package/dist/chunk-S57CDR2H.js +288 -0
  64. package/dist/{chunk-W2CECGTG.js → chunk-SMARDKAC.js} +1 -1
  65. package/dist/{chunk-QWKSKFKZ.js → chunk-SOR7OCYP.js} +1 -1
  66. package/dist/{chunk-I7FBZOEP.js → chunk-T3SMFF5Q.js} +11 -5
  67. package/dist/{chunk-4BHUSMNL.js → chunk-UI3ZJIG3.js} +1 -1
  68. package/dist/{chunk-WXJY3BKV.js → chunk-VBF2YXUW.js} +2 -2
  69. package/dist/{chunk-FQNXYA6W.js → chunk-VU3QBYL4.js} +36 -5
  70. package/dist/{chunk-VD2LV5WO.js → chunk-VZGPASGD.js} +37 -12
  71. package/dist/{chunk-UZFY3CKD.js → chunk-WEEVSWQB.js} +17 -6
  72. package/dist/chunk-XXRMF2BC.js +186 -0
  73. package/dist/{chunk-LRDIRJJL.js → chunk-YEISRT4S.js} +5 -11
  74. package/dist/{chunk-Q5JPPCZC.js → chunk-YJTXRH5Y.js} +3 -2
  75. package/dist/{chunk-Z5Q3TXRY.js → chunk-ZTCJCYLN.js} +3 -3
  76. package/dist/circuit-breaker.d.ts +1 -0
  77. package/dist/circuit-breaker.js +1 -1
  78. package/dist/clarify.d.ts +1 -0
  79. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +2 -3
  80. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +5 -4
  81. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +4 -3
  82. package/dist/codebase-index/codebase-index-tool.d.ts +2 -3
  83. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +2 -3
  84. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +4 -3
  85. package/dist/codebase-index/codebase-repo-map-tool.d.ts +2 -3
  86. package/dist/codebase-index/codebase-search-tool.d.ts +2 -3
  87. package/dist/codebase-index/codebase-skeleton-tool.d.ts +2 -3
  88. package/dist/codebase-index/codebase-stats-tool.d.ts +9 -3
  89. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +4 -3
  90. package/dist/codebase-index/index.d.ts +11 -11
  91. package/dist/codebase-index/index.js +8 -8
  92. package/dist/codebase-index/project-server-framing.d.ts +29 -0
  93. package/dist/codebase-index/project-server-lifecycle.d.ts +20 -0
  94. package/dist/codebase-index/project-server-operations.d.ts +37 -0
  95. package/dist/codebase-index/project-server-types.d.ts +30 -0
  96. package/dist/codebase-index/project-server-watcher.d.ts +25 -0
  97. package/dist/codebase-index/project-server.js +448 -391
  98. package/dist/codebase-index/worker.js +2 -2
  99. package/dist/codebase-index/writer-init.d.ts +13 -0
  100. package/dist/codebase-index/writer-maintenance.d.ts +14 -0
  101. package/dist/codebase-index/writer.d.ts +0 -15
  102. package/dist/design.d.ts +2 -2
  103. package/dist/design.js +1 -1
  104. package/dist/diff.d.ts +4 -4
  105. package/dist/diff.js +1 -1
  106. package/dist/document.d.ts +3 -4
  107. package/dist/document.js +1 -1
  108. package/dist/e2e.d.ts +1 -1
  109. package/dist/e2e.js +1 -1
  110. package/dist/edit.d.ts +3 -3
  111. package/dist/edit.js +6 -6
  112. package/dist/exec.d.ts +2 -3
  113. package/dist/exec.js +4 -4
  114. package/dist/fetch.d.ts +4 -3
  115. package/dist/fetch.js +1 -1
  116. package/dist/format.d.ts +17 -45
  117. package/dist/format.js +12 -8
  118. package/dist/git.d.ts +3 -3
  119. package/dist/git.js +1 -1
  120. package/dist/glob.d.ts +2 -3
  121. package/dist/glob.js +2 -2
  122. package/dist/grep.d.ts +7 -5
  123. package/dist/grep.js +3 -3
  124. package/dist/index.d.ts +54 -45
  125. package/dist/index.js +118 -59
  126. package/dist/install.d.ts +7 -55
  127. package/dist/install.js +6 -6
  128. package/dist/json.d.ts +3 -4
  129. package/dist/json.js +2 -2
  130. package/dist/kanban-tool-types.d.ts +1 -2
  131. package/dist/kanban.d.ts +3 -19
  132. package/dist/kanban.js +1 -1
  133. package/dist/languages/execute-tool.d.ts +2 -3
  134. package/dist/languages/index.d.ts +2 -2
  135. package/dist/languages/index.js +4 -4
  136. package/dist/languages/tool.d.ts +3 -4
  137. package/dist/{legacy-bridge-FOV5ODDI.js → legacy-bridge-YXANP5QB.js} +6 -6
  138. package/dist/lint.d.ts +5 -4
  139. package/dist/lint.js +6 -6
  140. package/dist/logs.d.ts +3 -4
  141. package/dist/logs.js +2 -2
  142. package/dist/memory.d.ts +7 -8
  143. package/dist/memory.js +1 -1
  144. package/dist/mode.d.ts +3 -4
  145. package/dist/mode.js +1 -1
  146. package/dist/next-steps-tool.d.ts +2 -3
  147. package/dist/next-steps.d.ts +4 -0
  148. package/dist/next-steps.js +9 -175
  149. package/dist/outdated.d.ts +5 -29
  150. package/dist/outdated.js +3 -3
  151. package/dist/pack.js +51 -51
  152. package/dist/patch.d.ts +2 -3
  153. package/dist/patch.js +5 -5
  154. package/dist/plan.d.ts +4 -4
  155. package/dist/plan.js +3 -3
  156. package/dist/process-registry.js +2 -2
  157. package/dist/ps-slash.js +4 -4
  158. package/dist/pwsh.d.ts +1 -0
  159. package/dist/read.d.ts +5 -5
  160. package/dist/read.js +5 -5
  161. package/dist/replace.d.ts +2 -3
  162. package/dist/replace.js +6 -6
  163. package/dist/scaffold.d.ts +7 -3
  164. package/dist/scaffold.js +3 -1
  165. package/dist/search.d.ts +17 -3
  166. package/dist/search.js +5 -1
  167. package/dist/set-working-dir.d.ts +2 -3
  168. package/dist/skill.d.ts +4 -5
  169. package/dist/skill.js +1 -1
  170. package/dist/task.d.ts +6 -6
  171. package/dist/task.js +3 -3
  172. package/dist/test.d.ts +5 -4
  173. package/dist/test.js +6 -6
  174. package/dist/todo.d.ts +8 -8
  175. package/dist/todo.js +2 -2
  176. package/dist/tool-diff.js +11 -230
  177. package/dist/tool-help.d.ts +2 -3
  178. package/dist/tool-help.js +1 -1
  179. package/dist/tool-search.d.ts +2 -3
  180. package/dist/tool-search.js +1 -1
  181. package/dist/tool-summary.js +5 -281
  182. package/dist/tool-tier.js +52 -52
  183. package/dist/tool-use.d.ts +2 -3
  184. package/dist/tool-use.js +1 -1
  185. package/dist/tree.d.ts +5 -3
  186. package/dist/tree.js +5 -1
  187. package/dist/typecheck.d.ts +3 -3
  188. package/dist/typecheck.js +6 -6
  189. package/dist/write.d.ts +2 -3
  190. package/dist/write.js +6 -6
  191. package/package.json +5 -5
  192. package/dist/spawn-background.d.ts +0 -80
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-BTSFTGIL.js";
4
4
  import {
5
5
  getPersistentProcessRegistry
6
- } from "./chunk-QGF2C7TF.js";
6
+ } from "./chunk-PVCB7RUZ.js";
7
7
  import {
8
8
  createOutputSpool,
9
9
  spoolNote
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  getProcessRegistry,
13
13
  redactCommand
14
- } from "./chunk-ESLPBT5A.js";
14
+ } from "./chunk-HDYUBRMF.js";
15
15
  import {
16
16
  buildWin32CmdShimInvocation,
17
17
  resolveWin32Command
@@ -47,6 +47,7 @@ var flagLetters = (args) => {
47
47
  }
48
48
  return seen;
49
49
  };
50
+ var isPowerShellCmd = (cmd) => /^(?:powershell|pwsh)(?:\.exe)?$/i.test(cmd);
50
51
  var RULES = [
51
52
  // ----- rm / rmdir: recursive force delete (any path) -----
52
53
  // Note: BLOCKED_ARG_PATTERNS already hard-denies root/home/glob paths,
@@ -85,7 +86,12 @@ var RULES = [
85
86
  id: "powershell-remove-item-recursive-force",
86
87
  level: "destructive",
87
88
  test: (cmd, args) => {
88
- if (cmd !== "powershell" && cmd !== "pwsh") return false;
89
+ const isPwsh = isPowerShellCmd(cmd);
90
+ const isRemoveItemCmd = /^(?:remove-item|ri)(?:\.exe)?$/i.test(cmd);
91
+ if (!isPwsh && !isRemoveItemCmd) return false;
92
+ if (isPwsh && !args.some((a) => /^(?:Remove-Item|ri|rm|del|erase|rd|rmdir)(?:\.exe)?$/i.test(a))) {
93
+ return false;
94
+ }
89
95
  const hasRecurse = argMatches(args, /^-(?:r|recurse)(?::\$true)?$/i);
90
96
  const hasForce = argMatches(args, /^-(?:f|force)(?::\$true)?$/i);
91
97
  if (argMatches(args, /^-whatif(?::\$true)?$/i)) return false;
@@ -98,7 +104,7 @@ var RULES = [
98
104
  id: "powershell-disk-volume-destroy",
99
105
  level: "destructive",
100
106
  test: (cmd, args) => {
101
- if (cmd !== "powershell" && cmd !== "pwsh") return false;
107
+ if (!isPowerShellCmd(cmd)) return false;
102
108
  return args.some(
103
109
  (a) => /^(?:Format-Volume|Clear-Disk|Initialize-Disk|Remove-Partition|Clear-Volume)(?:\s|$)/i.test(
104
110
  a
@@ -112,7 +118,7 @@ var RULES = [
112
118
  id: "powershell-stop-restart-computer",
113
119
  level: "destructive",
114
120
  test: (cmd, args) => {
115
- if (cmd !== "powershell" && cmd !== "pwsh") return false;
121
+ if (!isPowerShellCmd(cmd)) return false;
116
122
  return args.some((a) => /^(?:Stop-Computer|Restart-Computer)(?:\s|$)/i.test(a));
117
123
  },
118
124
  reason: "PowerShell system shutdown or restart"
@@ -122,7 +128,7 @@ var RULES = [
122
128
  id: "powershell-execution-policy-bypass",
123
129
  level: "caution",
124
130
  test: (cmd, args) => {
125
- if (cmd !== "powershell" && cmd !== "pwsh") return false;
131
+ if (!isPowerShellCmd(cmd)) return false;
126
132
  return args.some(
127
133
  (a) => /Set-ExecutionPolicy\s+(?:Bypass|Unrestricted)|-(?:EncodedCommand|enc)\b/i.test(a)
128
134
  );
@@ -269,7 +275,12 @@ var RULES = [
269
275
  level: "destructive",
270
276
  test: (cmd, args) => {
271
277
  if (!["npm", "pnpm", "yarn", "bun", "cargo"].includes(cmd)) return false;
272
- return args.includes("publish") || cmd === "cargo" && args.includes("yank");
278
+ const firstPositional = args.find((a) => !a.startsWith("-"));
279
+ if (!firstPositional) return false;
280
+ if (cmd === "cargo") {
281
+ return firstPositional === "publish" || firstPositional === "yank";
282
+ }
283
+ return firstPositional === "publish";
273
284
  },
274
285
  reason: "publishing to a public package registry (hard to reverse)"
275
286
  },
@@ -460,245 +471,6 @@ function levelRank(level) {
460
471
  }
461
472
  }
462
473
 
463
- // src/exec-kill-guard.ts
464
- import * as os from "node:os";
465
- import * as path from "node:path";
466
- var isWin = os.platform() === "win32";
467
- async function checkExecKillCommand(cmd, args) {
468
- if (!cmd) return { blocked: false };
469
- const cmdLower = cmd.toLowerCase().trim();
470
- const fullCommand = [cmdLower, ...args].join(" ").replace(/\s+/g, " ").trim();
471
- if (isWin) {
472
- if (cmdLower === "taskkill" || cmdLower === "taskkill.exe") {
473
- const hasForce = args.some((a) => a.toUpperCase() === "/F" || a.toUpperCase() === "-F");
474
- const signal = hasForce ? "FORCE" : "TERM";
475
- for (let i = 0; i < args.length; i++) {
476
- const a = args[i];
477
- if (a.toUpperCase() === "/IM" || a.toUpperCase() === "-IM") {
478
- const nameArg = args[i + 1];
479
- if (nameArg) {
480
- const result = await checkKillTarget({ name: nameArg, signal, cmd: fullCommand });
481
- if (result.blocked) return result;
482
- }
483
- }
484
- }
485
- for (let i = 0; i < args.length; i++) {
486
- const a = args[i];
487
- if (a.toUpperCase() === "/PID" || a.toUpperCase() === "-PID") {
488
- const pidArg = args[i + 1];
489
- if (pidArg && /^\d+$/.test(pidArg)) {
490
- const result = await checkKillTarget({
491
- pid: parseInt(pidArg, 10),
492
- signal,
493
- cmd: fullCommand
494
- });
495
- if (result.blocked) return result;
496
- }
497
- }
498
- }
499
- for (let i = 0; i < args.length; i++) {
500
- const a = args[i];
501
- if (a.toUpperCase() === "/FI" || a.toUpperCase() === "-FI") {
502
- const filterArg = args[i + 1];
503
- if (filterArg) {
504
- const nameMatch = filterArg.match(/IMAGENAME\s+eq\s+"?([^"\s]+)/i);
505
- if (nameMatch?.[1]) {
506
- const result = await checkKillTarget({
507
- name: nameMatch[1],
508
- signal,
509
- cmd: fullCommand
510
- });
511
- if (result.blocked) return result;
512
- }
513
- }
514
- }
515
- }
516
- return { blocked: false };
517
- }
518
- if (cmdLower === "powershell" || cmdLower === "powershell.exe" || cmdLower === "pwsh" || cmdLower === "pwsh.exe" || cmdLower === "cmd" || cmdLower === "cmd.exe") {
519
- const shellFlagIndex = args.findIndex((arg) => {
520
- const lower = arg.toLowerCase();
521
- return lower === "-c" || lower === "-command" || lower === "/c";
522
- });
523
- if (shellFlagIndex >= 0) {
524
- const innerTokens = tokenizeShellCommand(args.slice(shellFlagIndex + 1).join(" "));
525
- const innerCommand = innerTokens[0];
526
- if (innerCommand) {
527
- const result = await checkExecKillCommand(innerCommand, innerTokens.slice(1));
528
- if (result.blocked) return result;
529
- }
530
- }
531
- }
532
- if (cmdLower === "stop-process" || cmdLower === "kill") {
533
- for (let i = 0; i < args.length; i++) {
534
- const a = args[i];
535
- if (a === "-Name" || a === "-n") {
536
- const nameArg = args[i + 1]?.replace(/^['"]|['"]$/g, "");
537
- if (nameArg) {
538
- const result = await checkKillTarget({
539
- name: nameArg,
540
- signal: "FORCE",
541
- cmd: fullCommand
542
- });
543
- if (result.blocked) return result;
544
- }
545
- }
546
- if (a === "-Id" || a === "-PID" || a === "-pid") {
547
- const pidArg = args[i + 1];
548
- if (pidArg && /^\d+$/.test(pidArg)) {
549
- const result = await checkKillTarget({
550
- pid: parseInt(pidArg, 10),
551
- signal: "FORCE",
552
- cmd: fullCommand
553
- });
554
- if (result.blocked) return result;
555
- }
556
- }
557
- }
558
- const firstNonFlag = args.find((a) => !a.startsWith("-"));
559
- if (firstNonFlag) {
560
- const name = firstNonFlag.replace(/^['"]|['"]$/g, "");
561
- const result = await checkKillTarget({ name, signal: "TERM", cmd: fullCommand });
562
- if (result.blocked) return result;
563
- }
564
- }
565
- if (cmdLower === "wmic" || cmdLower === "wmic.exe") {
566
- const joined = args.join(" ").toLowerCase();
567
- if (/\bprocess\b/.test(joined) && /\bdelete\b/.test(joined)) {
568
- const nameMatch = joined.match(/name\s*=\s*['"]?([^'"]+)/);
569
- if (nameMatch?.[1]) {
570
- const result = await checkKillTarget({
571
- name: nameMatch[1].trim(),
572
- signal: "FORCE",
573
- cmd: fullCommand
574
- });
575
- if (result.blocked) return result;
576
- }
577
- return {
578
- blocked: true,
579
- reason: "Blocked: wmic process delete targets all matched processes \u2014 would include protected WrongStack processes."
580
- };
581
- }
582
- }
583
- if (cmdLower === "node" || cmdLower === "node.exe") {
584
- if (args.includes("-e") || args.includes("--eval")) {
585
- const evalIdx = args.indexOf("-e") !== -1 ? args.indexOf("-e") : args.indexOf("--eval");
586
- const evalCode = args[evalIdx + 1] ?? "";
587
- if (/\bprocess\.kill\s*\(/.test(evalCode)) {
588
- const pidMatch = evalCode.match(/process\.kill\s*\(\s*(\d+)/);
589
- if (pidMatch?.[1]) {
590
- const pid = parseInt(pidMatch[1], 10);
591
- const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
592
- if (result.blocked) return result;
593
- }
594
- return {
595
- blocked: true,
596
- reason: "Blocked: node -e with process.kill() \u2014 would target protected WrongStack process(es)."
597
- };
598
- }
599
- }
600
- }
601
- } else {
602
- if (cmdLower === "kill") {
603
- for (const a of args) {
604
- const num = a.replace(/^-/, "");
605
- if (/^\d+$/.test(num)) {
606
- const pid = parseInt(num, 10);
607
- const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
608
- if (result.blocked) return result;
609
- }
610
- }
611
- }
612
- if (cmdLower === "pkill" || cmdLower === "killall") {
613
- const firstNonFlag = args.find((a) => !a.startsWith("-"));
614
- if (firstNonFlag) {
615
- const result = await checkKillTarget({
616
- name: firstNonFlag,
617
- signal: "SIGTERM",
618
- cmd: fullCommand
619
- });
620
- if (result.blocked) return result;
621
- }
622
- }
623
- }
624
- return { blocked: false };
625
- }
626
- function tokenizeShellCommand(command) {
627
- const tokens = [];
628
- let current = "";
629
- let quote = null;
630
- for (const char of command.trim()) {
631
- if (quote) {
632
- if (char === quote) quote = null;
633
- else current += char;
634
- continue;
635
- }
636
- if (char === '"' || char === "'") {
637
- quote = char;
638
- } else if (/\s/.test(char)) {
639
- if (current) {
640
- tokens.push(current);
641
- current = "";
642
- }
643
- } else {
644
- current += char;
645
- }
646
- }
647
- if (current) tokens.push(current);
648
- return tokens;
649
- }
650
- async function checkKillTarget(target) {
651
- const registry = getPersistentProcessRegistry();
652
- if (target.pid !== void 0) {
653
- const blocked = await registry.shouldBlockKill(target.pid);
654
- if (blocked) {
655
- return {
656
- blocked: true,
657
- reason: `Blocked: kill ${target.signal} PID ${target.pid} targets a protected WrongStack process (${target.cmd.slice(0, 80)}).`
658
- };
659
- }
660
- if (target.pid === process.pid) {
661
- return {
662
- blocked: true,
663
- reason: "Blocked: cannot kill the current WrongStack process."
664
- };
665
- }
666
- if (target.pid === process.ppid) {
667
- return {
668
- blocked: true,
669
- reason: "Blocked: cannot kill the parent terminal hosting WrongStack."
670
- };
671
- }
672
- return { blocked: false };
673
- }
674
- if (target.name) {
675
- const nameLower = target.name.toLowerCase().replace(/\.exe$/, "");
676
- if (nameLower.includes("wrongstack")) {
677
- return {
678
- blocked: true,
679
- reason: `Blocked: kill ${target.signal} '${target.name}' targets a WrongStack process name.`
680
- };
681
- }
682
- const currentImage = path.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
683
- const targetsNodeRuntime = nameLower === "node" || nameLower.startsWith("node");
684
- if (targetsNodeRuntime && currentImage === "node") {
685
- return {
686
- blocked: true,
687
- reason: `Blocked: kill ${target.signal} '${target.name}' would kill the active WrongStack node.exe runtime.`
688
- };
689
- }
690
- const protectedPids = await registry.getAllProtectedPids();
691
- if (protectedPids.length > 0 && targetsNodeRuntime) {
692
- return {
693
- blocked: true,
694
- reason: `Blocked: kill ${target.signal} '${target.name}' would kill all node.exe processes including active WrongStack instance(s).`
695
- };
696
- }
697
- return { blocked: false };
698
- }
699
- return { blocked: false };
700
- }
701
-
702
474
  // src/exec-allowlist.ts
703
475
  var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
704
476
  // JS / TS toolchain
@@ -1289,6 +1061,245 @@ var DEFAULT_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
1289
1061
  "chaos"
1290
1062
  ]);
1291
1063
 
1064
+ // src/exec-kill-guard.ts
1065
+ import * as os from "node:os";
1066
+ import * as path from "node:path";
1067
+ var isWin = os.platform() === "win32";
1068
+ async function checkExecKillCommand(cmd, args) {
1069
+ if (!cmd) return { blocked: false };
1070
+ const cmdLower = cmd.toLowerCase().trim();
1071
+ const fullCommand = [cmdLower, ...args].join(" ").replace(/\s+/g, " ").trim();
1072
+ if (isWin) {
1073
+ if (cmdLower === "taskkill" || cmdLower === "taskkill.exe") {
1074
+ const hasForce = args.some((a) => a.toUpperCase() === "/F" || a.toUpperCase() === "-F");
1075
+ const signal = hasForce ? "FORCE" : "TERM";
1076
+ for (let i = 0; i < args.length; i++) {
1077
+ const a = args[i];
1078
+ if (a.toUpperCase() === "/IM" || a.toUpperCase() === "-IM") {
1079
+ const nameArg = args[i + 1];
1080
+ if (nameArg) {
1081
+ const result = await checkKillTarget({ name: nameArg, signal, cmd: fullCommand });
1082
+ if (result.blocked) return result;
1083
+ }
1084
+ }
1085
+ }
1086
+ for (let i = 0; i < args.length; i++) {
1087
+ const a = args[i];
1088
+ if (a.toUpperCase() === "/PID" || a.toUpperCase() === "-PID") {
1089
+ const pidArg = args[i + 1];
1090
+ if (pidArg && /^\d+$/.test(pidArg)) {
1091
+ const result = await checkKillTarget({
1092
+ pid: parseInt(pidArg, 10),
1093
+ signal,
1094
+ cmd: fullCommand
1095
+ });
1096
+ if (result.blocked) return result;
1097
+ }
1098
+ }
1099
+ }
1100
+ for (let i = 0; i < args.length; i++) {
1101
+ const a = args[i];
1102
+ if (a.toUpperCase() === "/FI" || a.toUpperCase() === "-FI") {
1103
+ const filterArg = args[i + 1];
1104
+ if (filterArg) {
1105
+ const nameMatch = filterArg.match(/IMAGENAME\s+eq\s+"?([^"\s]+)/i);
1106
+ if (nameMatch?.[1]) {
1107
+ const result = await checkKillTarget({
1108
+ name: nameMatch[1],
1109
+ signal,
1110
+ cmd: fullCommand
1111
+ });
1112
+ if (result.blocked) return result;
1113
+ }
1114
+ }
1115
+ }
1116
+ }
1117
+ return { blocked: false };
1118
+ }
1119
+ if (cmdLower === "powershell" || cmdLower === "powershell.exe" || cmdLower === "pwsh" || cmdLower === "pwsh.exe" || cmdLower === "cmd" || cmdLower === "cmd.exe") {
1120
+ const shellFlagIndex = args.findIndex((arg) => {
1121
+ const lower = arg.toLowerCase();
1122
+ return lower === "-c" || lower === "-command" || lower === "/c";
1123
+ });
1124
+ if (shellFlagIndex >= 0) {
1125
+ const innerTokens = tokenizeShellCommand(args.slice(shellFlagIndex + 1).join(" "));
1126
+ const innerCommand = innerTokens[0];
1127
+ if (innerCommand) {
1128
+ const result = await checkExecKillCommand(innerCommand, innerTokens.slice(1));
1129
+ if (result.blocked) return result;
1130
+ }
1131
+ }
1132
+ }
1133
+ if (cmdLower === "stop-process" || cmdLower === "kill") {
1134
+ for (let i = 0; i < args.length; i++) {
1135
+ const a = args[i];
1136
+ if (a === "-Name" || a === "-n") {
1137
+ const nameArg = args[i + 1]?.replace(/^['"]|['"]$/g, "");
1138
+ if (nameArg) {
1139
+ const result = await checkKillTarget({
1140
+ name: nameArg,
1141
+ signal: "FORCE",
1142
+ cmd: fullCommand
1143
+ });
1144
+ if (result.blocked) return result;
1145
+ }
1146
+ }
1147
+ if (a === "-Id" || a === "-PID" || a === "-pid") {
1148
+ const pidArg = args[i + 1];
1149
+ if (pidArg && /^\d+$/.test(pidArg)) {
1150
+ const result = await checkKillTarget({
1151
+ pid: parseInt(pidArg, 10),
1152
+ signal: "FORCE",
1153
+ cmd: fullCommand
1154
+ });
1155
+ if (result.blocked) return result;
1156
+ }
1157
+ }
1158
+ }
1159
+ const firstNonFlag = args.find((a) => !a.startsWith("-"));
1160
+ if (firstNonFlag) {
1161
+ const name = firstNonFlag.replace(/^['"]|['"]$/g, "");
1162
+ const result = await checkKillTarget({ name, signal: "TERM", cmd: fullCommand });
1163
+ if (result.blocked) return result;
1164
+ }
1165
+ }
1166
+ if (cmdLower === "wmic" || cmdLower === "wmic.exe") {
1167
+ const joined = args.join(" ").toLowerCase();
1168
+ if (/\bprocess\b/.test(joined) && /\bdelete\b/.test(joined)) {
1169
+ const nameMatch = joined.match(/name\s*=\s*['"]?([^'"]+)/);
1170
+ if (nameMatch?.[1]) {
1171
+ const result = await checkKillTarget({
1172
+ name: nameMatch[1].trim(),
1173
+ signal: "FORCE",
1174
+ cmd: fullCommand
1175
+ });
1176
+ if (result.blocked) return result;
1177
+ }
1178
+ return {
1179
+ blocked: true,
1180
+ reason: "Blocked: wmic process delete targets all matched processes \u2014 would include protected WrongStack processes."
1181
+ };
1182
+ }
1183
+ }
1184
+ if (cmdLower === "node" || cmdLower === "node.exe") {
1185
+ if (args.includes("-e") || args.includes("--eval")) {
1186
+ const evalIdx = args.indexOf("-e") !== -1 ? args.indexOf("-e") : args.indexOf("--eval");
1187
+ const evalCode = args[evalIdx + 1] ?? "";
1188
+ if (/\bprocess\.kill\s*\(/.test(evalCode)) {
1189
+ const pidMatch = evalCode.match(/process\.kill\s*\(\s*(\d+)/);
1190
+ if (pidMatch?.[1]) {
1191
+ const pid = parseInt(pidMatch[1], 10);
1192
+ const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
1193
+ if (result.blocked) return result;
1194
+ }
1195
+ return {
1196
+ blocked: true,
1197
+ reason: "Blocked: node -e with process.kill() \u2014 would target protected WrongStack process(es)."
1198
+ };
1199
+ }
1200
+ }
1201
+ }
1202
+ } else {
1203
+ if (cmdLower === "kill") {
1204
+ for (const a of args) {
1205
+ const num = a.replace(/^-/, "");
1206
+ if (/^\d+$/.test(num)) {
1207
+ const pid = parseInt(num, 10);
1208
+ const result = await checkKillTarget({ pid, signal: "SIGTERM", cmd: fullCommand });
1209
+ if (result.blocked) return result;
1210
+ }
1211
+ }
1212
+ }
1213
+ if (cmdLower === "pkill" || cmdLower === "killall") {
1214
+ const firstNonFlag = args.find((a) => !a.startsWith("-"));
1215
+ if (firstNonFlag) {
1216
+ const result = await checkKillTarget({
1217
+ name: firstNonFlag,
1218
+ signal: "SIGTERM",
1219
+ cmd: fullCommand
1220
+ });
1221
+ if (result.blocked) return result;
1222
+ }
1223
+ }
1224
+ }
1225
+ return { blocked: false };
1226
+ }
1227
+ function tokenizeShellCommand(command) {
1228
+ const tokens = [];
1229
+ let current = "";
1230
+ let quote = null;
1231
+ for (const char of command.trim()) {
1232
+ if (quote) {
1233
+ if (char === quote) quote = null;
1234
+ else current += char;
1235
+ continue;
1236
+ }
1237
+ if (char === '"' || char === "'") {
1238
+ quote = char;
1239
+ } else if (/\s/.test(char)) {
1240
+ if (current) {
1241
+ tokens.push(current);
1242
+ current = "";
1243
+ }
1244
+ } else {
1245
+ current += char;
1246
+ }
1247
+ }
1248
+ if (current) tokens.push(current);
1249
+ return tokens;
1250
+ }
1251
+ async function checkKillTarget(target) {
1252
+ const registry = getPersistentProcessRegistry();
1253
+ if (target.pid !== void 0) {
1254
+ const blocked = await registry.shouldBlockKill(target.pid);
1255
+ if (blocked) {
1256
+ return {
1257
+ blocked: true,
1258
+ reason: `Blocked: kill ${target.signal} PID ${target.pid} targets a protected WrongStack process (${target.cmd.slice(0, 80)}).`
1259
+ };
1260
+ }
1261
+ if (target.pid === process.pid) {
1262
+ return {
1263
+ blocked: true,
1264
+ reason: "Blocked: cannot kill the current WrongStack process."
1265
+ };
1266
+ }
1267
+ if (target.pid === process.ppid) {
1268
+ return {
1269
+ blocked: true,
1270
+ reason: "Blocked: cannot kill the parent terminal hosting WrongStack."
1271
+ };
1272
+ }
1273
+ return { blocked: false };
1274
+ }
1275
+ if (target.name) {
1276
+ const nameLower = target.name.toLowerCase().replace(/\.exe$/, "");
1277
+ if (nameLower.includes("wrongstack")) {
1278
+ return {
1279
+ blocked: true,
1280
+ reason: `Blocked: kill ${target.signal} '${target.name}' targets a WrongStack process name.`
1281
+ };
1282
+ }
1283
+ const currentImage = path.basename(process.execPath).toLowerCase().replace(/\.exe$/, "");
1284
+ const targetsNodeRuntime = nameLower === "node" || nameLower.startsWith("node");
1285
+ if (targetsNodeRuntime && currentImage === "node") {
1286
+ return {
1287
+ blocked: true,
1288
+ reason: `Blocked: kill ${target.signal} '${target.name}' would kill the active WrongStack node.exe runtime.`
1289
+ };
1290
+ }
1291
+ const protectedPids = await registry.getAllProtectedPids();
1292
+ if (protectedPids.length > 0 && targetsNodeRuntime) {
1293
+ return {
1294
+ blocked: true,
1295
+ reason: `Blocked: kill ${target.signal} '${target.name}' would kill all node.exe processes including active WrongStack instance(s).`
1296
+ };
1297
+ }
1298
+ return { blocked: false };
1299
+ }
1300
+ return { blocked: false };
1301
+ }
1302
+
1292
1303
  // src/exec.ts
1293
1304
  var isWin2 = process.platform === "win32";
1294
1305
  var allowedCommands = new Set(DEFAULT_ALLOWED_COMMANDS);
@@ -1340,10 +1351,9 @@ var BLOCKED_ARG_PATTERNS = {
1340
1351
  /^--exec=/,
1341
1352
  /^--upload-pack=/,
1342
1353
  /^--receive-pack=/,
1343
- /^-C$/,
1344
- /^-c$/,
1354
+ /^-C/,
1355
+ /^-c/,
1345
1356
  /^--config$/,
1346
- /^-c=/,
1347
1357
  /^--config=/,
1348
1358
  /^--config-env=/
1349
1359
  ],
@@ -1443,6 +1453,7 @@ function validateArgs(cmd, args) {
1443
1453
  const blocked = BLOCKED_ARG_PATTERNS[cmd];
1444
1454
  if (!blocked) return null;
1445
1455
  for (const arg of args) {
1456
+ if (arg === "--") break;
1446
1457
  for (const pattern of blocked) {
1447
1458
  if (pattern.test(arg)) {
1448
1459
  return `Blocked argument "${arg}" for command "${cmd}" (matches security pattern ${pattern})`;
@@ -1646,11 +1657,6 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1646
1657
  });
1647
1658
  return;
1648
1659
  }
1649
- const resolved = resolveWin32Command(cmd);
1650
- const needsShell = isWin2 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
1651
- const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
1652
- const spawnCmd = shim?.command ?? resolved;
1653
- const spawnArgs = shim?.args ?? args;
1654
1660
  const emitCompletedOnce = (exitCode, pid2, signal2) => {
1655
1661
  if (telemetryCompleted) return;
1656
1662
  telemetryCompleted = true;
@@ -1667,6 +1673,11 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1667
1673
  };
1668
1674
  let child;
1669
1675
  try {
1676
+ const resolved = resolveWin32Command(cmd);
1677
+ const needsShell = isWin2 && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
1678
+ const shim = needsShell ? buildWin32CmdShimInvocation(resolved, args) : null;
1679
+ const spawnCmd = shim?.command ?? resolved;
1680
+ const spawnArgs = shim?.args ?? args;
1670
1681
  child = spawn(spawnCmd, spawnArgs, {
1671
1682
  cwd,
1672
1683
  env: buildChildEnv(sessionId),
@@ -1676,6 +1687,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1676
1687
  ...shim ? { windowsVerbatimArguments: shim.windowsVerbatimArguments } : {}
1677
1688
  });
1678
1689
  } catch (err) {
1690
+ getProcessRegistry().afterCall(Date.now() - startedAt, true);
1679
1691
  spool.finalize();
1680
1692
  emitProcessStarted({
1681
1693
  parentPid: process.pid,
@@ -1707,10 +1719,18 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1707
1719
  background: false,
1708
1720
  startedAt: new Date(startedAt).toISOString()
1709
1721
  });
1722
+ const registry = getProcessRegistry();
1723
+ const pid = child.pid;
1724
+ let timer;
1725
+ const onAbort = () => {
1726
+ killed = true;
1727
+ if (typeof pid === "number") registry.kill(pid, { force: true });
1728
+ else child.kill("SIGTERM");
1729
+ };
1710
1730
  child.on("error", (err) => {
1711
1731
  const isAbort = err && err.code === "ABORT_ERR";
1712
1732
  const stderrText = isAbort ? `Aborted: ${err.message}` : err.message;
1713
- clearTimeout(timer);
1733
+ if (timer !== void 0) clearTimeout(timer);
1714
1734
  if (isWin2) signal.removeEventListener("abort", onAbort);
1715
1735
  if (typeof pid === "number") registry.unregister(pid);
1716
1736
  registry.afterCall(Date.now() - startedAt, true);
@@ -1727,8 +1747,6 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1727
1747
  danger
1728
1748
  });
1729
1749
  });
1730
- const registry = getProcessRegistry();
1731
- const pid = child.pid;
1732
1750
  if (typeof pid === "number") {
1733
1751
  const fullCommand = `${cmd} ${args.join(" ")}`;
1734
1752
  registry.register({
@@ -1740,17 +1758,12 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1740
1758
  child
1741
1759
  });
1742
1760
  }
1743
- const timer = setTimeout(() => {
1761
+ timer = setTimeout(() => {
1744
1762
  killed = true;
1745
1763
  timedOut = true;
1746
1764
  if (typeof pid === "number") registry.kill(pid);
1747
1765
  else child.kill("SIGTERM");
1748
1766
  }, timeout);
1749
- const onAbort = () => {
1750
- killed = true;
1751
- if (typeof pid === "number") registry.kill(pid, { force: true });
1752
- else child.kill("SIGTERM");
1753
- };
1754
1767
  if (isWin2) {
1755
1768
  if (signal.aborted) onAbort();
1756
1769
  else signal.addEventListener("abort", onAbort, { once: true });
@@ -1776,9 +1789,10 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId, danger) {
1776
1789
  }
1777
1790
  });
1778
1791
  child.on("close", (code) => {
1779
- clearTimeout(timer);
1792
+ if (timer !== void 0) clearTimeout(timer);
1780
1793
  if (isWin2) signal.removeEventListener("abort", onAbort);
1781
1794
  if (typeof pid === "number") registry.unregister(pid);
1795
+ if (resolvedOnce.value) return;
1782
1796
  const durationMs = Date.now() - startedAt;
1783
1797
  const exitCode = killed ? 124 : code ?? 1;
1784
1798
  emitCompletedOnce(exitCode, pid);
@@ -1821,4 +1835,4 @@ export {
1821
1835
  getExecAllowlist,
1822
1836
  execTool
1823
1837
  };
1824
- //# sourceMappingURL=chunk-OTPTQBYE.js.map
1838
+ //# sourceMappingURL=chunk-MGPR7VG3.js.map
@@ -269,4 +269,4 @@ function prettyJson(s) {
269
269
  export {
270
270
  fetchTool
271
271
  };
272
- //# sourceMappingURL=chunk-C2DQKVLO.js.map
272
+ //# sourceMappingURL=chunk-MJSJWXBF.js.map