@wrongstack/plugins 0.308.6 → 0.308.7

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 (51) hide show
  1. package/dist/accessibility-auditor.js +26 -82
  2. package/dist/agent-handoff.js +16 -26
  3. package/dist/auto-i18n-extractor.js +19 -23
  4. package/dist/branch-guard.js +19 -111
  5. package/dist/changelog-writer.js +20 -133
  6. package/dist/code-metrics.js +26 -71
  7. package/dist/commit-validator.js +16 -14
  8. package/dist/config-validator.js +18 -22
  9. package/dist/cost-tracker.js +15 -96
  10. package/dist/dead-code-detector.js +27 -31
  11. package/dist/dependency-vulnerability-gate.js +18 -15
  12. package/dist/diff-summary.js +19 -128
  13. package/dist/doc-sync-guard.js +24 -39
  14. package/dist/duplicate-code-detector.js +30 -169
  15. package/dist/feature-flag-tracker.js +26 -71
  16. package/dist/file-watcher.js +19 -23
  17. package/dist/format-on-save.js +25 -214
  18. package/dist/import-organizer.js +31 -106
  19. package/dist/index.js +452 -1236
  20. package/dist/interface-contract-guard.js +26 -71
  21. package/dist/lint-gate.js +19 -111
  22. package/dist/migration-planner.js +28 -120
  23. package/dist/notify-hub.js +18 -28
  24. package/dist/path-guard.js +27 -102
  25. package/dist/pr-drafter.js +18 -16
  26. package/dist/prompt-firewall.js +8 -205
  27. package/dist/refactor-suggester.js +27 -166
  28. package/dist/release-notes-generator.js +6 -35
  29. package/dist/runtime/bounded-map.d.ts +2 -85
  30. package/dist/runtime/credential-patterns.d.ts +2 -41
  31. package/dist/runtime/h1-state.d.ts +2 -61
  32. package/dist/runtime/handles.d.ts +2 -45
  33. package/dist/runtime/index.d.ts +8 -180
  34. package/dist/runtime/llm.d.ts +2 -43
  35. package/dist/runtime/local-bin.d.ts +2 -119
  36. package/dist/runtime/redos-guard.d.ts +2 -68
  37. package/dist/runtime/safe-json.d.ts +2 -24
  38. package/dist/runtime/sandbox.d.ts +2 -58
  39. package/dist/runtime.js +1 -868
  40. package/dist/schema-evolution-guard.js +20 -24
  41. package/dist/secret-scanner.js +22 -146
  42. package/dist/security-hotspot-scanner.js +24 -154
  43. package/dist/session-recap.js +16 -14
  44. package/dist/spec-linker.js +19 -17
  45. package/dist/template-engine.js +22 -37
  46. package/dist/test-coverage-gate.js +19 -34
  47. package/dist/test-generator.js +6 -35
  48. package/dist/test-runner-gate.js +34 -143
  49. package/dist/todo-listener.js +17 -38
  50. package/dist/type-gate.js +23 -311
  51. package/package.json +4 -3
@@ -1,29 +1,25 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
1
15
  // src/schema-evolution-guard/index.ts
2
16
  import { readFileSync } from "node:fs";
3
- import { basename as basename2 } from "node:path";
17
+ import { basename } from "node:path";
4
18
 
5
19
  // src/runtime/index.ts
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/index.ts
12
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
13
- function hasLeadingDash(arg) {
14
- return arg.length > 0 && arg.startsWith("-");
15
- }
16
- function withinProjectPath(projectRoot, candidate) {
17
- if (candidate.length === 0 || candidate.length > 4096) return false;
18
- if (hasLeadingDash(candidate)) return false;
19
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
20
- const rel = relative(projectRoot, resolved);
21
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
22
- }
23
- function withinProject(p) {
24
- const cwd = process.cwd();
25
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
26
- }
20
+ var runtime_exports = {};
21
+ __reExport(runtime_exports, runtime_star);
22
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
27
23
 
28
24
  // src/schema-evolution-guard/index.ts
29
25
  var API_VERSION = "^0.1.10";
@@ -212,7 +208,7 @@ var plugin = {
212
208
  const filePath = typeof toolInput["path"] === "string" ? toolInput["path"] : void 0;
213
209
  if (!filePath) return;
214
210
  state.invocationCount += 1;
215
- const fileName = basename2(filePath);
211
+ const fileName = basename(filePath);
216
212
  if (!matchesAnyPattern(fileName, cfg.filePatterns)) {
217
213
  state.skippedCount += 1;
218
214
  return;
@@ -225,7 +221,7 @@ var plugin = {
225
221
  let content;
226
222
  if (typeof toolInput["content"] === "string") {
227
223
  content = toolInput["content"];
228
- } else if (withinProject(filePath)) {
224
+ } else if ((0, runtime_exports.withinProject)(filePath)) {
229
225
  try {
230
226
  content = readFileSync(filePath, "utf-8");
231
227
  } catch {
@@ -1,151 +1,27 @@
1
- // src/runtime/credential-patterns.ts
2
- var CREDENTIAL_PATTERNS = [
3
- // LLM provider keys
4
- {
5
- type: "anthropic_key",
6
- regex: /(?<![A-Za-z0-9])sk-ant-api\d+-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g
7
- },
8
- { type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?!ant)(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g },
9
- // GitHub. `ghp_` is only the personal-access-token prefix the OAuth
10
- // (`gho_`), user-to-server (`ghu_`), server-to-server (`ghs_`) and
11
- // refresh (`ghr_`) tokens grant the same or broader access and were
12
- // previously not detected at all.
13
- { type: "github_pat", regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g },
14
- {
15
- type: "github_oauth_token",
16
- regex: /(?<![A-Za-z0-9])gh[ousr]_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g
17
- },
18
- { type: "github_pat_v2", regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g },
19
- // GitLab
20
- { type: "gitlab_pat", regex: /(?<![A-Za-z0-9])glpat-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
21
- {
22
- type: "gitlab_runner_token",
23
- regex: /(?<![A-Za-z0-9])glrt-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
24
- },
25
- // npm — a leaked publish token is a supply-chain compromise.
26
- { type: "npm_token", regex: /(?<![A-Za-z0-9])npm_[A-Za-z0-9]{36}(?![A-Za-z0-9])/g },
27
- // AWS
28
- { type: "aws_access_key", regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g },
29
- // GCP
30
- { type: "gcp_key", regex: /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9])/g },
31
- // Slack. `xoxe` (token-rotation) and `xapp` (app-level) were missing;
32
- // both are as sensitive as the bot/user tokens already covered.
33
- {
34
- type: "slack_token",
35
- regex: /(?<![A-Za-z0-9-])xox[abposer]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g
36
- },
37
- { type: "slack_app_token", regex: /(?<![A-Za-z0-9-])xapp-\d-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g },
38
- {
39
- type: "slack_webhook",
40
- regex: /https:\/\/hooks\.slack\.com\/services\/T[A-Za-z0-9_-]+\/B[A-Za-z0-9_-]+\/[A-Za-z0-9]{16,}/g
41
- },
42
- // Stripe
43
- {
44
- type: "stripe_key",
45
- regex: /(?<![A-Za-z0-9])sk_(?:live|test)_[A-Za-z0-9]{24,}(?![A-Za-z0-9])/g
46
- },
47
- // Twilio
48
- { type: "twilio_sid", regex: /(?<![A-Za-z0-9])AC[a-f0-9]{32}(?![A-Za-z0-9])/g },
49
- // Telegram
50
- {
51
- type: "telegram_bot_token",
52
- regex: /(?:(?<![A-Za-z0-9_])|(?<=(?:^|[^A-Za-z0-9_])bot))\d+:[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
53
- },
54
- // JWT
55
- {
56
- type: "jwt",
57
- regex: /(?<![A-Za-z0-9/+=])eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}(?![A-Za-z0-9/+=])/g
58
- },
59
- // Private keys
60
- {
61
- type: "private_key",
62
- regex: /(?:^|\n)(?:-----BEGIN (?:RSA|EC|OPENSSH|DSA)? ?PRIVATE KEY-----[\s\S]*?-----END (?:RSA|EC|OPENSSH|DSA)? ?PRIVATE KEY-----|-----BEGIN PGP PRIVATE KEY BLOCK-----[\s\S]*?-----END PGP PRIVATE KEY BLOCK-----)(?!\S)/g
63
- },
64
- // AI/ML provider tokens
65
- { type: "huggingface_token", regex: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{34}(?![A-Za-z0-9])/g },
66
- { type: "replicate_token", regex: /(?<![A-Za-z0-9])r8_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
67
- { type: "perplexity_key", regex: /(?<![A-Za-z0-9])pplx-[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
68
- { type: "groq_key", regex: /(?<![A-Za-z0-9])gsk_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
69
- // SaaS / infrastructure tokens — each grants API access on the user's
70
- // account, and each was previously invisible to this gate.
71
- { type: "sendgrid_key", regex: /(?<![A-Za-z0-9])SG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
72
- { type: "digitalocean_token", regex: /(?<![A-Za-z0-9])dop_v1_[a-f0-9]{64}(?![A-Za-z0-9])/g },
73
- { type: "doppler_token", regex: /(?<![A-Za-z0-9])dp\.(?:pt|st|sa|scim|audit)\.[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
74
- { type: "shopify_token", regex: /(?<![A-Za-z0-9])shp(?:at|ca|pa|ss)_[a-fA-F0-9]{32}(?![A-Za-z0-9])/g },
75
- { type: "docker_pat", regex: /(?<![A-Za-z0-9])dckr_pat_[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
76
- { type: "linear_key", regex: /(?<![A-Za-z0-9])lin_api_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
77
- { type: "atlassian_token", regex: /(?<![A-Za-z0-9])ATATT3[A-Za-z0-9_\-=]{40,}(?![A-Za-z0-9_\-=])/g },
78
- { type: "square_token", regex: /(?<![A-Za-z0-9])(?:sq0(?:atp|csp)-|EAAA)[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
79
- {
80
- type: "azure_storage_key",
81
- regex: /AccountKey=[A-Za-z0-9+/]{80,}={0,2}/g
82
- },
83
- {
84
- type: "google_oauth_client_secret",
85
- regex: /(?<![A-Za-z0-9_-])GOCSPX-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
86
- },
87
- // Bearer tokens
88
- {
89
- type: "bearer_token",
90
- regex: /(?<![A-Za-z0-9_.~+/-])Bearer\s+[A-Za-z0-9._~+/-]{12,512}=*(?![A-Za-z0-9._~+/-])/g
91
- },
92
- // Database URIs. Require password-bearing user-info; credential-free values stay scannable.
93
- { type: "mongodb_uri", regex: /mongodb(?:\+srv)?:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g },
94
- {
95
- type: "postgres_uri",
96
- // Query parsers decode percent-encoded parameter names. Recognize each
97
- // encoded character in `password` so mixed forms such as `pass%77ord`
98
- // cannot bypass detection while keeping the scan strictly bounded.
99
- regex: /postgres(?:ql)?:\/\/(?:[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+|[^&\s?"'`#]{1,2048}\?(?:(?!(?:p|%70)(?:a|%61)(?:s|%73)(?:s|%73)(?:w|%77)(?:o|%6[fF])(?:r|%72)(?:d|%64)=)[^&\s#"'`]{1,256}&){0,32}(?:p|%70)(?:a|%61)(?:s|%73)(?:s|%73)(?:w|%77)(?:o|%6[fF])(?:r|%72)(?:d|%64)=[^&\s#"'`]{1,4096})/g
100
- },
101
- { type: "mysql_uri", regex: /mysql:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g },
102
- { type: "redis_uri", regex: /redis:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g },
103
- {
104
- // Credentials serialised as JSON, keyed rather than prefixed. Every other
105
- // entry in this table recognises a credential by its SHAPE (`ghp_`, `sk-`,
106
- // `eyJ`), which means a key with no distinctive prefix — Azure, a
107
- // self-hosted gateway, an Anthropic/Codex OAuth token — was invisible to
108
- // both surfaces. `prompt-firewall` guards the outgoing provider request, so
109
- // this is what stops a JSON-shaped tool result carrying such a value to a
110
- // third party.
111
- //
112
- // The key is matched in a LOOKBEHIND, so the reported match is the secret
113
- // itself and the pattern keeps zero capturing groups — `secret-scanner`
114
- // maps a combined-regex group index back to the pattern that fired, and an
115
- // inner group would shift that mapping (see the style note above, enforced
116
- // by credential-pattern-parity.test.ts).
117
- //
118
- // Mirrors `json_credential_key` in
119
- // `@wrongstack/core` → `src/security/secret-scrubber.ts`. Keep the two key
120
- // lists in step; the core side additionally preserves the key name when it
121
- // rewrites, which is why it is written with capture groups instead.
122
- type: "json_credential_key",
123
- regex: /(?<="[A-Za-z0-9_]{0,64}(?:apiKey|api_key|token|secret|password|authorization|bearer|private_key|access_token|refresh_token|client_secret)"\s{0,8}:\s{0,8}")[^"\\]{8,512}(?=")/gi
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
124
10
  }
125
- ];
126
- function cloneCredentialPatterns() {
127
- return CREDENTIAL_PATTERNS.map((p) => ({
128
- type: p.type,
129
- regex: new RegExp(p.regex.source, p.regex.flags)
130
- }));
131
- }
132
-
133
- // src/runtime/local-bin.ts
134
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
135
14
 
136
- // src/runtime/handles.ts
137
- function releaseHandle(off) {
138
- if (off) {
139
- try {
140
- off();
141
- } catch {
142
- }
143
- }
144
- return null;
145
- }
15
+ // src/runtime/credential-patterns.ts
16
+ import {
17
+ cloneCredentialPatterns,
18
+ CREDENTIAL_PATTERNS
19
+ } from "@wrongstack/plugin-sdk/runtime";
146
20
 
147
21
  // src/runtime/index.ts
148
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
22
+ var runtime_exports = {};
23
+ __reExport(runtime_exports, runtime_star);
24
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
149
25
 
150
26
  // src/secret-scanner/index.ts
151
27
  var BASE_PATTERNS = cloneCredentialPatterns();
@@ -490,8 +366,8 @@ var plugin = {
490
366
  setup(api) {
491
367
  const previous = runtimes.get(api);
492
368
  if (previous) {
493
- previous.state.hookUnregister = releaseHandle(previous.state.hookUnregister);
494
- previous.state.postHookUnregister = releaseHandle(previous.state.postHookUnregister);
369
+ previous.state.hookUnregister = (0, runtime_exports.releaseHandle)(previous.state.hookUnregister);
370
+ previous.state.postHookUnregister = (0, runtime_exports.releaseHandle)(previous.state.postHookUnregister);
495
371
  }
496
372
  const cfg = readConfig(api.config.extensions?.["secret-scanner"]);
497
373
  PATTERNS = [...BASE_PATTERNS];
@@ -1,155 +1,25 @@
1
- // src/security-hotspot-scanner/index.ts
2
- import { readdir, readFile, stat } from "node:fs/promises";
3
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
-
5
- // src/runtime/index.ts
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
- var BoundedSet = class {
105
- inner;
106
- constructor(options) {
107
- this.inner = new BoundedMap(options);
108
- }
109
- has(value) {
110
- return this.inner.has(value);
111
- }
112
- add(value) {
113
- this.inner.set(value, true);
114
- return this;
115
- }
116
- delete(value) {
117
- return this.inner.delete(value);
118
- }
119
- clear() {
120
- this.inner.clear();
121
- }
122
- get size() {
123
- return this.inner.size;
124
- }
125
- /** How many entries have been dropped to respect `max`, since the last clear. */
126
- get evictionCount() {
127
- return this.inner.evictionCount;
128
- }
129
- *values() {
130
- for (const [key] of this.inner) yield key;
131
- }
132
- [Symbol.iterator]() {
133
- return this.values();
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
134
10
  }
11
+ return to;
135
12
  };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
15
+ // src/security-hotspot-scanner/index.ts
16
+ import { readdir, readFile, stat } from "node:fs/promises";
17
+ import { isAbsolute, relative, resolve } from "node:path";
136
18
 
137
19
  // src/runtime/index.ts
138
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
139
- function hasLeadingDash(arg) {
140
- return arg.length > 0 && arg.startsWith("-");
141
- }
142
- function withinProjectPath(projectRoot, candidate) {
143
- if (candidate.length === 0 || candidate.length > 4096) return false;
144
- if (hasLeadingDash(candidate)) return false;
145
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
146
- const rel = relative(projectRoot, resolved);
147
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
148
- }
149
- function withinProject(p) {
150
- const cwd = process.cwd();
151
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
152
- }
20
+ var runtime_exports = {};
21
+ __reExport(runtime_exports, runtime_star);
22
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
153
23
 
154
24
  // src/security-hotspot-scanner/index.ts
155
25
  var API_VERSION = "^0.1.10";
@@ -161,7 +31,7 @@ var state = {
161
31
  skippedCount: 0,
162
32
  blockedCount: 0,
163
33
  lastResult: null,
164
- knownHotspots: new BoundedSet({ max: 5e3 }),
34
+ knownHotspots: new runtime_exports.BoundedSet({ max: 5e3 }),
165
35
  hookUnregister: null
166
36
  };
167
37
  var DEFAULTS = {
@@ -242,8 +112,8 @@ function isSourceFile(filePath, extensions) {
242
112
  async function scanPath(inputPath, cfg) {
243
113
  const start = Date.now();
244
114
  const root = process.cwd();
245
- const resolved = isAbsolute2(inputPath) ? resolve2(inputPath) : resolve2(root, inputPath);
246
- if (!withinProject(inputPath)) {
115
+ const resolved = isAbsolute(inputPath) ? resolve(inputPath) : resolve(root, inputPath);
116
+ if (!(0, runtime_exports.withinProject)(inputPath)) {
247
117
  return {
248
118
  path: inputPath,
249
119
  scanned: false,
@@ -263,7 +133,7 @@ async function scanPath(inputPath, cfg) {
263
133
  filesScanned += 1;
264
134
  const findings = scanSource(content, maxPerFile);
265
135
  for (const f of findings) {
266
- allFindings.push({ ...f, snippet: `${relative2(root, filePath)}:${f.line}: ${f.snippet}` });
136
+ allFindings.push({ ...f, snippet: `${relative(root, filePath)}:${f.line}: ${f.snippet}` });
267
137
  if (allFindings.length >= cfg.maxFindings) return;
268
138
  }
269
139
  } catch {
@@ -278,7 +148,7 @@ async function scanPath(inputPath, cfg) {
278
148
  }
279
149
  for (const entry of entries) {
280
150
  if (allFindings.length >= cfg.maxFindings) return;
281
- const full = resolve2(dir, entry);
151
+ const full = resolve(dir, entry);
282
152
  try {
283
153
  const st = await stat(full);
284
154
  if (st.isDirectory()) {
@@ -382,7 +252,7 @@ var plugin = {
382
252
  const inp = input.toolInput ?? {};
383
253
  const sourcePath = inp["path"];
384
254
  if (!sourcePath || typeof sourcePath !== "string") return;
385
- if (!withinProject(sourcePath)) return;
255
+ if (!(0, runtime_exports.withinProject)(sourcePath)) return;
386
256
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
387
257
  if (!scanOnChangeSet.has(ext)) {
388
258
  state.skippedCount += 1;
@@ -1,19 +1,21 @@
1
- // src/runtime/local-bin.ts
2
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
3
-
4
- // src/runtime/handles.ts
5
- function releaseHandle(off) {
6
- if (off) {
7
- try {
8
- off();
9
- } catch {
10
- }
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
10
  }
12
- return null;
13
- }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
14
 
15
15
  // src/runtime/index.ts
16
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
16
+ var runtime_exports = {};
17
+ __reExport(runtime_exports, runtime_star);
18
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
17
19
 
18
20
  // src/session-recap/index.ts
19
21
  var state = {
@@ -206,7 +208,7 @@ var plugin = {
206
208
  state.commitCount = 0;
207
209
  state.startedAt = null;
208
210
  state.lastActivityAt = null;
209
- state.stopHookUnregister = releaseHandle(state.stopHookUnregister);
211
+ state.stopHookUnregister = (0, runtime_exports.releaseHandle)(state.stopHookUnregister);
210
212
  for (const off of state.eventUnsubscribers) {
211
213
  try {
212
214
  off();
@@ -1,22 +1,24 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
1
15
  // src/spec-linker/index.ts
2
16
  import * as fs from "node:fs/promises";
3
17
 
4
- // src/runtime/local-bin.ts
5
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
6
-
7
- // src/runtime/handles.ts
8
- function releaseHandle(off) {
9
- if (off) {
10
- try {
11
- off();
12
- } catch {
13
- }
14
- }
15
- return null;
16
- }
17
-
18
18
  // src/runtime/index.ts
19
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
19
+ var runtime_exports = {};
20
+ __reExport(runtime_exports, runtime_star);
21
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
20
22
 
21
23
  // src/manifest/index.ts
22
24
  var OFFICIAL_PLUGIN_NAMES = [
@@ -348,8 +350,8 @@ var plugin = {
348
350
  state.skippedNonMd = 0;
349
351
  state.readErrorCount = 0;
350
352
  state.autoFixApplied = 0;
351
- state.postHookUnregister = releaseHandle(state.postHookUnregister);
352
- state.preHookUnregister = releaseHandle(state.preHookUnregister);
353
+ state.postHookUnregister = (0, runtime_exports.releaseHandle)(state.postHookUnregister);
354
+ state.preHookUnregister = (0, runtime_exports.releaseHandle)(state.preHookUnregister);
353
355
  const cfg = readConfig(api.config.extensions?.["spec-linker"]);
354
356
  const postHook = async (input) => {
355
357
  if (!cfg.enabled) return;
@@ -1,40 +1,25 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
1
15
  // src/template-engine/index.ts
2
16
  import { readFile, writeFile } from "node:fs/promises";
3
- import { isAbsolute as isAbsolute2 } from "node:path";
4
-
5
- // src/runtime/index.ts
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/handles.ts
12
- function releaseHandle(off) {
13
- if (off) {
14
- try {
15
- off();
16
- } catch {
17
- }
18
- }
19
- return null;
20
- }
17
+ import { isAbsolute } from "node:path";
21
18
 
22
19
  // src/runtime/index.ts
23
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
24
- function hasLeadingDash(arg) {
25
- return arg.length > 0 && arg.startsWith("-");
26
- }
27
- function withinProjectPath(projectRoot, candidate) {
28
- if (candidate.length === 0 || candidate.length > 4096) return false;
29
- if (hasLeadingDash(candidate)) return false;
30
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
31
- const rel = relative(projectRoot, resolved);
32
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
33
- }
34
- function withinProject(p) {
35
- const cwd = process.cwd();
36
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
37
- }
20
+ var runtime_exports = {};
21
+ __reExport(runtime_exports, runtime_star);
22
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
38
23
 
39
24
  // src/template-engine/index.ts
40
25
  var API_VERSION = "^0.1.10";
@@ -92,10 +77,10 @@ function renderTemplateRaw(template, variables) {
92
77
  return result;
93
78
  }
94
79
  function validateRelativeTemplatePath(field, value) {
95
- if (isAbsolute2(value) || value.split(/[\\/]+/).includes("..")) {
80
+ if (isAbsolute(value) || value.split(/[\\/]+/).includes("..")) {
96
81
  return `${field} must be a relative path without ".." components`;
97
82
  }
98
- if (!withinProject(value)) {
83
+ if (!(0, runtime_exports.withinProject)(value)) {
99
84
  return `${field} must resolve inside the project directory`;
100
85
  }
101
86
  return null;
@@ -398,7 +383,7 @@ var plugin = {
398
383
  };
399
384
  }
400
385
  });
401
- contributorUnregister = releaseHandle(contributorUnregister);
386
+ contributorUnregister = (0, runtime_exports.releaseHandle)(contributorUnregister);
402
387
  contributorUnregister = api.registerSystemPromptContributor(async () => [
403
388
  {
404
389
  type: "text",
@@ -414,7 +399,7 @@ var plugin = {
414
399
  teardown(api) {
415
400
  const count = templates.size;
416
401
  templates.clear();
417
- contributorUnregister = releaseHandle(contributorUnregister);
402
+ contributorUnregister = (0, runtime_exports.releaseHandle)(contributorUnregister);
418
403
  api.log.info("template-engine: teardown complete", { cleared: count });
419
404
  },
420
405
  async health() {