@wrongstack/plugins 0.300.0 → 0.301.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 +3 -1
- package/dist/config-validator.js +32 -2
- package/dist/index.js +1328 -49
- package/dist/path-guard/index.d.ts +14 -12
- package/dist/path-guard.js +1226 -38
- package/dist/plugin-audit-catalog.js +7 -0
- package/dist/pr-drafter.js +8 -2
- package/dist/shell-check.js +1 -0
- package/dist/smart-rename.js +5 -1
- package/dist/template-engine.js +51 -6
- package/dist/test-generator.js +30 -0
- package/package.json +3 -3
|
@@ -466,6 +466,13 @@ var HOST_PLUGIN_AUDIT_ENTRIES = [
|
|
|
466
466
|
defaultState: "active",
|
|
467
467
|
canDisable: true
|
|
468
468
|
},
|
|
469
|
+
{
|
|
470
|
+
name: "wstack-cloud-config-sync",
|
|
471
|
+
risk: "medium",
|
|
472
|
+
summary: "my.wrongstack.com config synchronization over the namespaced sync API.",
|
|
473
|
+
defaultState: "active",
|
|
474
|
+
canDisable: true
|
|
475
|
+
},
|
|
469
476
|
{
|
|
470
477
|
name: "wstack-chimera",
|
|
471
478
|
risk: "medium",
|
package/dist/pr-drafter.js
CHANGED
|
@@ -267,9 +267,15 @@ var plugin = {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
},
|
|
270
|
-
|
|
270
|
+
// Writes the draft to disk (`writeFile` below), so `mutating: false` was
|
|
271
|
+
// not just a missing capability — it actively LIED, letting even a gate
|
|
272
|
+
// that reads `mutating` correctly through. It also flipped the tool onto
|
|
273
|
+
// the wrong side of `smoke.test.ts`, which skips `mutating: true` tools:
|
|
274
|
+
// this one was exercised by the suite and wrote to the repo during it.
|
|
275
|
+
permission: "confirm",
|
|
271
276
|
category: "Workflow",
|
|
272
|
-
mutating:
|
|
277
|
+
mutating: true,
|
|
278
|
+
capabilities: ["fs.write"],
|
|
273
279
|
async execute(input) {
|
|
274
280
|
if (!cfg.enabled) return { ok: false, error: "pr-drafter is disabled" };
|
|
275
281
|
const draft = await buildDraft(cfg, api.llm);
|
package/dist/shell-check.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readdir } from "node:fs/promises";
|
|
|
4
4
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
5
5
|
var API_VERSION = "^0.1.10";
|
|
6
6
|
function withinProject(p) {
|
|
7
|
+
if (p.startsWith("-")) return false;
|
|
7
8
|
const root = process.cwd();
|
|
8
9
|
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
9
10
|
const rel = relative(root, resolved);
|
package/dist/smart-rename.js
CHANGED
|
@@ -91,9 +91,13 @@ var plugin = {
|
|
|
91
91
|
},
|
|
92
92
|
required: ["path", "oldName", "newName"]
|
|
93
93
|
},
|
|
94
|
-
|
|
94
|
+
// Rewrites source files on `apply: true`. `auto` + no declared
|
|
95
|
+
// capability meant no confirmation prompt and no read-only-mode block —
|
|
96
|
+
// `readonly-permission-policy` keys on `capabilities`, not `mutating`.
|
|
97
|
+
permission: "confirm",
|
|
95
98
|
category: "Development",
|
|
96
99
|
mutating: true,
|
|
100
|
+
capabilities: ["fs.write"],
|
|
97
101
|
async execute(input) {
|
|
98
102
|
if (!cfg.enabled) return { ok: false, error: "smart-rename is disabled" };
|
|
99
103
|
const rawPath = input.path;
|
package/dist/template-engine.js
CHANGED
|
@@ -100,6 +100,33 @@ function validateRelativeTemplatePath(field, value) {
|
|
|
100
100
|
}
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
|
+
var PROTECTED_WRITE_PREFIXES = [
|
|
104
|
+
".git/",
|
|
105
|
+
".husky/",
|
|
106
|
+
".github/workflows/",
|
|
107
|
+
".wrongstack/",
|
|
108
|
+
".claude/",
|
|
109
|
+
"node_modules/"
|
|
110
|
+
];
|
|
111
|
+
var PROTECTED_WRITE_FILES = /* @__PURE__ */ new Set([
|
|
112
|
+
"package.json",
|
|
113
|
+
"pnpm-workspace.yaml",
|
|
114
|
+
"package-lock.json",
|
|
115
|
+
"pnpm-lock.yaml",
|
|
116
|
+
"yarn.lock",
|
|
117
|
+
".npmrc",
|
|
118
|
+
".gitattributes"
|
|
119
|
+
]);
|
|
120
|
+
function validateWritableTemplateTarget(field, value) {
|
|
121
|
+
const baseError = validateRelativeTemplatePath(field, value);
|
|
122
|
+
if (baseError) return baseError;
|
|
123
|
+
const norm = value.replace(/\\/g, "/").replace(/^\.\//, "").toLowerCase();
|
|
124
|
+
const base = norm.slice(norm.lastIndexOf("/") + 1);
|
|
125
|
+
if (PROTECTED_WRITE_PREFIXES.some((p) => norm.startsWith(p)) || PROTECTED_WRITE_FILES.has(base) || base === ".env" || base.startsWith(".env.")) {
|
|
126
|
+
return `${field} "${value}" is a protected path (VCS hooks, CI workflows, dependency manifests, or agent configuration). Write it with the \`write\` tool instead, which prompts for confirmation.`;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
103
130
|
var plugin = {
|
|
104
131
|
name: "template-engine",
|
|
105
132
|
version: "0.1.0",
|
|
@@ -145,7 +172,14 @@ var plugin = {
|
|
|
145
172
|
},
|
|
146
173
|
required: ["template", "variables"]
|
|
147
174
|
},
|
|
148
|
-
|
|
175
|
+
// Writes caller-supplied content to a caller-supplied path. `auto` +
|
|
176
|
+
// no declared capability meant no confirmation prompt, no read-only-mode
|
|
177
|
+
// block (`readonly-permission-policy` keys on `capabilities`, not
|
|
178
|
+
// `mutating`), and no PreToolUse hook — plugin tools reach the executor
|
|
179
|
+
// through `plugin_manager action:'use'`, which bypasses it.
|
|
180
|
+
permission: "confirm",
|
|
181
|
+
capabilities: ["fs.write"],
|
|
182
|
+
riskTier: "destructive",
|
|
149
183
|
category: "Project",
|
|
150
184
|
mutating: true,
|
|
151
185
|
async execute(input) {
|
|
@@ -166,9 +200,13 @@ var plugin = {
|
|
|
166
200
|
return { ok: false, error: String(err) };
|
|
167
201
|
}
|
|
168
202
|
if (output_path) {
|
|
169
|
-
const pathError =
|
|
203
|
+
const pathError = validateWritableTemplateTarget("output_path", output_path);
|
|
170
204
|
if (pathError) return { ok: false, error: pathError };
|
|
171
|
-
|
|
205
|
+
try {
|
|
206
|
+
await writeFile(output_path, result, "utf-8");
|
|
207
|
+
} catch (err) {
|
|
208
|
+
return { ok: false, error: `Could not write ${output_path}: ${String(err)}` };
|
|
209
|
+
}
|
|
172
210
|
return {
|
|
173
211
|
ok: true,
|
|
174
212
|
output_path,
|
|
@@ -204,7 +242,10 @@ var plugin = {
|
|
|
204
242
|
},
|
|
205
243
|
required: ["template_path", "variables"]
|
|
206
244
|
},
|
|
207
|
-
|
|
245
|
+
// Same reasoning as `template_expand` above.
|
|
246
|
+
permission: "confirm",
|
|
247
|
+
capabilities: ["fs.write"],
|
|
248
|
+
riskTier: "destructive",
|
|
208
249
|
mutating: true,
|
|
209
250
|
async execute(input) {
|
|
210
251
|
const template_path = input["template_path"];
|
|
@@ -232,9 +273,13 @@ var plugin = {
|
|
|
232
273
|
return { ok: false, error: `Template rendering failed: ${err}` };
|
|
233
274
|
}
|
|
234
275
|
if (output_path) {
|
|
235
|
-
const pathError =
|
|
276
|
+
const pathError = validateWritableTemplateTarget("output_path", output_path);
|
|
236
277
|
if (pathError) return { ok: false, error: pathError };
|
|
237
|
-
|
|
278
|
+
try {
|
|
279
|
+
await writeFile(output_path, result, "utf-8");
|
|
280
|
+
} catch (err) {
|
|
281
|
+
return { ok: false, error: `Could not write ${output_path}: ${String(err)}` };
|
|
282
|
+
}
|
|
238
283
|
return {
|
|
239
284
|
ok: true,
|
|
240
285
|
template_path,
|
package/dist/test-generator.js
CHANGED
|
@@ -71,6 +71,30 @@ function readConfig(raw) {
|
|
|
71
71
|
maxSourceChars: typeof r["maxSourceChars"] === "number" && r["maxSourceChars"] >= 1e3 && r["maxSourceChars"] <= 1e5 ? r["maxSourceChars"] : DEFAULTS.maxSourceChars
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
+
var SOURCE_EXTENSIONS = [
|
|
75
|
+
".ts",
|
|
76
|
+
".tsx",
|
|
77
|
+
".js",
|
|
78
|
+
".jsx",
|
|
79
|
+
".mjs",
|
|
80
|
+
".cjs",
|
|
81
|
+
".mts",
|
|
82
|
+
".cts",
|
|
83
|
+
".py",
|
|
84
|
+
".go",
|
|
85
|
+
".rs",
|
|
86
|
+
".java",
|
|
87
|
+
".kt",
|
|
88
|
+
".rb",
|
|
89
|
+
".php",
|
|
90
|
+
".cs",
|
|
91
|
+
".swift",
|
|
92
|
+
".c",
|
|
93
|
+
".h",
|
|
94
|
+
".cc",
|
|
95
|
+
".cpp",
|
|
96
|
+
".hpp"
|
|
97
|
+
];
|
|
74
98
|
function withinProject(p) {
|
|
75
99
|
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
76
100
|
const root = process.cwd();
|
|
@@ -298,6 +322,12 @@ var plugin = {
|
|
|
298
322
|
if (!withinProject(rawPath)) {
|
|
299
323
|
return { ok: false, error: "path is outside the project root" };
|
|
300
324
|
}
|
|
325
|
+
if (!SOURCE_EXTENSIONS.some((ext) => rawPath.toLowerCase().endsWith(ext))) {
|
|
326
|
+
return {
|
|
327
|
+
ok: false,
|
|
328
|
+
error: `test generation only reads source files (${SOURCE_EXTENSIONS.join(", ")}); refusing "${rawPath}"`
|
|
329
|
+
};
|
|
330
|
+
}
|
|
301
331
|
const resolved = resolve(process.cwd(), rawPath);
|
|
302
332
|
state.generateCount += 1;
|
|
303
333
|
let result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.301.0",
|
|
4
4
|
"description": "Official WrongStack collection of focused plugins for code quality, security, observability, planning, and agent coordination",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ECOSTACK TECHNOLOGY OÜ",
|
|
@@ -299,8 +299,8 @@
|
|
|
299
299
|
"vitest": "^4.1.10"
|
|
300
300
|
},
|
|
301
301
|
"dependencies": {
|
|
302
|
-
"@wrongstack/core": "0.
|
|
303
|
-
"@wrongstack/tools": "0.
|
|
302
|
+
"@wrongstack/core": "0.301.0",
|
|
303
|
+
"@wrongstack/tools": "0.301.0"
|
|
304
304
|
},
|
|
305
305
|
"scripts": {
|
|
306
306
|
"build": "node ../../scripts/build-package.mjs",
|