@wrongstack/plugins 0.293.0 → 0.295.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 (211) hide show
  1. package/README.md +7 -71
  2. package/dist/accessibility-auditor/index.d.ts +1 -1
  3. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  4. package/dist/accessibility-auditor.js +50 -33
  5. package/dist/agent-handoff/index.d.ts +1 -1
  6. package/dist/agent-handoff/index.d.ts.map +1 -1
  7. package/dist/agent-handoff.js +30 -1
  8. package/dist/api-compatibility-gate/index.d.ts +1 -1
  9. package/dist/api-compatibility-gate/index.d.ts.map +1 -1
  10. package/dist/api-compatibility-gate.js +21 -16
  11. package/dist/audit/index.d.ts +386 -0
  12. package/dist/audit/index.d.ts.map +1 -0
  13. package/dist/audit.d.ts +1 -0
  14. package/dist/audit.js +454 -0
  15. package/dist/auto-doc/index.d.ts +1 -1
  16. package/dist/auto-doc/index.d.ts.map +1 -1
  17. package/dist/auto-doc.js +3 -1
  18. package/dist/auto-escalate/index.d.ts +1 -1
  19. package/dist/auto-escalate/index.d.ts.map +1 -1
  20. package/dist/auto-i18n-extractor/index.d.ts +1 -1
  21. package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
  22. package/dist/auto-i18n-extractor.js +7 -1
  23. package/dist/branch-guard/index.d.ts +1 -1
  24. package/dist/branch-guard/index.d.ts.map +1 -1
  25. package/dist/branch-guard.js +111 -1
  26. package/dist/catalog.d.ts +5 -30
  27. package/dist/catalog.d.ts.map +1 -1
  28. package/dist/changelog-writer/index.d.ts +1 -1
  29. package/dist/changelog-writer/index.d.ts.map +1 -1
  30. package/dist/changelog-writer.js +137 -3
  31. package/dist/checkpoint/index.d.ts +3 -1
  32. package/dist/checkpoint/index.d.ts.map +1 -1
  33. package/dist/checkpoint.js +41 -16
  34. package/dist/code-metrics/index.d.ts +1 -1
  35. package/dist/code-metrics/index.d.ts.map +1 -1
  36. package/dist/code-metrics.js +34 -29
  37. package/dist/commit-validator/index.d.ts +1 -1
  38. package/dist/commit-validator/index.d.ts.map +1 -1
  39. package/dist/commit-validator.js +17 -7
  40. package/dist/config-validator/index.d.ts +1 -1
  41. package/dist/config-validator/index.d.ts.map +1 -1
  42. package/dist/context-pins/index.d.ts +1 -1
  43. package/dist/context-pins/index.d.ts.map +1 -1
  44. package/dist/context-pins.js +6 -5
  45. package/dist/cost-tracker/index.d.ts +1 -1
  46. package/dist/cost-tracker/index.d.ts.map +1 -1
  47. package/dist/cost-tracker.js +109 -2
  48. package/dist/cron/index.d.ts +1 -1
  49. package/dist/cron/index.d.ts.map +1 -1
  50. package/dist/cron.js +1 -0
  51. package/dist/dead-code-detector/index.d.ts +1 -1
  52. package/dist/dead-code-detector/index.d.ts.map +1 -1
  53. package/dist/dead-code-detector.js +31 -18
  54. package/dist/dep-guard/index.d.ts +1 -1
  55. package/dist/dep-guard/index.d.ts.map +1 -1
  56. package/dist/dependency-vulnerability-gate/index.d.ts +1 -1
  57. package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -1
  58. package/dist/dependency-vulnerability-gate.js +67 -20
  59. package/dist/diff-summary/index.d.ts +1 -1
  60. package/dist/diff-summary/index.d.ts.map +1 -1
  61. package/dist/diff-summary.js +128 -30
  62. package/dist/doc-sync-guard/index.d.ts +1 -1
  63. package/dist/doc-sync-guard/index.d.ts.map +1 -1
  64. package/dist/doc-sync-guard.js +7 -1
  65. package/dist/duplicate-code-detector/index.d.ts +26 -1
  66. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  67. package/dist/duplicate-code-detector.js +280 -69
  68. package/dist/error-lens/index.d.ts +1 -1
  69. package/dist/error-lens/index.d.ts.map +1 -1
  70. package/dist/factories/index.d.ts +4 -0
  71. package/dist/factories/index.d.ts.map +1 -0
  72. package/dist/factories.d.ts +1 -0
  73. package/dist/factories.js +74 -0
  74. package/dist/feature-flag-tracker/index.d.ts +1 -1
  75. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  76. package/dist/feature-flag-tracker.js +59 -33
  77. package/dist/file-watcher/index.d.ts +1 -1
  78. package/dist/file-watcher/index.d.ts.map +1 -1
  79. package/dist/file-watcher.js +6 -7
  80. package/dist/format-on-save/index.d.ts +3 -1
  81. package/dist/format-on-save/index.d.ts.map +1 -1
  82. package/dist/format-on-save.js +289 -59
  83. package/dist/generated-plugin-exports.d.ts +65 -0
  84. package/dist/generated-plugin-exports.d.ts.map +1 -0
  85. package/dist/git-autocommit/index.d.ts +1 -1
  86. package/dist/git-autocommit/index.d.ts.map +1 -1
  87. package/dist/import-organizer/index.d.ts +1 -1
  88. package/dist/import-organizer/index.d.ts.map +1 -1
  89. package/dist/import-organizer.js +141 -20
  90. package/dist/index.d.ts +4 -183
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +18298 -17279
  93. package/dist/injection-shield/index.d.ts +1 -1
  94. package/dist/injection-shield/index.d.ts.map +1 -1
  95. package/dist/interface-contract-guard/index.d.ts +1 -1
  96. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  97. package/dist/interface-contract-guard.js +87 -53
  98. package/dist/knowledge-graph/index.d.ts +1 -1
  99. package/dist/knowledge-graph/index.d.ts.map +1 -1
  100. package/dist/knowledge-graph.js +7 -6
  101. package/dist/license-audit-gate/index.d.ts +1 -1
  102. package/dist/license-audit-gate/index.d.ts.map +1 -1
  103. package/dist/lint-gate/index.d.ts +1 -1
  104. package/dist/lint-gate/index.d.ts.map +1 -1
  105. package/dist/lint-gate.js +112 -1
  106. package/dist/llm-cache/index.d.ts +5 -1
  107. package/dist/llm-cache/index.d.ts.map +1 -1
  108. package/dist/llm-cache.js +16 -8
  109. package/dist/loop-breaker/index.d.ts +1 -1
  110. package/dist/loop-breaker/index.d.ts.map +1 -1
  111. package/dist/loop-breaker.js +25 -9
  112. package/dist/manifest/index.d.ts +16 -0
  113. package/dist/manifest/index.d.ts.map +1 -0
  114. package/dist/manifest.d.ts +1 -0
  115. package/dist/manifest.js +152 -0
  116. package/dist/migration-planner/index.d.ts +1 -1
  117. package/dist/migration-planner/index.d.ts.map +1 -1
  118. package/dist/migration-planner.js +5 -1
  119. package/dist/model-router/index.d.ts +1 -1
  120. package/dist/model-router/index.d.ts.map +1 -1
  121. package/dist/notify-hub/index.d.ts +1 -1
  122. package/dist/notify-hub/index.d.ts.map +1 -1
  123. package/dist/notify-hub/webhook-channel.d.ts +1 -1
  124. package/dist/notify-hub/webhook-channel.d.ts.map +1 -1
  125. package/dist/notify-hub.js +41 -4
  126. package/dist/path-guard/index.d.ts +1 -1
  127. package/dist/path-guard/index.d.ts.map +1 -1
  128. package/dist/performance-regression-gate/index.d.ts +1 -1
  129. package/dist/performance-regression-gate/index.d.ts.map +1 -1
  130. package/dist/plugin-stack-observer/index.d.ts +1 -1
  131. package/dist/plugin-stack-observer/index.d.ts.map +1 -1
  132. package/dist/pr-drafter/index.d.ts +1 -1
  133. package/dist/pr-drafter/index.d.ts.map +1 -1
  134. package/dist/pr-drafter.js +28 -29
  135. package/dist/process-guard/index.d.ts +1 -1
  136. package/dist/process-guard/index.d.ts.map +1 -1
  137. package/dist/prompt-firewall/index.d.ts +1 -1
  138. package/dist/prompt-firewall/index.d.ts.map +1 -1
  139. package/dist/prompt-firewall.js +140 -11
  140. package/dist/refactor-suggester/index.d.ts +1 -1
  141. package/dist/refactor-suggester/index.d.ts.map +1 -1
  142. package/dist/refactor-suggester.js +148 -33
  143. package/dist/release-notes-generator/index.d.ts +1 -1
  144. package/dist/release-notes-generator/index.d.ts.map +1 -1
  145. package/dist/release-notes-generator.js +29 -22
  146. package/dist/runtime/bounded-map.d.ts +86 -0
  147. package/dist/runtime/bounded-map.d.ts.map +1 -0
  148. package/dist/runtime/credential-patterns.d.ts +42 -0
  149. package/dist/runtime/credential-patterns.d.ts.map +1 -0
  150. package/dist/runtime/index.d.ts +18 -0
  151. package/dist/runtime/index.d.ts.map +1 -1
  152. package/dist/runtime/llm.d.ts +1 -1
  153. package/dist/runtime/llm.d.ts.map +1 -1
  154. package/dist/runtime/local-bin.d.ts +120 -0
  155. package/dist/runtime/local-bin.d.ts.map +1 -0
  156. package/dist/runtime/safe-json.d.ts +25 -0
  157. package/dist/runtime/safe-json.d.ts.map +1 -0
  158. package/dist/runtime.js +332 -22
  159. package/dist/schema-evolution-guard/index.d.ts +1 -1
  160. package/dist/schema-evolution-guard/index.d.ts.map +1 -1
  161. package/dist/schema-evolution-guard.js +7 -1
  162. package/dist/secret-scanner/index.d.ts +1 -1
  163. package/dist/secret-scanner/index.d.ts.map +1 -1
  164. package/dist/secret-scanner.js +181 -48
  165. package/dist/security-hotspot-scanner/index.d.ts +1 -1
  166. package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
  167. package/dist/security-hotspot-scanner.js +158 -20
  168. package/dist/semantic-search-indexer/index.d.ts +1 -1
  169. package/dist/semantic-search-indexer/index.d.ts.map +1 -1
  170. package/dist/semantic-search-indexer.js +7 -1
  171. package/dist/semver-bump/index.d.ts +1 -1
  172. package/dist/semver-bump/index.d.ts.map +1 -1
  173. package/dist/semver-bump.js +97 -43
  174. package/dist/session-recap/index.d.ts +1 -1
  175. package/dist/session-recap/index.d.ts.map +1 -1
  176. package/dist/shell-check/index.d.ts +1 -1
  177. package/dist/shell-check/index.d.ts.map +1 -1
  178. package/dist/smart-rename/index.d.ts +1 -1
  179. package/dist/smart-rename/index.d.ts.map +1 -1
  180. package/dist/spec-linker/index.d.ts +1 -1
  181. package/dist/spec-linker/index.d.ts.map +1 -1
  182. package/dist/spec-linker.js +222 -20772
  183. package/dist/template-engine/index.d.ts +1 -1
  184. package/dist/template-engine/index.d.ts.map +1 -1
  185. package/dist/template-engine.js +34 -8
  186. package/dist/test-coverage-gate/index.d.ts +1 -1
  187. package/dist/test-coverage-gate/index.d.ts.map +1 -1
  188. package/dist/test-coverage-gate.js +34 -14
  189. package/dist/test-flake-detector/index.d.ts +1 -1
  190. package/dist/test-flake-detector/index.d.ts.map +1 -1
  191. package/dist/test-flake-detector.js +31 -20
  192. package/dist/test-generator/index.d.ts +1 -1
  193. package/dist/test-generator/index.d.ts.map +1 -1
  194. package/dist/test-runner-gate/index.d.ts +1 -1
  195. package/dist/test-runner-gate/index.d.ts.map +1 -1
  196. package/dist/test-runner-gate.js +132 -9
  197. package/dist/todo-listener/index.d.ts +1 -32
  198. package/dist/todo-listener/index.d.ts.map +1 -1
  199. package/dist/todo-listener.js +30 -1
  200. package/dist/todo-tracker/index.d.ts +1 -1
  201. package/dist/todo-tracker/index.d.ts.map +1 -1
  202. package/dist/todo-tracker.js +3 -4
  203. package/dist/token-budget/index.d.ts +1 -1
  204. package/dist/token-budget/index.d.ts.map +1 -1
  205. package/dist/token-throttle/index.d.ts +1 -1
  206. package/dist/token-throttle/index.d.ts.map +1 -1
  207. package/dist/token-throttle.js +17 -2
  208. package/dist/type-gate/index.d.ts +1 -1
  209. package/dist/type-gate/index.d.ts.map +1 -1
  210. package/dist/type-gate.js +106 -19
  211. package/package.json +80 -68
@@ -1,6 +1,24 @@
1
1
  // src/dependency-vulnerability-gate/index.ts
2
- import { execFileSync } from "node:child_process";
3
- import { existsSync } from "node:fs";
2
+ import { execFile } from "node:child_process";
3
+ import { access } from "node:fs/promises";
4
+
5
+ // src/runtime/local-bin.ts
6
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
7
+ function resolveExecInvocation(command, args = []) {
8
+ const resolved = resolveWin32Command(command);
9
+ const normalizedResolved = resolved.toLowerCase();
10
+ const needsShell = process.platform === "win32" && (normalizedResolved.endsWith(".cmd") || normalizedResolved.endsWith(".bat"));
11
+ if (needsShell) {
12
+ const shim = buildWin32CmdShimInvocation(resolved, args);
13
+ return { cmd: shim.command, args: shim.args, windowsVerbatimArguments: true };
14
+ }
15
+ return { cmd: resolved, args: [...args], windowsVerbatimArguments: false };
16
+ }
17
+
18
+ // src/runtime/index.ts
19
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
20
+
21
+ // src/dependency-vulnerability-gate/index.ts
4
22
  var API_VERSION = "^0.1.10";
5
23
  var state = {
6
24
  invocations: 0,
@@ -112,26 +130,55 @@ function isInstallCommand(input) {
112
130
  const command = typeof ti["command"] === "string" ? ti["command"] : "";
113
131
  return INSTALL_RE.test(command);
114
132
  }
115
- function detectManager() {
116
- return existsSync("pnpm-lock.yaml") ? "pnpm" : "npm";
133
+ var LOCKFILE_MANAGERS = [
134
+ { file: "pnpm-lock.yaml", manager: "pnpm" },
135
+ { file: "bun.lockb", manager: "bun" },
136
+ { file: "bun.lock", manager: "bun" },
137
+ { file: "yarn.lock", manager: "yarn" },
138
+ { file: "package-lock.json", manager: "npm" }
139
+ ];
140
+ async function detectManager() {
141
+ for (const { file, manager } of LOCKFILE_MANAGERS) {
142
+ try {
143
+ await access(file);
144
+ return manager;
145
+ } catch {
146
+ }
147
+ }
148
+ return "npm";
117
149
  }
118
- function runAudit(cfg) {
119
- const manager = detectManager();
150
+ async function runAudit(cfg) {
151
+ const manager = await detectManager();
120
152
  const start = Date.now();
121
- let stdout = "";
153
+ let invocation;
122
154
  try {
123
- stdout = execFileSync(manager, ["audit", "--json"], {
124
- encoding: "utf-8",
125
- timeout: cfg.timeoutMs,
126
- cwd: process.cwd(),
127
- stdio: ["pipe", "pipe", "pipe"],
128
- shell: false
129
- });
130
- } catch (err) {
131
- const e = err;
132
- if (e.killed) return null;
133
- stdout = e.stdout ?? "";
155
+ invocation = resolveExecInvocation(manager, ["audit", "--json"]);
156
+ } catch {
157
+ return null;
134
158
  }
159
+ const stdout = await new Promise((resolve) => {
160
+ execFile(
161
+ invocation.cmd,
162
+ invocation.args,
163
+ {
164
+ encoding: "utf8",
165
+ timeout: cfg.timeoutMs,
166
+ cwd: process.cwd(),
167
+ windowsHide: true,
168
+ maxBuffer: 10 * 1024 * 1024,
169
+ shell: false,
170
+ ...invocation.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
171
+ },
172
+ (error, output) => {
173
+ if (error && error.killed) {
174
+ resolve(null);
175
+ return;
176
+ }
177
+ resolve(output);
178
+ }
179
+ );
180
+ });
181
+ if (stdout === null) return null;
135
182
  const report = parseAuditJson(stdout);
136
183
  if (!report) return null;
137
184
  return { manager, report, durationMs: Date.now() - start };
@@ -186,14 +233,14 @@ var plugin = {
186
233
  state.hookUnregister = null;
187
234
  }
188
235
  const cfg = readConfig(api.config.extensions?.["dependency-vulnerability-gate"]);
189
- const hook = (input) => {
236
+ const hook = async (input) => {
190
237
  if (!cfg.enabled) return;
191
238
  state.invocations += 1;
192
239
  if (input.toolResult?.isError) return;
193
240
  if (!isInstallCommand(input)) return;
194
241
  state.installsSeen += 1;
195
242
  api.metrics.counter("installs_seen");
196
- const result = runAudit(cfg);
243
+ const result = await runAudit(cfg);
197
244
  if (!result) {
198
245
  state.errors += 1;
199
246
  return;
@@ -28,7 +28,7 @@
28
28
  *
29
29
  * @public
30
30
  */
31
- import type { Plugin } from '@wrongstack/core';
31
+ import type { Plugin } from '@wrongstack/core/types';
32
32
  declare const plugin: Plugin;
33
33
  export default plugin;
34
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff-summary/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwP/C,QAAA,MAAM,MAAM,EAAE,MA4Pb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff-summary/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA+PrD,QAAA,MAAM,MAAM,EAAE,MA4Pb,CAAC;eAEa,MAAM"}
@@ -1,8 +1,107 @@
1
1
  // src/diff-summary/index.ts
2
- import { execFileSync } from "node:child_process";
2
+ import { execFile } from "node:child_process";
3
3
 
4
4
  // src/runtime/index.ts
5
5
  import { basename, extname, isAbsolute, relative, resolve } from "node:path";
6
+
7
+ // src/runtime/local-bin.ts
8
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
9
+
10
+ // src/runtime/bounded-map.ts
11
+ var BoundedMap = class {
12
+ map = /* @__PURE__ */ new Map();
13
+ max;
14
+ ttlMs;
15
+ now;
16
+ /** Entries dropped to stay under `max`. Surfaced by plugin health(). */
17
+ evictions = 0;
18
+ constructor(options) {
19
+ const normalizedMax = Math.floor(options.max);
20
+ this.max = Number.isSafeInteger(normalizedMax) ? Math.max(1, normalizedMax) : 1;
21
+ this.ttlMs = options.ttlMs;
22
+ this.now = options.now ?? Date.now;
23
+ }
24
+ expired(entry) {
25
+ return this.ttlMs !== void 0 && this.now() - entry.storedAt > this.ttlMs;
26
+ }
27
+ get(key) {
28
+ const entry = this.map.get(key);
29
+ if (entry === void 0) return void 0;
30
+ if (this.expired(entry)) {
31
+ this.map.delete(key);
32
+ return void 0;
33
+ }
34
+ this.map.delete(key);
35
+ this.map.set(key, entry);
36
+ return entry.value;
37
+ }
38
+ /**
39
+ * Read without promoting the key to most-recently-used. Use for
40
+ * diagnostics that must not perturb the eviction order.
41
+ */
42
+ peek(key) {
43
+ const entry = this.map.get(key);
44
+ if (entry === void 0 || this.expired(entry)) return void 0;
45
+ return entry.value;
46
+ }
47
+ has(key) {
48
+ const entry = this.map.get(key);
49
+ if (entry === void 0) return false;
50
+ if (this.expired(entry)) {
51
+ this.map.delete(key);
52
+ return false;
53
+ }
54
+ return true;
55
+ }
56
+ set(key, value) {
57
+ this.map.delete(key);
58
+ this.map.set(key, { value, storedAt: this.now() });
59
+ while (this.map.size > this.max) {
60
+ const coldest = this.map.keys().next().value;
61
+ if (coldest === void 0) break;
62
+ this.map.delete(coldest);
63
+ this.evictions += 1;
64
+ }
65
+ return this;
66
+ }
67
+ delete(key) {
68
+ return this.map.delete(key);
69
+ }
70
+ clear() {
71
+ this.map.clear();
72
+ this.evictions = 0;
73
+ }
74
+ get size() {
75
+ return this.map.size;
76
+ }
77
+ /** How many entries have been dropped to respect `max`, since the last clear. */
78
+ get evictionCount() {
79
+ return this.evictions;
80
+ }
81
+ /** Drop every expired entry. Cheap enough to call from a status tool. */
82
+ prune() {
83
+ if (this.ttlMs === void 0) return 0;
84
+ let removed = 0;
85
+ for (const [key, entry] of this.map) {
86
+ if (this.expired(entry)) {
87
+ this.map.delete(key);
88
+ removed += 1;
89
+ }
90
+ }
91
+ return removed;
92
+ }
93
+ /** Live (non-expired) entries, coldest first. */
94
+ *entries() {
95
+ for (const [key, entry] of this.map) {
96
+ if (!this.expired(entry)) yield [key, entry.value];
97
+ }
98
+ }
99
+ [Symbol.iterator]() {
100
+ return this.entries();
101
+ }
102
+ };
103
+
104
+ // src/runtime/index.ts
6
105
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
7
106
  function hasLeadingDash(arg) {
8
107
  return arg.length > 0 && arg.startsWith("-");
@@ -15,7 +114,8 @@ function withinProjectPath(projectRoot, candidate) {
15
114
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
16
115
  }
17
116
  function withinProject(p) {
18
- return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
117
+ const cwd = process.cwd();
118
+ return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
19
119
  }
20
120
 
21
121
  // src/diff-summary/index.ts
@@ -63,37 +163,35 @@ function contentHash(s) {
63
163
  }
64
164
  return h >>> 0;
65
165
  }
66
- var pathMemo = /* @__PURE__ */ new Map();
67
- function getGitDiff(filePath, contextLines, cwd) {
68
- const opts = {
69
- encoding: "utf-8",
70
- timeout: 3e3,
71
- cwd,
72
- stdio: ["pipe", "pipe", "pipe"]
73
- };
74
- let isTracked = false;
75
- try {
76
- execFileSync("git", ["ls-files", "--error-unmatch", "--", filePath], opts);
77
- isTracked = true;
78
- } catch {
79
- isTracked = false;
80
- }
166
+ var pathMemo = new BoundedMap({ max: 512 });
167
+ function runGit(args, cwd) {
168
+ return new Promise((resolveCommand) => {
169
+ execFile(
170
+ "git",
171
+ args,
172
+ {
173
+ encoding: "utf8",
174
+ timeout: 3e3,
175
+ cwd,
176
+ windowsHide: true,
177
+ maxBuffer: 5 * 1024 * 1024
178
+ },
179
+ (error, stdout) => resolveCommand({ ok: !error, stdout })
180
+ );
181
+ });
182
+ }
183
+ async function getGitDiff(filePath, contextLines, cwd) {
184
+ const tracked = await runGit(["ls-files", "--error-unmatch", "--", filePath], cwd);
185
+ const isTracked = tracked.ok;
81
186
  try {
82
187
  let rawDiff;
83
188
  const contextFlag = `-U${contextLines}`;
84
189
  if (isTracked) {
85
- rawDiff = execFileSync("git", ["diff", contextFlag, "--", filePath], opts);
190
+ const result = await runGit(["diff", contextFlag, "--", filePath], cwd);
191
+ if (!result.ok) return null;
192
+ rawDiff = result.stdout;
86
193
  } else {
87
- try {
88
- rawDiff = execFileSync(
89
- "git",
90
- ["diff", "--no-index", contextFlag, "/dev/null", filePath],
91
- opts
92
- );
93
- } catch (err) {
94
- const e = err;
95
- rawDiff = e.stdout ?? "";
96
- }
194
+ rawDiff = (await runGit(["diff", "--no-index", contextFlag, "/dev/null", filePath], cwd)).stdout;
97
195
  }
98
196
  if (!rawDiff.trim()) {
99
197
  return { diff: "", added: 0, removed: 0, isNewFile: !isTracked };
@@ -185,7 +283,7 @@ var plugin = {
185
283
  pathMemo.clear();
186
284
  const cfg = readConfig(api.config.extensions?.["diff-summary"]);
187
285
  const cwd = typeof process.cwd === "function" ? process.cwd() : void 0;
188
- const hook = (input) => {
286
+ const hook = async (input) => {
189
287
  if (cfg.mode === "off") return;
190
288
  if (input.toolResult?.isError) return;
191
289
  const toolName = input.toolName ?? "";
@@ -212,7 +310,7 @@ var plugin = {
212
310
  return;
213
311
  }
214
312
  }
215
- const result = getGitDiff(filePath, cfg.includeContext, cwd);
313
+ const result = await getGitDiff(filePath, cfg.includeContext, cwd);
216
314
  if (!result) {
217
315
  state.fallbackCount += 1;
218
316
  return;
@@ -25,7 +25,7 @@
25
25
  *
26
26
  * @public
27
27
  */
28
- import type { Plugin } from '@wrongstack/core';
28
+ import type { Plugin } from '@wrongstack/core/types';
29
29
  declare const plugin: Plugin;
30
30
  export default plugin;
31
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doc-sync-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA0I/C,QAAA,MAAM,MAAM,EAAE,MAuJb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doc-sync-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA0IrD,QAAA,MAAM,MAAM,EAAE,MAuJb,CAAC;eAEa,MAAM"}
@@ -3,6 +3,11 @@ import { basename as basename2, extname as extname2 } from "node:path";
3
3
 
4
4
  // src/runtime/index.ts
5
5
  import { basename, extname, isAbsolute, relative, resolve } from "node:path";
6
+
7
+ // src/runtime/local-bin.ts
8
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
9
+
10
+ // src/runtime/index.ts
6
11
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
7
12
  function hasLeadingDash(arg) {
8
13
  return arg.length > 0 && arg.startsWith("-");
@@ -15,7 +20,8 @@ function withinProjectPath(projectRoot, candidate) {
15
20
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
16
21
  }
17
22
  function withinProject(p) {
18
- return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
23
+ const cwd = process.cwd();
24
+ return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
19
25
  }
20
26
 
21
27
  // src/doc-sync-guard/index.ts
@@ -25,7 +25,32 @@
25
25
  *
26
26
  * @public
27
27
  */
28
- import type { Plugin } from '@wrongstack/core';
28
+ import type { Plugin } from '@wrongstack/core/types';
29
+ /**
30
+ * Tunable budgets that bound the hook fingerprint index. Keeping the defaults
31
+ * together makes the file, fingerprint, and byte limits explicit.
32
+ */
33
+ export declare const hookIndexBudgets: {
34
+ /** Max number of files retained in the hook fingerprint index (LRU-evicted). */
35
+ maxFiles: number;
36
+ /** Max total fingerprints across the whole index (running-sum enforced, LRU-evicted). */
37
+ maxFingerprints: number;
38
+ /**
39
+ * Max candidate windows hashed and cached per file by the advisory hook. The
40
+ * on-demand detect_duplicate_code tool intentionally scans every window.
41
+ */
42
+ maxFingerprintsPerFile: number;
43
+ /** Files larger than this are skipped entirely by the hook (never read/extracted/cached). */
44
+ maxFileBytes: number;
45
+ };
46
+ /**
47
+ * Compact 53-bit hash of a fingerprint string. The hook index can retain up to
48
+ * 300k fingerprints, where a 32-bit hash has a material birthday-collision risk
49
+ * and can emit a false duplicate warning. The result remains a JS-safe integer,
50
+ * so the index keeps the compact `Set<number>` representation instead of storing
51
+ * raw fingerprint text.
52
+ */
53
+ export declare function hashFingerprint(fp: string): number;
29
54
  declare const plugin: Plugin;
30
55
  export default plugin;
31
56
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/duplicate-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAiN/C,QAAA,MAAM,MAAM,EAAE,MAySb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/duplicate-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AA8FrD;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B,gFAAgF;IAChF,QAAQ;IACR,yFAAyF;IACzF,eAAe;IACf;;;OAGG;IACH,sBAAsB;IACtB,6FAA6F;IAC7F,YAAY;CACb,CAAC;AAyGF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAelD;AA4HD,QAAA,MAAM,MAAM,EAAE,MA4Wb,CAAC;eAEa,MAAM"}