@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.
- package/README.md +20 -11
- package/dist/accessibility-auditor/index.d.ts.map +1 -1
- package/dist/accessibility-auditor.js +25 -16
- package/dist/api-compatibility-gate.js +1 -1
- package/dist/auto-doc.js +1 -1
- package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
- package/dist/auto-i18n-extractor.js +20 -12
- package/dist/changelog-writer.js +1 -1
- package/dist/code-metrics/index.d.ts.map +1 -1
- package/dist/code-metrics.js +26 -17
- package/dist/commit-validator.js +1 -1
- package/dist/config-validator.js +1 -1
- package/dist/cron/index.d.ts.map +1 -1
- package/dist/cron.js +29 -0
- package/dist/dead-code-detector/index.d.ts.map +1 -1
- package/dist/dead-code-detector.js +27 -18
- package/dist/dep-guard.js +1 -1
- package/dist/diff-summary/index.d.ts.map +1 -1
- package/dist/diff-summary.js +19 -11
- package/dist/doc-sync-guard/index.d.ts.map +1 -1
- package/dist/doc-sync-guard.js +24 -15
- package/dist/duplicate-code-detector/index.d.ts.map +1 -1
- package/dist/duplicate-code-detector.js +27 -18
- package/dist/error-lens.js +1 -1
- package/dist/feature-flag-tracker/index.d.ts.map +1 -1
- package/dist/feature-flag-tracker.js +26 -17
- package/dist/file-watcher/index.d.ts.map +1 -1
- package/dist/file-watcher.js +15 -2
- package/dist/format-on-save/index.d.ts.map +1 -1
- package/dist/format-on-save.js +19 -11
- package/dist/git-autocommit.js +1 -1
- package/dist/import-organizer/index.d.ts.map +1 -1
- package/dist/import-organizer.js +22 -13
- package/dist/index.d.ts +4 -4
- package/dist/index.js +961 -699
- package/dist/interface-contract-guard/index.d.ts.map +1 -1
- package/dist/interface-contract-guard.js +26 -17
- package/dist/migration-planner/index.d.ts +12 -2
- package/dist/migration-planner/index.d.ts.map +1 -1
- package/dist/migration-planner.js +210 -28
- package/dist/pr-drafter.js +1 -1
- package/dist/refactor-suggester/index.d.ts.map +1 -1
- package/dist/refactor-suggester.js +26 -17
- package/dist/release-notes-generator/index.d.ts +3 -1
- package/dist/release-notes-generator/index.d.ts.map +1 -1
- package/dist/release-notes-generator.js +152 -12
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/llm.d.ts +33 -0
- package/dist/runtime/llm.d.ts.map +1 -0
- package/dist/runtime.js +56 -1
- package/dist/schema-evolution-guard/index.d.ts.map +1 -1
- package/dist/schema-evolution-guard.js +21 -12
- package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
- package/dist/security-hotspot-scanner.js +24 -15
- package/dist/session-recap.js +1 -1
- package/dist/spec-linker.js +961 -699
- package/dist/test-generator/index.d.ts +5 -3
- package/dist/test-generator/index.d.ts.map +1 -1
- package/dist/test-generator.js +169 -26
- package/dist/test-runner-gate/index.d.ts.map +1 -1
- package/dist/test-runner-gate.js +65 -43
- package/dist/type-gate/index.d.ts.map +1 -1
- package/dist/type-gate.js +4 -12
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ under the `BUILTIN_PLUGIN_FACTORIES` array. The canonical default is
|
|
|
68
68
|
| 41 | [`knowledge-graph`](./src/knowledge-graph) | `kg_add_fact`, `kg_query`, `kg_remove_fact`, `kg_status` | System prompt contributor | Persistent structured (subject, relation, object) project facts |
|
|
69
69
|
| 42 | [`dead-code-detector`](./src/dead-code-detector) | `dead_code_scan` | `PostToolUse` | Regex-based scan for exported identifiers that appear unused |
|
|
70
70
|
| 43 | [`dependency-vulnerability-gate`](./src/dependency-vulnerability-gate) | `dependency_audit_status` | `PostToolUse` | Opt-in blocking `npm/pnpm audit` after installs |
|
|
71
|
-
| 44 | [`migration-planner`](./src/migration-planner) | `migration_plan`, `migration_status` | `PostToolUse` |
|
|
71
|
+
| 44 | [`migration-planner`](./src/migration-planner) | `migration_plan`, `migration_status` | `PostToolUse` | Evidence-backed checklists + optional `api.llm` risk/verification analysis |
|
|
72
72
|
| 45 | [`semantic-search-indexer`](./src/semantic-search-indexer) | `semantic_search`, `semantic_index_status` | — | Lightweight keyword index over project source files |
|
|
73
73
|
| 46 | [`auto-i18n-extractor`](./src/auto-i18n-extractor) | `i18n_extract`, `i18n_status` | `PostToolUse` | Detects hardcoded user-facing strings and suggests i18n keys |
|
|
74
74
|
| 47 | [`doc-sync-guard`](./src/doc-sync-guard) | `doc_sync_status` | `PostToolUse` | Warns when README/docs edits omit recently changed source files |
|
|
@@ -82,11 +82,12 @@ under the `BUILTIN_PLUGIN_FACTORIES` array. The canonical default is
|
|
|
82
82
|
| 55 | [`duplicate-code-detector`](./src/duplicate-code-detector) | `detect_duplicate_code`, `duplicate_code_status` | `PostToolUse` | Detects duplicate/similar code blocks using normalized-line fingerprints |
|
|
83
83
|
| 56 | [`code-metrics`](./src/code-metrics) | `measure_code_metrics`, `metrics_status` | `PostToolUse` | Computes LOC, comment ratio, function count, and approximate cyclomatic complexity |
|
|
84
84
|
| 57 | [`refactor-suggester`](./src/refactor-suggester) | `suggest_refactors`, `refactor_status` | `PostToolUse` | Flags long functions, deep nesting, many parameters, magic numbers, console.log |
|
|
85
|
-
| 58 | [`test-generator`](./src/test-generator) | `generate_unit_tests` | — |
|
|
86
|
-
| 59 | [`release-notes-generator`](./src/release-notes-generator) | `generate_release_notes` | — |
|
|
85
|
+
| 58 | [`test-generator`](./src/test-generator) | `generate_unit_tests` | — | Framework-correct skeletons + optional behavior-focused `api.llm` tests |
|
|
86
|
+
| 59 | [`release-notes-generator`](./src/release-notes-generator) | `generate_release_notes` | — | Traceable notes + optional hash-preserving `api.llm` polish |
|
|
87
87
|
| 60 | [`smart-rename`](./src/smart-rename) | `smart_rename` | — | Whole-word symbol rename with preview and optional apply |
|
|
88
88
|
| 61 | [`feature-flag-tracker`](./src/feature-flag-tracker) | `scan_feature_flags`, `feature_flag_status` | `PostToolUse` | Scans source files for feature-flag usage and reports flag inventory |
|
|
89
89
|
| 62 | [`interface-contract-guard`](./src/interface-contract-guard) | `check_interface_contracts`, `interface_contract_status` | `PostToolUse` | Warns when TypeScript interfaces change or lack implementers |
|
|
90
|
+
| 63 | [`plugin-stack-observer`](./src/plugin-stack-observer) | `plugin_stack_status` | Event listener + optional system prompt contributor | Reports active provider-runner wrappers in registration order |
|
|
90
91
|
|
|
91
92
|
### Removed plugins (use built-in tools instead)
|
|
92
93
|
|
|
@@ -97,7 +98,7 @@ under the `BUILTIN_PLUGIN_FACTORIES` array. The canonical default is
|
|
|
97
98
|
|
|
98
99
|
If a user lists either name in `config.plugins`, the loader emits a
|
|
99
100
|
one-shot `log.warn` and skips loading. See
|
|
100
|
-
[`DEPRECATED_PLUGIN_NAMES`](
|
|
101
|
+
[`DEPRECATED_PLUGIN_NAMES`](../cli/src/wiring/plugins.ts)
|
|
101
102
|
in `packages/cli/src/wiring/plugins.ts` for the canonical list and
|
|
102
103
|
migration hints.
|
|
103
104
|
|
|
@@ -701,7 +702,7 @@ context. Increase `includeTranscriptTail` for more history.
|
|
|
701
702
|
Two hooks working together:
|
|
702
703
|
|
|
703
704
|
**PostToolUse** (always active when the plugin is enabled):
|
|
704
|
-
scans markdown files for *unlinked* references to one of the
|
|
705
|
+
scans markdown files for *unlinked* references to one of the 63
|
|
705
706
|
known plugins and surfaces them to the LLM via
|
|
706
707
|
`additionalContext`. The plugin does NOT modify the file — it
|
|
707
708
|
only injects a low-noise context block listing the unlinked
|
|
@@ -1043,18 +1044,26 @@ There are two surfaces for plugin configuration:
|
|
|
1043
1044
|
{
|
|
1044
1045
|
"plugins": [
|
|
1045
1046
|
{ "name": "auto-doc", "enabled": true },
|
|
1046
|
-
{
|
|
1047
|
+
{
|
|
1048
|
+
"name": "git-autocommit",
|
|
1049
|
+
"enabled": true,
|
|
1050
|
+
"options": { "conventionalCommits": true }
|
|
1051
|
+
}
|
|
1047
1052
|
]
|
|
1048
1053
|
}
|
|
1049
1054
|
```
|
|
1050
|
-
2. **Options** — `
|
|
1051
|
-
plugin
|
|
1052
|
-
|
|
1055
|
+
2. **Options** — set an entry's `options` field or use
|
|
1056
|
+
`config.extensions["<plugin-name>"]`; the CLI merges both before `setup()`.
|
|
1057
|
+
If both are present, `config.extensions` wins for duplicate keys.
|
|
1053
1058
|
|
|
1054
1059
|
```jsonc
|
|
1055
1060
|
{
|
|
1056
|
-
"plugins":
|
|
1057
|
-
"auto-doc"
|
|
1061
|
+
"plugins": [
|
|
1062
|
+
{ "name": "auto-doc", "enabled": true },
|
|
1063
|
+
{ "name": "git-autocommit", "enabled": true },
|
|
1064
|
+
{ "name": "secret-scanner", "enabled": true }
|
|
1065
|
+
],
|
|
1066
|
+
"extensions": {
|
|
1058
1067
|
"git-autocommit": { "conventionalCommits": true },
|
|
1059
1068
|
"secret-scanner": { "mode": "block", "matcher": "bash|write|edit" }
|
|
1060
1069
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,qBAAqB,GACrB,0BAA0B,GAC1B,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AA+RD,QAAA,MAAM,MAAM,EAAE,MA0Nb,CAAC;eAEa,MAAM"}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
// src/accessibility-auditor/index.ts
|
|
2
2
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
-
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
|
+
import { 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/accessibility-auditor/index.ts
|
|
4
23
|
var API_VERSION = "^0.1.10";
|
|
5
24
|
var state = {
|
|
6
25
|
auditCount: 0,
|
|
@@ -28,16 +47,6 @@ function readConfig(raw) {
|
|
|
28
47
|
onWriteEdit: r["onWriteEdit"] !== false
|
|
29
48
|
};
|
|
30
49
|
}
|
|
31
|
-
function withinProject(p) {
|
|
32
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
33
|
-
const root = process.cwd();
|
|
34
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
35
|
-
const rel = relative(root, resolved);
|
|
36
|
-
if (rel === "" || rel === ".") return true;
|
|
37
|
-
if (rel.startsWith("..")) return false;
|
|
38
|
-
if (isAbsolute(rel)) return false;
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
50
|
function normalizeExtensions(exts) {
|
|
42
51
|
return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
|
|
43
52
|
}
|
|
@@ -63,7 +72,7 @@ function collectUiFiles(root, exts) {
|
|
|
63
72
|
return;
|
|
64
73
|
}
|
|
65
74
|
for (const entry of entries) {
|
|
66
|
-
const full =
|
|
75
|
+
const full = resolve2(dir, entry);
|
|
67
76
|
let st;
|
|
68
77
|
try {
|
|
69
78
|
st = statSync(full);
|
|
@@ -109,7 +118,7 @@ function auditFile(filePath, projectRoot) {
|
|
|
109
118
|
const idsByValue = /* @__PURE__ */ new Map();
|
|
110
119
|
function add(line, rule, severity, message) {
|
|
111
120
|
findings.push({
|
|
112
|
-
file:
|
|
121
|
+
file: relative2(projectRoot, filePath),
|
|
113
122
|
line,
|
|
114
123
|
rule,
|
|
115
124
|
severity,
|
|
@@ -188,7 +197,7 @@ function auditFile(filePath, projectRoot) {
|
|
|
188
197
|
}
|
|
189
198
|
function auditPath(rawPath, cfg) {
|
|
190
199
|
const root = process.cwd();
|
|
191
|
-
const resolved =
|
|
200
|
+
const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
|
|
192
201
|
const exts = normalizeExtensions(cfg.includeExtensions);
|
|
193
202
|
const files = collectUiFiles(resolved, exts);
|
|
194
203
|
const findings = [];
|
|
@@ -198,7 +207,7 @@ function auditPath(rawPath, cfg) {
|
|
|
198
207
|
if (findings.length >= cfg.maxFindings) break;
|
|
199
208
|
}
|
|
200
209
|
return {
|
|
201
|
-
path:
|
|
210
|
+
path: relative2(root, resolved),
|
|
202
211
|
findings: findings.slice(0, cfg.maxFindings),
|
|
203
212
|
fileCount: files.length
|
|
204
213
|
};
|
|
@@ -289,7 +298,7 @@ var plugin = {
|
|
|
289
298
|
}
|
|
290
299
|
return { additionalContext: summary };
|
|
291
300
|
};
|
|
292
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
301
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
293
302
|
api.tools.register({
|
|
294
303
|
name: "a11y_audit",
|
|
295
304
|
description: "Audit a file or directory for accessibility issues. Scans .tsx/.jsx/.html/.vue files for missing alt text, missing labels, low-contrast placeholders, missing button text, and duplicate ids.",
|
|
@@ -279,7 +279,7 @@ var plugin = {
|
|
|
279
279
|
}
|
|
280
280
|
return { additionalContext: message };
|
|
281
281
|
};
|
|
282
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
282
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
283
283
|
api.tools.register({
|
|
284
284
|
name: "api_compat_status",
|
|
285
285
|
description: "Reports api-compatibility-gate state: severity, entry-point patterns, and per-session counters.",
|
package/dist/auto-doc.js
CHANGED
|
@@ -241,7 +241,7 @@ var plugin = {
|
|
|
241
241
|
version: "0.2.0",
|
|
242
242
|
description: "Auto-generates JSDoc/TSDoc comments for functions, classes, types, and interfaces",
|
|
243
243
|
apiVersion: AUTO_DOC_API_VERSION,
|
|
244
|
-
capabilities: { tools: true, pipelines: ["toolCall"] },
|
|
244
|
+
capabilities: { tools: true, pipelines: ["toolCall"], llm: true },
|
|
245
245
|
defaultConfig: {
|
|
246
246
|
style: "tsdoc",
|
|
247
247
|
includeTypes: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auto-i18n-extractor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auto-i18n-extractor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwK/C,QAAA,MAAM,MAAM,EAAE,MAsQb,CAAC;eAEa,MAAM"}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
// src/auto-i18n-extractor/index.ts
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
-
|
|
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/auto-i18n-extractor/index.ts
|
|
4
22
|
var API_VERSION = "^0.1.10";
|
|
5
23
|
var state = {
|
|
6
24
|
filesScanned: 0,
|
|
@@ -41,16 +59,6 @@ function readConfig(raw) {
|
|
|
41
59
|
excludeAttributes: Array.isArray(r["excludeAttributes"]) ? r["excludeAttributes"].filter((x) => typeof x === "string") : DEFAULTS.excludeAttributes
|
|
42
60
|
};
|
|
43
61
|
}
|
|
44
|
-
function withinProject(p) {
|
|
45
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
46
|
-
const root = process.cwd();
|
|
47
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
48
|
-
const rel = relative(root, resolved);
|
|
49
|
-
if (rel === "" || rel === ".") return true;
|
|
50
|
-
if (rel.startsWith("..")) return false;
|
|
51
|
-
if (isAbsolute(rel)) return false;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
62
|
function fileExtension(p) {
|
|
55
63
|
const dot = p.lastIndexOf(".");
|
|
56
64
|
return dot > 0 ? p.slice(dot).toLowerCase() : "";
|
|
@@ -201,7 +209,7 @@ var plugin = {
|
|
|
201
209
|
${lines.join("\n")}${more}`;
|
|
202
210
|
return { additionalContext: context };
|
|
203
211
|
};
|
|
204
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
212
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
205
213
|
api.tools.register({
|
|
206
214
|
name: "i18n_extract",
|
|
207
215
|
description: "Scan a UI source file (.tsx/.jsx/.vue) for hardcoded user-facing string literals and return suggested i18n keys.",
|
package/dist/changelog-writer.js
CHANGED
|
@@ -138,7 +138,7 @@ var plugin = {
|
|
|
138
138
|
version: "0.1.0",
|
|
139
139
|
description: "Collects session work (commits, edits, manual notes) and writes Keep-a-Changelog entries under [Unreleased] on demand",
|
|
140
140
|
apiVersion: "^0.1.10",
|
|
141
|
-
capabilities: { tools: true },
|
|
141
|
+
capabilities: { tools: true, llm: true },
|
|
142
142
|
defaultConfig: { ...DEFAULTS },
|
|
143
143
|
configSchema: {
|
|
144
144
|
type: "object",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoP/C,QAAA,MAAM,MAAM,EAAE,MAgMb,CAAC;eAEa,MAAM"}
|
package/dist/code-metrics.js
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
// src/code-metrics/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/code-metrics/index.ts
|
|
4
23
|
var API_VERSION = "^0.1.10";
|
|
5
24
|
var state = {
|
|
6
25
|
measureCount: 0,
|
|
@@ -23,16 +42,6 @@ function readConfig(raw) {
|
|
|
23
42
|
maxFiles: typeof r["maxFiles"] === "number" && r["maxFiles"] >= 1 && r["maxFiles"] <= 500 ? r["maxFiles"] : DEFAULTS.maxFiles
|
|
24
43
|
};
|
|
25
44
|
}
|
|
26
|
-
function withinProject(p) {
|
|
27
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
28
|
-
const root = process.cwd();
|
|
29
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
30
|
-
const rel = relative(root, resolved);
|
|
31
|
-
if (rel === "" || rel === ".") return true;
|
|
32
|
-
if (rel.startsWith("..")) return false;
|
|
33
|
-
if (isAbsolute(rel)) return false;
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
45
|
function normalizeExtensions(exts) {
|
|
37
46
|
return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
|
|
38
47
|
}
|
|
@@ -57,7 +66,7 @@ function collectSourceFiles(root, exts) {
|
|
|
57
66
|
}
|
|
58
67
|
for (const entry of entries) {
|
|
59
68
|
if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
|
|
60
|
-
const full =
|
|
69
|
+
const full = resolve2(dir, entry);
|
|
61
70
|
let st;
|
|
62
71
|
try {
|
|
63
72
|
st = statSync(full);
|
|
@@ -78,7 +87,7 @@ function toPosix(p) {
|
|
|
78
87
|
return p.replace(/\\/g, "/");
|
|
79
88
|
}
|
|
80
89
|
function relativePath(p) {
|
|
81
|
-
return toPosix(
|
|
90
|
+
return toPosix(relative2(process.cwd(), p));
|
|
82
91
|
}
|
|
83
92
|
function countFunctions(content) {
|
|
84
93
|
let count = 0;
|
|
@@ -155,7 +164,7 @@ function analyzeFile(filePath, content) {
|
|
|
155
164
|
}
|
|
156
165
|
function measurePath(rawPath, cfg) {
|
|
157
166
|
const root = process.cwd();
|
|
158
|
-
const resolved =
|
|
167
|
+
const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
|
|
159
168
|
const exts = normalizeExtensions(cfg.extensions);
|
|
160
169
|
const allFiles = collectSourceFiles(resolved, exts);
|
|
161
170
|
const files = allFiles.slice(0, cfg.maxFiles);
|
|
@@ -218,7 +227,7 @@ var plugin = {
|
|
|
218
227
|
const exts = normalizeExtensions(cfg.extensions);
|
|
219
228
|
if (!matchesExtension(sourcePath, exts)) return;
|
|
220
229
|
state.hookInvocationCount += 1;
|
|
221
|
-
const resolved =
|
|
230
|
+
const resolved = resolve2(process.cwd(), sourcePath);
|
|
222
231
|
let content;
|
|
223
232
|
try {
|
|
224
233
|
content = readFileSync(resolved, "utf-8");
|
|
@@ -232,7 +241,7 @@ var plugin = {
|
|
|
232
241
|
\u{1F4CA} code-metrics: ${relativePath(resolved)} \u2014 ${metrics.lines} lines (${metrics.codeLines} code, ${metrics.commentLines} comments, ${metrics.blankLines} blank), ${metrics.functionCount} function(s), complexity ${metrics.complexity}.`
|
|
233
242
|
};
|
|
234
243
|
};
|
|
235
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
244
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
236
245
|
api.tools.register({
|
|
237
246
|
name: "measure_code_metrics",
|
|
238
247
|
description: "Measure lines, comments, blank lines, function count, and cyclomatic-complexity-like score for a source file or directory.",
|
|
@@ -262,7 +271,7 @@ var plugin = {
|
|
|
262
271
|
state.fileCount += result.files.length;
|
|
263
272
|
return {
|
|
264
273
|
ok: true,
|
|
265
|
-
path: relativePath(
|
|
274
|
+
path: relativePath(resolve2(process.cwd(), rawPath)),
|
|
266
275
|
files: result.files,
|
|
267
276
|
totalFiles: result.totalFiles,
|
|
268
277
|
capped: result.totalFiles > cfg.maxFiles
|
package/dist/commit-validator.js
CHANGED
|
@@ -130,7 +130,7 @@ var plugin = {
|
|
|
130
130
|
version: "0.1.0",
|
|
131
131
|
description: "PreToolUse hook that validates conventional-commit format before git_autocommit or bash git commit runs",
|
|
132
132
|
apiVersion: API_VERSION,
|
|
133
|
-
capabilities: { tools: true, hooks: true },
|
|
133
|
+
capabilities: { tools: true, hooks: true, llm: true },
|
|
134
134
|
defaultConfig: { ...DEFAULTS },
|
|
135
135
|
configSchema: {
|
|
136
136
|
type: "object",
|
package/dist/config-validator.js
CHANGED
|
@@ -282,7 +282,7 @@ var plugin = {
|
|
|
282
282
|
\u2026 and ${problems.length - 10} more` : "") + "\nFix these before moving on \u2014 downstream tools will fail on this file."
|
|
283
283
|
};
|
|
284
284
|
};
|
|
285
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
285
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
286
286
|
api.tools.register({
|
|
287
287
|
name: "config_validator_status",
|
|
288
288
|
description: "Reports config-validator state: watched extensions and counters (files checked, problems found).",
|
package/dist/cron/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cron/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cron/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA+F/C,QAAA,MAAM,MAAM,EAAE,MAqRb,CAAC;eAEa,MAAM"}
|
package/dist/cron.js
CHANGED
|
@@ -11,6 +11,19 @@ function formatNextRun(intervalMs) {
|
|
|
11
11
|
const ms = Number.isNaN(intervalMs) || intervalMs <= 0 ? 6e4 : intervalMs;
|
|
12
12
|
return new Date(Date.now() + ms).toISOString();
|
|
13
13
|
}
|
|
14
|
+
function buildSnapshot(s, maxConcurrent) {
|
|
15
|
+
const jobs = Array.from(s.jobs.values()).map((j) => ({
|
|
16
|
+
name: j.name,
|
|
17
|
+
intervalMs: j.intervalMs,
|
|
18
|
+
action: j.action,
|
|
19
|
+
enabled: j.enabled,
|
|
20
|
+
lastRun: j.lastRun,
|
|
21
|
+
nextRun: j.nextRun,
|
|
22
|
+
runCount: j.runCount,
|
|
23
|
+
overdue: new Date(j.nextRun).getTime() < Date.now()
|
|
24
|
+
}));
|
|
25
|
+
return { count: jobs.length, maxConcurrent, jobs };
|
|
26
|
+
}
|
|
14
27
|
function clearCronResources() {
|
|
15
28
|
for (const timer of state.timers.values()) {
|
|
16
29
|
clearTimeout(timer);
|
|
@@ -64,6 +77,7 @@ var plugin = {
|
|
|
64
77
|
runCount: job.runCount,
|
|
65
78
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
66
79
|
});
|
|
80
|
+
api.emitCustom("cron:state_snapshot", buildSnapshot(state, maxConcurrent));
|
|
67
81
|
api.metrics.counter("cron_job_fired", 1, { job: name });
|
|
68
82
|
api.metrics.histogram("cron_job_interval_ms", job.intervalMs, { job: name });
|
|
69
83
|
scheduleNextRun(name);
|
|
@@ -165,6 +179,7 @@ var plugin = {
|
|
|
165
179
|
state.jobs.set(name, job);
|
|
166
180
|
scheduleNextRun(name);
|
|
167
181
|
api.metrics.gauge("cron_active_jobs", state.jobs.size);
|
|
182
|
+
api.emitCustom("cron:state_snapshot", buildSnapshot(state, maxConcurrent));
|
|
168
183
|
return {
|
|
169
184
|
ok: true,
|
|
170
185
|
name,
|
|
@@ -220,6 +235,7 @@ var plugin = {
|
|
|
220
235
|
}
|
|
221
236
|
cancelJob(name);
|
|
222
237
|
api.metrics.gauge("cron_active_jobs", state.jobs.size);
|
|
238
|
+
api.emitCustom("cron:state_snapshot", buildSnapshot(state, maxConcurrent));
|
|
223
239
|
return {
|
|
224
240
|
ok: true,
|
|
225
241
|
name,
|
|
@@ -232,6 +248,19 @@ var plugin = {
|
|
|
232
248
|
teardown(api) {
|
|
233
249
|
clearCronResources();
|
|
234
250
|
api.log.info("cron plugin unloaded");
|
|
251
|
+
},
|
|
252
|
+
async health() {
|
|
253
|
+
const jobs = Array.from(state.jobs.values());
|
|
254
|
+
const overdue = jobs.filter(
|
|
255
|
+
(job) => job.enabled && new Date(job.nextRun).getTime() < Date.now()
|
|
256
|
+
).length;
|
|
257
|
+
return {
|
|
258
|
+
ok: overdue === 0,
|
|
259
|
+
message: overdue > 0 ? `cron: ${overdue} overdue job(s) out of ${jobs.length}` : `cron: ${jobs.length} active job(s)`,
|
|
260
|
+
activeJobs: jobs.length,
|
|
261
|
+
overdueJobs: overdue,
|
|
262
|
+
totalRuns: jobs.reduce((sum, job) => sum + job.runCount, 0)
|
|
263
|
+
};
|
|
235
264
|
}
|
|
236
265
|
};
|
|
237
266
|
var cron_default = plugin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dead-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dead-code-detector/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAiQ/C,QAAA,MAAM,MAAM,EAAE,MAkOb,CAAC;eAEa,MAAM"}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
// src/dead-code-detector/index.ts
|
|
2
2
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
-
import { extname,
|
|
3
|
+
import { extname, join, 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/dead-code-detector/index.ts
|
|
4
23
|
var API_VERSION = "^0.1.10";
|
|
5
24
|
var state = {
|
|
6
25
|
scanCount: 0,
|
|
@@ -51,7 +70,7 @@ function gatherFiles(root, depth, cfg) {
|
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
72
|
}
|
|
54
|
-
walk(
|
|
73
|
+
walk(resolve2(root), depth);
|
|
55
74
|
return files;
|
|
56
75
|
}
|
|
57
76
|
function stripNoise(content) {
|
|
@@ -134,22 +153,12 @@ function scan(root, depth, cfg) {
|
|
|
134
153
|
}
|
|
135
154
|
return { findings: findUnusedSymbols(files), scannedFiles: files.length };
|
|
136
155
|
}
|
|
137
|
-
function withinProject(p) {
|
|
138
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
139
|
-
const root = process.cwd();
|
|
140
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
141
|
-
const rel = relative(root, resolved);
|
|
142
|
-
if (rel === "" || rel === ".") return true;
|
|
143
|
-
if (rel.startsWith("..")) return false;
|
|
144
|
-
if (isAbsolute(rel)) return false;
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
156
|
function resolveScanRoot(rawPath) {
|
|
148
|
-
const resolved =
|
|
157
|
+
const resolved = resolve2(process.cwd(), rawPath);
|
|
149
158
|
try {
|
|
150
159
|
const stats = statSync(resolved);
|
|
151
160
|
if (!stats.isDirectory()) {
|
|
152
|
-
return
|
|
161
|
+
return resolve2(resolved, "..");
|
|
153
162
|
}
|
|
154
163
|
} catch {
|
|
155
164
|
}
|
|
@@ -159,7 +168,7 @@ function toPosix(p) {
|
|
|
159
168
|
return p.replace(/\\/g, "/");
|
|
160
169
|
}
|
|
161
170
|
function relativePath(p) {
|
|
162
|
-
return toPosix(
|
|
171
|
+
return toPosix(relative2(process.cwd(), p));
|
|
163
172
|
}
|
|
164
173
|
var plugin = {
|
|
165
174
|
name: "dead-code-detector",
|
|
@@ -230,8 +239,8 @@ var plugin = {
|
|
|
230
239
|
state.errorCount += 1;
|
|
231
240
|
return;
|
|
232
241
|
}
|
|
233
|
-
const changedFile =
|
|
234
|
-
const relevant = result.findings.filter((f) =>
|
|
242
|
+
const changedFile = resolve2(process.cwd(), sourcePath);
|
|
243
|
+
const relevant = result.findings.filter((f) => resolve2(f.file) === changedFile);
|
|
235
244
|
if (relevant.length === 0) {
|
|
236
245
|
state.missCount += 1;
|
|
237
246
|
return;
|
|
@@ -247,7 +256,7 @@ ${list}
|
|
|
247
256
|
Consider removing the export if it is not part of the public API.`;
|
|
248
257
|
return { additionalContext: message };
|
|
249
258
|
};
|
|
250
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
259
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
251
260
|
api.tools.register({
|
|
252
261
|
name: "dead_code_scan",
|
|
253
262
|
description: "Scan TypeScript/JavaScript source files for exported symbols that appear unused anywhere in the project.",
|
package/dist/dep-guard.js
CHANGED
|
@@ -138,7 +138,7 @@ var plugin = {
|
|
|
138
138
|
version: "0.1.0",
|
|
139
139
|
description: "Supervises dependency installs: blocks deny-listed packages, flags typosquat lookalikes, and optionally warns on unpinned versions",
|
|
140
140
|
apiVersion: "^0.1.10",
|
|
141
|
-
capabilities: { tools: true, hooks: true },
|
|
141
|
+
capabilities: { tools: true, hooks: true, llm: true },
|
|
142
142
|
defaultConfig: { ...DEFAULTS },
|
|
143
143
|
configSchema: {
|
|
144
144
|
type: "object",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff-summary/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff-summary/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwP/C,QAAA,MAAM,MAAM,EAAE,MA4Pb,CAAC;eAEa,MAAM"}
|
package/dist/diff-summary.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
// src/diff-summary/index.ts
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
}
|
|
5
17
|
function withinProject(p) {
|
|
6
|
-
|
|
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;
|
|
18
|
+
return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
|
|
14
19
|
}
|
|
20
|
+
|
|
21
|
+
// src/diff-summary/index.ts
|
|
22
|
+
var API_VERSION = "^0.1.10";
|
|
15
23
|
var state = {
|
|
16
24
|
invocationCount: 0,
|
|
17
25
|
/** Times a diff was successfully generated and injected. */
|
|
@@ -243,7 +251,7 @@ var plugin = {
|
|
|
243
251
|
additionalContext: header + summary
|
|
244
252
|
};
|
|
245
253
|
};
|
|
246
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
254
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
247
255
|
api.tools.register({
|
|
248
256
|
name: "diff_summary_status",
|
|
249
257
|
description: "Reports diff-summary state: mode, maxLines, and per-session invocation/injected/fallback counters.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doc-sync-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doc-sync-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA0I/C,QAAA,MAAM,MAAM,EAAE,MAuJb,CAAC;eAEa,MAAM"}
|