@gempack/squad-mcp 0.6.4 → 0.7.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +6 -3
- package/CHANGELOG.md +37 -0
- package/INSTALL.md +15 -0
- package/README.md +32 -0
- package/agents/product-owner.md +9 -0
- package/agents/senior-architect.md +12 -0
- package/agents/senior-dba.md +15 -1
- package/agents/senior-dev-reviewer.md +100 -29
- package/agents/senior-dev-security.md +13 -0
- package/agents/senior-developer.md +15 -0
- package/agents/senior-qa.md +13 -0
- package/agents/tech-lead-consolidator.md +10 -0
- package/agents/tech-lead-planner.md +9 -0
- package/commands/squad-next.md +24 -0
- package/commands/squad-task.md +29 -0
- package/commands/squad-tasks.md +21 -0
- package/dist/config/ownership-matrix.js +4 -20
- package/dist/config/ownership-matrix.js.map +1 -1
- package/dist/config/squad-yaml.js +3 -7
- package/dist/config/squad-yaml.js.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/exec/git.d.ts +1 -1
- package/dist/exec/git.js +0 -0
- package/dist/exec/git.js.map +1 -1
- package/dist/format/pr-review.js +1 -3
- package/dist/format/pr-review.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/learning/format.js +1 -5
- package/dist/learning/format.js.map +1 -1
- package/dist/learning/store.js +89 -16
- package/dist/learning/store.js.map +1 -1
- package/dist/observability/logger.d.ts +2 -2
- package/dist/observability/logger.js +20 -20
- package/dist/observability/logger.js.map +1 -1
- package/dist/prompts/registry.js.map +1 -1
- package/dist/resources/agent-loader.js.map +1 -1
- package/dist/resources/registry.js +28 -28
- package/dist/tasks/select.js.map +1 -1
- package/dist/tasks/store.js +49 -11
- package/dist/tasks/store.js.map +1 -1
- package/dist/tools/_shared/schemas.d.ts +21 -0
- package/dist/tools/_shared/schemas.js +25 -0
- package/dist/tools/_shared/schemas.js.map +1 -0
- package/dist/tools/agents.d.ts +3 -3
- package/dist/tools/agents.js +9 -9
- package/dist/tools/agents.js.map +1 -1
- package/dist/tools/classify-work-type.d.ts +5 -5
- package/dist/tools/classify-work-type.js +0 -0
- package/dist/tools/classify-work-type.js.map +1 -1
- package/dist/tools/compose-advisory-bundle.js +4 -14
- package/dist/tools/compose-advisory-bundle.js.map +1 -1
- package/dist/tools/compose-prd-parse.js.map +1 -1
- package/dist/tools/compose-squad-workflow.js +0 -0
- package/dist/tools/compose-squad-workflow.js.map +1 -1
- package/dist/tools/consolidate.js +1 -3
- package/dist/tools/consolidate.js.map +1 -1
- package/dist/tools/detect-changed-files.d.ts +5 -6
- package/dist/tools/detect-changed-files.js +0 -0
- package/dist/tools/detect-changed-files.js.map +1 -1
- package/dist/tools/list-tasks.js +1 -8
- package/dist/tools/list-tasks.js.map +1 -1
- package/dist/tools/next-task.js +1 -8
- package/dist/tools/next-task.js.map +1 -1
- package/dist/tools/read-learnings.js +2 -4
- package/dist/tools/read-learnings.js.map +1 -1
- package/dist/tools/read-squad-config.js +1 -1
- package/dist/tools/read-squad-config.js.map +1 -1
- package/dist/tools/record-tasks.js.map +1 -1
- package/dist/tools/registry.js +2 -4
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/score-risk.d.ts +3 -3
- package/dist/tools/score-risk.js +15 -15
- package/dist/tools/score-rubric.js.map +1 -1
- package/dist/tools/select-squad.d.ts +5 -5
- package/dist/tools/select-squad.js +0 -0
- package/dist/tools/select-squad.js.map +1 -1
- package/dist/tools/slice-files-for-task.js.map +1 -1
- package/dist/tools/slice-files.d.ts +2 -2
- package/dist/tools/slice-files.js +0 -0
- package/dist/tools/slice-files.js.map +1 -1
- package/dist/tools/update-task-status.js +1 -8
- package/dist/tools/update-task-status.js.map +1 -1
- package/dist/tools/validate-plan-text.d.ts +3 -3
- package/dist/tools/validate-plan-text.js +0 -0
- package/dist/tools/validate-plan-text.js.map +1 -1
- package/dist/util/file-lock.d.ts +10 -0
- package/dist/util/file-lock.js +102 -0
- package/dist/util/file-lock.js.map +1 -0
- package/dist/util/override-allowlist.d.ts +4 -4
- package/dist/util/override-allowlist.js +36 -27
- package/dist/util/override-allowlist.js.map +1 -1
- package/dist/util/path-internal.js +10 -8
- package/dist/util/path-internal.js.map +1 -1
- package/dist/util/path-safety.d.ts +15 -0
- package/dist/util/path-safety.js +47 -13
- package/dist/util/path-safety.js.map +1 -1
- package/package.json +13 -2
- package/shared/Skill-Squad-Dev.md +38 -27
- package/shared/Skill-Squad-Review.md +49 -26
- package/shared/_Severity-and-Ownership.md +6 -6
- package/skills/brainstorm/SKILL.md +31 -20
- package/skills/commit-suggest/SKILL.md +32 -14
- package/tools/_tasks-io.mjs +25 -16
- package/tools/list-tasks.mjs +1 -4
- package/tools/next-task.mjs +4 -13
- package/tools/post-review.mjs +20 -30
- package/tools/record-learning.mjs +8 -11
- package/tools/record-tasks.mjs +2 -9
- package/tools/update-task-status.mjs +2 -9
package/tools/post-review.mjs
CHANGED
|
@@ -77,8 +77,7 @@ function parseArgs(argv) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
if (!out.pr) fail(2, "--pr <number> is required");
|
|
80
|
-
if (!/^\d+$/.test(out.pr))
|
|
81
|
-
fail(2, `--pr must be a positive integer, got "${out.pr}"`);
|
|
80
|
+
if (!/^\d+$/.test(out.pr)) fail(2, `--pr must be a positive integer, got "${out.pr}"`);
|
|
82
81
|
return out;
|
|
83
82
|
}
|
|
84
83
|
|
|
@@ -100,10 +99,7 @@ function ensureGh() {
|
|
|
100
99
|
const r = spawnSync("gh", ["--version"], { encoding: "utf8" });
|
|
101
100
|
if (r.error) {
|
|
102
101
|
if (r.error.code === "ENOENT") {
|
|
103
|
-
fail(
|
|
104
|
-
3,
|
|
105
|
-
"gh CLI not found in PATH. Install: https://cli.github.com/manual/installation",
|
|
106
|
-
);
|
|
102
|
+
fail(3, "gh CLI not found in PATH. Install: https://cli.github.com/manual/installation");
|
|
107
103
|
}
|
|
108
104
|
fail(3, `gh check failed: ${r.error.message}`);
|
|
109
105
|
}
|
|
@@ -121,8 +117,19 @@ function runGh(args, body) {
|
|
|
121
117
|
proc.stderr.on("data", (d) => (stderr += d));
|
|
122
118
|
proc.on("error", reject);
|
|
123
119
|
proc.on("close", (code) => resolve({ code, stdout, stderr }));
|
|
124
|
-
proc.stdin.
|
|
125
|
-
|
|
120
|
+
proc.stdin.on("error", reject);
|
|
121
|
+
// Respect backpressure: if the kernel pipe is full, write() returns false
|
|
122
|
+
// and we must wait for "drain" before continuing. Pre-fix this code wrote
|
|
123
|
+
// a large body without awaiting drain, which on small pipe buffers
|
|
124
|
+
// truncated the body silently (gh exits 0 with the prefix only).
|
|
125
|
+
const ok = proc.stdin.write(body, (err) => {
|
|
126
|
+
if (err) reject(err);
|
|
127
|
+
});
|
|
128
|
+
if (ok) {
|
|
129
|
+
proc.stdin.end();
|
|
130
|
+
} else {
|
|
131
|
+
proc.stdin.once("drain", () => proc.stdin.end());
|
|
132
|
+
}
|
|
126
133
|
});
|
|
127
134
|
}
|
|
128
135
|
|
|
@@ -145,11 +152,7 @@ async function main() {
|
|
|
145
152
|
} catch (err) {
|
|
146
153
|
fail(2, `invalid JSON on stdin: ${err.message}`);
|
|
147
154
|
}
|
|
148
|
-
if (
|
|
149
|
-
!consolidation ||
|
|
150
|
-
typeof consolidation !== "object" ||
|
|
151
|
-
!consolidation.verdict
|
|
152
|
-
) {
|
|
155
|
+
if (!consolidation || typeof consolidation !== "object" || !consolidation.verdict) {
|
|
153
156
|
fail(
|
|
154
157
|
2,
|
|
155
158
|
"stdin JSON missing required `verdict` field — expected output of apply_consolidation_rules",
|
|
@@ -169,14 +172,7 @@ async function main() {
|
|
|
169
172
|
body = body.replace(/\n\n---\n[\s\S]*$/, "\n");
|
|
170
173
|
}
|
|
171
174
|
|
|
172
|
-
const ghArgs = [
|
|
173
|
-
"pr",
|
|
174
|
-
"review",
|
|
175
|
-
opts.pr,
|
|
176
|
-
`--${payload.action}`,
|
|
177
|
-
"--body-file",
|
|
178
|
-
"-",
|
|
179
|
-
];
|
|
175
|
+
const ghArgs = ["pr", "review", opts.pr, `--${payload.action}`, "--body-file", "-"];
|
|
180
176
|
if (opts.repo) ghArgs.push("--repo", opts.repo);
|
|
181
177
|
|
|
182
178
|
if (opts.dryRun) {
|
|
@@ -186,25 +182,19 @@ async function main() {
|
|
|
186
182
|
);
|
|
187
183
|
process.stdout.write(body);
|
|
188
184
|
process.stdout.write(`EOF\n`);
|
|
189
|
-
process.stdout.write(
|
|
190
|
-
`\n# Action: ${payload.action}\n# Summary: ${payload.summary}\n`,
|
|
191
|
-
);
|
|
185
|
+
process.stdout.write(`\n# Action: ${payload.action}\n# Summary: ${payload.summary}\n`);
|
|
192
186
|
process.exit(0);
|
|
193
187
|
}
|
|
194
188
|
|
|
195
189
|
ensureGh();
|
|
196
190
|
const r = await runGh(ghArgs, body);
|
|
197
191
|
if (r.code !== 0) {
|
|
198
|
-
process.stderr.write(
|
|
199
|
-
`gh ${payload.action} failed (exit ${r.code}):\n${r.stderr}`,
|
|
200
|
-
);
|
|
192
|
+
process.stderr.write(`gh ${payload.action} failed (exit ${r.code}):\n${r.stderr}`);
|
|
201
193
|
process.exit(4);
|
|
202
194
|
}
|
|
203
195
|
// gh prints the review URL on success; surface it to the caller.
|
|
204
196
|
if (r.stdout) process.stdout.write(r.stdout);
|
|
205
|
-
process.stdout.write(
|
|
206
|
-
`\nposted: ${payload.action} on PR #${opts.pr} | ${payload.summary}\n`,
|
|
207
|
-
);
|
|
197
|
+
process.stdout.write(`\nposted: ${payload.action} on PR #${opts.pr} | ${payload.summary}\n`);
|
|
208
198
|
}
|
|
209
199
|
|
|
210
200
|
main().catch((err) => {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
import { promises as fs } from "node:fs";
|
|
34
34
|
import path from "node:path";
|
|
35
|
+
import { ensureRelativeInsideRoot } from "./_tasks-io.mjs";
|
|
35
36
|
|
|
36
37
|
const args = process.argv.slice(2);
|
|
37
38
|
|
|
@@ -57,13 +58,11 @@ function parseArgs(argv) {
|
|
|
57
58
|
const a = argv[i];
|
|
58
59
|
switch (a) {
|
|
59
60
|
case "--accept":
|
|
60
|
-
if (out.decision)
|
|
61
|
-
fail(2, "--accept and --reject are mutually exclusive");
|
|
61
|
+
if (out.decision) fail(2, "--accept and --reject are mutually exclusive");
|
|
62
62
|
out.decision = "accept";
|
|
63
63
|
break;
|
|
64
64
|
case "--reject":
|
|
65
|
-
if (out.decision)
|
|
66
|
-
fail(2, "--accept and --reject are mutually exclusive");
|
|
65
|
+
if (out.decision) fail(2, "--accept and --reject are mutually exclusive");
|
|
67
66
|
out.decision = "reject";
|
|
68
67
|
break;
|
|
69
68
|
case "--agent":
|
|
@@ -127,16 +126,14 @@ async function main() {
|
|
|
127
126
|
if (opts.branch) entry.branch = opts.branch;
|
|
128
127
|
if (opts.scope) entry.scope = opts.scope;
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
opts.workspace,
|
|
132
|
-
|
|
133
|
-
);
|
|
129
|
+
if (opts.file !== undefined) {
|
|
130
|
+
ensureRelativeInsideRoot(opts.workspace, opts.file, "learnings.path");
|
|
131
|
+
}
|
|
132
|
+
const target = path.resolve(opts.workspace, opts.file ?? ".squad/learnings.jsonl");
|
|
134
133
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
135
134
|
await fs.appendFile(target, JSON.stringify(entry) + "\n", "utf8");
|
|
136
135
|
|
|
137
|
-
process.stdout.write(
|
|
138
|
-
`recorded: ${opts.decision} on ${opts.agent} — "${opts.finding}"\n`,
|
|
139
|
-
);
|
|
136
|
+
process.stdout.write(`recorded: ${opts.decision} on ${opts.agent} — "${opts.finding}"\n`);
|
|
140
137
|
process.stdout.write(`file: ${target}\n`);
|
|
141
138
|
}
|
|
142
139
|
|
package/tools/record-tasks.mjs
CHANGED
|
@@ -25,12 +25,7 @@
|
|
|
25
25
|
// validates the full zod schema.
|
|
26
26
|
|
|
27
27
|
import { promises as fs } from "node:fs";
|
|
28
|
-
import {
|
|
29
|
-
readTasksFile,
|
|
30
|
-
writeTasksFile,
|
|
31
|
-
VALID_PRIORITIES,
|
|
32
|
-
fail,
|
|
33
|
-
} from "./_tasks-io.mjs";
|
|
28
|
+
import { readTasksFile, writeTasksFile, VALID_PRIORITIES, fail } from "./_tasks-io.mjs";
|
|
34
29
|
|
|
35
30
|
const args = process.argv.slice(2);
|
|
36
31
|
const PROG = "record-tasks";
|
|
@@ -101,9 +96,7 @@ function validateInputs(inputs) {
|
|
|
101
96
|
|
|
102
97
|
async function main() {
|
|
103
98
|
const opts = parseArgs(args);
|
|
104
|
-
const raw = opts.input
|
|
105
|
-
? await fs.readFile(opts.input, "utf8")
|
|
106
|
-
: await readStdin();
|
|
99
|
+
const raw = opts.input ? await fs.readFile(opts.input, "utf8") : await readStdin();
|
|
107
100
|
|
|
108
101
|
let inputs;
|
|
109
102
|
try {
|
|
@@ -16,12 +16,7 @@
|
|
|
16
16
|
// 0 success
|
|
17
17
|
// 2 invalid input or task/subtask not found
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
readTasksFile,
|
|
21
|
-
writeTasksFile,
|
|
22
|
-
VALID_STATUSES,
|
|
23
|
-
fail,
|
|
24
|
-
} from "./_tasks-io.mjs";
|
|
19
|
+
import { readTasksFile, writeTasksFile, VALID_STATUSES, fail } from "./_tasks-io.mjs";
|
|
25
20
|
|
|
26
21
|
const args = process.argv.slice(2);
|
|
27
22
|
const PROG = "update-task-status";
|
|
@@ -87,9 +82,7 @@ async function main() {
|
|
|
87
82
|
const original = data.tasks[idx];
|
|
88
83
|
|
|
89
84
|
if (opts.subtask !== null) {
|
|
90
|
-
const sIdx = (original.subtasks ?? []).findIndex(
|
|
91
|
-
(s) => s.id === opts.subtask,
|
|
92
|
-
);
|
|
85
|
+
const sIdx = (original.subtasks ?? []).findIndex((s) => s.id === opts.subtask);
|
|
93
86
|
if (sIdx < 0) {
|
|
94
87
|
fail(PROG, 2, `subtask ${opts.subtask} not found on task ${opts.task}`);
|
|
95
88
|
}
|