@gempack/squad-mcp 0.5.0 → 0.6.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 +2 -2
- package/.claude-plugin/plugin.json +3 -2
- package/CHANGELOG.md +260 -17
- package/INSTALL.md +156 -24
- package/README.md +279 -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 +1 -1
- package/dist/resources/agent-loader.js +53 -40
- 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 +4 -1
- package/skills/squad/SKILL.md +454 -0
- package/tools/post-review.mjs +212 -0
- /package/agents/{Skill-Squad-Dev.md → _shared/Skill-Squad-Dev.md} +0 -0
- /package/agents/{Skill-Squad-Review.md → _shared/Skill-Squad-Review.md} +0 -0
- /package/agents/{_Severity-and-Ownership.md → _shared/_Severity-and-Ownership.md} +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readTasks } from "../tasks/store.js";
|
|
3
|
+
import { nextTask as nextTaskFn } from "../tasks/select.js";
|
|
4
|
+
import { readSquadYaml } from "../config/squad-yaml.js";
|
|
5
|
+
import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
|
|
6
|
+
import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
|
|
7
|
+
const taskStatusEnum = z.enum([
|
|
8
|
+
"pending",
|
|
9
|
+
"in-progress",
|
|
10
|
+
"review",
|
|
11
|
+
"done",
|
|
12
|
+
"blocked",
|
|
13
|
+
"cancelled",
|
|
14
|
+
]);
|
|
15
|
+
const schema = z.object({
|
|
16
|
+
workspace_root: z.string().min(1).max(4096),
|
|
17
|
+
agent: z.enum(AGENT_NAMES_TUPLE).optional(),
|
|
18
|
+
changed_files: z.array(z.string().min(1).max(4096)).max(5000).optional(),
|
|
19
|
+
/** Override default candidate statuses (default `["pending"]`). */
|
|
20
|
+
candidate_statuses: z.array(taskStatusEnum).max(6).optional(),
|
|
21
|
+
/** Override what "complete" means for dep checks (default `["done"]`). */
|
|
22
|
+
done_statuses: z.array(taskStatusEnum).max(6).optional(),
|
|
23
|
+
});
|
|
24
|
+
export async function nextTaskTool(input) {
|
|
25
|
+
const ctx = createSafePathContext();
|
|
26
|
+
const safeRoot = await resolveSafePath(input.workspace_root, ".", ctx);
|
|
27
|
+
const config = await readSquadYaml(safeRoot);
|
|
28
|
+
if (!config.tasks.enabled) {
|
|
29
|
+
return { task: null, reason: "no_candidates", blocked: [] };
|
|
30
|
+
}
|
|
31
|
+
const file = await readTasks(safeRoot, { configuredPath: config.tasks.path });
|
|
32
|
+
const result = nextTaskFn(file.tasks, {
|
|
33
|
+
...(input.agent !== undefined && { agent: input.agent }),
|
|
34
|
+
...(input.changed_files !== undefined && {
|
|
35
|
+
changed_files: input.changed_files,
|
|
36
|
+
}),
|
|
37
|
+
...(input.candidate_statuses !== undefined && {
|
|
38
|
+
candidate_statuses: input.candidate_statuses,
|
|
39
|
+
}),
|
|
40
|
+
...(input.done_statuses !== undefined && {
|
|
41
|
+
done_statuses: input.done_statuses,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
task: result.task,
|
|
46
|
+
reason: result.reason,
|
|
47
|
+
blocked: result.blocked.map((b) => ({
|
|
48
|
+
id: b.task.id,
|
|
49
|
+
title: b.task.title,
|
|
50
|
+
missing_deps: b.missing_deps,
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export const nextTaskToolDef = {
|
|
55
|
+
name: "next_task",
|
|
56
|
+
description: "Pick the next ready task: candidate status (default pending), all dependencies done, optional agent / changed_files filter. Tiebreaker priority then id. Returns null with reason when none ready, plus the blocked list so callers can show 'X is next when Y completes'.",
|
|
57
|
+
schema,
|
|
58
|
+
handler: nextTaskTool,
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=next-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-task.js","sourceRoot":"","sources":["../../src/tools/next-task.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolDef } from "./registry.js";
|
|
3
|
+
import { type LearningEntry } from "../learning/store.js";
|
|
4
|
+
declare const schema: z.ZodObject<{
|
|
5
|
+
workspace_root: z.ZodString;
|
|
6
|
+
/** Cap rendered/returned entries. Default 50. */
|
|
7
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
8
|
+
/** When set, restrict to learnings for this agent. */
|
|
9
|
+
agent: z.ZodOptional<z.ZodEnum<[import("../config/ownership-matrix.js").AgentName, ...import("../config/ownership-matrix.js").AgentName[]]>>;
|
|
10
|
+
/** When set, restrict to accepts or rejects. Default both. */
|
|
11
|
+
decision: z.ZodOptional<z.ZodEnum<["accept", "reject"]>>;
|
|
12
|
+
/**
|
|
13
|
+
* When set, filter scope-tagged entries to those whose scope glob matches
|
|
14
|
+
* at least one of these files. Entries without a scope always pass.
|
|
15
|
+
*/
|
|
16
|
+
changed_files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
17
|
+
/**
|
|
18
|
+
* When true (default), also return the rendered markdown block ready to
|
|
19
|
+
* inject into an agent / consolidator prompt. When false, only the entries
|
|
20
|
+
* array. Skip the render when the caller will format their own.
|
|
21
|
+
*/
|
|
22
|
+
include_rendered: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
workspace_root: string;
|
|
25
|
+
limit: number;
|
|
26
|
+
include_rendered: boolean;
|
|
27
|
+
agent?: import("../config/ownership-matrix.js").AgentName | undefined;
|
|
28
|
+
decision?: "accept" | "reject" | undefined;
|
|
29
|
+
changed_files?: string[] | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
workspace_root: string;
|
|
32
|
+
agent?: import("../config/ownership-matrix.js").AgentName | undefined;
|
|
33
|
+
decision?: "accept" | "reject" | undefined;
|
|
34
|
+
limit?: number | undefined;
|
|
35
|
+
changed_files?: string[] | undefined;
|
|
36
|
+
include_rendered?: boolean | undefined;
|
|
37
|
+
}>;
|
|
38
|
+
type Input = z.infer<typeof schema>;
|
|
39
|
+
export interface ReadLearningsOutput {
|
|
40
|
+
entries: LearningEntry[];
|
|
41
|
+
total_in_store: number;
|
|
42
|
+
rendered: string;
|
|
43
|
+
source: string | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Read recent learnings from `.squad/learnings.jsonl` (path overridable via
|
|
47
|
+
* `.squad.yaml`.learnings.path). Returns the filtered entries plus a
|
|
48
|
+
* pre-rendered markdown block ready to inject into an agent / consolidator
|
|
49
|
+
* prompt. Pure-ish — reads filesystem, no writes.
|
|
50
|
+
*/
|
|
51
|
+
export declare function readLearningsTool(input: Input): Promise<ReadLearningsOutput>;
|
|
52
|
+
export declare const readLearningsToolDef: ToolDef<typeof schema>;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readLearnings, tailRecent, } from "../learning/store.js";
|
|
3
|
+
import { formatLearningsForPrompt } from "../learning/format.js";
|
|
4
|
+
import { readSquadYaml } from "../config/squad-yaml.js";
|
|
5
|
+
import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
|
|
6
|
+
import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
|
|
7
|
+
const schema = z.object({
|
|
8
|
+
workspace_root: z.string().min(1).max(4096),
|
|
9
|
+
/** Cap rendered/returned entries. Default 50. */
|
|
10
|
+
limit: z.number().int().positive().max(200).optional().default(50),
|
|
11
|
+
/** When set, restrict to learnings for this agent. */
|
|
12
|
+
agent: z.enum(AGENT_NAMES_TUPLE).optional(),
|
|
13
|
+
/** When set, restrict to accepts or rejects. Default both. */
|
|
14
|
+
decision: z.enum(["accept", "reject"]).optional(),
|
|
15
|
+
/**
|
|
16
|
+
* When set, filter scope-tagged entries to those whose scope glob matches
|
|
17
|
+
* at least one of these files. Entries without a scope always pass.
|
|
18
|
+
*/
|
|
19
|
+
changed_files: z.array(z.string().min(1).max(4096)).max(5000).optional(),
|
|
20
|
+
/**
|
|
21
|
+
* When true (default), also return the rendered markdown block ready to
|
|
22
|
+
* inject into an agent / consolidator prompt. When false, only the entries
|
|
23
|
+
* array. Skip the render when the caller will format their own.
|
|
24
|
+
*/
|
|
25
|
+
include_rendered: z.boolean().optional().default(true),
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Read recent learnings from `.squad/learnings.jsonl` (path overridable via
|
|
29
|
+
* `.squad.yaml`.learnings.path). Returns the filtered entries plus a
|
|
30
|
+
* pre-rendered markdown block ready to inject into an agent / consolidator
|
|
31
|
+
* prompt. Pure-ish — reads filesystem, no writes.
|
|
32
|
+
*/
|
|
33
|
+
export async function readLearningsTool(input) {
|
|
34
|
+
const ctx = createSafePathContext();
|
|
35
|
+
const safeRoot = await resolveSafePath(input.workspace_root, ".", ctx);
|
|
36
|
+
const config = await readSquadYaml(safeRoot);
|
|
37
|
+
// Honor the master switch — if learnings disabled, return empty without
|
|
38
|
+
// touching the filesystem (the user explicitly turned it off).
|
|
39
|
+
if (!config.learnings.enabled) {
|
|
40
|
+
return { entries: [], total_in_store: 0, rendered: "", source: null };
|
|
41
|
+
}
|
|
42
|
+
const configuredPath = config.learnings.path;
|
|
43
|
+
const allEntries = await readLearnings(safeRoot, { configuredPath });
|
|
44
|
+
const filtered = tailRecent(allEntries, input.limit, {
|
|
45
|
+
...(input.agent !== undefined ? { agent: input.agent } : {}),
|
|
46
|
+
...(input.decision !== undefined ? { decision: input.decision } : {}),
|
|
47
|
+
});
|
|
48
|
+
const rendered = input.include_rendered
|
|
49
|
+
? formatLearningsForPrompt(filtered, {
|
|
50
|
+
...(input.changed_files ? { changedFiles: input.changed_files } : {}),
|
|
51
|
+
limit: input.limit,
|
|
52
|
+
})
|
|
53
|
+
: "";
|
|
54
|
+
return {
|
|
55
|
+
entries: filtered,
|
|
56
|
+
total_in_store: allEntries.length,
|
|
57
|
+
rendered,
|
|
58
|
+
source: allEntries.length > 0
|
|
59
|
+
? `${safeRoot}/${configuredPath ?? ".squad/learnings.jsonl"}`
|
|
60
|
+
: null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export const readLearningsToolDef = {
|
|
64
|
+
name: "read_learnings",
|
|
65
|
+
description: "Read recent team decisions from `.squad/learnings.jsonl` (path overridable via .squad.yaml.learnings.path). " +
|
|
66
|
+
"Returns the filtered entries plus a pre-rendered markdown block ready to inject into agent / consolidator prompts. " +
|
|
67
|
+
"Filters: agent, decision (accept|reject), changed_files (matches scoped entries against these paths). " +
|
|
68
|
+
"Used by the /squad-review skill in Phase 5 (advisory) and Phase 10 (consolidation) to make the squad less repetitive over time.",
|
|
69
|
+
schema,
|
|
70
|
+
handler: readLearningsTool,
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=read-learnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-learnings.js","sourceRoot":"","sources":["../../src/tools/read-learnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolDef } from "./registry.js";
|
|
3
|
+
import { type ResolvedSquadConfig } from "../config/squad-yaml.js";
|
|
4
|
+
declare const schema: z.ZodObject<{
|
|
5
|
+
workspace_root: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
workspace_root: string;
|
|
8
|
+
}, {
|
|
9
|
+
workspace_root: string;
|
|
10
|
+
}>;
|
|
11
|
+
type Input = z.infer<typeof schema>;
|
|
12
|
+
/**
|
|
13
|
+
* MCP tool wrapper around the YAML reader. Lets non-Claude-Code clients (or
|
|
14
|
+
* non-composer callers) inspect the resolved config explicitly. Pure tools
|
|
15
|
+
* (apply_consolidation_rules, score_rubric, select_squad) do NOT call this —
|
|
16
|
+
* the composers (compose_squad_workflow, compose_advisory_bundle) read
|
|
17
|
+
* .squad.yaml automatically when they receive workspace_root, then pass the
|
|
18
|
+
* concrete values down. This tool is for direct introspection and for clients
|
|
19
|
+
* that want to construct a tailored bundle themselves.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readSquadConfig(input: Input): Promise<ResolvedSquadConfig>;
|
|
22
|
+
export declare const readSquadConfigTool: ToolDef<typeof schema>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readSquadYaml, } from "../config/squad-yaml.js";
|
|
3
|
+
import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
|
|
4
|
+
const schema = z.object({
|
|
5
|
+
workspace_root: z.string().min(1).max(4096),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* MCP tool wrapper around the YAML reader. Lets non-Claude-Code clients (or
|
|
9
|
+
* non-composer callers) inspect the resolved config explicitly. Pure tools
|
|
10
|
+
* (apply_consolidation_rules, score_rubric, select_squad) do NOT call this —
|
|
11
|
+
* the composers (compose_squad_workflow, compose_advisory_bundle) read
|
|
12
|
+
* .squad.yaml automatically when they receive workspace_root, then pass the
|
|
13
|
+
* concrete values down. This tool is for direct introspection and for clients
|
|
14
|
+
* that want to construct a tailored bundle themselves.
|
|
15
|
+
*/
|
|
16
|
+
export async function readSquadConfig(input) {
|
|
17
|
+
// Containment check — canonicalise the workspace root via the same machinery
|
|
18
|
+
// every other path-receiving tool uses. resolveSafePath returns the realpath
|
|
19
|
+
// of `<root>/.` which is the root itself.
|
|
20
|
+
const ctx = createSafePathContext();
|
|
21
|
+
const safe = await resolveSafePath(input.workspace_root, ".", ctx);
|
|
22
|
+
return await readSquadYaml(safe);
|
|
23
|
+
}
|
|
24
|
+
export const readSquadConfigTool = {
|
|
25
|
+
name: "read_squad_config",
|
|
26
|
+
description: "Read and resolve `.squad.yaml` (or `.squad.yml`) at the given workspace_root. " +
|
|
27
|
+
"Returns effective weights (defaults merged), threshold, min_score, skip_paths, disable_agents, " +
|
|
28
|
+
"and the source path (or null if no file present). Composers (compose_squad_workflow, " +
|
|
29
|
+
"compose_advisory_bundle) read this automatically when they receive workspace_root; this tool " +
|
|
30
|
+
"is for explicit introspection and for clients that build their own bundle.",
|
|
31
|
+
schema,
|
|
32
|
+
handler: readSquadConfig,
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=read-squad-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-squad-config.js","sourceRoot":"","sources":["../../src/tools/read-squad-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,aAAa,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;CAC5C,CAAC,CAAC;AAIH;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAY;IAEZ,6EAA6E;IAC7E,6EAA6E;IAC7E,0CAA0C;IAC1C,MAAM,GAAG,GAAG,qBAAqB,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACnE,OAAO,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAA2B;IACzD,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,gFAAgF;QAChF,iGAAiG;QACjG,uFAAuF;QACvF,+FAA+F;QAC/F,4EAA4E;IAC9E,MAAM;IACN,OAAO,EAAE,eAAe;CACzB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolDef } from "./registry.js";
|
|
3
|
+
declare const schema: z.ZodObject<{
|
|
4
|
+
workspace_root: z.ZodString;
|
|
5
|
+
/** Which agent's finding this decision concerns. */
|
|
6
|
+
agent: z.ZodEnum<[import("../config/ownership-matrix.js").AgentName, ...import("../config/ownership-matrix.js").AgentName[]]>;
|
|
7
|
+
/** Short title of the finding (matches finding.title from consolidate). */
|
|
8
|
+
finding: z.ZodString;
|
|
9
|
+
/** Whether the team accepted or rejected this finding. */
|
|
10
|
+
decision: z.ZodEnum<["accept", "reject"]>;
|
|
11
|
+
/** Severity at the time of the decision. */
|
|
12
|
+
severity: z.ZodOptional<z.ZodEnum<["Blocker", "Major", "Minor", "Suggestion"]>>;
|
|
13
|
+
/** Free-form rationale. Surfaces in the consolidator prompt. */
|
|
14
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
15
|
+
/** PR number when recorded from `/squad-review #N`. */
|
|
16
|
+
pr: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
/** Branch name when recorded from a local review. */
|
|
18
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
19
|
+
/** Glob-ish path scope (e.g. "src/auth/**"). When absent, repo-wide. */
|
|
20
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
workspace_root: string;
|
|
23
|
+
agent: import("../config/ownership-matrix.js").AgentName;
|
|
24
|
+
finding: string;
|
|
25
|
+
decision: "accept" | "reject";
|
|
26
|
+
reason?: string | undefined;
|
|
27
|
+
severity?: "Blocker" | "Major" | "Minor" | "Suggestion" | undefined;
|
|
28
|
+
pr?: number | undefined;
|
|
29
|
+
branch?: string | undefined;
|
|
30
|
+
scope?: string | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
workspace_root: string;
|
|
33
|
+
agent: import("../config/ownership-matrix.js").AgentName;
|
|
34
|
+
finding: string;
|
|
35
|
+
decision: "accept" | "reject";
|
|
36
|
+
reason?: string | undefined;
|
|
37
|
+
severity?: "Blocker" | "Major" | "Minor" | "Suggestion" | undefined;
|
|
38
|
+
pr?: number | undefined;
|
|
39
|
+
branch?: string | undefined;
|
|
40
|
+
scope?: string | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
type Input = z.infer<typeof schema>;
|
|
43
|
+
/**
|
|
44
|
+
* Append a new entry to `.squad/learnings.jsonl`. Atomic per-line. Skill calls
|
|
45
|
+
* this in Phase 14 (post-PR record). The CLI helper `tools/record-learning.mjs`
|
|
46
|
+
* is the equivalent for non-MCP clients.
|
|
47
|
+
*
|
|
48
|
+
* Side-effecting (writes to disk). The skill or CLI is responsible for
|
|
49
|
+
* confirming with the user before invoking — this tool itself never asks
|
|
50
|
+
* (MCP tools don't have user prompts).
|
|
51
|
+
*/
|
|
52
|
+
export declare function recordLearningTool(input: Input): Promise<{
|
|
53
|
+
recorded: true;
|
|
54
|
+
file: string;
|
|
55
|
+
entry: {
|
|
56
|
+
ts: string;
|
|
57
|
+
agent: string;
|
|
58
|
+
decision: string;
|
|
59
|
+
};
|
|
60
|
+
}>;
|
|
61
|
+
export declare const recordLearningToolDef: ToolDef<typeof schema>;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { appendLearning } from "../learning/store.js";
|
|
3
|
+
import { readSquadYaml } from "../config/squad-yaml.js";
|
|
4
|
+
import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
|
|
5
|
+
import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
|
|
6
|
+
const schema = z.object({
|
|
7
|
+
workspace_root: z.string().min(1).max(4096),
|
|
8
|
+
/** Which agent's finding this decision concerns. */
|
|
9
|
+
agent: z.enum(AGENT_NAMES_TUPLE),
|
|
10
|
+
/** Short title of the finding (matches finding.title from consolidate). */
|
|
11
|
+
finding: z.string().min(1).max(2048),
|
|
12
|
+
/** Whether the team accepted or rejected this finding. */
|
|
13
|
+
decision: z.enum(["accept", "reject"]),
|
|
14
|
+
/** Severity at the time of the decision. */
|
|
15
|
+
severity: z.enum(["Blocker", "Major", "Minor", "Suggestion"]).optional(),
|
|
16
|
+
/** Free-form rationale. Surfaces in the consolidator prompt. */
|
|
17
|
+
reason: z.string().max(4096).optional(),
|
|
18
|
+
/** PR number when recorded from `/squad-review #N`. */
|
|
19
|
+
pr: z.number().int().positive().optional(),
|
|
20
|
+
/** Branch name when recorded from a local review. */
|
|
21
|
+
branch: z.string().min(1).max(255).optional(),
|
|
22
|
+
/** Glob-ish path scope (e.g. "src/auth/**"). When absent, repo-wide. */
|
|
23
|
+
scope: z.string().min(1).max(512).optional(),
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Append a new entry to `.squad/learnings.jsonl`. Atomic per-line. Skill calls
|
|
27
|
+
* this in Phase 14 (post-PR record). The CLI helper `tools/record-learning.mjs`
|
|
28
|
+
* is the equivalent for non-MCP clients.
|
|
29
|
+
*
|
|
30
|
+
* Side-effecting (writes to disk). The skill or CLI is responsible for
|
|
31
|
+
* confirming with the user before invoking — this tool itself never asks
|
|
32
|
+
* (MCP tools don't have user prompts).
|
|
33
|
+
*/
|
|
34
|
+
export async function recordLearningTool(input) {
|
|
35
|
+
const ctx = createSafePathContext();
|
|
36
|
+
const safeRoot = await resolveSafePath(input.workspace_root, ".", ctx);
|
|
37
|
+
const config = await readSquadYaml(safeRoot);
|
|
38
|
+
// Recording IS allowed even when reads are disabled — turning off injection
|
|
39
|
+
// (e.g. for a quiet release window) shouldn't throw away the journal. The
|
|
40
|
+
// skill is responsible for not calling record_learning when the user did
|
|
41
|
+
// not authorise the decision.
|
|
42
|
+
const configuredPath = config.learnings.path;
|
|
43
|
+
const entry = {
|
|
44
|
+
agent: input.agent,
|
|
45
|
+
finding: input.finding,
|
|
46
|
+
decision: input.decision,
|
|
47
|
+
};
|
|
48
|
+
if (input.severity !== undefined)
|
|
49
|
+
entry.severity = input.severity;
|
|
50
|
+
if (input.reason !== undefined)
|
|
51
|
+
entry.reason = input.reason;
|
|
52
|
+
if (input.pr !== undefined)
|
|
53
|
+
entry.pr = input.pr;
|
|
54
|
+
if (input.branch !== undefined)
|
|
55
|
+
entry.branch = input.branch;
|
|
56
|
+
if (input.scope !== undefined)
|
|
57
|
+
entry.scope = input.scope;
|
|
58
|
+
const result = await appendLearning(safeRoot, entry, {
|
|
59
|
+
...(configuredPath !== undefined ? { configuredPath } : {}),
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
recorded: true,
|
|
63
|
+
file: result.filePath,
|
|
64
|
+
entry: {
|
|
65
|
+
ts: result.entry.ts,
|
|
66
|
+
agent: result.entry.agent,
|
|
67
|
+
decision: result.entry.decision,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export const recordLearningToolDef = {
|
|
72
|
+
name: "record_learning",
|
|
73
|
+
description: "Append a team decision (accept | reject) on a finding to `.squad/learnings.jsonl`. " +
|
|
74
|
+
"Future runs of the squad will inject the most recent entries into agent / consolidator prompts so " +
|
|
75
|
+
"the squad stops re-suggesting things the team has already declined (with reason). " +
|
|
76
|
+
"Side-effecting — writes to disk. Caller (skill or CLI) is responsible for user confirmation.",
|
|
77
|
+
schema,
|
|
78
|
+
handler: recordLearningTool,
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=record-learning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-learning.js","sourceRoot":"","sources":["../../src/tools/record-learning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolDef } from "./registry.js";
|
|
3
|
+
declare const schema: z.ZodObject<{
|
|
4
|
+
workspace_root: z.ZodString;
|
|
5
|
+
tasks: z.ZodArray<z.ZodObject<{
|
|
6
|
+
id: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
title: z.ZodString;
|
|
8
|
+
description: z.ZodOptional<z.ZodString>;
|
|
9
|
+
dependencies: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
|
|
10
|
+
priority: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
|
|
11
|
+
details: z.ZodOptional<z.ZodString>;
|
|
12
|
+
test_strategy: z.ZodOptional<z.ZodString>;
|
|
13
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
14
|
+
agent_hints: z.ZodOptional<z.ZodArray<z.ZodEnum<[import("../config/ownership-matrix.js").AgentName, ...import("../config/ownership-matrix.js").AgentName[]]>, "many">>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
title: string;
|
|
17
|
+
details?: string | undefined;
|
|
18
|
+
scope?: string | undefined;
|
|
19
|
+
id?: number | undefined;
|
|
20
|
+
description?: string | undefined;
|
|
21
|
+
dependencies?: number[] | undefined;
|
|
22
|
+
priority?: "high" | "medium" | "low" | undefined;
|
|
23
|
+
test_strategy?: string | undefined;
|
|
24
|
+
agent_hints?: import("../config/ownership-matrix.js").AgentName[] | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
title: string;
|
|
27
|
+
details?: string | undefined;
|
|
28
|
+
scope?: string | undefined;
|
|
29
|
+
id?: number | undefined;
|
|
30
|
+
description?: string | undefined;
|
|
31
|
+
dependencies?: number[] | undefined;
|
|
32
|
+
priority?: "high" | "medium" | "low" | undefined;
|
|
33
|
+
test_strategy?: string | undefined;
|
|
34
|
+
agent_hints?: import("../config/ownership-matrix.js").AgentName[] | undefined;
|
|
35
|
+
}>, "many">;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
workspace_root: string;
|
|
38
|
+
tasks: {
|
|
39
|
+
title: string;
|
|
40
|
+
details?: string | undefined;
|
|
41
|
+
scope?: string | undefined;
|
|
42
|
+
id?: number | undefined;
|
|
43
|
+
description?: string | undefined;
|
|
44
|
+
dependencies?: number[] | undefined;
|
|
45
|
+
priority?: "high" | "medium" | "low" | undefined;
|
|
46
|
+
test_strategy?: string | undefined;
|
|
47
|
+
agent_hints?: import("../config/ownership-matrix.js").AgentName[] | undefined;
|
|
48
|
+
}[];
|
|
49
|
+
}, {
|
|
50
|
+
workspace_root: string;
|
|
51
|
+
tasks: {
|
|
52
|
+
title: string;
|
|
53
|
+
details?: string | undefined;
|
|
54
|
+
scope?: string | undefined;
|
|
55
|
+
id?: number | undefined;
|
|
56
|
+
description?: string | undefined;
|
|
57
|
+
dependencies?: number[] | undefined;
|
|
58
|
+
priority?: "high" | "medium" | "low" | undefined;
|
|
59
|
+
test_strategy?: string | undefined;
|
|
60
|
+
agent_hints?: import("../config/ownership-matrix.js").AgentName[] | undefined;
|
|
61
|
+
}[];
|
|
62
|
+
}>;
|
|
63
|
+
type Input = z.infer<typeof schema>;
|
|
64
|
+
export interface RecordTasksOutput {
|
|
65
|
+
recorded: true;
|
|
66
|
+
file: string;
|
|
67
|
+
ids: number[];
|
|
68
|
+
}
|
|
69
|
+
export declare function recordTasksTool(input: Input): Promise<RecordTasksOutput>;
|
|
70
|
+
export declare const recordTasksToolDef: ToolDef<typeof schema>;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { recordTasks } from "../tasks/store.js";
|
|
3
|
+
import { readSquadYaml } from "../config/squad-yaml.js";
|
|
4
|
+
import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
|
|
5
|
+
import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
|
|
6
|
+
const taskInputSchema = z.object({
|
|
7
|
+
id: z.number().int().positive().optional(),
|
|
8
|
+
title: z.string().min(1).max(512),
|
|
9
|
+
description: z.string().max(4096).optional(),
|
|
10
|
+
dependencies: z.array(z.number().int().positive()).max(50).optional(),
|
|
11
|
+
priority: z.enum(["low", "medium", "high"]).optional(),
|
|
12
|
+
details: z.string().max(16384).optional(),
|
|
13
|
+
test_strategy: z.string().max(4096).optional(),
|
|
14
|
+
scope: z.string().min(1).max(512).optional(),
|
|
15
|
+
agent_hints: z.array(z.enum(AGENT_NAMES_TUPLE)).optional(),
|
|
16
|
+
});
|
|
17
|
+
const schema = z.object({
|
|
18
|
+
workspace_root: z.string().min(1).max(4096),
|
|
19
|
+
tasks: z.array(taskInputSchema).min(1).max(500),
|
|
20
|
+
});
|
|
21
|
+
export async function recordTasksTool(input) {
|
|
22
|
+
const ctx = createSafePathContext();
|
|
23
|
+
const safeRoot = await resolveSafePath(input.workspace_root, ".", ctx);
|
|
24
|
+
const config = await readSquadYaml(safeRoot);
|
|
25
|
+
// Writes stay open even when reads disabled — same policy as learnings.
|
|
26
|
+
const result = await recordTasks(safeRoot, input.tasks.map((t) => ({
|
|
27
|
+
...(t.id !== undefined && { id: t.id }),
|
|
28
|
+
title: t.title,
|
|
29
|
+
...(t.description !== undefined && { description: t.description }),
|
|
30
|
+
...(t.dependencies !== undefined && { dependencies: t.dependencies }),
|
|
31
|
+
...(t.priority !== undefined && { priority: t.priority }),
|
|
32
|
+
...(t.details !== undefined && { details: t.details }),
|
|
33
|
+
...(t.test_strategy !== undefined && { test_strategy: t.test_strategy }),
|
|
34
|
+
...(t.scope !== undefined && { scope: t.scope }),
|
|
35
|
+
...(t.agent_hints !== undefined && { agent_hints: t.agent_hints }),
|
|
36
|
+
})), { configuredPath: config.tasks.path });
|
|
37
|
+
return { recorded: true, file: result.filePath, ids: result.ids };
|
|
38
|
+
}
|
|
39
|
+
export const recordTasksToolDef = {
|
|
40
|
+
name: "record_tasks",
|
|
41
|
+
description: "Bulk-create tasks in `.squad/tasks.json`. Each task: id (optional, auto-allocated), title, description, dependencies, priority, details, test_strategy, scope (glob), agent_hints. Side-effecting — atomic write (tmp + rename). Validates: unique ids, all dependencies resolve, no self-deps. The host LLM is responsible for confirming with the user before bulk-recording from a parsed PRD.",
|
|
42
|
+
schema,
|
|
43
|
+
handler: recordTasksTool,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=record-tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-tasks.js","sourceRoot":"","sources":["../../src/tools/record-tasks.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/registry.d.ts
CHANGED