@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,10 +1,108 @@
1
1
  // src/duplicate-code-detector/index.ts
2
- import { readFileSync, statSync as statSync2 } from "node:fs";
3
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
2
+ import { readFile, realpath, stat } from "node:fs/promises";
3
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "node:path";
4
4
 
5
5
  // src/runtime/index.ts
6
- import { existsSync, readdirSync, statSync } from "node:fs";
7
6
  import { basename, extname, isAbsolute, relative, resolve } from "node:path";
7
+
8
+ // src/runtime/local-bin.ts
9
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
10
+
11
+ // src/runtime/bounded-map.ts
12
+ var BoundedMap = class {
13
+ map = /* @__PURE__ */ new Map();
14
+ max;
15
+ ttlMs;
16
+ now;
17
+ /** Entries dropped to stay under `max`. Surfaced by plugin health(). */
18
+ evictions = 0;
19
+ constructor(options) {
20
+ const normalizedMax = Math.floor(options.max);
21
+ this.max = Number.isSafeInteger(normalizedMax) ? Math.max(1, normalizedMax) : 1;
22
+ this.ttlMs = options.ttlMs;
23
+ this.now = options.now ?? Date.now;
24
+ }
25
+ expired(entry) {
26
+ return this.ttlMs !== void 0 && this.now() - entry.storedAt > this.ttlMs;
27
+ }
28
+ get(key) {
29
+ const entry = this.map.get(key);
30
+ if (entry === void 0) return void 0;
31
+ if (this.expired(entry)) {
32
+ this.map.delete(key);
33
+ return void 0;
34
+ }
35
+ this.map.delete(key);
36
+ this.map.set(key, entry);
37
+ return entry.value;
38
+ }
39
+ /**
40
+ * Read without promoting the key to most-recently-used. Use for
41
+ * diagnostics that must not perturb the eviction order.
42
+ */
43
+ peek(key) {
44
+ const entry = this.map.get(key);
45
+ if (entry === void 0 || this.expired(entry)) return void 0;
46
+ return entry.value;
47
+ }
48
+ has(key) {
49
+ const entry = this.map.get(key);
50
+ if (entry === void 0) return false;
51
+ if (this.expired(entry)) {
52
+ this.map.delete(key);
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ set(key, value) {
58
+ this.map.delete(key);
59
+ this.map.set(key, { value, storedAt: this.now() });
60
+ while (this.map.size > this.max) {
61
+ const coldest = this.map.keys().next().value;
62
+ if (coldest === void 0) break;
63
+ this.map.delete(coldest);
64
+ this.evictions += 1;
65
+ }
66
+ return this;
67
+ }
68
+ delete(key) {
69
+ return this.map.delete(key);
70
+ }
71
+ clear() {
72
+ this.map.clear();
73
+ this.evictions = 0;
74
+ }
75
+ get size() {
76
+ return this.map.size;
77
+ }
78
+ /** How many entries have been dropped to respect `max`, since the last clear. */
79
+ get evictionCount() {
80
+ return this.evictions;
81
+ }
82
+ /** Drop every expired entry. Cheap enough to call from a status tool. */
83
+ prune() {
84
+ if (this.ttlMs === void 0) return 0;
85
+ let removed = 0;
86
+ for (const [key, entry] of this.map) {
87
+ if (this.expired(entry)) {
88
+ this.map.delete(key);
89
+ removed += 1;
90
+ }
91
+ }
92
+ return removed;
93
+ }
94
+ /** Live (non-expired) entries, coldest first. */
95
+ *entries() {
96
+ for (const [key, entry] of this.map) {
97
+ if (!this.expired(entry)) yield [key, entry.value];
98
+ }
99
+ }
100
+ [Symbol.iterator]() {
101
+ return this.entries();
102
+ }
103
+ };
104
+
105
+ // src/runtime/index.ts
8
106
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
9
107
  function hasLeadingDash(arg) {
10
108
  return arg.length > 0 && arg.startsWith("-");
@@ -17,44 +115,45 @@ function withinProjectPath(projectRoot, candidate) {
17
115
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
18
116
  }
19
117
  function withinProject(p) {
20
- return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
118
+ const cwd = process.cwd();
119
+ return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
21
120
  }
22
121
  var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
23
- function collectSourceFiles(root, opts) {
122
+ async function collectSourceFilesAsync(root, opts) {
123
+ const { readdir, stat: stat2 } = await import("node:fs/promises");
24
124
  const files = [];
25
- if (!existsSync(root)) return files;
26
- const s = statSync(root);
27
- if (s.isFile()) {
28
- if (matchesExtension(root, opts.extensions)) files.push(root);
125
+ try {
126
+ const s = await stat2(root);
127
+ if (s.isFile()) {
128
+ if (matchesExtension(root, opts.extensions)) files.push(root);
129
+ return files;
130
+ }
131
+ if (!s.isDirectory()) return files;
132
+ } catch {
29
133
  return files;
30
134
  }
31
- if (!s.isDirectory()) return files;
32
135
  const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
33
- function walk(dir, depth) {
136
+ const excludeSet = new Set(exclude);
137
+ async function walk(dir, depth) {
34
138
  if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
35
139
  let entries;
36
140
  try {
37
- entries = readdirSync(dir);
141
+ entries = await readdir(dir, { withFileTypes: true });
38
142
  } catch {
39
143
  return;
40
144
  }
145
+ entries.sort((a, b) => a.name.localeCompare(b.name));
41
146
  for (const entry of entries) {
42
- if (exclude.includes(entry)) continue;
43
- const full = resolve(dir, entry);
44
- let st;
45
- try {
46
- st = statSync(full);
47
- } catch {
48
- continue;
49
- }
50
- if (st.isDirectory()) {
51
- walk(full, depth + 1);
52
- } else if (st.isFile() && matchesExtension(full, opts.extensions)) {
147
+ if (excludeSet.has(entry.name)) continue;
148
+ const full = resolve(dir, entry.name);
149
+ if (entry.isDirectory()) {
150
+ await walk(full, depth + 1);
151
+ } else if (entry.isFile() && matchesExtension(full, opts.extensions)) {
53
152
  files.push(full);
54
153
  }
55
154
  }
56
155
  }
57
- walk(root, 0);
156
+ await walk(root, 0);
58
157
  return files;
59
158
  }
60
159
  function matchesExtension(p, exts) {
@@ -63,6 +162,7 @@ function matchesExtension(p, exts) {
63
162
 
64
163
  // src/duplicate-code-detector/index.ts
65
164
  var API_VERSION = "^0.1.10";
165
+ var HOOK_WARNING_COOLDOWN_MS = 6e4;
66
166
  var state = {
67
167
  scanCount: 0,
68
168
  findingCount: 0,
@@ -70,8 +170,25 @@ var state = {
70
170
  warningCount: 0,
71
171
  errorCount: 0,
72
172
  hookUnregister: null,
73
- lastHookWarning: /* @__PURE__ */ new Map(),
74
- fileIndex: /* @__PURE__ */ new Map()
173
+ lastHookWarning: new BoundedMap({ max: 512, ttlMs: HOOK_WARNING_COOLDOWN_MS }),
174
+ fileIndex: /* @__PURE__ */ new Map(),
175
+ inFlightFingerprintReads: /* @__PURE__ */ new Map(),
176
+ indexFingerprintCount: 0,
177
+ hookIndexEvictions: 0,
178
+ oversizedFileSkips: 0
179
+ };
180
+ var hookIndexBudgets = {
181
+ /** Max number of files retained in the hook fingerprint index (LRU-evicted). */
182
+ maxFiles: 5e3,
183
+ /** Max total fingerprints across the whole index (running-sum enforced, LRU-evicted). */
184
+ maxFingerprints: 3e5,
185
+ /**
186
+ * Max candidate windows hashed and cached per file by the advisory hook. The
187
+ * on-demand detect_duplicate_code tool intentionally scans every window.
188
+ */
189
+ maxFingerprintsPerFile: 25e3,
190
+ /** Files larger than this are skipped entirely by the hook (never read/extracted/cached). */
191
+ maxFileBytes: 2 * 1024 * 1024
75
192
  };
76
193
  var DEFAULTS = {
77
194
  enabled: false,
@@ -81,18 +198,28 @@ var DEFAULTS = {
81
198
  excludeDirs: ["node_modules", "dist", ".git", "coverage"],
82
199
  maxFindings: 5
83
200
  };
201
+ var extensionsSet = new Set(DEFAULTS.extensions);
84
202
  function readConfig(raw) {
85
- if (!raw || typeof raw !== "object") return { ...DEFAULTS };
203
+ if (!raw || typeof raw !== "object") {
204
+ extensionsSet = new Set(DEFAULTS.extensions);
205
+ return { ...DEFAULTS };
206
+ }
86
207
  const r = raw;
208
+ const extensions = Array.isArray(r["extensions"]) ? r["extensions"].filter((x) => typeof x === "string") : DEFAULTS.extensions;
209
+ extensionsSet = new Set(extensions);
87
210
  return {
88
211
  enabled: r["enabled"] === true,
89
212
  minLines: typeof r["minLines"] === "number" && r["minLines"] >= 2 && r["minLines"] <= 100 ? r["minLines"] : DEFAULTS.minLines,
90
213
  threshold: typeof r["threshold"] === "number" && r["threshold"] > 0 && r["threshold"] <= 1 ? r["threshold"] : DEFAULTS.threshold,
91
- extensions: Array.isArray(r["extensions"]) ? r["extensions"].filter((x) => typeof x === "string") : DEFAULTS.extensions,
214
+ extensions,
92
215
  excludeDirs: Array.isArray(r["excludeDirs"]) ? r["excludeDirs"].filter((x) => typeof x === "string") : DEFAULTS.excludeDirs,
93
216
  maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS.maxFindings
94
217
  };
95
218
  }
219
+ function isWithinRoot(projectRoot, candidate) {
220
+ const rel = relative2(projectRoot, candidate);
221
+ return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
222
+ }
96
223
  function toPosix(p) {
97
224
  return p.replace(/\\/g, "/");
98
225
  }
@@ -111,6 +238,40 @@ function normalizeLine(line) {
111
238
  function buildFingerprint(lines) {
112
239
  return lines.map(normalizeLine).filter((l) => l.length > 0).join("\n");
113
240
  }
241
+ function hashFingerprint(fp) {
242
+ let low = 3735928559;
243
+ let high = 1103547991;
244
+ for (let index = 0; index < fp.length; index += 1) {
245
+ const code = fp.charCodeAt(index);
246
+ low = Math.imul(low ^ code, 2654435761);
247
+ high = Math.imul(high ^ code, 1597334677);
248
+ }
249
+ low = Math.imul(low ^ low >>> 16, 2246822507) ^ Math.imul(high ^ high >>> 13, 3266489909);
250
+ high = Math.imul(high ^ high >>> 16, 2246822507) ^ Math.imul(low ^ low >>> 13, 3266489909);
251
+ return 4294967296 * (high & 2097151) + (low >>> 0);
252
+ }
253
+ function extractFingerprintHashes(content, minLines, maxWindows) {
254
+ const rawLines = content.split(/\r?\n/);
255
+ const normalizedLines = rawLines.map(normalizeLine);
256
+ const fingerprints = /* @__PURE__ */ new Set();
257
+ const windowCount = Math.min(Math.max(rawLines.length - minLines + 1, 0), maxWindows);
258
+ for (let index = 0; index < windowCount; index += 1) {
259
+ const fingerprint = normalizedLines.slice(index, index + minLines).filter((line) => line.length > 0).join("\n");
260
+ if (fingerprint.length > 0) fingerprints.add(hashFingerprint(fingerprint));
261
+ }
262
+ return fingerprints;
263
+ }
264
+ function evictHookIndex() {
265
+ while (state.fileIndex.size > hookIndexBudgets.maxFiles || state.indexFingerprintCount > hookIndexBudgets.maxFingerprints) {
266
+ const oldest = state.fileIndex.keys().next();
267
+ if (oldest.done) break;
268
+ const key = oldest.value;
269
+ const entry = state.fileIndex.get(key);
270
+ if (entry) state.indexFingerprintCount -= entry.fingerprints.size;
271
+ state.fileIndex.delete(key);
272
+ state.hookIndexEvictions += 1;
273
+ }
274
+ }
114
275
  function extractWindows(filePath, content, minLines) {
115
276
  const rawLines = content.split(/\r?\n/);
116
277
  const windows = [];
@@ -153,14 +314,17 @@ function findDuplicates(files, minLines, maxFindings) {
153
314
  }
154
315
  return findings;
155
316
  }
156
- function scanPath(rawPath, cfg) {
317
+ async function scanPath(rawPath, cfg) {
157
318
  const root = process.cwd();
158
319
  const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
159
- const filePaths = collectSourceFiles(resolved, { extensions: cfg.extensions, excludeDirs: cfg.excludeDirs });
320
+ const filePaths = await collectSourceFilesAsync(resolved, {
321
+ extensions: cfg.extensions,
322
+ excludeDirs: cfg.excludeDirs
323
+ });
160
324
  const files = /* @__PURE__ */ new Map();
161
325
  for (const p of filePaths) {
162
326
  try {
163
- files.set(p, readFileSync(p, "utf-8"));
327
+ files.set(p, await readFile(p, "utf-8"));
164
328
  } catch {
165
329
  }
166
330
  }
@@ -220,6 +384,9 @@ var plugin = {
220
384
  state.errorCount = 0;
221
385
  state.lastHookWarning.clear();
222
386
  state.fileIndex.clear();
387
+ state.indexFingerprintCount = 0;
388
+ state.hookIndexEvictions = 0;
389
+ state.oversizedFileSkips = 0;
223
390
  if (state.hookUnregister) {
224
391
  try {
225
392
  state.hookUnregister();
@@ -228,77 +395,103 @@ var plugin = {
228
395
  state.hookUnregister = null;
229
396
  }
230
397
  const cfg = readConfig(api.config.extensions?.["duplicate-code-detector"]);
231
- function readCachedWindows(filePath, minLines) {
398
+ async function readCachedFingerprints(filePath, minLines) {
232
399
  let st;
233
400
  try {
234
- st = statSync2(filePath);
401
+ st = await stat(filePath);
235
402
  } catch {
236
403
  return null;
237
404
  }
238
405
  const cached = state.fileIndex.get(filePath);
239
406
  if (cached && cached.mtimeMs === st.mtimeMs && cached.size === st.size) {
240
- return cached.windows;
407
+ state.fileIndex.delete(filePath);
408
+ state.fileIndex.set(filePath, cached);
409
+ return cached.fingerprints;
410
+ }
411
+ if (st.size > hookIndexBudgets.maxFileBytes) {
412
+ if (cached) {
413
+ state.indexFingerprintCount -= cached.fingerprints.size;
414
+ state.fileIndex.delete(filePath);
415
+ }
416
+ state.oversizedFileSkips += 1;
417
+ api.log.trace("duplicate-code-detector: skipped oversized file in hook index", {
418
+ file: relativePath(filePath),
419
+ sizeBytes: st.size,
420
+ maxFileBytes: hookIndexBudgets.maxFileBytes
421
+ });
422
+ return /* @__PURE__ */ new Set();
241
423
  }
242
424
  let content;
243
425
  try {
244
- content = readFileSync(filePath, "utf-8");
426
+ content = await readFile(filePath, "utf-8");
245
427
  } catch {
246
428
  return null;
247
429
  }
248
- const windows = extractWindows(filePath, content, minLines);
249
- state.fileIndex.set(filePath, { mtimeMs: st.mtimeMs, size: st.size, windows });
250
- return windows;
430
+ const fingerprints = extractFingerprintHashes(
431
+ content,
432
+ minLines,
433
+ hookIndexBudgets.maxFingerprintsPerFile
434
+ );
435
+ if (cached) state.indexFingerprintCount -= cached.fingerprints.size;
436
+ state.fileIndex.set(filePath, { mtimeMs: st.mtimeMs, size: st.size, fingerprints });
437
+ state.indexFingerprintCount += fingerprints.size;
438
+ evictHookIndex();
439
+ return fingerprints;
251
440
  }
252
- const hook = (input) => {
441
+ const hook = async (input) => {
253
442
  if (!cfg.enabled) return;
254
443
  if (input.toolResult?.isError) return;
255
444
  const inp = input.toolInput ?? {};
256
445
  const sourcePath = inp["path"];
257
446
  if (!sourcePath || typeof sourcePath !== "string") return;
258
- if (!withinProject(sourcePath)) return;
447
+ const projectRoot = resolve2(process.cwd());
448
+ const resolvedFile = isAbsolute2(sourcePath) ? resolve2(sourcePath) : resolve2(projectRoot, sourcePath);
449
+ if (!isWithinRoot(projectRoot, resolvedFile)) return;
450
+ let changedFile;
451
+ try {
452
+ changedFile = await realpath(resolvedFile);
453
+ } catch {
454
+ state.errorCount += 1;
455
+ return;
456
+ }
457
+ if (!isWithinRoot(projectRoot, changedFile)) return;
259
458
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
260
- if (!cfg.extensions.includes(ext)) return;
459
+ if (!extensionsSet.has(ext)) return;
261
460
  state.hookInvocationCount += 1;
262
461
  const now = Date.now();
263
- const lastWarning = state.lastHookWarning.get(sourcePath);
264
- if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
265
- const changedFile = resolve2(process.cwd(), sourcePath);
266
- const changedWindows = readCachedWindows(changedFile, cfg.minLines);
267
- if (changedWindows === null) {
462
+ const lastWarning = state.lastHookWarning.get(changedFile);
463
+ if (lastWarning !== void 0 && now - lastWarning < HOOK_WARNING_COOLDOWN_MS) return;
464
+ const changedFps = await readCachedFingerprints(changedFile, cfg.minLines);
465
+ if (changedFps === null) {
268
466
  state.errorCount += 1;
269
467
  return;
270
468
  }
271
- if (changedWindows.length === 0) return;
272
- const projectRoot = resolve2(process.cwd());
469
+ if (changedFps.size === 0) return;
273
470
  let otherFilePaths;
274
471
  try {
275
- otherFilePaths = collectSourceFiles(projectRoot, {
472
+ otherFilePaths = await collectSourceFilesAsync(projectRoot, {
276
473
  extensions: cfg.extensions,
277
474
  excludeDirs: cfg.excludeDirs
278
- }).filter((p) => p !== changedFile);
475
+ });
279
476
  } catch {
280
477
  state.errorCount += 1;
281
478
  return;
282
479
  }
283
- const existingWindows = [];
480
+ const matched = /* @__PURE__ */ new Set();
284
481
  for (const p of otherFilePaths) {
285
- const w = readCachedWindows(p, cfg.minLines);
286
- if (w !== null) existingWindows.push(...w);
287
- }
288
- const hits = [];
289
- for (const cw of changedWindows) {
290
- for (const ew of existingWindows) {
291
- if (cw.fingerprint === ew.fingerprint) {
292
- hits.push(ew);
293
- break;
294
- }
482
+ if (resolve2(p) === resolve2(changedFile)) continue;
483
+ const otherFps = await readCachedFingerprints(p, cfg.minLines);
484
+ if (otherFps === null || otherFps.size === 0) continue;
485
+ for (const fp of changedFps) {
486
+ if (!matched.has(fp) && otherFps.has(fp)) matched.add(fp);
295
487
  }
488
+ if (matched.size === changedFps.size) break;
296
489
  }
297
- if (hits.length === 0) return;
298
- state.warningCount += hits.length;
299
- state.lastHookWarning.set(sourcePath, now);
490
+ if (matched.size === 0) return;
491
+ state.warningCount += matched.size;
492
+ state.lastHookWarning.set(changedFile, now);
300
493
  return {
301
- additionalContext: `\u26A0\uFE0F duplicate-code-detector: ${sourcePath} contains ${hits.length} block(s) already present elsewhere. Run detect_duplicate_code for details.`,
494
+ additionalContext: `\u26A0\uFE0F duplicate-code-detector: ${sourcePath} contains ${matched.size} block(s) already present elsewhere. Run detect_duplicate_code for details.`,
302
495
  contextAs: "separate"
303
496
  };
304
497
  };
@@ -324,7 +517,7 @@ var plugin = {
324
517
  state.scanCount += 1;
325
518
  let result;
326
519
  try {
327
- result = scanPath(rawPath, cfg);
520
+ result = await scanPath(rawPath, cfg);
328
521
  } catch (err) {
329
522
  state.errorCount += 1;
330
523
  return { ok: false, error: String(err) };
@@ -360,7 +553,15 @@ var plugin = {
360
553
  findings: state.findingCount,
361
554
  hookInvocations: state.hookInvocationCount,
362
555
  warnings: state.warningCount,
363
- errors: state.errorCount
556
+ errors: state.errorCount,
557
+ // Hook fingerprint-index footprint (bounded; see hookIndexBudgets).
558
+ indexedFiles: state.fileIndex.size,
559
+ indexedFingerprints: state.indexFingerprintCount,
560
+ hookIndexEvictions: state.hookIndexEvictions,
561
+ oversizedFileSkips: state.oversizedFileSkips,
562
+ // Rough retained-bytes estimate: ~8B per numeric fingerprint + ~120B
563
+ // per file entry (key string + Set/entry overhead). Compact by design.
564
+ approxIndexBytes: state.indexFingerprintCount * 8 + state.fileIndex.size * 120
364
565
  }
365
566
  };
366
567
  }
@@ -392,6 +593,10 @@ var plugin = {
392
593
  state.warningCount = 0;
393
594
  state.errorCount = 0;
394
595
  state.lastHookWarning.clear();
596
+ state.fileIndex.clear();
597
+ state.indexFingerprintCount = 0;
598
+ state.hookIndexEvictions = 0;
599
+ state.oversizedFileSkips = 0;
395
600
  api.log.info("duplicate-code-detector: teardown complete", { final });
396
601
  },
397
602
  async health() {
@@ -403,12 +608,18 @@ var plugin = {
403
608
  findings: state.findingCount,
404
609
  hookInvocations: state.hookInvocationCount,
405
610
  warnings: state.warningCount,
406
- errors: state.errorCount
611
+ errors: state.errorCount,
612
+ indexedFiles: state.fileIndex.size,
613
+ indexedFingerprints: state.indexFingerprintCount,
614
+ hookIndexEvictions: state.hookIndexEvictions,
615
+ oversizedFileSkips: state.oversizedFileSkips
407
616
  }
408
617
  };
409
618
  }
410
619
  };
411
620
  var duplicate_code_detector_default = plugin;
412
621
  export {
413
- duplicate_code_detector_default as default
622
+ duplicate_code_detector_default as default,
623
+ hashFingerprint,
624
+ hookIndexBudgets
414
625
  };
@@ -43,7 +43,7 @@
43
43
  *
44
44
  * @public
45
45
  */
46
- import type { Plugin } from '@wrongstack/core';
46
+ import type { Plugin } from '@wrongstack/core/types';
47
47
  export interface FailureRecord {
48
48
  when: string;
49
49
  tool: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error-lens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM/C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AA6FD,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBzE;AAUD,QAAA,MAAM,MAAM,EAAE,MAoOb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error-lens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAMrD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AA6FD,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBzE;AAUD,QAAA,MAAM,MAAM,EAAE,MAoOb,CAAC;eAEa,MAAM"}
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from '@wrongstack/core/types';
2
+ export declare const OFFICIAL_PLUGIN_SPECIFIERS: readonly ['@wrongstack/plugins/agent-handoff', '@wrongstack/plugins/cost-tracker', '@wrongstack/plugins/file-watcher', '@wrongstack/plugins/git-autocommit', '@wrongstack/plugins/auto-doc', '@wrongstack/plugins/shell-check', '@wrongstack/plugins/cron', '@wrongstack/plugins/template-engine', '@wrongstack/plugins/semver-bump', '@wrongstack/plugins/secret-scanner', '@wrongstack/plugins/todo-tracker', '@wrongstack/plugins/token-budget', '@wrongstack/plugins/lint-gate', '@wrongstack/plugins/branch-guard', '@wrongstack/plugins/diff-summary', '@wrongstack/plugins/commit-validator', '@wrongstack/plugins/format-on-save', '@wrongstack/plugins/test-runner-gate', '@wrongstack/plugins/import-organizer', '@wrongstack/plugins/knowledge-graph', '@wrongstack/plugins/todo-listener', '@wrongstack/plugins/session-recap', '@wrongstack/plugins/spec-linker', '@wrongstack/plugins/loop-breaker', '@wrongstack/plugins/path-guard', '@wrongstack/plugins/process-guard', '@wrongstack/plugins/context-pins', '@wrongstack/plugins/checkpoint', '@wrongstack/plugins/error-lens', '@wrongstack/plugins/dep-guard', '@wrongstack/plugins/config-validator', '@wrongstack/plugins/notify-hub', '@wrongstack/plugins/changelog-writer', '@wrongstack/plugins/injection-shield', '@wrongstack/plugins/llm-cache', '@wrongstack/plugins/model-router', '@wrongstack/plugins/pr-drafter', '@wrongstack/plugins/prompt-firewall', '@wrongstack/plugins/auto-escalate', '@wrongstack/plugins/test-coverage-gate', '@wrongstack/plugins/type-gate', '@wrongstack/plugins/token-throttle', '@wrongstack/plugins/plugin-stack-observer', '@wrongstack/plugins/dead-code-detector', '@wrongstack/plugins/dependency-vulnerability-gate', '@wrongstack/plugins/migration-planner', '@wrongstack/plugins/semantic-search-indexer', '@wrongstack/plugins/auto-i18n-extractor', '@wrongstack/plugins/doc-sync-guard', '@wrongstack/plugins/api-compatibility-gate', '@wrongstack/plugins/performance-regression-gate', '@wrongstack/plugins/test-flake-detector', '@wrongstack/plugins/schema-evolution-guard', '@wrongstack/plugins/license-audit-gate', '@wrongstack/plugins/accessibility-auditor', '@wrongstack/plugins/security-hotspot-scanner', '@wrongstack/plugins/duplicate-code-detector', '@wrongstack/plugins/code-metrics', '@wrongstack/plugins/refactor-suggester', '@wrongstack/plugins/test-generator', '@wrongstack/plugins/release-notes-generator', '@wrongstack/plugins/smart-rename', '@wrongstack/plugins/feature-flag-tracker', '@wrongstack/plugins/interface-contract-guard'];
3
+ export declare const OFFICIAL_PLUGIN_FACTORIES: readonly (() => Promise<Plugin>)[];
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factories/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD,eAAO,MAAM,0BAA0B,YACrC,mCAAmC,EACnC,kCAAkC,EAClC,kCAAkC,EAClC,oCAAoC,EACpC,8BAA8B,EAC9B,iCAAiC,EACjC,0BAA0B,EAC1B,qCAAqC,EACrC,iCAAiC,EACjC,oCAAoC,EACpC,kCAAkC,EAClC,kCAAkC,EAClC,+BAA+B,EAC/B,kCAAkC,EAClC,kCAAkC,EAClC,sCAAsC,EACtC,oCAAoC,EACpC,sCAAsC,EACtC,sCAAsC,EACtC,qCAAqC,EACrC,mCAAmC,EACnC,mCAAmC,EACnC,iCAAiC,EACjC,kCAAkC,EAClC,gCAAgC,EAChC,mCAAmC,EACnC,kCAAkC,EAClC,gCAAgC,EAChC,gCAAgC,EAChC,+BAA+B,EAC/B,sCAAsC,EACtC,gCAAgC,EAChC,sCAAsC,EACtC,sCAAsC,EACtC,+BAA+B,EAC/B,kCAAkC,EAClC,gCAAgC,EAChC,qCAAqC,EACrC,mCAAmC,EACnC,wCAAwC,EACxC,+BAA+B,EAC/B,oCAAoC,EACpC,2CAA2C,EAC3C,wCAAwC,EACxC,mDAAmD,EACnD,uCAAuC,EACvC,6CAA6C,EAC7C,yCAAyC,EACzC,oCAAoC,EACpC,4CAA4C,EAC5C,iDAAiD,EACjD,yCAAyC,EACzC,4CAA4C,EAC5C,wCAAwC,EACxC,2CAA2C,EAC3C,8CAA8C,EAC9C,6CAA6C,EAC7C,kCAAkC,EAClC,wCAAwC,EACxC,oCAAoC,EACpC,6CAA6C,EAC7C,kCAAkC,EAClC,0CAA0C,EAC1C,8CAA8C,CACtC,CAAC;AAEX,eAAO,MAAM,yBAAyB,EAAE,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAGrE,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './factories/index.js';
@@ -0,0 +1,74 @@
1
+ // src/factories/index.ts
2
+ var OFFICIAL_PLUGIN_SPECIFIERS = [
3
+ "@wrongstack/plugins/agent-handoff",
4
+ "@wrongstack/plugins/cost-tracker",
5
+ "@wrongstack/plugins/file-watcher",
6
+ "@wrongstack/plugins/git-autocommit",
7
+ "@wrongstack/plugins/auto-doc",
8
+ "@wrongstack/plugins/shell-check",
9
+ "@wrongstack/plugins/cron",
10
+ "@wrongstack/plugins/template-engine",
11
+ "@wrongstack/plugins/semver-bump",
12
+ "@wrongstack/plugins/secret-scanner",
13
+ "@wrongstack/plugins/todo-tracker",
14
+ "@wrongstack/plugins/token-budget",
15
+ "@wrongstack/plugins/lint-gate",
16
+ "@wrongstack/plugins/branch-guard",
17
+ "@wrongstack/plugins/diff-summary",
18
+ "@wrongstack/plugins/commit-validator",
19
+ "@wrongstack/plugins/format-on-save",
20
+ "@wrongstack/plugins/test-runner-gate",
21
+ "@wrongstack/plugins/import-organizer",
22
+ "@wrongstack/plugins/knowledge-graph",
23
+ "@wrongstack/plugins/todo-listener",
24
+ "@wrongstack/plugins/session-recap",
25
+ "@wrongstack/plugins/spec-linker",
26
+ "@wrongstack/plugins/loop-breaker",
27
+ "@wrongstack/plugins/path-guard",
28
+ "@wrongstack/plugins/process-guard",
29
+ "@wrongstack/plugins/context-pins",
30
+ "@wrongstack/plugins/checkpoint",
31
+ "@wrongstack/plugins/error-lens",
32
+ "@wrongstack/plugins/dep-guard",
33
+ "@wrongstack/plugins/config-validator",
34
+ "@wrongstack/plugins/notify-hub",
35
+ "@wrongstack/plugins/changelog-writer",
36
+ "@wrongstack/plugins/injection-shield",
37
+ "@wrongstack/plugins/llm-cache",
38
+ "@wrongstack/plugins/model-router",
39
+ "@wrongstack/plugins/pr-drafter",
40
+ "@wrongstack/plugins/prompt-firewall",
41
+ "@wrongstack/plugins/auto-escalate",
42
+ "@wrongstack/plugins/test-coverage-gate",
43
+ "@wrongstack/plugins/type-gate",
44
+ "@wrongstack/plugins/token-throttle",
45
+ "@wrongstack/plugins/plugin-stack-observer",
46
+ "@wrongstack/plugins/dead-code-detector",
47
+ "@wrongstack/plugins/dependency-vulnerability-gate",
48
+ "@wrongstack/plugins/migration-planner",
49
+ "@wrongstack/plugins/semantic-search-indexer",
50
+ "@wrongstack/plugins/auto-i18n-extractor",
51
+ "@wrongstack/plugins/doc-sync-guard",
52
+ "@wrongstack/plugins/api-compatibility-gate",
53
+ "@wrongstack/plugins/performance-regression-gate",
54
+ "@wrongstack/plugins/test-flake-detector",
55
+ "@wrongstack/plugins/schema-evolution-guard",
56
+ "@wrongstack/plugins/license-audit-gate",
57
+ "@wrongstack/plugins/accessibility-auditor",
58
+ "@wrongstack/plugins/security-hotspot-scanner",
59
+ "@wrongstack/plugins/duplicate-code-detector",
60
+ "@wrongstack/plugins/code-metrics",
61
+ "@wrongstack/plugins/refactor-suggester",
62
+ "@wrongstack/plugins/test-generator",
63
+ "@wrongstack/plugins/release-notes-generator",
64
+ "@wrongstack/plugins/smart-rename",
65
+ "@wrongstack/plugins/feature-flag-tracker",
66
+ "@wrongstack/plugins/interface-contract-guard"
67
+ ];
68
+ var OFFICIAL_PLUGIN_FACTORIES = OFFICIAL_PLUGIN_SPECIFIERS.map(
69
+ (specifier) => async () => (await import(specifier)).default
70
+ );
71
+ export {
72
+ OFFICIAL_PLUGIN_FACTORIES,
73
+ OFFICIAL_PLUGIN_SPECIFIERS
74
+ };
@@ -23,7 +23,7 @@
23
23
  *
24
24
  * @public
25
25
  */
26
- import type { Plugin } from '@wrongstack/core';
26
+ import type { Plugin } from '@wrongstack/core/types';
27
27
  export interface FeatureFlagUsage {
28
28
  flag: string;
29
29
  file: string;
@@ -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;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;AA0ID,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,wBAAwB,CAAC;AASrD,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;AAmLD,QAAA,MAAM,MAAM,EAAE,MAmNb,CAAC;eAEa,MAAM"}