@wrongstack/tools 0.319.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) 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 +8 -8
  5. package/dist/auto-proceed-loop-guard.js +9 -160
  6. package/dist/bash-kill-guard.d.ts +2 -3
  7. package/dist/bash.d.ts +2 -3
  8. package/dist/bash.js +6 -6
  9. package/dist/batch-tool-use.d.ts +2 -3
  10. package/dist/batch-tool-use.js +1 -1
  11. package/dist/browser/index.d.ts +1 -1
  12. package/dist/browser/index.js +1 -1
  13. package/dist/browser/tools.d.ts +56 -45
  14. package/dist/builtin.js +55 -55
  15. package/dist/{chunk-RJZQWEMS.js → chunk-24T5XIJU.js} +3 -2
  16. package/dist/{chunk-DTQ75VBC.js → chunk-2CTZW6JQ.js} +2 -2
  17. package/dist/chunk-37QKUQ2Z.js +171 -0
  18. package/dist/{chunk-LOBRWKCR.js → chunk-3D5DJWOE.js} +3 -3
  19. package/dist/{chunk-YOKD4GWJ.js → chunk-4ERMPDHV.js} +14 -8
  20. package/dist/{chunk-5EUJF3WC.js → chunk-4WPBS45A.js} +4 -5
  21. package/dist/{chunk-42BHI7TN.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-IYKXK356.js → chunk-6GOZTS6F.js} +4 -4
  25. package/dist/{chunk-OG2BEUBY.js → chunk-7HL23T3T.js} +73 -16
  26. package/dist/{chunk-HFXSNKCV.js → chunk-7JJFC6CT.js} +1 -1
  27. package/dist/{chunk-TTZOK6IY.js → chunk-7N5U2RAU.js} +2 -2
  28. package/dist/{chunk-QBV725YG.js → chunk-7ODZTPCU.js} +2 -2
  29. package/dist/{chunk-OTINMOKK.js → chunk-AB2CAUOP.js} +66 -55
  30. package/dist/{chunk-6AAOT4PW.js → chunk-AQ5YBURX.js} +16 -4
  31. package/dist/{chunk-JDPQOR7C.js → chunk-ASEXQRA7.js} +19 -19
  32. package/dist/{chunk-FRN7TIAA.js → chunk-B3MGJBFI.js} +1 -1
  33. package/dist/{chunk-IWS56OY7.js → chunk-CGXTR34H.js} +63 -4
  34. package/dist/{chunk-IU4DV2PA.js → chunk-CHEK3ASV.js} +6 -3
  35. package/dist/{chunk-GOIZNNOA.js → chunk-DJYLI7EW.js} +1 -1
  36. package/dist/{chunk-CFLJFDYV.js → chunk-DK4J2WMH.js} +14 -11
  37. package/dist/{chunk-ZHH3BEWU.js → chunk-DRRY6SCM.js} +49 -22
  38. package/dist/{chunk-BK732J7I.js → chunk-FBUP524S.js} +4 -4
  39. package/dist/{chunk-WHIIIREL.js → chunk-FVM3O4JQ.js} +7 -3
  40. package/dist/chunk-FYDBUVQD.js +244 -0
  41. package/dist/{chunk-UDVKRX5R.js → chunk-GDDXX27P.js} +50 -50
  42. package/dist/{chunk-O44IMQCN.js → chunk-GKSG5CPH.js} +6 -6
  43. package/dist/{chunk-3PVYQFRQ.js → chunk-HDYUBRMF.js} +5 -3
  44. package/dist/{chunk-ELRRTWNP.js → chunk-IXIS7RSG.js} +2 -2
  45. package/dist/{chunk-X5FOFGXX.js → chunk-IYH4OHBP.js} +6 -6
  46. package/dist/{chunk-MNP3GE7H.js → chunk-JDOO4P6Z.js} +21 -16
  47. package/dist/{chunk-BSJSNVGA.js → chunk-KDEXUQY7.js} +24 -11
  48. package/dist/{chunk-V43EQ6VR.js → chunk-KE7A76VC.js} +3 -2
  49. package/dist/{chunk-2OXHS3KZ.js → chunk-KLJZ4WV4.js} +4 -3
  50. package/dist/{chunk-3M7LLN7W.js → chunk-LQSOU63Z.js} +12 -11
  51. package/dist/{chunk-DC4KMPJO.js → chunk-M6UV67BH.js} +2 -2
  52. package/dist/{chunk-C2DQKVLO.js → chunk-MJSJWXBF.js} +1 -1
  53. package/dist/{chunk-RNWUCZ2U.js → chunk-MK2JK35J.js} +29 -12
  54. package/dist/{chunk-FQZOHLG3.js → chunk-MSOAX3GC.js} +3 -2
  55. package/dist/{chunk-KY4PXYSO.js → chunk-N3K2SFEI.js} +534 -494
  56. package/dist/{chunk-EADULOZV.js → chunk-NJX2RXKJ.js} +50 -7
  57. package/dist/{chunk-AKHYMB4V.js → chunk-NN2SNP2R.js} +6 -6
  58. package/dist/{chunk-CMOUCKGC.js → chunk-NU2IZ72J.js} +6 -6
  59. package/dist/{chunk-RLMX75EM.js → chunk-O6BY43ZB.js} +29 -8
  60. package/dist/{chunk-NKNOBUBU.js → chunk-PVCB7RUZ.js} +2 -2
  61. package/dist/{chunk-UQQS3VNT.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-2VSZC6QM.js → chunk-SCMRM6NL.js} +6 -4
  65. package/dist/{chunk-W2CECGTG.js → chunk-SMARDKAC.js} +1 -1
  66. package/dist/{chunk-45JPRMC2.js → chunk-SOR7OCYP.js} +7 -3
  67. package/dist/{chunk-ATSKPZUK.js → chunk-T3SMFF5Q.js} +11 -5
  68. package/dist/{chunk-4BHUSMNL.js → chunk-UI3ZJIG3.js} +1 -1
  69. package/dist/{chunk-WXJY3BKV.js → chunk-VBF2YXUW.js} +2 -2
  70. package/dist/{chunk-FQNXYA6W.js → chunk-VU3QBYL4.js} +36 -5
  71. package/dist/{chunk-IIF5HIVF.js → chunk-VVZPQPTY.js} +2 -2
  72. package/dist/{chunk-VD2LV5WO.js → chunk-VZGPASGD.js} +37 -12
  73. package/dist/{chunk-64VIJPFV.js → chunk-WEEVSWQB.js} +17 -6
  74. package/dist/chunk-XXRMF2BC.js +186 -0
  75. package/dist/{chunk-RTZWBNTY.js → chunk-YEISRT4S.js} +7 -12
  76. package/dist/{chunk-Q5JPPCZC.js → chunk-YJTXRH5Y.js} +3 -2
  77. package/dist/{chunk-GMZYW52L.js → chunk-YULVUTK5.js} +6 -3
  78. package/dist/{chunk-NWZ6XGBJ.js → chunk-ZBMANLYH.js} +5 -3
  79. package/dist/{chunk-DP6CXMJZ.js → chunk-ZTCJCYLN.js} +3 -3
  80. package/dist/circuit-breaker.d.ts +1 -0
  81. package/dist/circuit-breaker.js +1 -1
  82. package/dist/clarify.d.ts +1 -0
  83. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +2 -3
  84. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +5 -4
  85. package/dist/codebase-index/codebase-incoming-calls-tool.d.ts +4 -3
  86. package/dist/codebase-index/codebase-index-tool.d.ts +2 -3
  87. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +2 -3
  88. package/dist/codebase-index/codebase-outgoing-calls-tool.d.ts +4 -3
  89. package/dist/codebase-index/codebase-repo-map-tool.d.ts +2 -3
  90. package/dist/codebase-index/codebase-search-tool.d.ts +2 -3
  91. package/dist/codebase-index/codebase-skeleton-tool.d.ts +2 -3
  92. package/dist/codebase-index/codebase-stats-tool.d.ts +9 -3
  93. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +4 -3
  94. package/dist/codebase-index/index.d.ts +11 -11
  95. package/dist/codebase-index/index.js +12 -12
  96. package/dist/codebase-index/parser-worker-script.js +3 -3
  97. package/dist/codebase-index/project-server-framing.d.ts +29 -0
  98. package/dist/codebase-index/project-server-lifecycle.d.ts +20 -0
  99. package/dist/codebase-index/project-server-operations.d.ts +37 -0
  100. package/dist/codebase-index/project-server-types.d.ts +30 -0
  101. package/dist/codebase-index/project-server-watcher.d.ts +25 -0
  102. package/dist/codebase-index/project-server.js +451 -394
  103. package/dist/codebase-index/worker.js +5 -5
  104. package/dist/codebase-index/writer-init.d.ts +13 -0
  105. package/dist/codebase-index/writer-maintenance.d.ts +14 -0
  106. package/dist/codebase-index/writer.d.ts +0 -15
  107. package/dist/design.d.ts +2 -2
  108. package/dist/design.js +1 -1
  109. package/dist/diff.d.ts +4 -4
  110. package/dist/diff.js +2 -2
  111. package/dist/document.d.ts +3 -4
  112. package/dist/document.js +1 -1
  113. package/dist/e2e.d.ts +1 -1
  114. package/dist/e2e.js +1 -1
  115. package/dist/edit.d.ts +3 -3
  116. package/dist/edit.js +9 -9
  117. package/dist/exec.d.ts +2 -3
  118. package/dist/exec.js +6 -6
  119. package/dist/fetch.d.ts +4 -3
  120. package/dist/fetch.js +1 -1
  121. package/dist/format.d.ts +17 -45
  122. package/dist/format.js +14 -10
  123. package/dist/git.d.ts +3 -3
  124. package/dist/git.js +1 -1
  125. package/dist/glob.d.ts +2 -3
  126. package/dist/glob.js +3 -3
  127. package/dist/{go-parser-IKHW67WE.js → go-parser-D7ELWQ7F.js} +2 -2
  128. package/dist/grep.d.ts +7 -5
  129. package/dist/grep.js +4 -4
  130. package/dist/index.d.ts +54 -45
  131. package/dist/index.js +122 -63
  132. package/dist/install.d.ts +7 -55
  133. package/dist/install.js +8 -8
  134. package/dist/{json-parser-2EOVP5MR.js → json-parser-34DHYCPW.js} +1 -18
  135. package/dist/json.d.ts +3 -4
  136. package/dist/json.js +2 -2
  137. package/dist/kanban-tool-types.d.ts +1 -2
  138. package/dist/kanban.d.ts +3 -19
  139. package/dist/kanban.js +1 -1
  140. package/dist/languages/execute-tool.d.ts +2 -3
  141. package/dist/languages/index.d.ts +2 -2
  142. package/dist/languages/index.js +6 -6
  143. package/dist/languages/tool.d.ts +3 -4
  144. package/dist/legacy-bridge-YXANP5QB.js +18 -0
  145. package/dist/lint.d.ts +5 -4
  146. package/dist/lint.js +8 -8
  147. package/dist/logs.d.ts +3 -4
  148. package/dist/logs.js +2 -2
  149. package/dist/memory.d.ts +7 -8
  150. package/dist/memory.js +1 -1
  151. package/dist/mode.d.ts +3 -4
  152. package/dist/mode.js +1 -1
  153. package/dist/next-steps-tool.d.ts +2 -3
  154. package/dist/next-steps.d.ts +11 -0
  155. package/dist/next-steps.js +10 -132
  156. package/dist/outdated.d.ts +5 -29
  157. package/dist/outdated.js +4 -4
  158. package/dist/pack.js +56 -56
  159. package/dist/{parser-dispatch-QGC4HSP5.js → parser-dispatch-BDVCJXTV.js} +4 -4
  160. package/dist/patch.d.ts +2 -3
  161. package/dist/patch.js +8 -8
  162. package/dist/plan.d.ts +4 -4
  163. package/dist/plan.js +3 -3
  164. package/dist/process-registry.js +2 -2
  165. package/dist/ps-slash.js +4 -4
  166. package/dist/pwsh.d.ts +1 -0
  167. package/dist/{py-parser-RFWG2HYI.js → py-parser-QC6MR4GB.js} +3 -3
  168. package/dist/read.d.ts +5 -5
  169. package/dist/read.js +8 -8
  170. package/dist/replace.d.ts +2 -3
  171. package/dist/replace.js +10 -10
  172. package/dist/scaffold.d.ts +7 -3
  173. package/dist/scaffold.js +3 -1
  174. package/dist/search.d.ts +17 -3
  175. package/dist/search.js +5 -1
  176. package/dist/set-working-dir.d.ts +2 -3
  177. package/dist/skill.d.ts +4 -5
  178. package/dist/skill.js +1 -1
  179. package/dist/task.d.ts +6 -6
  180. package/dist/task.js +3 -3
  181. package/dist/test.d.ts +5 -4
  182. package/dist/test.js +8 -8
  183. package/dist/todo.d.ts +8 -8
  184. package/dist/todo.js +2 -2
  185. package/dist/tool-diff.js +11 -230
  186. package/dist/tool-help.d.ts +2 -3
  187. package/dist/tool-help.js +1 -1
  188. package/dist/tool-search.d.ts +2 -3
  189. package/dist/tool-search.js +1 -1
  190. package/dist/tool-summary.js +5 -281
  191. package/dist/tool-tier.js +57 -57
  192. package/dist/tool-use.d.ts +2 -3
  193. package/dist/tool-use.js +1 -1
  194. package/dist/tree.d.ts +5 -3
  195. package/dist/tree.js +5 -1
  196. package/dist/typecheck.d.ts +3 -3
  197. package/dist/typecheck.js +8 -8
  198. package/dist/win32.js +1 -1
  199. package/dist/write.d.ts +2 -3
  200. package/dist/write.js +9 -9
  201. package/package.json +5 -5
  202. package/dist/legacy-bridge-3T7SR4SK.js +0 -18
  203. package/dist/spawn-background.d.ts +0 -80
@@ -13,7 +13,8 @@ var DEFAULT_IGNORE = /* @__PURE__ */ new Set([
13
13
  ".gnupg",
14
14
  ".aws"
15
15
  ]);
16
- var DEFAULT_MAX_ENTRIES = 5e3;
16
+ var DEFAULT_MAX_TREE_ENTRIES = 5e3;
17
+ var DEFAULT_MAX_ENTRIES = DEFAULT_MAX_TREE_ENTRIES;
17
18
  var MAX_TREE_OUTPUT_BYTES = 256 * 1024;
18
19
  var treeTool = {
19
20
  name: "tree",
@@ -84,10 +85,11 @@ var treeTool = {
84
85
  const showFiles = input.show_files ?? true;
85
86
  const showDirs = input.show_dirs ?? true;
86
87
  const showHidden = input.show_hidden ?? false;
88
+ const rawExclude = Array.isArray(input.exclude) ? input.exclude : typeof input.exclude === "string" ? [input.exclude] : [];
87
89
  const exclude = /* @__PURE__ */ new Set([
88
90
  ...DEFAULT_IGNORE,
89
- ...(input.exclude ?? []).map(
90
- (s) => s.trim().replace(/[\\/]+$/, "").replace(/^\.\//, "")
91
+ ...rawExclude.filter((s) => typeof s === "string").map(
92
+ (s) => s.trim().replace(/\\/g, "/").replace(/\/+$/, "").replace(/^\.\//, "")
91
93
  ).filter(Boolean)
92
94
  ]);
93
95
  const globRe = input.glob ? compileGlob(input.glob) : void 0;
@@ -203,7 +205,7 @@ async function walkDir(dir, depth, opts) {
203
205
  opts.totalDirs.value += dirCount;
204
206
  opts.totalFiles.value += fileCount;
205
207
  opts.onProgress?.();
206
- const items = filtered.sort((a, b) => {
208
+ const items = filtered.filter((e) => e.isDirectory() || opts.showFiles).sort((a, b) => {
207
209
  if (a.isDirectory() && !b.isDirectory()) return -1;
208
210
  if (!a.isDirectory() && b.isDirectory()) return 1;
209
211
  return a.name.localeCompare(b.name);
@@ -218,19 +220,20 @@ async function walkDir(dir, depth, opts) {
218
220
  const branch = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
219
221
  const displayName = entry.name + (entry.isDirectory() ? "/" : "");
220
222
  const isDir = entry.isDirectory();
221
- if (!opts.showDirs && isDir) continue;
222
- if (!opts.showFiles && !isDir) continue;
223
- const line = opts.prefix + branch + displayName;
224
- const lineBytes = Buffer.byteLength(line, "utf8") + 1;
225
- if (opts.retention.entries >= opts.retention.maxEntries || opts.retention.outputBytes + lineBytes > opts.retention.maxOutputBytes) {
226
- opts.retention.truncated = true;
227
- return;
223
+ const showEntry = isDir && opts.showDirs || !isDir && opts.showFiles;
224
+ if (showEntry) {
225
+ const line = opts.prefix + branch + displayName;
226
+ const lineBytes = Buffer.byteLength(line, "utf8") + 1;
227
+ if (opts.retention.entries >= opts.retention.maxEntries || opts.retention.outputBytes + lineBytes > opts.retention.maxOutputBytes) {
228
+ opts.retention.truncated = true;
229
+ return;
230
+ }
231
+ opts.lines.push(line);
232
+ opts.retention.entries++;
233
+ opts.retention.outputBytes += lineBytes;
228
234
  }
229
- opts.lines.push(line);
230
- opts.retention.entries++;
231
- opts.retention.outputBytes += lineBytes;
232
235
  if (entry.isDirectory() && (opts.maxDepth === 0 || depth < opts.maxDepth)) {
233
- const childPrefix = opts.prefix + connector;
236
+ const childPrefix = showEntry ? opts.prefix + connector : opts.prefix;
234
237
  await walkDir(path.join(dir, entry.name), depth + 1, {
235
238
  ...opts,
236
239
  prefix: childPrefix,
@@ -241,6 +244,8 @@ async function walkDir(dir, depth, opts) {
241
244
  }
242
245
 
243
246
  export {
247
+ DEFAULT_MAX_TREE_ENTRIES,
248
+ MAX_TREE_OUTPUT_BYTES,
244
249
  treeTool
245
250
  };
246
- //# sourceMappingURL=chunk-MNP3GE7H.js.map
251
+ //# sourceMappingURL=chunk-JDOO4P6Z.js.map
@@ -3,19 +3,19 @@ import {
3
3
  } from "./chunk-BTSFTGIL.js";
4
4
  import {
5
5
  getPersistentProcessRegistry
6
- } from "./chunk-NKNOBUBU.js";
6
+ } from "./chunk-PVCB7RUZ.js";
7
7
  import {
8
8
  createOutputSpool,
9
9
  spoolNote
10
- } from "./chunk-2VSZC6QM.js";
10
+ } from "./chunk-SCMRM6NL.js";
11
11
  import {
12
12
  getProcessRegistry,
13
13
  redactCommand
14
- } from "./chunk-3PVYQFRQ.js";
14
+ } from "./chunk-HDYUBRMF.js";
15
15
  import {
16
16
  buildWin32CmdShimInvocation,
17
17
  resolveWin32Command
18
- } from "./chunk-V43EQ6VR.js";
18
+ } from "./chunk-KE7A76VC.js";
19
19
  import {
20
20
  COMMAND_OUTPUT_MAX_BYTES,
21
21
  normalizeCommandOutput,
@@ -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
  },
@@ -428,12 +439,14 @@ var RULES = [
428
439
  }
429
440
  ];
430
441
  function detectDanger(cmd, args, bypass) {
442
+ if (typeof cmd !== "string") return { level: "safe", reasons: [] };
443
+ const safeArgs = Array.isArray(args) ? args : [];
431
444
  const reasons = [];
432
445
  let level = "safe";
433
446
  let matchedRule;
434
447
  for (const rule of RULES) {
435
448
  if (bypass?.has(rule.id)) continue;
436
- if (!rule.test(cmd, args)) continue;
449
+ if (!rule.test(cmd, safeArgs)) continue;
437
450
  reasons.push(rule.reason);
438
451
  if (matchedRule === void 0 || levelRank(rule.level) >= levelRank(level)) {
439
452
  matchedRule = rule.id;
@@ -1819,4 +1832,4 @@ export {
1819
1832
  getExecAllowlist,
1820
1833
  execTool
1821
1834
  };
1822
- //# sourceMappingURL=chunk-BSJSNVGA.js.map
1835
+ //# sourceMappingURL=chunk-KDEXUQY7.js.map
@@ -56,7 +56,8 @@ function buildWin32CmdShimInvocation(command, args = []) {
56
56
  };
57
57
  }
58
58
  function quoteWin32CmdArg(arg) {
59
- return `"${arg}"`;
59
+ const escaped = arg.replace(/(\\+)$/, "$1$1");
60
+ return `"${escaped}"`;
60
61
  }
61
62
 
62
63
  export {
@@ -65,4 +66,4 @@ export {
65
66
  assertSafeWin32ShellArgs,
66
67
  buildWin32CmdShimInvocation
67
68
  };
68
- //# sourceMappingURL=chunk-V43EQ6VR.js.map
69
+ //# sourceMappingURL=chunk-KE7A76VC.js.map
@@ -100,7 +100,7 @@ describe('{{Name}}', () => {
100
100
  var scaffoldTool = {
101
101
  name: "scaffold",
102
102
  category: "Project",
103
- description: "Generate new files and folder structures from built-in templates or custom definitions. This is the recommended way to bootstrap new packages, components, or modules instead of creating files one by one with `write`.",
103
+ description: "Generate or preview files and folder structures from built-in templates or custom definitions. Writes files to disk unless dry_run is set. This is the recommended way to bootstrap new packages, components, or modules instead of creating files one by one with `write`.",
104
104
  usageHint: "PREFERRED FOR SCAFFOLDING:\n\n- Use built-in templates when they match your needs (e.g. react-component, npm-package).\n- Supports `dry_run` so you can preview exactly what will be created.\n- Has the powerful `fs.write.outside-project` capability \u2014 review paths carefully.\nMuch cleaner and safer than manually writing multiple files.",
105
105
  permission: "confirm",
106
106
  mutating: true,
@@ -195,7 +195,7 @@ function escapeRegexLiteral(value) {
195
195
  }
196
196
  function substituteVars(content, name, vars) {
197
197
  const kebab = name.toLowerCase().replace(/\s+/g, "-");
198
- const pascal = name.replace(/(?:^|[-_\s]+)([a-z])/g, (_, c) => c.toUpperCase());
198
+ const pascal = name.replace(/(?:^|[-_\s]+)([a-zA-Z])/g, (_, c) => c.toUpperCase());
199
199
  let result = content;
200
200
  result = result.replace(/\{\{name\}\}/g, () => kebab);
201
201
  result = result.replace(/\{\{Name\}\}/g, () => pascal);
@@ -207,6 +207,7 @@ function substituteVars(content, name, vars) {
207
207
  }
208
208
 
209
209
  export {
210
+ BUILT_IN_TEMPLATES,
210
211
  scaffoldTool
211
212
  };
212
- //# sourceMappingURL=chunk-2OXHS3KZ.js.map
213
+ //# sourceMappingURL=chunk-KLJZ4WV4.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  todoTool
3
- } from "./chunk-BK732J7I.js";
3
+ } from "./chunk-FBUP524S.js";
4
4
  import {
5
5
  mirrorSessionTasksToKanban
6
6
  } from "./chunk-X6KXNHUO.js";
@@ -17,13 +17,13 @@ import {
17
17
  import { ToolValidationError } from "@wrongstack/core/types";
18
18
  import { computeTaskItemProgress, formatTaskList } from "@wrongstack/core/utils";
19
19
  function findTaskIndex(tasks, query) {
20
- const asNum = Number.parseInt(query, 10);
21
- if (!Number.isNaN(asNum)) {
22
- const idx = asNum - 1;
23
- if (tasks[idx]) return idx;
24
- }
25
20
  const byId = tasks.findIndex((t) => t.id === query);
26
21
  if (byId >= 0) return byId;
22
+ const trimmed = query.trim();
23
+ if (/^[1-9]\d*$/.test(trimmed)) {
24
+ const idx = Number.parseInt(trimmed, 10) - 1;
25
+ if (tasks[idx]) return idx;
26
+ }
27
27
  const lower = query.toLowerCase();
28
28
  return tasks.findIndex((t) => t.title.toLowerCase().includes(lower));
29
29
  }
@@ -384,7 +384,7 @@ var taskTool = {
384
384
  break;
385
385
  }
386
386
  case "promote": {
387
- const target = input.target?.trim();
387
+ const target = (input.target ?? input.id)?.trim();
388
388
  if (!target) {
389
389
  early = {
390
390
  ok: false,
@@ -438,11 +438,12 @@ var taskTool = {
438
438
  promotedFromTask: match.id
439
439
  });
440
440
  }
441
- if (input.subtasks && input.subtasks.length > 0) {
441
+ if (Array.isArray(input.subtasks) && input.subtasks.length > 0) {
442
442
  for (const st of input.subtasks) {
443
+ if (typeof st !== "string" || !st.trim()) continue;
443
444
  todos.push({
444
445
  id: `todo_${ts}_${randomUUID().slice(0, 6)}`,
445
- content: st,
446
+ content: st.trim(),
446
447
  status: "pending",
447
448
  promotedFromTask: match.id
448
449
  });
@@ -454,7 +455,7 @@ var taskTool = {
454
455
  break;
455
456
  }
456
457
  case "planify": {
457
- const target = input.target?.trim();
458
+ const target = (input.target ?? input.id)?.trim();
458
459
  if (!target) {
459
460
  early = {
460
461
  ok: false,
@@ -581,4 +582,4 @@ ${formatTaskList(file.tasks)}` : file.tasks.length > 0 ? formatTaskList(file.tas
581
582
  export {
582
583
  taskTool
583
584
  };
584
- //# sourceMappingURL=chunk-3M7LLN7W.js.map
585
+ //# sourceMappingURL=chunk-LQSOU63Z.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  builtinTools
3
- } from "./chunk-OTINMOKK.js";
3
+ } from "./chunk-AB2CAUOP.js";
4
4
 
5
5
  // src/pack.ts
6
6
  var builtinToolsPack = {
@@ -12,4 +12,4 @@ var builtinToolsPack = {
12
12
  export {
13
13
  builtinToolsPack
14
14
  };
15
- //# sourceMappingURL=chunk-DC4KMPJO.js.map
15
+ //# sourceMappingURL=chunk-M6UV67BH.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
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getIndexState,
3
3
  searchCodebaseIndex
4
- } from "./chunk-DP6CXMJZ.js";
4
+ } from "./chunk-ZTCJCYLN.js";
5
5
  import {
6
6
  codebaseIndexDirOverride
7
- } from "./chunk-KY4PXYSO.js";
7
+ } from "./chunk-N3K2SFEI.js";
8
8
  import {
9
9
  isBinaryBuffer,
10
10
  safeResolveReal,
@@ -71,7 +71,7 @@ var readTool = {
71
71
  const signal = execOpts?.signal ?? ctx?.signal;
72
72
  signal?.throwIfAborted();
73
73
  const absPath = await safeResolveReal(input.path, ctx);
74
- const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta[ADVANCED_MODE_META_KEY] === true;
74
+ const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta?.[ADVANCED_MODE_META_KEY] === true;
75
75
  let stat2;
76
76
  try {
77
77
  stat2 = await fs.stat(absPath);
@@ -109,12 +109,14 @@ var readTool = {
109
109
  context: { size: stat2.size, limit: MAX_BYTES, reason: "too-large" }
110
110
  });
111
111
  }
112
- const offset = Math.max(1, input.offset ?? 1);
113
- const limit = Math.max(0, Math.min(input.limit ?? 2e3, 5e3));
112
+ const rawOffset = typeof input.offset === "number" && Number.isFinite(input.offset) ? input.offset : 1;
113
+ const offset = Math.max(1, Math.floor(rawOffset));
114
+ const rawLimit = typeof input.limit === "number" && Number.isFinite(input.limit) ? input.limit : 2e3;
115
+ const limit = Math.max(0, Math.min(Math.floor(rawLimit), 5e3));
114
116
  const prior = getReadRangeRecord(ctx, absPath);
115
117
  const requestedEnd = prior ? Math.min(offset + limit - 1, prior.totalLines) : offset + limit - 1;
116
118
  if (input.mode !== "summary" && limit > 0 && prior && offset <= requestedEnd && coversRange(prior, stat2.mtimeMs, stat2.size, offset, requestedEnd)) {
117
- ctx.recordRead(absPath, stat2.mtimeMs, "user", ctx.lastReadHash?.(absPath));
119
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", ctx.lastReadHash?.(absPath));
118
120
  const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
119
121
  return {
120
122
  text: `[unchanged since previous read: "${input.path}" mtime=${Math.round(stat2.mtimeMs)}; requested lines ${offset}-${requestedEnd} were already shown. Use offset/limit for a new range if needed.]`,
@@ -138,10 +140,22 @@ var readTool = {
138
140
  }
139
141
  const text = buf.toString("utf8");
140
142
  const contentHash = sha256hex(text);
141
- const allLines = text.split(/\r?\n/);
143
+ const allLines = text.length === 0 ? [] : text.split(/\r?\n/);
142
144
  const total = allLines.length;
145
+ if (total === 0) {
146
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", contentHash);
147
+ const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
148
+ return {
149
+ text: "",
150
+ total_lines: 0,
151
+ encoding: "utf8",
152
+ truncated: false,
153
+ ...symResult2?.symbols ? { symbols: symResult2.symbols } : {},
154
+ ...symResult2?.note ? { note: symResult2.note } : {}
155
+ };
156
+ }
143
157
  if (input.mode === "summary") {
144
- ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
158
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", contentHash);
145
159
  rememberReadRange(ctx, absPath, stat2.mtimeMs, stat2.size, total, 1, Math.min(total, 200));
146
160
  const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
147
161
  const summary = summarizeFile(input.path, stat2.size, allLines);
@@ -158,7 +172,7 @@ var readTool = {
158
172
  };
159
173
  }
160
174
  if (limit === 0) {
161
- ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
175
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", contentHash);
162
176
  rememberReadRange(ctx, absPath, stat2.mtimeMs, stat2.size, total, 1, 0);
163
177
  const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
164
178
  return {
@@ -171,7 +185,7 @@ var readTool = {
171
185
  };
172
186
  }
173
187
  if (offset > total) {
174
- ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
188
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", contentHash);
175
189
  const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, signal) : void 0;
176
190
  return {
177
191
  text: `[offset ${offset} is past end of file "${input.path}" \u2014 file has ${total} line(s). Do not retry this offset.]`,
@@ -194,7 +208,7 @@ var readTool = {
194
208
  parts[i] = `${pad}${numStr}\u2192${slice[i]}`;
195
209
  }
196
210
  const numbered = parts.join("\n");
197
- ctx.recordRead(absPath, stat2.mtimeMs, "user", contentHash);
211
+ ctx.recordRead?.(absPath, stat2.mtimeMs, "user", contentHash);
198
212
  rememberReadRange(
199
213
  ctx,
200
214
  absPath,
@@ -253,6 +267,9 @@ function mergeSymbolNote(note, symNote) {
253
267
  }
254
268
  var READ_RANGES_META_KEY = "tools.read.ranges.v1";
255
269
  function getReadRanges(ctx) {
270
+ if (!ctx.meta) {
271
+ ctx.meta = {};
272
+ }
256
273
  const existing = ctx.meta[READ_RANGES_META_KEY];
257
274
  if (existing && typeof existing === "object" && !Array.isArray(existing)) {
258
275
  return existing;
@@ -323,4 +340,4 @@ ${interesting.join("\n")}` : "symbols/imports: (none detected)"
323
340
  export {
324
341
  readTool
325
342
  };
326
- //# sourceMappingURL=chunk-RNWUCZ2U.js.map
343
+ //# sourceMappingURL=chunk-MK2JK35J.js.map
@@ -12,11 +12,12 @@ function loadTypescript() {
12
12
  return tsLoad;
13
13
  }
14
14
  async function checkSyntax(filePath, content, previousContent) {
15
+ if (typeof filePath !== "string" || typeof content !== "string") return void 0;
15
16
  const errors = await parseErrors(filePath, content);
16
17
  if (errors === void 0) return void 0;
17
18
  if (errors.length === 0) return { errors, preExisting: false };
18
19
  let preExisting = false;
19
- if (previousContent !== void 0) {
20
+ if (typeof previousContent === "string") {
20
21
  const prevErrors = await parseErrors(filePath, previousContent);
21
22
  preExisting = prevErrors !== void 0 && prevErrors.length > 0;
22
23
  }
@@ -86,4 +87,4 @@ function formatDiag(ts, diag, content, sourceFile) {
86
87
  export {
87
88
  checkSyntax
88
89
  };
89
- //# sourceMappingURL=chunk-FQZOHLG3.js.map
90
+ //# sourceMappingURL=chunk-MSOAX3GC.js.map