@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.
Files changed (102) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +3 -2
  3. package/CHANGELOG.md +271 -17
  4. package/INSTALL.md +156 -24
  5. package/README.md +278 -27
  6. package/agents/{PO.md → product-owner.md} +33 -1
  7. package/agents/{Senior-Architect.md → senior-architect.md} +33 -1
  8. package/agents/{Senior-DBA.md → senior-dba.md} +33 -1
  9. package/agents/{Senior-Dev-Reviewer.md → senior-dev-reviewer.md} +33 -1
  10. package/agents/{Senior-Dev-Security.md → senior-dev-security.md} +33 -1
  11. package/agents/{Senior-Developer.md → senior-developer.md} +33 -1
  12. package/agents/{Senior-QA.md → senior-qa.md} +33 -1
  13. package/agents/{TechLead-Consolidator.md → tech-lead-consolidator.md} +7 -1
  14. package/agents/{TechLead-Planner.md → tech-lead-planner.md} +7 -1
  15. package/commands/squad-review.md +10 -58
  16. package/commands/squad.md +11 -70
  17. package/dist/config/ownership-matrix.d.ts +24 -2
  18. package/dist/config/ownership-matrix.js +466 -139
  19. package/dist/config/ownership-matrix.js.map +1 -1
  20. package/dist/config/squad-yaml.d.ts +242 -0
  21. package/dist/config/squad-yaml.js +403 -0
  22. package/dist/config/squad-yaml.js.map +1 -0
  23. package/dist/errors.d.ts +1 -1
  24. package/dist/errors.js +1 -1
  25. package/dist/errors.js.map +1 -1
  26. package/dist/format/pr-review.d.ts +61 -0
  27. package/dist/format/pr-review.js +146 -0
  28. package/dist/format/pr-review.js.map +1 -0
  29. package/dist/index.js +19 -13
  30. package/dist/index.js.map +1 -1
  31. package/dist/learning/format.d.ts +29 -0
  32. package/dist/learning/format.js +55 -0
  33. package/dist/learning/format.js.map +1 -0
  34. package/dist/learning/store.d.ts +102 -0
  35. package/dist/learning/store.js +169 -0
  36. package/dist/learning/store.js.map +1 -0
  37. package/dist/resources/agent-loader.d.ts +8 -1
  38. package/dist/resources/agent-loader.js +83 -48
  39. package/dist/resources/agent-loader.js.map +1 -1
  40. package/dist/tasks/select.d.ts +64 -0
  41. package/dist/tasks/select.js +84 -0
  42. package/dist/tasks/select.js.map +1 -0
  43. package/dist/tasks/store.d.ts +338 -0
  44. package/dist/tasks/store.js +321 -0
  45. package/dist/tasks/store.js.map +1 -0
  46. package/dist/tools/compose-advisory-bundle.d.ts +5 -5
  47. package/dist/tools/compose-advisory-bundle.js +24 -12
  48. package/dist/tools/compose-advisory-bundle.js.map +1 -1
  49. package/dist/tools/compose-prd-parse.d.ts +53 -0
  50. package/dist/tools/compose-prd-parse.js +167 -0
  51. package/dist/tools/compose-prd-parse.js.map +1 -0
  52. package/dist/tools/compose-squad-workflow.d.ts +28 -10
  53. package/dist/tools/compose-squad-workflow.js +0 -0
  54. package/dist/tools/compose-squad-workflow.js.map +1 -1
  55. package/dist/tools/consolidate.d.ts +55 -4
  56. package/dist/tools/consolidate.js +87 -15
  57. package/dist/tools/consolidate.js.map +1 -1
  58. package/dist/tools/expand-task.d.ts +51 -0
  59. package/dist/tools/expand-task.js +35 -0
  60. package/dist/tools/expand-task.js.map +1 -0
  61. package/dist/tools/list-tasks.d.ts +31 -0
  62. package/dist/tools/list-tasks.js +50 -0
  63. package/dist/tools/list-tasks.js.map +1 -0
  64. package/dist/tools/next-task.d.ts +37 -0
  65. package/dist/tools/next-task.js +60 -0
  66. package/dist/tools/next-task.js.map +1 -0
  67. package/dist/tools/read-learnings.d.ts +53 -0
  68. package/dist/tools/read-learnings.js +72 -0
  69. package/dist/tools/read-learnings.js.map +1 -0
  70. package/dist/tools/read-squad-config.d.ts +23 -0
  71. package/dist/tools/read-squad-config.js +34 -0
  72. package/dist/tools/read-squad-config.js.map +1 -0
  73. package/dist/tools/record-learning.d.ts +62 -0
  74. package/dist/tools/record-learning.js +80 -0
  75. package/dist/tools/record-learning.js.map +1 -0
  76. package/dist/tools/record-tasks.d.ts +71 -0
  77. package/dist/tools/record-tasks.js +45 -0
  78. package/dist/tools/record-tasks.js.map +1 -0
  79. package/dist/tools/registry.d.ts +1 -1
  80. package/dist/tools/registry.js +71 -39
  81. package/dist/tools/registry.js.map +1 -1
  82. package/dist/tools/score-rubric.d.ts +74 -0
  83. package/dist/tools/score-rubric.js +140 -0
  84. package/dist/tools/score-rubric.js.map +1 -0
  85. package/dist/tools/slice-files-for-task.d.ts +31 -0
  86. package/dist/tools/slice-files-for-task.js +52 -0
  87. package/dist/tools/slice-files-for-task.js.map +1 -0
  88. package/dist/tools/update-task-status.d.ts +29 -0
  89. package/dist/tools/update-task-status.js +35 -0
  90. package/dist/tools/update-task-status.js.map +1 -0
  91. package/package.json +11 -1
  92. package/skills/squad/SKILL.md +454 -0
  93. package/tools/_tasks-io.mjs +69 -0
  94. package/tools/list-tasks.mjs +110 -0
  95. package/tools/next-task.mjs +131 -0
  96. package/tools/post-review.mjs +212 -0
  97. package/tools/record-learning.mjs +145 -0
  98. package/tools/record-tasks.mjs +186 -0
  99. package/tools/update-task-status.mjs +114 -0
  100. /package/{agents → shared}/Skill-Squad-Dev.md +0 -0
  101. /package/{agents → shared}/Skill-Squad-Review.md +0 -0
  102. /package/{agents → shared}/_Severity-and-Ownership.md +0 -0
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
- import { registerTools, dispatchTool, listTools } from './tools/registry.js';
6
- import { listResources, readResource } from './resources/registry.js';
7
- import { listPrompts, getPrompt } from './prompts/registry.js';
8
- import { logger, setupProcessHandlers } from './observability/logger.js';
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { registerTools, dispatchTool, listTools } from "./tools/registry.js";
6
+ import { listResources, readResource } from "./resources/registry.js";
7
+ import { listPrompts, getPrompt } from "./prompts/registry.js";
8
+ import { logger, setupProcessHandlers } from "./observability/logger.js";
9
9
  setupProcessHandlers();
10
- const SERVER_VERSION = '0.5.0';
10
+ const SERVER_VERSION = "0.6.1";
11
11
  const server = new Server({
12
- name: 'squad-mcp',
12
+ name: "squad-mcp",
13
13
  version: SERVER_VERSION,
14
14
  }, {
15
15
  capabilities: {
@@ -19,15 +19,21 @@ const server = new Server({
19
19
  },
20
20
  });
21
21
  registerTools();
22
- server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: listTools() }));
22
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
23
+ tools: listTools(),
24
+ }));
23
25
  server.setRequestHandler(CallToolRequestSchema, async (req) => dispatchTool(req.params.name, req.params.arguments ?? {}));
24
- server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: await listResources() }));
26
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
27
+ resources: await listResources(),
28
+ }));
25
29
  server.setRequestHandler(ReadResourceRequestSchema, async (req) => readResource(req.params.uri));
26
- server.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: listPrompts() }));
30
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
31
+ prompts: listPrompts(),
32
+ }));
27
33
  server.setRequestHandler(GetPromptRequestSchema, async (req) => getPrompt(req.params.name, req.params.arguments ?? {}));
28
34
  const transport = new StdioServerTransport();
29
35
  await server.connect(transport);
30
- logger.info('server started', {
36
+ logger.info("server started", {
31
37
  details: { version: SERVER_VERSION, tools: listTools().length },
32
38
  });
33
39
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,oBAAoB,EAAE,CAAC;AAEvB,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,cAAc;CACxB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;KACZ;CACF,CACF,CAAC;AAEF,aAAa,EAAE,CAAC;AAEhB,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;AACvF,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;AAE1H,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;AACzG,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjG,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7F,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;AAExH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE;IAC5B,OAAO,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE;CAChE,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,oBAAoB,EAAE,CAAC;AAEvB,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,cAAc;CACxB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;KACZ;CACF,CACF,CAAC;AAEF,aAAa,EAAE,CAAC;AAEhB,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE,SAAS,EAAE;CACnB,CAAC,CAAC,CAAC;AACJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAC5D,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAC1D,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAChE,SAAS,EAAE,MAAM,aAAa,EAAE;CACjC,CAAC,CAAC,CAAC;AACJ,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAChE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAC7B,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9D,OAAO,EAAE,WAAW,EAAE;CACvB,CAAC,CAAC,CAAC;AACJ,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAC7D,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CACvD,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE;IAC5B,OAAO,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE;CAChE,CAAC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { LearningEntry } from "./store.js";
2
+ export interface FormatLearningsOptions {
3
+ /**
4
+ * Filter to learnings whose `scope` glob matches at least one of these
5
+ * paths. Used to narrow per-PR injection to learnings relevant to the
6
+ * files actually changed. When empty / undefined, all entries pass.
7
+ */
8
+ changedFiles?: string[];
9
+ /**
10
+ * Cap the rendered list. Default 50. Tail-most-recent. Hard cap of 200
11
+ * to prevent prompt bloat.
12
+ */
13
+ limit?: number;
14
+ /**
15
+ * Heading level for the section. Default `## Past team decisions`. Adjust
16
+ * when injecting into a prompt that already nests under a higher heading.
17
+ */
18
+ heading?: string;
19
+ }
20
+ /**
21
+ * Render a slice of learning entries as a markdown block ready to inject into
22
+ * an agent or consolidator prompt. Pure function. The block is intentionally
23
+ * compact — each entry is one numbered line so the LLM can scan quickly and
24
+ * reference back ("see decision #4 — already declined this CSRF flag").
25
+ *
26
+ * Returns `''` when no entries qualify after filtering. Callers should check
27
+ * the empty case before injecting (avoid empty headers in prompts).
28
+ */
29
+ export declare function formatLearningsForPrompt(entries: LearningEntry[], options?: FormatLearningsOptions): string;
@@ -0,0 +1,55 @@
1
+ import { matchesGlob } from "../config/squad-yaml.js";
2
+ const HARD_LIMIT = 200;
3
+ const DEFAULT_LIMIT = 50;
4
+ const DEFAULT_HEADING = "## Past team decisions";
5
+ /**
6
+ * Render a slice of learning entries as a markdown block ready to inject into
7
+ * an agent or consolidator prompt. Pure function. The block is intentionally
8
+ * compact — each entry is one numbered line so the LLM can scan quickly and
9
+ * reference back ("see decision #4 — already declined this CSRF flag").
10
+ *
11
+ * Returns `''` when no entries qualify after filtering. Callers should check
12
+ * the empty case before injecting (avoid empty headers in prompts).
13
+ */
14
+ export function formatLearningsForPrompt(entries, options = {}) {
15
+ const limit = Math.min(options.limit ?? DEFAULT_LIMIT, HARD_LIMIT);
16
+ const heading = options.heading ?? DEFAULT_HEADING;
17
+ // Filter by scope glob match against changedFiles. An entry without a scope
18
+ // is repo-wide and always passes. An entry WITH a scope passes if any
19
+ // changed file matches the scope glob.
20
+ let relevant = entries;
21
+ if (options.changedFiles && options.changedFiles.length > 0) {
22
+ relevant = entries.filter((e) => {
23
+ if (!e.scope)
24
+ return true;
25
+ return options.changedFiles.some((p) => matchesGlob(e.scope, p));
26
+ });
27
+ }
28
+ // Tail-N most recent. Append order = chronological, so slice from end.
29
+ const tail = relevant.slice(-limit);
30
+ if (tail.length === 0)
31
+ return "";
32
+ // Render most-recent-first to bias the LLM's attention.
33
+ const ordered = [...tail].reverse();
34
+ const lines = [];
35
+ lines.push(heading);
36
+ lines.push("");
37
+ lines.push(`Recent decisions on similar findings (${ordered.length} of ${entries.length} total, most recent first). When evaluating a new finding that matches a past **rejected** decision (similar agent + similar finding text + matching scope), suppress or downgrade severity. When a finding contradicts a past **accepted** decision, flag the contradiction explicitly.`);
38
+ lines.push("");
39
+ ordered.forEach((e, i) => {
40
+ const ref = e.pr
41
+ ? `PR #${e.pr}`
42
+ : e.branch
43
+ ? `branch ${e.branch}`
44
+ : e.ts.slice(0, 10);
45
+ const verdict = e.decision === "reject" ? "REJECTED" : "ACCEPTED";
46
+ const sev = e.severity ? ` [${e.severity}]` : "";
47
+ const scope = e.scope ? ` (scope: \`${e.scope}\`)` : "";
48
+ lines.push(`${i + 1}. **${verdict}** at ${ref}${scope} — ${e.agent}${sev}: "${e.finding}"`);
49
+ if (e.reason) {
50
+ lines.push(` Reason: ${e.reason}`);
51
+ }
52
+ });
53
+ return lines.join("\n") + "\n";
54
+ }
55
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/learning/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { z } from "zod";
2
+ import { type AgentName } from "../config/ownership-matrix.js";
3
+ /**
4
+ * One row in `.squad/learnings.jsonl`. Append-only — entries are never
5
+ * rewritten, just superseded by later ones with the same (agent, finding,
6
+ * scope) tuple. Keep the schema small; rich query semantics are out of
7
+ * scope for V1 (the consolidator does free-text recall, not vector search).
8
+ */
9
+ declare const learningEntrySchema: z.ZodObject<{
10
+ /** ISO 8601 timestamp. Required for ordering. */
11
+ ts: z.ZodString;
12
+ /** PR number when recorded from `/squad-review #N`; optional otherwise. */
13
+ pr: z.ZodOptional<z.ZodNumber>;
14
+ /** Branch name when recorded from a local review (no PR ref). */
15
+ branch: z.ZodOptional<z.ZodString>;
16
+ /** Which agent's finding this decision concerns. */
17
+ agent: z.ZodEnum<[AgentName, ...AgentName[]]>;
18
+ /** Severity at the time of the decision (Blocker / Major / Minor / Suggestion). */
19
+ severity: z.ZodOptional<z.ZodEnum<["Blocker", "Major", "Minor", "Suggestion"]>>;
20
+ /** Short title of the finding — same shape as Finding.title in consolidate. */
21
+ finding: z.ZodString;
22
+ /** Whether the team accepted or rejected this finding. */
23
+ decision: z.ZodEnum<["accept", "reject"]>;
24
+ /** Free-form rationale. Surfaces in the consolidator prompt. */
25
+ reason: z.ZodOptional<z.ZodString>;
26
+ /**
27
+ * Glob-ish path scope this decision applies to (e.g. "src/auth/**"). When
28
+ * absent, the decision applies repo-wide. Used by the formatter to filter
29
+ * learnings down to those relevant to the current diff.
30
+ */
31
+ scope: z.ZodOptional<z.ZodString>;
32
+ }, "strip", z.ZodTypeAny, {
33
+ agent: AgentName;
34
+ ts: string;
35
+ finding: string;
36
+ decision: "accept" | "reject";
37
+ reason?: string | undefined;
38
+ severity?: "Blocker" | "Major" | "Minor" | "Suggestion" | undefined;
39
+ pr?: number | undefined;
40
+ branch?: string | undefined;
41
+ scope?: string | undefined;
42
+ }, {
43
+ agent: AgentName;
44
+ ts: string;
45
+ finding: string;
46
+ decision: "accept" | "reject";
47
+ reason?: string | undefined;
48
+ severity?: "Blocker" | "Major" | "Minor" | "Suggestion" | undefined;
49
+ pr?: number | undefined;
50
+ branch?: string | undefined;
51
+ scope?: string | undefined;
52
+ }>;
53
+ export type LearningEntry = z.infer<typeof learningEntrySchema>;
54
+ /**
55
+ * Default location for the JSONL file, relative to workspace_root. Repo-versioned
56
+ * by convention; the team commits `.squad/learnings.jsonl` along with the code so
57
+ * decisions are auditable in PR diffs.
58
+ */
59
+ export declare const DEFAULT_LEARNING_PATH = ".squad/learnings.jsonl";
60
+ /** Test-only: clear the per-process cache. Production code MUST NOT call this. */
61
+ export declare function __resetLearningStoreCacheForTests(): void;
62
+ /**
63
+ * Read all learnings from the JSONL file. Returns [] if the file does not exist
64
+ * (a fresh repo with no decisions recorded is the common case). Throws on
65
+ * parse failure of any individual line — callers may want to soft-fail, but
66
+ * silent corruption is worse than loud rejection.
67
+ */
68
+ export declare function readLearnings(workspaceRoot: string, options?: {
69
+ configuredPath?: string;
70
+ }): Promise<LearningEntry[]>;
71
+ /**
72
+ * Append a new learning entry to the JSONL file. Creates the directory and
73
+ * file if needed. Atomic at the append level (single fs.appendFile call —
74
+ * Node serialises this on POSIX); concurrent appenders may interleave entries
75
+ * but never corrupt them line-wise.
76
+ *
77
+ * Stamps the timestamp here if the caller did not supply one — gives a single
78
+ * source of clock truth and prevents stale ts in CLI invocations.
79
+ */
80
+ export declare function appendLearning(workspaceRoot: string, entry: Omit<LearningEntry, "ts"> & {
81
+ ts?: string;
82
+ }, options?: {
83
+ configuredPath?: string;
84
+ }): Promise<{
85
+ filePath: string;
86
+ entry: LearningEntry;
87
+ }>;
88
+ /**
89
+ * Filter helper: pick the most recent N entries, optionally narrowed by
90
+ * agent. Used by the formatter to inject a small, relevant slice into the
91
+ * agent / consolidator prompt.
92
+ *
93
+ * Sort: input is in append order (oldest first). We slice the tail. The
94
+ * filter happens BEFORE the slice — `recentForAgent('senior-dba', 50)`
95
+ * returns the last 50 DBA decisions, not the last 50 decisions overall
96
+ * filtered to DBA (which would often return zero on diverse repos).
97
+ */
98
+ export declare function tailRecent(entries: LearningEntry[], limit: number, options?: {
99
+ agent?: AgentName;
100
+ decision?: "accept" | "reject";
101
+ }): LearningEntry[];
102
+ export {};
@@ -0,0 +1,169 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { z } from "zod";
4
+ import { AGENT_NAMES_TUPLE, } from "../config/ownership-matrix.js";
5
+ import { SquadError } from "../errors.js";
6
+ import { logger } from "../observability/logger.js";
7
+ /**
8
+ * One row in `.squad/learnings.jsonl`. Append-only — entries are never
9
+ * rewritten, just superseded by later ones with the same (agent, finding,
10
+ * scope) tuple. Keep the schema small; rich query semantics are out of
11
+ * scope for V1 (the consolidator does free-text recall, not vector search).
12
+ */
13
+ const learningEntrySchema = z.object({
14
+ /** ISO 8601 timestamp. Required for ordering. */
15
+ ts: z.string().min(1).max(40),
16
+ /** PR number when recorded from `/squad-review #N`; optional otherwise. */
17
+ pr: z.number().int().positive().optional(),
18
+ /** Branch name when recorded from a local review (no PR ref). */
19
+ branch: z.string().min(1).max(255).optional(),
20
+ /** Which agent's finding this decision concerns. */
21
+ agent: z.enum(AGENT_NAMES_TUPLE),
22
+ /** Severity at the time of the decision (Blocker / Major / Minor / Suggestion). */
23
+ severity: z.enum(["Blocker", "Major", "Minor", "Suggestion"]).optional(),
24
+ /** Short title of the finding — same shape as Finding.title in consolidate. */
25
+ finding: z.string().min(1).max(2048),
26
+ /** Whether the team accepted or rejected this finding. */
27
+ decision: z.enum(["accept", "reject"]),
28
+ /** Free-form rationale. Surfaces in the consolidator prompt. */
29
+ reason: z.string().max(4096).optional(),
30
+ /**
31
+ * Glob-ish path scope this decision applies to (e.g. "src/auth/**"). When
32
+ * absent, the decision applies repo-wide. Used by the formatter to filter
33
+ * learnings down to those relevant to the current diff.
34
+ */
35
+ scope: z.string().min(1).max(512).optional(),
36
+ });
37
+ /**
38
+ * Default location for the JSONL file, relative to workspace_root. Repo-versioned
39
+ * by convention; the team commits `.squad/learnings.jsonl` along with the code so
40
+ * decisions are auditable in PR diffs.
41
+ */
42
+ export const DEFAULT_LEARNING_PATH = ".squad/learnings.jsonl";
43
+ const cache = new Map();
44
+ /** Test-only: clear the per-process cache. Production code MUST NOT call this. */
45
+ export function __resetLearningStoreCacheForTests() {
46
+ cache.clear();
47
+ }
48
+ function resolveLearningFile(workspaceRoot, configuredPath) {
49
+ const rel = configuredPath ?? DEFAULT_LEARNING_PATH;
50
+ return path.resolve(workspaceRoot, rel);
51
+ }
52
+ /**
53
+ * Read all learnings from the JSONL file. Returns [] if the file does not exist
54
+ * (a fresh repo with no decisions recorded is the common case). Throws on
55
+ * parse failure of any individual line — callers may want to soft-fail, but
56
+ * silent corruption is worse than loud rejection.
57
+ */
58
+ export async function readLearnings(workspaceRoot, options = {}) {
59
+ const filePath = resolveLearningFile(workspaceRoot, options.configuredPath);
60
+ const absRoot = path.resolve(workspaceRoot);
61
+ let stat;
62
+ try {
63
+ stat = await fs.stat(filePath);
64
+ }
65
+ catch {
66
+ // No file — first run, no learnings yet.
67
+ return [];
68
+ }
69
+ if (!stat.isFile()) {
70
+ return [];
71
+ }
72
+ const cached = cache.get(absRoot);
73
+ if (cached &&
74
+ cached.filePath === filePath &&
75
+ cached.mtimeMs === stat.mtimeMs) {
76
+ return cached.entries;
77
+ }
78
+ let raw;
79
+ try {
80
+ raw = await fs.readFile(filePath, "utf8");
81
+ }
82
+ catch (err) {
83
+ throw new SquadError("CONFIG_READ_FAILED", `failed to read learnings file ${filePath}: ${err.message}`, { source: filePath });
84
+ }
85
+ const lines = raw.split(/\r?\n/);
86
+ const entries = [];
87
+ let lineNo = 0;
88
+ for (const line of lines) {
89
+ lineNo++;
90
+ const trimmed = line.trim();
91
+ if (trimmed === "")
92
+ continue; // skip blank lines (trailing newline, spacing)
93
+ let parsed;
94
+ try {
95
+ parsed = JSON.parse(trimmed);
96
+ }
97
+ catch (err) {
98
+ throw new SquadError("INVALID_INPUT", `${filePath}:${lineNo}: invalid JSON: ${err.message}`, { source: filePath, line: lineNo });
99
+ }
100
+ const validated = learningEntrySchema.safeParse(parsed);
101
+ if (!validated.success) {
102
+ throw new SquadError("INVALID_INPUT", `${filePath}:${lineNo}: schema violation: ${validated.error.message}`, {
103
+ source: filePath,
104
+ line: lineNo,
105
+ issues: validated.error.issues.length,
106
+ });
107
+ }
108
+ entries.push(validated.data);
109
+ }
110
+ cache.set(absRoot, { mtimeMs: stat.mtimeMs, filePath, entries });
111
+ return entries;
112
+ }
113
+ /**
114
+ * Append a new learning entry to the JSONL file. Creates the directory and
115
+ * file if needed. Atomic at the append level (single fs.appendFile call —
116
+ * Node serialises this on POSIX); concurrent appenders may interleave entries
117
+ * but never corrupt them line-wise.
118
+ *
119
+ * Stamps the timestamp here if the caller did not supply one — gives a single
120
+ * source of clock truth and prevents stale ts in CLI invocations.
121
+ */
122
+ export async function appendLearning(workspaceRoot, entry, options = {}) {
123
+ const ts = entry.ts ?? new Date().toISOString();
124
+ const candidate = { ...entry, ts };
125
+ const validated = learningEntrySchema.safeParse(candidate);
126
+ if (!validated.success) {
127
+ throw new SquadError("INVALID_INPUT", `learning entry schema violation: ${validated.error.message}`, { issues: validated.error.issues.length });
128
+ }
129
+ const filePath = resolveLearningFile(workspaceRoot, options.configuredPath);
130
+ const dir = path.dirname(filePath);
131
+ await fs.mkdir(dir, { recursive: true });
132
+ // One JSON object per line, no pretty-print — keeps the file grep-friendly
133
+ // and minimises diff churn when entries get re-ordered (which they don't,
134
+ // but defensive).
135
+ const line = JSON.stringify(validated.data) + "\n";
136
+ await fs.appendFile(filePath, line, "utf8");
137
+ // Invalidate cache so next readLearnings reflects the append.
138
+ const absRoot = path.resolve(workspaceRoot);
139
+ cache.delete(absRoot);
140
+ logger.info("learning appended", {
141
+ details: {
142
+ file: filePath,
143
+ agent: validated.data.agent,
144
+ decision: validated.data.decision,
145
+ },
146
+ });
147
+ return { filePath, entry: validated.data };
148
+ }
149
+ /**
150
+ * Filter helper: pick the most recent N entries, optionally narrowed by
151
+ * agent. Used by the formatter to inject a small, relevant slice into the
152
+ * agent / consolidator prompt.
153
+ *
154
+ * Sort: input is in append order (oldest first). We slice the tail. The
155
+ * filter happens BEFORE the slice — `recentForAgent('senior-dba', 50)`
156
+ * returns the last 50 DBA decisions, not the last 50 decisions overall
157
+ * filtered to DBA (which would often return zero on diverse repos).
158
+ */
159
+ export function tailRecent(entries, limit, options = {}) {
160
+ let filtered = entries;
161
+ if (options.agent) {
162
+ filtered = filtered.filter((e) => e.agent === options.agent);
163
+ }
164
+ if (options.decision) {
165
+ filtered = filtered.filter((e) => e.decision === options.decision);
166
+ }
167
+ return filtered.slice(-limit);
168
+ }
169
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/learning/store.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type AgentName } from '../config/ownership-matrix.js';
1
+ import { type AgentName } from "../config/ownership-matrix.js";
2
2
  export declare const SHARED_FILES: string[];
3
3
  /**
4
4
  * Returns the configured override directory and whether it was set explicitly
@@ -9,6 +9,13 @@ export declare function getLocalDir(): {
9
9
  explicit: boolean;
10
10
  };
11
11
  export declare function getEmbeddedDir(): string;
12
+ /**
13
+ * Path to the shared docs directory at repo root (`<repo>/shared/`). Lives
14
+ * outside `agents/` so the Claude Code plugin manifest's agent validator does
15
+ * not see non-agent files. Mirrors to `<localOverrideDir>/shared/` when the
16
+ * user runs init_local_config.
17
+ */
18
+ export declare function getEmbeddedSharedDir(): string;
12
19
  /**
13
20
  * Test-only: reset all module-level caches and one-shot flags.
14
21
  * Production code MUST NOT call this.