@wrongstack/plugins 0.286.0 → 0.287.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 (65) hide show
  1. package/README.md +20 -11
  2. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  3. package/dist/accessibility-auditor.js +25 -16
  4. package/dist/api-compatibility-gate.js +1 -1
  5. package/dist/auto-doc.js +1 -1
  6. package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
  7. package/dist/auto-i18n-extractor.js +20 -12
  8. package/dist/changelog-writer.js +1 -1
  9. package/dist/code-metrics/index.d.ts.map +1 -1
  10. package/dist/code-metrics.js +26 -17
  11. package/dist/commit-validator.js +1 -1
  12. package/dist/config-validator.js +1 -1
  13. package/dist/cron/index.d.ts.map +1 -1
  14. package/dist/cron.js +29 -0
  15. package/dist/dead-code-detector/index.d.ts.map +1 -1
  16. package/dist/dead-code-detector.js +27 -18
  17. package/dist/dep-guard.js +1 -1
  18. package/dist/diff-summary/index.d.ts.map +1 -1
  19. package/dist/diff-summary.js +19 -11
  20. package/dist/doc-sync-guard/index.d.ts.map +1 -1
  21. package/dist/doc-sync-guard.js +24 -15
  22. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  23. package/dist/duplicate-code-detector.js +27 -18
  24. package/dist/error-lens.js +1 -1
  25. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  26. package/dist/feature-flag-tracker.js +26 -17
  27. package/dist/file-watcher/index.d.ts.map +1 -1
  28. package/dist/file-watcher.js +15 -2
  29. package/dist/format-on-save/index.d.ts.map +1 -1
  30. package/dist/format-on-save.js +19 -11
  31. package/dist/git-autocommit.js +1 -1
  32. package/dist/import-organizer/index.d.ts.map +1 -1
  33. package/dist/import-organizer.js +22 -13
  34. package/dist/index.d.ts +4 -4
  35. package/dist/index.js +961 -699
  36. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  37. package/dist/interface-contract-guard.js +26 -17
  38. package/dist/migration-planner/index.d.ts +12 -2
  39. package/dist/migration-planner/index.d.ts.map +1 -1
  40. package/dist/migration-planner.js +210 -28
  41. package/dist/pr-drafter.js +1 -1
  42. package/dist/refactor-suggester/index.d.ts.map +1 -1
  43. package/dist/refactor-suggester.js +26 -17
  44. package/dist/release-notes-generator/index.d.ts +3 -1
  45. package/dist/release-notes-generator/index.d.ts.map +1 -1
  46. package/dist/release-notes-generator.js +152 -12
  47. package/dist/runtime/index.d.ts +12 -0
  48. package/dist/runtime/index.d.ts.map +1 -1
  49. package/dist/runtime/llm.d.ts +33 -0
  50. package/dist/runtime/llm.d.ts.map +1 -0
  51. package/dist/runtime.js +56 -1
  52. package/dist/schema-evolution-guard/index.d.ts.map +1 -1
  53. package/dist/schema-evolution-guard.js +21 -12
  54. package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
  55. package/dist/security-hotspot-scanner.js +24 -15
  56. package/dist/session-recap.js +1 -1
  57. package/dist/spec-linker.js +961 -699
  58. package/dist/test-generator/index.d.ts +5 -3
  59. package/dist/test-generator/index.d.ts.map +1 -1
  60. package/dist/test-generator.js +169 -26
  61. package/dist/test-runner-gate/index.d.ts.map +1 -1
  62. package/dist/test-runner-gate.js +65 -43
  63. package/dist/type-gate/index.d.ts.map +1 -1
  64. package/dist/type-gate.js +4 -12
  65. package/package.json +3 -3
@@ -1,5 +1,24 @@
1
1
  // src/doc-sync-guard/index.ts
2
- import { isAbsolute, relative, resolve, basename, extname } from "node:path";
2
+ import { basename as basename2, extname } from "node:path";
3
+
4
+ // src/runtime/index.ts
5
+ import { basename, isAbsolute, relative, resolve } from "node:path";
6
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
7
+ function hasLeadingDash(arg) {
8
+ return arg.length > 0 && arg.startsWith("-");
9
+ }
10
+ function withinProjectPath(projectRoot, candidate) {
11
+ if (candidate.length === 0 || candidate.length > 4096) return false;
12
+ if (hasLeadingDash(candidate)) return false;
13
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
14
+ const rel = relative(projectRoot, resolved);
15
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
16
+ }
17
+ function withinProject(p) {
18
+ return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
19
+ }
20
+
21
+ // src/doc-sync-guard/index.ts
3
22
  var API_VERSION = "^0.1.10";
4
23
  var state = {
5
24
  changedFiles: [],
@@ -24,16 +43,6 @@ function readConfig(raw) {
24
43
  maxTrackedFiles: typeof r["maxTrackedFiles"] === "number" && r["maxTrackedFiles"] >= 1 && r["maxTrackedFiles"] <= 200 ? r["maxTrackedFiles"] : DEFAULTS.maxTrackedFiles
25
44
  };
26
45
  }
27
- function withinProject(p) {
28
- if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
29
- const root = process.cwd();
30
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
31
- const rel = relative(root, resolved);
32
- if (rel === "" || rel === ".") return true;
33
- if (rel.startsWith("..")) return false;
34
- if (isAbsolute(rel)) return false;
35
- return true;
36
- }
37
46
  function normalizeSlashes(p) {
38
47
  return p.replace(/\\/g, "/");
39
48
  }
@@ -45,14 +54,14 @@ function isPublicSource(p, extensions) {
45
54
  if (!isSourceFile(p, extensions)) return false;
46
55
  const norm = normalizeSlashes(p);
47
56
  if (norm.includes("/node_modules/") || norm.startsWith("node_modules/")) return false;
48
- const base = basename(norm).toLowerCase();
57
+ const base = basename2(norm).toLowerCase();
49
58
  if (/\.(test|spec)\./.test(base)) return false;
50
59
  if (base.startsWith("_")) return false;
51
60
  return true;
52
61
  }
53
62
  function isDocFile(p, docNames) {
54
63
  const norm = normalizeSlashes(p);
55
- const base = basename(norm);
64
+ const base = basename2(norm);
56
65
  const lowerBase = base.toLowerCase();
57
66
  if (docNames.some((name) => lowerBase === name.toLowerCase())) return true;
58
67
  if (norm.includes("/docs/") || norm.startsWith("docs/")) return true;
@@ -70,7 +79,7 @@ function extractDocContent(toolInput) {
70
79
  return void 0;
71
80
  }
72
81
  function referenceTokens(p) {
73
- const base = basename(p);
82
+ const base = basename2(p);
74
83
  const withoutExt = base.replace(/\.[^.]+$/, "");
75
84
  const tokens = [base];
76
85
  if (withoutExt && withoutExt !== base) tokens.push(withoutExt);
@@ -155,7 +164,7 @@ Consider mentioning these changes in the documentation.`;
155
164
  return { additionalContext: message };
156
165
  }
157
166
  };
158
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
167
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
159
168
  api.tools.register({
160
169
  name: "doc_sync_status",
161
170
  description: "Reports doc-sync-guard state: tracked changed files, doc-write count, and warning count.",
@@ -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;AAsP/C,QAAA,MAAM,MAAM,EAAE,MA8Qb,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,kBAAkB,CAAC;AA8O/C,QAAA,MAAM,MAAM,EAAE,MA8Qb,CAAC;eAEa,MAAM"}
@@ -1,6 +1,25 @@
1
1
  // src/duplicate-code-detector/index.ts
2
2
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
- import { extname, isAbsolute, relative, resolve } from "node:path";
3
+ import { extname, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
+
5
+ // src/runtime/index.ts
6
+ import { basename, isAbsolute, relative, resolve } from "node:path";
7
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
+ function hasLeadingDash(arg) {
9
+ return arg.length > 0 && arg.startsWith("-");
10
+ }
11
+ function withinProjectPath(projectRoot, candidate) {
12
+ if (candidate.length === 0 || candidate.length > 4096) return false;
13
+ if (hasLeadingDash(candidate)) return false;
14
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
15
+ const rel = relative(projectRoot, resolved);
16
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
17
+ }
18
+ function withinProject(p) {
19
+ return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
20
+ }
21
+
22
+ // src/duplicate-code-detector/index.ts
4
23
  var API_VERSION = "^0.1.10";
5
24
  var state = {
6
25
  scanCount: 0,
@@ -31,16 +50,6 @@ function readConfig(raw) {
31
50
  maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS.maxFindings
32
51
  };
33
52
  }
34
- function withinProject(p) {
35
- if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
36
- const root = process.cwd();
37
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
38
- const rel = relative(root, resolved);
39
- if (rel === "" || rel === ".") return true;
40
- if (rel.startsWith("..")) return false;
41
- if (isAbsolute(rel)) return false;
42
- return true;
43
- }
44
53
  function matchesExtension(p, exts) {
45
54
  const ext = extname(p).toLowerCase();
46
55
  return exts.includes(ext);
@@ -62,7 +71,7 @@ function collectSourceFiles(root, cfg) {
62
71
  return;
63
72
  }
64
73
  for (const entry of entries) {
65
- const full = resolve(dir, entry);
74
+ const full = resolve2(dir, entry);
66
75
  let st;
67
76
  try {
68
77
  st = statSync(full);
@@ -83,7 +92,7 @@ function toPosix(p) {
83
92
  return p.replace(/\\/g, "/");
84
93
  }
85
94
  function relativePath(p) {
86
- return toPosix(relative(process.cwd(), p));
95
+ return toPosix(relative2(process.cwd(), p));
87
96
  }
88
97
  function removeInlineComments(line) {
89
98
  return line.replace(/\/\/.*$/, "").replace(/\/\*[\s\S]*?\*\//, "");
@@ -141,7 +150,7 @@ function findDuplicates(files, minLines, maxFindings) {
141
150
  }
142
151
  function scanPath(rawPath, cfg) {
143
152
  const root = process.cwd();
144
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
153
+ const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
145
154
  const filePaths = collectSourceFiles(resolved, cfg);
146
155
  const files = /* @__PURE__ */ new Map();
147
156
  for (const p of filePaths) {
@@ -226,7 +235,7 @@ var plugin = {
226
235
  const now = Date.now();
227
236
  const lastWarning = state.lastHookWarning.get(sourcePath);
228
237
  if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
229
- const changedFile = resolve(process.cwd(), sourcePath);
238
+ const changedFile = resolve2(process.cwd(), sourcePath);
230
239
  let content;
231
240
  try {
232
241
  content = readFileSync(changedFile, "utf-8");
@@ -236,7 +245,7 @@ var plugin = {
236
245
  }
237
246
  const changedWindows = extractWindows(changedFile, content, cfg.minLines);
238
247
  if (changedWindows.length === 0) return;
239
- const projectRoot = resolve(process.cwd());
248
+ const projectRoot = resolve2(process.cwd());
240
249
  let otherFiles;
241
250
  try {
242
251
  const filePaths = collectSourceFiles(projectRoot, cfg).filter((p) => p !== changedFile);
@@ -272,7 +281,7 @@ var plugin = {
272
281
  contextAs: "separate"
273
282
  };
274
283
  };
275
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
284
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
276
285
  api.tools.register({
277
286
  name: "detect_duplicate_code",
278
287
  description: "Scan source files for duplicated code blocks. Uses normalized-line fingerprinting to find identical multi-line blocks across files.",
@@ -302,7 +311,7 @@ var plugin = {
302
311
  state.findingCount += result.findings.length;
303
312
  return {
304
313
  ok: true,
305
- path: relativePath(resolve(process.cwd(), rawPath)),
314
+ path: relativePath(resolve2(process.cwd(), rawPath)),
306
315
  scannedFiles: result.scannedFiles,
307
316
  minLines: cfg.minLines,
308
317
  findings: result.findings
@@ -85,7 +85,7 @@ var plugin = {
85
85
  version: "0.1.0",
86
86
  description: "Distills failed command output into a compact digest (error line + project stack frames) and flags repeated failures",
87
87
  apiVersion: "^0.1.10",
88
- capabilities: { tools: true, hooks: true },
88
+ capabilities: { tools: true, hooks: true, llm: true },
89
89
  defaultConfig: { ...DEFAULTS },
90
90
  configSchema: {
91
91
  type: "object",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feature-flag-tracker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ/C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AA6LD,QAAA,MAAM,MAAM,EAAE,MA+Mb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feature-flag-tracker/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAoLD,QAAA,MAAM,MAAM,EAAE,MA+Mb,CAAC;eAEa,MAAM"}
@@ -1,6 +1,25 @@
1
1
  // src/feature-flag-tracker/index.ts
2
2
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
- import { extname, isAbsolute, relative, resolve } from "node:path";
3
+ import { extname, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
+
5
+ // src/runtime/index.ts
6
+ import { basename, isAbsolute, relative, resolve } from "node:path";
7
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
+ function hasLeadingDash(arg) {
9
+ return arg.length > 0 && arg.startsWith("-");
10
+ }
11
+ function withinProjectPath(projectRoot, candidate) {
12
+ if (candidate.length === 0 || candidate.length > 4096) return false;
13
+ if (hasLeadingDash(candidate)) return false;
14
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
15
+ const rel = relative(projectRoot, resolved);
16
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
17
+ }
18
+ function withinProject(p) {
19
+ return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
20
+ }
21
+
22
+ // src/feature-flag-tracker/index.ts
4
23
  var API_VERSION = "^0.1.10";
5
24
  var state = {
6
25
  scanCount: 0,
@@ -32,16 +51,6 @@ function readConfig(raw) {
32
51
  maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS.maxFindings
33
52
  };
34
53
  }
35
- function withinProject(p) {
36
- if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
37
- const root = process.cwd();
38
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
39
- const rel = relative(root, resolved);
40
- if (rel === "" || rel === ".") return true;
41
- if (rel.startsWith("..")) return false;
42
- if (isAbsolute(rel)) return false;
43
- return true;
44
- }
45
54
  function normalizeExtensions(exts) {
46
55
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
47
56
  }
@@ -66,7 +75,7 @@ function collectSourceFiles(root, exts) {
66
75
  }
67
76
  for (const entry of entries) {
68
77
  if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
69
- const full = resolve(dir, entry);
78
+ const full = resolve2(dir, entry);
70
79
  let st;
71
80
  try {
72
81
  st = statSync(full);
@@ -87,7 +96,7 @@ function toPosix(p) {
87
96
  return p.replace(/\\/g, "/");
88
97
  }
89
98
  function relativePath(p) {
90
- return toPosix(relative(process.cwd(), p));
99
+ return toPosix(relative2(process.cwd(), p));
91
100
  }
92
101
  function compilePatterns(patterns) {
93
102
  const sources = [...DEFAULT_PATTERNS, ...patterns];
@@ -117,7 +126,7 @@ function scanFile(filePath, content, patterns, maxFindings) {
117
126
  }
118
127
  function scanPath(rawPath, cfg) {
119
128
  const root = process.cwd();
120
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
129
+ const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
121
130
  const exts = normalizeExtensions(cfg.extensions);
122
131
  const files = collectSourceFiles(resolved, exts);
123
132
  const patterns = compilePatterns(cfg.patterns);
@@ -188,7 +197,7 @@ var plugin = {
188
197
  const exts = normalizeExtensions(cfg.extensions);
189
198
  if (!matchesExtension(sourcePath, exts)) return;
190
199
  state.hookInvocationCount += 1;
191
- const resolved = resolve(process.cwd(), sourcePath);
200
+ const resolved = resolve2(process.cwd(), sourcePath);
192
201
  let content;
193
202
  try {
194
203
  content = readFileSync(resolved, "utf-8");
@@ -207,7 +216,7 @@ var plugin = {
207
216
  Make sure flag behavior is intentional and consider updating flag inventory/docs.`
208
217
  };
209
218
  };
210
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
219
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
211
220
  api.tools.register({
212
221
  name: "scan_feature_flags",
213
222
  description: "Scan source files for feature-flag-like expressions (isFeatureEnabled, featureFlags.*, useFeatureFlag, flags.*, plus custom patterns).",
@@ -237,7 +246,7 @@ Make sure flag behavior is intentional and consider updating flag inventory/docs
237
246
  state.flagCount += result.usages.length;
238
247
  return {
239
248
  ok: true,
240
- path: relativePath(resolve(process.cwd(), rawPath)),
249
+ path: relativePath(resolve2(process.cwd(), rawPath)),
241
250
  scannedFiles: result.scannedFiles,
242
251
  usages: result.usages
243
252
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file-watcher/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA2D/C,QAAA,MAAM,MAAM,EAAE,MAsWb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file-watcher/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA2D/C,QAAA,MAAM,MAAM,EAAE,MAqXb,CAAC;eAEa,MAAM"}
@@ -294,6 +294,7 @@ var plugin = {
294
294
  api.log.info("file-watcher plugin loaded", { version: "0.1.0" });
295
295
  },
296
296
  teardown(api) {
297
+ const closed = watches.size;
297
298
  for (const handle of watches.values()) {
298
299
  for (const w of handle.watchers) {
299
300
  try {
@@ -306,9 +307,21 @@ var plugin = {
306
307
  for (const t of debounceTimers.values()) clearTimeout(t);
307
308
  debounceTimers.clear();
308
309
  api.log.info("file-watcher: teardown complete", {
309
- closed: 0
310
- // recorded for log symmetry; actual count cleared above
310
+ closed
311
311
  });
312
+ },
313
+ async health() {
314
+ const watcherCount = Array.from(watches.values()).reduce(
315
+ (sum, handle) => sum + handle.watchers.length,
316
+ 0
317
+ );
318
+ return {
319
+ ok: true,
320
+ message: `file-watcher: ${watches.size} active watch group(s), ${watcherCount} filesystem watcher(s)`,
321
+ activeWatchGroups: watches.size,
322
+ filesystemWatchers: watcherCount,
323
+ pendingDebounces: debounceTimers.size
324
+ };
312
325
  }
313
326
  };
314
327
  var file_watcher_default = plugin;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/format-on-save/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAmO/C,QAAA,MAAM,MAAM,EAAE,MA2Ob,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/format-on-save/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA2N/C,QAAA,MAAM,MAAM,EAAE,MA2Ob,CAAC;eAEa,MAAM"}
@@ -1,18 +1,26 @@
1
1
  // src/format-on-save/index.ts
2
2
  import { execFileSync, execSync } from "node:child_process";
3
3
  import { existsSync, statSync } from "node:fs";
4
- import { isAbsolute, relative, resolve } from "node:path";
5
- var API_VERSION = "^0.1.10";
4
+
5
+ // src/runtime/index.ts
6
+ import { basename, isAbsolute, relative, resolve } from "node:path";
7
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
+ function hasLeadingDash(arg) {
9
+ return arg.length > 0 && arg.startsWith("-");
10
+ }
11
+ function withinProjectPath(projectRoot, candidate) {
12
+ if (candidate.length === 0 || candidate.length > 4096) return false;
13
+ if (hasLeadingDash(candidate)) return false;
14
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
15
+ const rel = relative(projectRoot, resolved);
16
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
17
+ }
6
18
  function withinProject(p) {
7
- if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
8
- const root = process.cwd();
9
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
10
- const rel = relative(root, resolved);
11
- if (rel === "" || rel === ".") return true;
12
- if (rel.startsWith("..")) return false;
13
- if (isAbsolute(rel)) return false;
14
- return true;
19
+ return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
15
20
  }
21
+
22
+ // src/format-on-save/index.ts
23
+ var API_VERSION = "^0.1.10";
16
24
  var state = {
17
25
  invocationCount: 0,
18
26
  /** Times formatting was applied (file changed). */
@@ -219,7 +227,7 @@ var plugin = {
219
227
  state.cleanCount += 1;
220
228
  return;
221
229
  };
222
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
230
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
223
231
  state.patternUnregister = api.onPattern(
224
232
  "import-organizer:done",
225
233
  (_eventName, payload) => {
@@ -160,7 +160,7 @@ var plugin = {
160
160
  version: "0.2.0",
161
161
  description: "AI-powered git staging and conventional commit message generation",
162
162
  apiVersion: API_VERSION,
163
- capabilities: { tools: true },
163
+ capabilities: { tools: true, llm: true },
164
164
  defaultConfig: {
165
165
  conventionalCommits: true,
166
166
  autoStage: false,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/import-organizer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA4R/C,QAAA,MAAM,MAAM,EAAE,MA8Nb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/import-organizer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoR/C,QAAA,MAAM,MAAM,EAAE,MA8Nb,CAAC;eAEa,MAAM"}
@@ -1,17 +1,26 @@
1
1
  // src/import-organizer/index.ts
2
2
  import { spawn } from "node:child_process";
3
3
  import { existsSync, statSync } from "node:fs";
4
+ import { basename as basename2, isAbsolute as isAbsolute2 } from "node:path";
5
+
6
+ // src/runtime/index.ts
4
7
  import { basename, isAbsolute, relative, resolve } from "node:path";
8
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
9
+ function hasLeadingDash(arg) {
10
+ return arg.length > 0 && arg.startsWith("-");
11
+ }
12
+ function withinProjectPath(projectRoot, candidate) {
13
+ if (candidate.length === 0 || candidate.length > 4096) return false;
14
+ if (hasLeadingDash(candidate)) return false;
15
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
16
+ const rel = relative(projectRoot, resolved);
17
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
18
+ }
5
19
  function withinProject(p) {
6
- if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
7
- const root = process.cwd();
8
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
9
- const rel = relative(root, resolved);
10
- if (rel === "" || rel === ".") return true;
11
- if (rel.startsWith("..")) return false;
12
- if (isAbsolute(rel)) return false;
13
- return true;
20
+ return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
14
21
  }
22
+
23
+ // src/import-organizer/index.ts
15
24
  var ALLOWED_FIRST_TOKENS = /* @__PURE__ */ new Set([
16
25
  "npx",
17
26
  "pnpm",
@@ -31,13 +40,13 @@ function resolveAllowedCommand(command) {
31
40
  if (ALLOWED_FIRST_TOKENS.has(head)) {
32
41
  return { cmd: head, args: tokens.slice(1) };
33
42
  }
34
- if (isAbsolute(head)) {
43
+ if (isAbsolute2(head)) {
35
44
  if (!withinProject(head)) return null;
36
- const base = basename(head);
45
+ const base = basename2(head);
37
46
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
38
47
  }
39
- if (!isAbsolute(head) && withinProject(head)) {
40
- const base = basename(head);
48
+ if (!isAbsolute2(head) && withinProject(head)) {
49
+ const base = basename2(head);
41
50
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
42
51
  }
43
52
  return null;
@@ -256,7 +265,7 @@ ${result.stderr.trim()}`
256
265
  }
257
266
  return;
258
267
  };
259
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
268
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
260
269
  api.tools.register({
261
270
  name: "import_organizer_status",
262
271
  description: "Reports import-organizer state: linter availability, config, and per-session organized/clean/error counters.",
package/dist/index.d.ts CHANGED
@@ -90,10 +90,10 @@
90
90
  * count, and approximate cyclomatic complexity
91
91
  * 39. refactor-suggester — Flags long functions, deep nesting, many
92
92
  * parameters, magic numbers, and console.log usage
93
- * 40. test-generator — Generates a unit-test skeleton from exported
94
- * functions/classes in a source file
95
- * 41. release-notes-generator — Groups conventional commits into a release
96
- * notes markdown draft
93
+ * 40. test-generator — Generates framework-correct test files with an
94
+ * optional behavior-focused api.llm pass
95
+ * 41. release-notes-generator — Produces traceable notes with optional,
96
+ * hash-preserving api.llm polish
97
97
  * 42. smart-rename — Whole-word symbol rename with preview and
98
98
  * optional apply
99
99
  * 43. feature-flag-tracker — Scans source files for feature-flag usage and