@gempack/squad-mcp 0.5.0 → 0.6.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +3 -2
- package/CHANGELOG.md +271 -17
- package/INSTALL.md +156 -24
- package/README.md +278 -27
- package/agents/{PO.md → product-owner.md} +33 -1
- package/agents/{Senior-Architect.md → senior-architect.md} +33 -1
- package/agents/{Senior-DBA.md → senior-dba.md} +33 -1
- package/agents/{Senior-Dev-Reviewer.md → senior-dev-reviewer.md} +33 -1
- package/agents/{Senior-Dev-Security.md → senior-dev-security.md} +33 -1
- package/agents/{Senior-Developer.md → senior-developer.md} +33 -1
- package/agents/{Senior-QA.md → senior-qa.md} +33 -1
- package/agents/{TechLead-Consolidator.md → tech-lead-consolidator.md} +7 -1
- package/agents/{TechLead-Planner.md → tech-lead-planner.md} +7 -1
- package/commands/squad-review.md +10 -58
- package/commands/squad.md +11 -70
- package/dist/config/ownership-matrix.d.ts +24 -2
- package/dist/config/ownership-matrix.js +466 -139
- package/dist/config/ownership-matrix.js.map +1 -1
- package/dist/config/squad-yaml.d.ts +242 -0
- package/dist/config/squad-yaml.js +403 -0
- package/dist/config/squad-yaml.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/format/pr-review.d.ts +61 -0
- package/dist/format/pr-review.js +146 -0
- package/dist/format/pr-review.js.map +1 -0
- package/dist/index.js +19 -13
- package/dist/index.js.map +1 -1
- package/dist/learning/format.d.ts +29 -0
- package/dist/learning/format.js +55 -0
- package/dist/learning/format.js.map +1 -0
- package/dist/learning/store.d.ts +102 -0
- package/dist/learning/store.js +169 -0
- package/dist/learning/store.js.map +1 -0
- package/dist/resources/agent-loader.d.ts +8 -1
- package/dist/resources/agent-loader.js +83 -48
- package/dist/resources/agent-loader.js.map +1 -1
- package/dist/tasks/select.d.ts +64 -0
- package/dist/tasks/select.js +84 -0
- package/dist/tasks/select.js.map +1 -0
- package/dist/tasks/store.d.ts +338 -0
- package/dist/tasks/store.js +321 -0
- package/dist/tasks/store.js.map +1 -0
- package/dist/tools/compose-advisory-bundle.d.ts +5 -5
- package/dist/tools/compose-advisory-bundle.js +24 -12
- package/dist/tools/compose-advisory-bundle.js.map +1 -1
- package/dist/tools/compose-prd-parse.d.ts +53 -0
- package/dist/tools/compose-prd-parse.js +167 -0
- package/dist/tools/compose-prd-parse.js.map +1 -0
- package/dist/tools/compose-squad-workflow.d.ts +28 -10
- package/dist/tools/compose-squad-workflow.js +0 -0
- package/dist/tools/compose-squad-workflow.js.map +1 -1
- package/dist/tools/consolidate.d.ts +55 -4
- package/dist/tools/consolidate.js +87 -15
- package/dist/tools/consolidate.js.map +1 -1
- package/dist/tools/expand-task.d.ts +51 -0
- package/dist/tools/expand-task.js +35 -0
- package/dist/tools/expand-task.js.map +1 -0
- package/dist/tools/list-tasks.d.ts +31 -0
- package/dist/tools/list-tasks.js +50 -0
- package/dist/tools/list-tasks.js.map +1 -0
- package/dist/tools/next-task.d.ts +37 -0
- package/dist/tools/next-task.js +60 -0
- package/dist/tools/next-task.js.map +1 -0
- package/dist/tools/read-learnings.d.ts +53 -0
- package/dist/tools/read-learnings.js +72 -0
- package/dist/tools/read-learnings.js.map +1 -0
- package/dist/tools/read-squad-config.d.ts +23 -0
- package/dist/tools/read-squad-config.js +34 -0
- package/dist/tools/read-squad-config.js.map +1 -0
- package/dist/tools/record-learning.d.ts +62 -0
- package/dist/tools/record-learning.js +80 -0
- package/dist/tools/record-learning.js.map +1 -0
- package/dist/tools/record-tasks.d.ts +71 -0
- package/dist/tools/record-tasks.js +45 -0
- package/dist/tools/record-tasks.js.map +1 -0
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.js +71 -39
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/score-rubric.d.ts +74 -0
- package/dist/tools/score-rubric.js +140 -0
- package/dist/tools/score-rubric.js.map +1 -0
- package/dist/tools/slice-files-for-task.d.ts +31 -0
- package/dist/tools/slice-files-for-task.js +52 -0
- package/dist/tools/slice-files-for-task.js.map +1 -0
- package/dist/tools/update-task-status.d.ts +29 -0
- package/dist/tools/update-task-status.js +35 -0
- package/dist/tools/update-task-status.js.map +1 -0
- package/package.json +11 -1
- package/skills/squad/SKILL.md +454 -0
- package/tools/_tasks-io.mjs +69 -0
- package/tools/list-tasks.mjs +110 -0
- package/tools/next-task.mjs +131 -0
- package/tools/post-review.mjs +212 -0
- package/tools/record-learning.mjs +145 -0
- package/tools/record-tasks.mjs +186 -0
- package/tools/update-task-status.mjs +114 -0
- /package/{agents → shared}/Skill-Squad-Dev.md +0 -0
- /package/{agents → shared}/Skill-Squad-Review.md +0 -0
- /package/{agents → shared}/_Severity-and-Ownership.md +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { AGENT_NAMES_TUPLE, DEFAULT_RUBRIC_WEIGHTS, } from "./ownership-matrix.js";
|
|
6
|
+
import { SquadError } from "../errors.js";
|
|
7
|
+
import { logger } from "../observability/logger.js";
|
|
8
|
+
/**
|
|
9
|
+
* `.squad.yaml` schema. All fields optional; absent keys fall back to package defaults.
|
|
10
|
+
*
|
|
11
|
+
* Repo-versioned config. Lives at workspace_root. Loaded by composers
|
|
12
|
+
* (compose_squad_workflow, compose_advisory_bundle) automatically when they
|
|
13
|
+
* receive a workspace_root. Pure tools (apply_consolidation_rules, score_rubric,
|
|
14
|
+
* select_squad) do NOT read it directly — that would make them stateful and
|
|
15
|
+
* couple their inputs to the filesystem. Composers do the read; pure tools
|
|
16
|
+
* receive the resolved values via parameters.
|
|
17
|
+
*/
|
|
18
|
+
const squadYamlSchema = z.object({
|
|
19
|
+
/**
|
|
20
|
+
* Override default rubric weights. Keys are agent names; values 0-100. The set
|
|
21
|
+
* of supplied keys MUST sum to 100 across the agents you list. Agents not
|
|
22
|
+
* listed fall back to the package default. Use weight 0 to ignore a dimension.
|
|
23
|
+
*/
|
|
24
|
+
weights: z
|
|
25
|
+
.record(z.enum(AGENT_NAMES_TUPLE), z.number().min(0).max(100))
|
|
26
|
+
.optional(),
|
|
27
|
+
/**
|
|
28
|
+
* Per-dimension threshold (0-100). Below this, the dimension is flagged in the
|
|
29
|
+
* scorecard. Default 75 (in code, not duplicated here).
|
|
30
|
+
*/
|
|
31
|
+
threshold: z.number().min(0).max(100).optional(),
|
|
32
|
+
/**
|
|
33
|
+
* Quality floor. If supplied AND the weighted score is below it AND verdict
|
|
34
|
+
* would otherwise be APPROVED, the consolidator downgrades to CHANGES_REQUIRED.
|
|
35
|
+
*/
|
|
36
|
+
min_score: z.number().min(0).max(100).optional(),
|
|
37
|
+
/**
|
|
38
|
+
* Glob patterns (relative to workspace_root) of files to exclude from advisory.
|
|
39
|
+
* Matched against `changed_files` BEFORE squad selection. Use to silence
|
|
40
|
+
* docs-only changes, generated code, etc.
|
|
41
|
+
*/
|
|
42
|
+
skip_paths: z.array(z.string().min(1).max(512)).max(200).optional(),
|
|
43
|
+
/**
|
|
44
|
+
* Agents to disable for this repo. Removed from the selected squad in
|
|
45
|
+
* compose_squad_workflow. Useful for repos that don't have, say, a database
|
|
46
|
+
* (disable senior-dba) or aren't user-facing (disable product-owner).
|
|
47
|
+
*/
|
|
48
|
+
disable_agents: z.array(z.enum(AGENT_NAMES_TUPLE)).max(20).optional(),
|
|
49
|
+
/**
|
|
50
|
+
* Optional GitHub PR posting policy used by `tools/post-review.mjs` and the
|
|
51
|
+
* `/squad-review` skill. Default behaviour without this section: dry-run.
|
|
52
|
+
* The skill prepares the post and shows the user — never posts unsolicited.
|
|
53
|
+
*
|
|
54
|
+
* - `auto_post`: when true, the skill posts without asking for confirmation
|
|
55
|
+
* each time. The user opted in by editing this YAML — no AI action without
|
|
56
|
+
* prior authorisation.
|
|
57
|
+
* - `request_changes_below_score`: when set, an APPROVED verdict with
|
|
58
|
+
* weighted score below this floor is posted as `--request-changes` instead
|
|
59
|
+
* of `--approve`. Independent of `min_score` (which downgrades the verdict
|
|
60
|
+
* itself).
|
|
61
|
+
* - `omit_attribution_footer`: omits the trailing "Generated by squad-mcp"
|
|
62
|
+
* line from the PR body. Useful for orgs that prefer a leaner PR.
|
|
63
|
+
*/
|
|
64
|
+
pr_posting: z
|
|
65
|
+
.object({
|
|
66
|
+
auto_post: z.boolean().optional(),
|
|
67
|
+
request_changes_below_score: z.number().min(0).max(100).optional(),
|
|
68
|
+
omit_attribution_footer: z.boolean().optional(),
|
|
69
|
+
})
|
|
70
|
+
.optional(),
|
|
71
|
+
/**
|
|
72
|
+
* Optional `.squad/learnings.jsonl` configuration. The store records
|
|
73
|
+
* accept/reject decisions on findings; future advisory runs read the
|
|
74
|
+
* recent tail and inject it into agent / consolidator prompts so the
|
|
75
|
+
* squad stops re-suggesting things the team has already declined.
|
|
76
|
+
*
|
|
77
|
+
* - `path`: relative location of the JSONL file (default
|
|
78
|
+
* `.squad/learnings.jsonl`). Override only if the repo already uses
|
|
79
|
+
* `.squad/` for something else.
|
|
80
|
+
* - `max_recent`: how many entries to inject per advisory run (default 50,
|
|
81
|
+
* hard cap 200). Larger = more context but more prompt cost.
|
|
82
|
+
* - `enabled`: master switch. Default true. Set false to disable the
|
|
83
|
+
* read/inject side without deleting the file.
|
|
84
|
+
*/
|
|
85
|
+
learnings: z
|
|
86
|
+
.object({
|
|
87
|
+
path: z.string().min(1).max(512).optional(),
|
|
88
|
+
max_recent: z.number().int().positive().max(200).optional(),
|
|
89
|
+
enabled: z.boolean().optional(),
|
|
90
|
+
})
|
|
91
|
+
.optional(),
|
|
92
|
+
/**
|
|
93
|
+
* Optional `.squad/tasks.json` configuration. The store holds the task list
|
|
94
|
+
* decomposed from a PRD (or seeded manually); the squad workflow runs one
|
|
95
|
+
* task at a time with scope-narrowed context to avoid prompt bloat.
|
|
96
|
+
*
|
|
97
|
+
* - `path`: relative location of the JSON file (default `.squad/tasks.json`).
|
|
98
|
+
* Override only if the repo already uses `.squad/` for something else.
|
|
99
|
+
* - `enabled`: master switch. Default true. Set false to silence task tools
|
|
100
|
+
* without deleting the file.
|
|
101
|
+
*/
|
|
102
|
+
tasks: z
|
|
103
|
+
.object({
|
|
104
|
+
path: z.string().min(1).max(512).optional(),
|
|
105
|
+
enabled: z.boolean().optional(),
|
|
106
|
+
})
|
|
107
|
+
.optional(),
|
|
108
|
+
});
|
|
109
|
+
const CANDIDATE_FILENAMES = [".squad.yaml", ".squad.yml"];
|
|
110
|
+
const cache = new Map();
|
|
111
|
+
/**
|
|
112
|
+
* Test-only: clear the cache. Production code MUST NOT call this.
|
|
113
|
+
*/
|
|
114
|
+
export function __resetSquadYamlCacheForTests() {
|
|
115
|
+
cache.clear();
|
|
116
|
+
}
|
|
117
|
+
async function locate(workspaceRoot) {
|
|
118
|
+
for (const name of CANDIDATE_FILENAMES) {
|
|
119
|
+
const candidate = path.join(workspaceRoot, name);
|
|
120
|
+
try {
|
|
121
|
+
const s = await fs.stat(candidate);
|
|
122
|
+
if (s.isFile()) {
|
|
123
|
+
return { filePath: candidate, mtimeMs: s.mtimeMs };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// ENOENT or stat failure — try next.
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
function applyDefaults(parsed, source) {
|
|
133
|
+
// Merge weights: parsed override sums to 100 across its keys (validated below);
|
|
134
|
+
// missing keys take the default. Returning a fully-populated map keeps the
|
|
135
|
+
// downstream score_rubric simple (no fallback chain in math).
|
|
136
|
+
const weights = { ...DEFAULT_RUBRIC_WEIGHTS };
|
|
137
|
+
if (parsed.weights) {
|
|
138
|
+
const supplied = Object.entries(parsed.weights);
|
|
139
|
+
const sum = supplied.reduce((acc, [, v]) => acc + v, 0);
|
|
140
|
+
if (Math.abs(sum - 100) > 0.01) {
|
|
141
|
+
throw new SquadError("INVALID_INPUT", `.squad.yaml weights must sum to 100 across the agents listed; got ${sum}`, { source: source ?? "<inline>", supplied: parsed.weights });
|
|
142
|
+
}
|
|
143
|
+
for (const [name, w] of supplied) {
|
|
144
|
+
weights[name] = w;
|
|
145
|
+
}
|
|
146
|
+
// Zero-out the agents NOT supplied — the YAML user explicitly chose a
|
|
147
|
+
// partial set of weights, so anything missing is "this dimension does not
|
|
148
|
+
// count for this repo". Keeping defaults would let ungated dimensions sneak
|
|
149
|
+
// back into the rollup.
|
|
150
|
+
const overridden = new Set(supplied.map(([name]) => name));
|
|
151
|
+
for (const name of AGENT_NAMES_TUPLE) {
|
|
152
|
+
if (!overridden.has(name))
|
|
153
|
+
weights[name] = 0;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const pr_posting = {
|
|
157
|
+
auto_post: parsed.pr_posting?.auto_post ?? false,
|
|
158
|
+
request_changes_below_score: parsed.pr_posting?.request_changes_below_score,
|
|
159
|
+
omit_attribution_footer: parsed.pr_posting?.omit_attribution_footer ?? false,
|
|
160
|
+
};
|
|
161
|
+
const learnings = {
|
|
162
|
+
path: parsed.learnings?.path ?? ".squad/learnings.jsonl",
|
|
163
|
+
max_recent: parsed.learnings?.max_recent ?? 50,
|
|
164
|
+
enabled: parsed.learnings?.enabled ?? true,
|
|
165
|
+
};
|
|
166
|
+
const tasks = {
|
|
167
|
+
path: parsed.tasks?.path ?? ".squad/tasks.json",
|
|
168
|
+
enabled: parsed.tasks?.enabled ?? true,
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
weights,
|
|
172
|
+
threshold: parsed.threshold ?? 75,
|
|
173
|
+
min_score: parsed.min_score,
|
|
174
|
+
skip_paths: parsed.skip_paths ?? [],
|
|
175
|
+
disable_agents: parsed.disable_agents ?? [],
|
|
176
|
+
pr_posting,
|
|
177
|
+
learnings,
|
|
178
|
+
tasks,
|
|
179
|
+
source,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Read `.squad.yaml` (or `.squad.yml`) from workspace_root. Returns the resolved
|
|
184
|
+
* config with defaults filled in. If no file is present, returns defaults.
|
|
185
|
+
* Caches by absolute path + mtimeMs.
|
|
186
|
+
*
|
|
187
|
+
* Throws `SquadError(INVALID_INPUT)` only on malformed YAML or schema violations
|
|
188
|
+
* (e.g. weights not summing to 100). Missing-file and partial config are NOT
|
|
189
|
+
* errors — they fall back gracefully.
|
|
190
|
+
*/
|
|
191
|
+
export async function readSquadYaml(workspaceRoot) {
|
|
192
|
+
const absRoot = path.resolve(workspaceRoot);
|
|
193
|
+
const located = await locate(absRoot);
|
|
194
|
+
if (!located) {
|
|
195
|
+
// No file. Cache the "no file" sentinel keyed by mtimeMs=0.
|
|
196
|
+
const cached = cache.get(absRoot);
|
|
197
|
+
if (cached && cached.filePath === null && cached.mtimeMs === 0) {
|
|
198
|
+
return cached.resolved;
|
|
199
|
+
}
|
|
200
|
+
const resolved = applyDefaults({}, null);
|
|
201
|
+
cache.set(absRoot, { mtimeMs: 0, resolved, filePath: null });
|
|
202
|
+
return resolved;
|
|
203
|
+
}
|
|
204
|
+
const cached = cache.get(absRoot);
|
|
205
|
+
if (cached &&
|
|
206
|
+
cached.filePath === located.filePath &&
|
|
207
|
+
cached.mtimeMs === located.mtimeMs) {
|
|
208
|
+
return cached.resolved;
|
|
209
|
+
}
|
|
210
|
+
let raw;
|
|
211
|
+
try {
|
|
212
|
+
raw = await fs.readFile(located.filePath, "utf8");
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
throw new SquadError("CONFIG_READ_FAILED", `failed to read ${located.filePath}: ${err.message}`, {
|
|
216
|
+
source: located.filePath,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
let doc;
|
|
220
|
+
try {
|
|
221
|
+
doc = yaml.load(raw, {
|
|
222
|
+
filename: located.filePath,
|
|
223
|
+
schema: yaml.FAILSAFE_SCHEMA,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
throw new SquadError("INVALID_INPUT", `invalid YAML in ${located.filePath}: ${err.message}`, {
|
|
228
|
+
source: located.filePath,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// FAILSAFE_SCHEMA returns strings for everything; coerce numbers in known fields.
|
|
232
|
+
// Doing this here keeps the zod schema strict (numbers stay numbers) while
|
|
233
|
+
// tolerating YAML's "1" vs 1 ambiguity.
|
|
234
|
+
if (typeof doc === "object" && doc !== null) {
|
|
235
|
+
const o = doc;
|
|
236
|
+
if (o.threshold !== undefined)
|
|
237
|
+
o.threshold = coerceNumber(o.threshold, "threshold", located.filePath);
|
|
238
|
+
if (o.min_score !== undefined)
|
|
239
|
+
o.min_score = coerceNumber(o.min_score, "min_score", located.filePath);
|
|
240
|
+
if (o.weights && typeof o.weights === "object") {
|
|
241
|
+
const w = o.weights;
|
|
242
|
+
for (const [k, v] of Object.entries(w)) {
|
|
243
|
+
w[k] = coerceNumber(v, `weights.${k}`, located.filePath);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (o.pr_posting && typeof o.pr_posting === "object") {
|
|
247
|
+
const p = o.pr_posting;
|
|
248
|
+
if (p.request_changes_below_score !== undefined) {
|
|
249
|
+
p.request_changes_below_score = coerceNumber(p.request_changes_below_score, "pr_posting.request_changes_below_score", located.filePath);
|
|
250
|
+
}
|
|
251
|
+
// FAILSAFE_SCHEMA returns booleans as the strings "true"/"false". Coerce.
|
|
252
|
+
if (typeof p.auto_post === "string") {
|
|
253
|
+
p.auto_post = p.auto_post === "true";
|
|
254
|
+
}
|
|
255
|
+
if (typeof p.omit_attribution_footer === "string") {
|
|
256
|
+
p.omit_attribution_footer = p.omit_attribution_footer === "true";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (o.learnings && typeof o.learnings === "object") {
|
|
260
|
+
const l = o.learnings;
|
|
261
|
+
if (l.max_recent !== undefined) {
|
|
262
|
+
l.max_recent = coerceNumber(l.max_recent, "learnings.max_recent", located.filePath);
|
|
263
|
+
}
|
|
264
|
+
if (typeof l.enabled === "string") {
|
|
265
|
+
l.enabled = l.enabled === "true";
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (doc === null || doc === undefined) {
|
|
270
|
+
// Empty YAML file — treat as empty object.
|
|
271
|
+
doc = {};
|
|
272
|
+
}
|
|
273
|
+
const parsed = squadYamlSchema.safeParse(doc);
|
|
274
|
+
if (!parsed.success) {
|
|
275
|
+
throw new SquadError("INVALID_INPUT", `${located.filePath}: ${parsed.error.message}`, {
|
|
276
|
+
source: located.filePath,
|
|
277
|
+
issues: parsed.error.issues.length,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
const resolved = applyDefaults(parsed.data, located.filePath);
|
|
281
|
+
cache.set(absRoot, {
|
|
282
|
+
mtimeMs: located.mtimeMs,
|
|
283
|
+
resolved,
|
|
284
|
+
filePath: located.filePath,
|
|
285
|
+
});
|
|
286
|
+
logger.info("squad-yaml loaded", {
|
|
287
|
+
details: {
|
|
288
|
+
source: located.filePath,
|
|
289
|
+
has_weights: Boolean(parsed.data.weights),
|
|
290
|
+
threshold: resolved.threshold,
|
|
291
|
+
skip_paths_count: resolved.skip_paths.length,
|
|
292
|
+
disabled_agents_count: resolved.disable_agents.length,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
return resolved;
|
|
296
|
+
}
|
|
297
|
+
function coerceNumber(value, field, source) {
|
|
298
|
+
if (typeof value === "number")
|
|
299
|
+
return value;
|
|
300
|
+
if (typeof value === "string") {
|
|
301
|
+
const n = Number(value);
|
|
302
|
+
if (!Number.isFinite(n)) {
|
|
303
|
+
throw new SquadError("INVALID_INPUT", `${source}: ${field} must be a number, got "${value}"`, { source });
|
|
304
|
+
}
|
|
305
|
+
return n;
|
|
306
|
+
}
|
|
307
|
+
throw new SquadError("INVALID_INPUT", `${source}: ${field} must be a number`, { source });
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Glob-ish path matching used for skip_paths. Supports:
|
|
311
|
+
* - double-star matches any number of segments (zero or more)
|
|
312
|
+
* - single star matches anything within a single segment
|
|
313
|
+
* - `?` matches one character within a segment
|
|
314
|
+
* - exact strings
|
|
315
|
+
*
|
|
316
|
+
* Patterns and paths are matched after normalising path separators to `/`.
|
|
317
|
+
* NOT a full minimatch — kept tiny on purpose to avoid pulling minimatch as a
|
|
318
|
+
* dep. Sufficient for the canonical use cases (docs/double-star, double-star
|
|
319
|
+
* slash *.md, double-star slash generated slash *.ts, vendor/double-star).
|
|
320
|
+
*/
|
|
321
|
+
export function matchesGlob(pattern, p) {
|
|
322
|
+
const normPattern = pattern.replace(/\\/g, "/");
|
|
323
|
+
const normPath = p.replace(/\\/g, "/");
|
|
324
|
+
const re = globToRegExp(normPattern);
|
|
325
|
+
return re.test(normPath);
|
|
326
|
+
}
|
|
327
|
+
function globToRegExp(pattern) {
|
|
328
|
+
let i = 0;
|
|
329
|
+
let out = "^";
|
|
330
|
+
while (i < pattern.length) {
|
|
331
|
+
const c = pattern[i];
|
|
332
|
+
if (c === "*" && pattern[i + 1] === "*") {
|
|
333
|
+
// `**` — zero or more segments
|
|
334
|
+
// Handle `**/`, `/**`, `/**/`, or bare `**`.
|
|
335
|
+
if (pattern[i + 2] === "/") {
|
|
336
|
+
// `**/` — zero or more segments followed by /
|
|
337
|
+
out += "(?:.*/)?";
|
|
338
|
+
i += 3;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
out += ".*";
|
|
342
|
+
i += 2;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
if (c === "*") {
|
|
346
|
+
// single segment
|
|
347
|
+
out += "[^/]*";
|
|
348
|
+
i += 1;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (c === "?") {
|
|
352
|
+
out += "[^/]";
|
|
353
|
+
i += 1;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
if (".+^${}()|[]\\".includes(c)) {
|
|
357
|
+
out += "\\" + c;
|
|
358
|
+
i += 1;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
out += c;
|
|
362
|
+
i += 1;
|
|
363
|
+
}
|
|
364
|
+
out += "$";
|
|
365
|
+
return new RegExp(out);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Apply `skip_paths` filter to a list of files. Returns { kept, skipped }.
|
|
369
|
+
* Skipped files are excluded from advisory; they still appear in the diff but
|
|
370
|
+
* agents don't see them.
|
|
371
|
+
*/
|
|
372
|
+
export function applySkipPaths(files, skipPaths) {
|
|
373
|
+
if (skipPaths.length === 0)
|
|
374
|
+
return { kept: files, skipped: [] };
|
|
375
|
+
const kept = [];
|
|
376
|
+
const skipped = [];
|
|
377
|
+
for (const f of files) {
|
|
378
|
+
if (skipPaths.some((p) => matchesGlob(p, f))) {
|
|
379
|
+
skipped.push(f);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
kept.push(f);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return { kept, skipped };
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Filter a selected squad against `disable_agents`. Returns the agents that
|
|
389
|
+
* remain. Logs a warning if every agent was disabled (likely a misconfig).
|
|
390
|
+
*/
|
|
391
|
+
export function applyDisableAgents(squad, disableAgents) {
|
|
392
|
+
if (disableAgents.length === 0)
|
|
393
|
+
return squad;
|
|
394
|
+
const disabled = new Set(disableAgents);
|
|
395
|
+
const remaining = squad.filter((a) => !disabled.has(a));
|
|
396
|
+
if (remaining.length === 0 && squad.length > 0) {
|
|
397
|
+
logger.warn("squad-yaml disable_agents removed every selected agent", {
|
|
398
|
+
details: { selected: squad, disabled: disableAgents },
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
return remaining;
|
|
402
|
+
}
|
|
403
|
+
//# sourceMappingURL=squad-yaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"squad-yaml.js","sourceRoot":"","sources":["../../src/config/squad-yaml.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type SquadErrorCode =
|
|
1
|
+
export type SquadErrorCode = "PATH_TRAVERSAL_DENIED" | "PATH_REQUIRES_WORKSPACE" | "PATH_INVALID" | "AGENT_DIR_MISSING" | "UNKNOWN_AGENT" | "OVERRIDE_REJECTED" | "INVALID_INPUT" | "INTERNAL_ERROR" | "GIT_EXEC_DENIED" | "GIT_EXEC_TIMEOUT" | "GIT_NOT_FOUND" | "GIT_OUTPUT_TOO_LARGE" | "GIT_NOT_A_REPO" | "CONFIG_READ_FAILED";
|
|
2
2
|
export declare class SquadError extends Error {
|
|
3
3
|
readonly code: SquadErrorCode;
|
|
4
4
|
readonly details?: Record<string, unknown>;
|
package/dist/errors.js
CHANGED
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,IAAI,CAAiB;IACrB,OAAO,CAA2B;IAE3C,YACE,IAAoB,EACpB,OAAe,EACf,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,GAAG,YAAY,UAAU,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ConsolidationOutput } from "../tools/consolidate.js";
|
|
2
|
+
/**
|
|
3
|
+
* Verdict → `gh pr review` action mapping. The CLI passes the chosen action as
|
|
4
|
+
* a flag; we compute it deterministically from verdict + score so the formatter
|
|
5
|
+
* stays pure (no env reads, no auth).
|
|
6
|
+
*
|
|
7
|
+
* REJECTED -> request-changes (blocks merge)
|
|
8
|
+
* CHANGES_REQUIRED -> comment (advisory, doesn't block)
|
|
9
|
+
* APPROVED + downgraded_by_score=true -> comment (downgraded, treat like CR)
|
|
10
|
+
* APPROVED + score < request_changes_below -> request-changes (project-policy gate)
|
|
11
|
+
* APPROVED otherwise -> approve
|
|
12
|
+
*
|
|
13
|
+
* `request_changes_below_score` is opt-in via .squad.yaml.pr_posting; without
|
|
14
|
+
* it, APPROVED always maps to approve.
|
|
15
|
+
*/
|
|
16
|
+
export type GhReviewAction = "approve" | "comment" | "request-changes";
|
|
17
|
+
export interface FormatPrReviewOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Below this weighted score, force `request-changes` even when verdict is
|
|
20
|
+
* APPROVED. Lets a repo enforce a hard quality bar at PR review time.
|
|
21
|
+
* Default: undefined (no override — APPROVED stays APPROVED).
|
|
22
|
+
*/
|
|
23
|
+
requestChangesBelowScore?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Optional repo identifier shown in the review header (e.g. "ggemba/squad-mcp").
|
|
26
|
+
* Cosmetic — surface where the review came from when the PR aggregates many
|
|
27
|
+
* sources.
|
|
28
|
+
*/
|
|
29
|
+
repoLabel?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface PrReviewPayload {
|
|
32
|
+
/** Markdown body to pass to `gh pr review --body-file -`. */
|
|
33
|
+
body: string;
|
|
34
|
+
/** Which `gh pr review --<action>` flag to invoke. */
|
|
35
|
+
action: GhReviewAction;
|
|
36
|
+
/** Short one-line summary suitable for `gh pr review --body` if you want a fallback. */
|
|
37
|
+
summary: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute the `gh pr review` action for the given consolidation output and
|
|
41
|
+
* options. Pure function; deterministic.
|
|
42
|
+
*
|
|
43
|
+
* Promotion never happens — a low-severity verdict cannot become approval.
|
|
44
|
+
* Demotion (score-driven) only applies to APPROVED.
|
|
45
|
+
*/
|
|
46
|
+
export declare function chooseGhAction(consolidation: ConsolidationOutput, options: FormatPrReviewOptions): GhReviewAction;
|
|
47
|
+
/**
|
|
48
|
+
* Build the PR review payload from a consolidation output. Pure, deterministic.
|
|
49
|
+
*
|
|
50
|
+
* Output shape mirrors the squad's terminal report, repurposed as a markdown PR
|
|
51
|
+
* review body:
|
|
52
|
+
* 1. Header with verdict + weighted score
|
|
53
|
+
* 2. Rubric scorecard (fenced code block — keeps the bars monospace)
|
|
54
|
+
* 3. Findings grouped by agent (Blockers + unjustified Majors expanded;
|
|
55
|
+
* Minor/Suggestion totals only)
|
|
56
|
+
* 4. Footer with attribution + override hint
|
|
57
|
+
*
|
|
58
|
+
* The action is chosen via `chooseGhAction` — caller passes it to
|
|
59
|
+
* `gh pr review --<action>`.
|
|
60
|
+
*/
|
|
61
|
+
export declare function formatPrReview(consolidation: ConsolidationOutput, options?: FormatPrReviewOptions): PrReviewPayload;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const SEVERITY_ORDER = ["Blocker", "Major", "Minor", "Suggestion"];
|
|
2
|
+
/**
|
|
3
|
+
* Compute the `gh pr review` action for the given consolidation output and
|
|
4
|
+
* options. Pure function; deterministic.
|
|
5
|
+
*
|
|
6
|
+
* Promotion never happens — a low-severity verdict cannot become approval.
|
|
7
|
+
* Demotion (score-driven) only applies to APPROVED.
|
|
8
|
+
*/
|
|
9
|
+
export function chooseGhAction(consolidation, options) {
|
|
10
|
+
if (consolidation.verdict === "REJECTED")
|
|
11
|
+
return "request-changes";
|
|
12
|
+
if (consolidation.verdict === "CHANGES_REQUIRED")
|
|
13
|
+
return "comment";
|
|
14
|
+
// APPROVED. Check downgrade signals.
|
|
15
|
+
if (consolidation.downgraded_by_score)
|
|
16
|
+
return "comment";
|
|
17
|
+
if (consolidation.rubric &&
|
|
18
|
+
typeof options.requestChangesBelowScore === "number" &&
|
|
19
|
+
consolidation.rubric.weighted_score < options.requestChangesBelowScore) {
|
|
20
|
+
return "request-changes";
|
|
21
|
+
}
|
|
22
|
+
return "approve";
|
|
23
|
+
}
|
|
24
|
+
function verdictHeader(consolidation) {
|
|
25
|
+
const r = consolidation.rubric;
|
|
26
|
+
const v = consolidation.verdict;
|
|
27
|
+
if (r) {
|
|
28
|
+
const score = r.weighted_score.toFixed(1);
|
|
29
|
+
if (v === "APPROVED" &&
|
|
30
|
+
r.passes_threshold &&
|
|
31
|
+
!consolidation.downgraded_by_score) {
|
|
32
|
+
return `Squad Advisory: APPROVED (${score} / 100)`;
|
|
33
|
+
}
|
|
34
|
+
if (v === "APPROVED") {
|
|
35
|
+
return `Squad Advisory: APPROVED with attention (${score} / 100)`;
|
|
36
|
+
}
|
|
37
|
+
return `Squad Advisory: ${v} (${score} / 100)`;
|
|
38
|
+
}
|
|
39
|
+
return `Squad Advisory: ${v}`;
|
|
40
|
+
}
|
|
41
|
+
function groupFindingsByAgent(consolidation) {
|
|
42
|
+
// Consolidator output retains blocker/major lists with agent attribution; we
|
|
43
|
+
// need the full set including Minor/Suggestion. The current ConsolidationOutput
|
|
44
|
+
// shape only exposes blockers + majors_unjustified explicitly; severity_counts
|
|
45
|
+
// is aggregate. To produce a per-agent listing of all findings, we'd need the
|
|
46
|
+
// raw reports. The skill is responsible for passing that input — but post-review
|
|
47
|
+
// CLI receives the consolidator output. We work with what's exposed here, which
|
|
48
|
+
// is enough for the v1 PR comment: blockers + unjustified majors are the actionable
|
|
49
|
+
// items. Minor/Suggestion counts go in the summary.
|
|
50
|
+
const grouped = new Map();
|
|
51
|
+
for (const b of consolidation.blockers) {
|
|
52
|
+
const list = grouped.get(b.agent) ?? [];
|
|
53
|
+
list.push({ severity: "Blocker", title: b.title });
|
|
54
|
+
grouped.set(b.agent, list);
|
|
55
|
+
}
|
|
56
|
+
for (const m of consolidation.majors_unjustified) {
|
|
57
|
+
const list = grouped.get(m.agent) ?? [];
|
|
58
|
+
list.push({ severity: "Major", title: m.title });
|
|
59
|
+
grouped.set(m.agent, list);
|
|
60
|
+
}
|
|
61
|
+
return grouped;
|
|
62
|
+
}
|
|
63
|
+
function formatFindingsSection(consolidation) {
|
|
64
|
+
const grouped = groupFindingsByAgent(consolidation);
|
|
65
|
+
const c = consolidation.severity_counts;
|
|
66
|
+
const totalFindings = c.Blocker + c.Major + c.Minor + c.Suggestion;
|
|
67
|
+
// Clean review with zero of every severity — skip the section entirely.
|
|
68
|
+
if (totalFindings === 0)
|
|
69
|
+
return "";
|
|
70
|
+
const totals = `**Severity totals:** ${c.Blocker} blocker / ${c.Major} major / ${c.Minor} minor / ${c.Suggestion} suggestion`;
|
|
71
|
+
// No actionable findings (no Blockers, no unjustified Majors) but Minor/Suggestion
|
|
72
|
+
// counts exist. Emit just the totals — no per-agent expansion needed.
|
|
73
|
+
if (grouped.size === 0) {
|
|
74
|
+
return ["### Findings", "", totals].join("\n");
|
|
75
|
+
}
|
|
76
|
+
const sections = [];
|
|
77
|
+
// Sort agents alphabetically for stable output (snapshot-friendly).
|
|
78
|
+
const agentNames = Array.from(grouped.keys()).sort();
|
|
79
|
+
for (const agent of agentNames) {
|
|
80
|
+
const findings = grouped.get(agent) ?? [];
|
|
81
|
+
findings.sort((a, b) => SEVERITY_ORDER.indexOf(a.severity) - SEVERITY_ORDER.indexOf(b.severity));
|
|
82
|
+
const lines = [`#### ${agent}`];
|
|
83
|
+
for (const f of findings) {
|
|
84
|
+
lines.push(`- **${f.severity}** — ${f.title}`);
|
|
85
|
+
}
|
|
86
|
+
sections.push(lines.join("\n"));
|
|
87
|
+
}
|
|
88
|
+
return ["### Findings", "", sections.join("\n\n"), "", totals].join("\n");
|
|
89
|
+
}
|
|
90
|
+
function formatRubricBlock(rubric) {
|
|
91
|
+
if (!rubric)
|
|
92
|
+
return "";
|
|
93
|
+
// Wrap the existing scorecard_text in a fenced block so the bars and ⚠ flags
|
|
94
|
+
// render as monospace in the GitHub PR review body.
|
|
95
|
+
return ["```", rubric.scorecard_text, "```"].join("\n");
|
|
96
|
+
}
|
|
97
|
+
function formatFooter(consolidation, action, options) {
|
|
98
|
+
const lines = [];
|
|
99
|
+
lines.push("---");
|
|
100
|
+
if (consolidation.downgraded_by_score) {
|
|
101
|
+
lines.push(`_Verdict downgraded from APPROVED to CHANGES_REQUIRED because the weighted score is below the configured floor._`);
|
|
102
|
+
}
|
|
103
|
+
if (action === "request-changes" && consolidation.verdict === "APPROVED") {
|
|
104
|
+
lines.push(`_Posting as request-changes because score is below \`request_changes_below_score\` (${options.requestChangesBelowScore})._`);
|
|
105
|
+
}
|
|
106
|
+
const suffix = options.repoLabel ? ` (\`${options.repoLabel}\`)` : "";
|
|
107
|
+
lines.push(`_Generated by [@gempack/squad-mcp](https://github.com/ggemba/squad-mcp)${suffix}. Each agent reviewed only its sliced jurisdiction; the rubric is the weighted rollup. Tune \`.squad.yaml\` to override weights, threshold, or skip paths._`);
|
|
108
|
+
return lines.join("\n\n");
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build the PR review payload from a consolidation output. Pure, deterministic.
|
|
112
|
+
*
|
|
113
|
+
* Output shape mirrors the squad's terminal report, repurposed as a markdown PR
|
|
114
|
+
* review body:
|
|
115
|
+
* 1. Header with verdict + weighted score
|
|
116
|
+
* 2. Rubric scorecard (fenced code block — keeps the bars monospace)
|
|
117
|
+
* 3. Findings grouped by agent (Blockers + unjustified Majors expanded;
|
|
118
|
+
* Minor/Suggestion totals only)
|
|
119
|
+
* 4. Footer with attribution + override hint
|
|
120
|
+
*
|
|
121
|
+
* The action is chosen via `chooseGhAction` — caller passes it to
|
|
122
|
+
* `gh pr review --<action>`.
|
|
123
|
+
*/
|
|
124
|
+
export function formatPrReview(consolidation, options = {}) {
|
|
125
|
+
const action = chooseGhAction(consolidation, options);
|
|
126
|
+
const sections = [];
|
|
127
|
+
sections.push(`## ${verdictHeader(consolidation)}`);
|
|
128
|
+
const rubricBlock = formatRubricBlock(consolidation.rubric);
|
|
129
|
+
if (rubricBlock)
|
|
130
|
+
sections.push(rubricBlock);
|
|
131
|
+
const findings = formatFindingsSection(consolidation);
|
|
132
|
+
if (findings)
|
|
133
|
+
sections.push(findings);
|
|
134
|
+
sections.push(formatFooter(consolidation, action, options));
|
|
135
|
+
const body = sections.join("\n\n") + "\n";
|
|
136
|
+
// Single-line summary for fallbacks. Capped at ~200 chars — gh accepts more,
|
|
137
|
+
// but PR review bodies that go in `--body` instead of `--body-file` get
|
|
138
|
+
// shell-quoted and long lines invite escaping bugs.
|
|
139
|
+
const c = consolidation.severity_counts;
|
|
140
|
+
const scoreSegment = consolidation.rubric
|
|
141
|
+
? ` | score ${consolidation.rubric.weighted_score.toFixed(1)}/100`
|
|
142
|
+
: "";
|
|
143
|
+
const summary = `Squad: ${consolidation.verdict}${scoreSegment} | ${c.Blocker}B/${c.Major}M/${c.Minor}m/${c.Suggestion}s`;
|
|
144
|
+
return { body, action, summary };
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=pr-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-review.js","sourceRoot":"","sources":["../../src/format/pr-review.ts"],"names":[],"mappings":"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"}
|