@gempack/squad-mcp 0.8.2 → 0.10.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 (39) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +7 -4
  3. package/CHANGELOG.md +92 -0
  4. package/README.md +41 -35
  5. package/agents/senior-debugger.md +85 -0
  6. package/commands/debug.md +22 -0
  7. package/commands/stats.md +22 -0
  8. package/dist/config/ownership-matrix.d.ts +1 -1
  9. package/dist/config/ownership-matrix.js +16 -0
  10. package/dist/config/ownership-matrix.js.map +1 -1
  11. package/dist/errors.d.ts +1 -1
  12. package/dist/errors.js.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/resources/agent-loader.js +1 -0
  16. package/dist/resources/agent-loader.js.map +1 -1
  17. package/dist/runs/aggregate.d.ts +166 -0
  18. package/dist/runs/aggregate.js +378 -0
  19. package/dist/runs/aggregate.js.map +1 -0
  20. package/dist/runs/store.d.ts +328 -0
  21. package/dist/runs/store.js +406 -0
  22. package/dist/runs/store.js.map +1 -0
  23. package/dist/tools/list-runs.d.ts +52 -0
  24. package/dist/tools/list-runs.js +142 -0
  25. package/dist/tools/list-runs.js.map +1 -0
  26. package/dist/tools/record-run.d.ts +202 -0
  27. package/dist/tools/record-run.js +124 -0
  28. package/dist/tools/record-run.js.map +1 -0
  29. package/dist/tools/registry.js +15 -1
  30. package/dist/tools/registry.js.map +1 -1
  31. package/dist/util/path-safety.d.ts +36 -0
  32. package/dist/util/path-safety.js +76 -0
  33. package/dist/util/path-safety.js.map +1 -1
  34. package/package.json +1 -1
  35. package/skills/brainstorm/SKILL.md +70 -7
  36. package/skills/debug/SKILL.md +345 -0
  37. package/skills/question/SKILL.md +73 -1
  38. package/skills/squad/SKILL.md +83 -0
  39. package/skills/stats/SKILL.md +189 -0
@@ -0,0 +1,328 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * SQUAD RUNS STORE — telemetry journal for skill invocations. As of v0.10.0
4
+ * the legitimate writers are the squad skill (`/squad:implement` and
5
+ * `/squad:review`, invocations `implement | review | task`) and the debug
6
+ * skill (`/squad:debug`, invocation `debug`). Each writer follows the same
7
+ * two-phase contract: one row at start (`in_flight`) and one at end
8
+ * (`completed | aborted`), paired by id. Mirrored line-for-line after
9
+ * `src/learning/store.ts` — same lock + quarantine + mtime cache + atomic-
10
+ * append-under-PIPE_BUF discipline.
11
+ *
12
+ * Plan v4 (cycle 2 advisory consensus) explicit decisions:
13
+ *
14
+ * - NO multi-row partial fallback. If `JSON.stringify(record)` exceeds
15
+ * MAX_RECORD_BYTES the store rejects with `RECORD_TOO_LARGE` rather
16
+ * than splitting into continuation rows. Five advisors converged on
17
+ * "splitting erodes the one-row-per-record JSONL invariant and
18
+ * reopens parsing ambiguities"; rejection puts the burden on the
19
+ * caller to cap their `mode_warning.message` (already capped 512B)
20
+ * or shorten their inputs.
21
+ *
22
+ * - File mode 0o600 (user-only), directory mode 0o700. The journal
23
+ * contains commit refs and prompt-length signals that can leak
24
+ * business context (branch names like `feat/acme-acquisition`); on
25
+ * shared workstations world-readable 0o644 would expose them to
26
+ * co-tenants.
27
+ *
28
+ * - Single-writer contract: the squad skill (`skills/squad/SKILL.md`)
29
+ * AND the debug skill (`skills/debug/SKILL.md`) are the only legitimate
30
+ * callers of `appendRun`. `apply_consolidation_rules` and other server-
31
+ * side code MUST NOT emit terminal rows; doing so breaks the two-phase
32
+ * `(in_flight, completed)` pair-by-id invariant.
33
+ */
34
+ /**
35
+ * Hard cap per JSONL entry so a single line fits in POSIX PIPE_BUF
36
+ * (4096 bytes) and `fs.appendFile` remains atomic w.r.t. concurrent
37
+ * appenders. Length includes serialised JSON + trailing newline.
38
+ *
39
+ * Realistic finalization row with 9 agents + capped mode_warning.message
40
+ * lands around 1.5-2 KB — well under the limit. Oversize is a hard error,
41
+ * not a soft truncation (see RECORD_TOO_LARGE in errors.ts).
42
+ */
43
+ export declare const MAX_RECORD_BYTES = 4000;
44
+ /**
45
+ * Default location for the JSONL file, relative to workspace_root.
46
+ * Defaults are gitignored at the v0.9.0 release — the journal contains
47
+ * local-only operational telemetry; users opting into team-wide sharing
48
+ * remove `.squad/runs.jsonl` from their `.gitignore` deliberately.
49
+ */
50
+ export declare const DEFAULT_RUNS_PATH = ".squad/runs.jsonl";
51
+ /**
52
+ * Severity tally compacted into a single sortable number. The cycle-1
53
+ * design carried `{ Blocker, Major, Minor, Suggestion }` per agent
54
+ * (~30 bytes / agent of JSON overhead); cycle 2 architects + dev flagged
55
+ * this as PIPE_BUF-budget waste on 9-agent runs. Collapsed to one number
56
+ * with positional digits: B*1000 + M*100 + m*10 + s. Inverse decode in
57
+ * aggregate.ts. Safe up to 9 of each severity per agent (more than that
58
+ * is itself a signal something went sideways).
59
+ */
60
+ declare function severityScore(counts: {
61
+ Blocker: number;
62
+ Major: number;
63
+ Minor: number;
64
+ Suggestion: number;
65
+ }): number;
66
+ /** Inverse of `severityScore`. Used by aggregate.ts. */
67
+ export declare function decodeSeverityScore(n: number): {
68
+ Blocker: number;
69
+ Major: number;
70
+ Minor: number;
71
+ Suggestion: number;
72
+ };
73
+ /** Public re-export so callers can build records without re-implementing the encoding. */
74
+ export { severityScore };
75
+ /**
76
+ * Canonical tuple of accepted journal invocations. Single source of truth.
77
+ *
78
+ * Why a tuple, not just a Zod enum: the same set is consumed by FIVE call
79
+ * sites — this store's `InvocationEnum`, the tool boundary at
80
+ * `src/tools/record-run.ts`, the filter schema at `src/tools/list-runs.ts`,
81
+ * the Record literal in the aggregate output type, and the `invocation_counts`
82
+ * initialiser in `src/runs/aggregate.ts`. Exporting one tuple makes "add a
83
+ * new invocation" a single-line change instead of five-sites-must-stay-in-
84
+ * sync. Pattern parallels `AGENT_NAMES_TUPLE` in `src/config/ownership-matrix.ts`.
85
+ *
86
+ * `as const` (readonly tuple) is what Zod's `z.enum` requires.
87
+ */
88
+ export declare const INVOCATION_VALUES: readonly ["implement", "review", "task", "question", "brainstorm", "debug"];
89
+ declare const InvocationEnum: z.ZodEnum<["implement", "review", "task", "question", "brainstorm", "debug"]>;
90
+ declare const StatusEnum: z.ZodEnum<["in_flight", "completed", "aborted"]>;
91
+ declare const WorkTypeEnum: z.ZodEnum<["Feature", "Bug Fix", "Refactor", "Performance", "Security", "Business Rule"]>;
92
+ declare const VerdictEnum: z.ZodEnum<["APPROVED", "CHANGES_REQUIRED", "REJECTED"]>;
93
+ declare const GitRefSchema: z.ZodNullable<z.ZodObject<{
94
+ kind: z.ZodEnum<["head", "diff_base", "pr_head"]>;
95
+ value: z.ZodEffects<z.ZodString, string, string>;
96
+ }, "strip", z.ZodTypeAny, {
97
+ value: string;
98
+ kind: "head" | "diff_base" | "pr_head";
99
+ }, {
100
+ value: string;
101
+ kind: "head" | "diff_base" | "pr_head";
102
+ }>>;
103
+ /**
104
+ * Per-agent dispatch metrics captured by the squad skill orchestrator.
105
+ *
106
+ * - `batch_duration_ms` (renamed from `duration_ms` in v0.9.0): wall-clock
107
+ * from this agent's Task() dispatch to its result. Note that advisors in
108
+ * a parallel batch overlap; this is "round-trip latency for this dispatch"
109
+ * not "exclusive time spent on this agent's work". Reflected in the
110
+ * /squad:stats output label.
111
+ *
112
+ * - `prompt_chars` / `response_chars` (renamed from input/output_chars in
113
+ * v0.9.0): orchestrator-visible character counts of the dispatch prompt
114
+ * and the agent's returned string. EXCLUDES the agent's own internal
115
+ * tool_use roundtrips (file reads, sub-dispatches like code-explorer).
116
+ * For agents that read heavily, the recorded chars are a substantial
117
+ * underestimate — documented in `est_tokens_method` and rendered in the
118
+ * stats panel disclaimer.
119
+ *
120
+ * - `severity_score`: encoded findings tally (see severityScore()).
121
+ */
122
+ declare const AgentMetricsSchema: z.ZodObject<{
123
+ name: z.ZodEnum<[import("../config/ownership-matrix.js").AgentName, ...import("../config/ownership-matrix.js").AgentName[]]>;
124
+ model: z.ZodEnum<["haiku", "sonnet", "opus", "inherit"]>;
125
+ score: z.ZodNullable<z.ZodNumber>;
126
+ severity_score: z.ZodNullable<z.ZodNumber>;
127
+ batch_duration_ms: z.ZodNumber;
128
+ prompt_chars: z.ZodNumber;
129
+ response_chars: z.ZodNumber;
130
+ }, "strip", z.ZodTypeAny, {
131
+ name: import("../config/ownership-matrix.js").AgentName;
132
+ score: number | null;
133
+ model: "haiku" | "inherit" | "sonnet" | "opus";
134
+ severity_score: number | null;
135
+ batch_duration_ms: number;
136
+ prompt_chars: number;
137
+ response_chars: number;
138
+ }, {
139
+ name: import("../config/ownership-matrix.js").AgentName;
140
+ score: number | null;
141
+ model: "haiku" | "inherit" | "sonnet" | "opus";
142
+ severity_score: number | null;
143
+ batch_duration_ms: number;
144
+ prompt_chars: number;
145
+ response_chars: number;
146
+ }>;
147
+ /**
148
+ * RunRecord schema_version 1. PUBLIC STABLE CONTRACT from v0.9.0 — readers
149
+ * (the `list_runs` MCP tool, the `/squad:stats` skill) key on
150
+ * `schema_version` and quarantine unknown versions rather than failing.
151
+ *
152
+ * Discriminated by `status`:
153
+ * - `in_flight` rows carry only the Phase-1-known fields (skill knows what
154
+ * it's about to do; verdict/scores are still pending).
155
+ * - `completed | aborted` rows carry full metrics + verdict.
156
+ *
157
+ * For ergonomics under Zod we keep finalisation fields optional on the base
158
+ * schema rather than splitting into two schemas; the writer validates the
159
+ * appropriate subset at the call site (`appendRun` vs `finalizeRun`).
160
+ */
161
+ declare const runRecordSchema: z.ZodObject<{
162
+ schema_version: z.ZodLiteral<1>;
163
+ id: z.ZodEffects<z.ZodString, string, string>;
164
+ status: z.ZodEnum<["in_flight", "completed", "aborted"]>;
165
+ started_at: z.ZodEffects<z.ZodString, string, string>;
166
+ completed_at: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
167
+ duration_ms: z.ZodOptional<z.ZodNumber>;
168
+ invocation: z.ZodEnum<["implement", "review", "task", "question", "brainstorm", "debug"]>;
169
+ mode: z.ZodEnum<["quick", "normal", "deep"]>;
170
+ mode_source: z.ZodEnum<["user", "auto"]>;
171
+ work_type: z.ZodOptional<z.ZodEnum<["Feature", "Bug Fix", "Refactor", "Performance", "Security", "Business Rule"]>>;
172
+ git_ref: z.ZodNullable<z.ZodObject<{
173
+ kind: z.ZodEnum<["head", "diff_base", "pr_head"]>;
174
+ value: z.ZodEffects<z.ZodString, string, string>;
175
+ }, "strip", z.ZodTypeAny, {
176
+ value: string;
177
+ kind: "head" | "diff_base" | "pr_head";
178
+ }, {
179
+ value: string;
180
+ kind: "head" | "diff_base" | "pr_head";
181
+ }>>;
182
+ files_count: z.ZodNumber;
183
+ agents: z.ZodArray<z.ZodObject<{
184
+ name: z.ZodEnum<[import("../config/ownership-matrix.js").AgentName, ...import("../config/ownership-matrix.js").AgentName[]]>;
185
+ model: z.ZodEnum<["haiku", "sonnet", "opus", "inherit"]>;
186
+ score: z.ZodNullable<z.ZodNumber>;
187
+ severity_score: z.ZodNullable<z.ZodNumber>;
188
+ batch_duration_ms: z.ZodNumber;
189
+ prompt_chars: z.ZodNumber;
190
+ response_chars: z.ZodNumber;
191
+ }, "strip", z.ZodTypeAny, {
192
+ name: import("../config/ownership-matrix.js").AgentName;
193
+ score: number | null;
194
+ model: "haiku" | "inherit" | "sonnet" | "opus";
195
+ severity_score: number | null;
196
+ batch_duration_ms: number;
197
+ prompt_chars: number;
198
+ response_chars: number;
199
+ }, {
200
+ name: import("../config/ownership-matrix.js").AgentName;
201
+ score: number | null;
202
+ model: "haiku" | "inherit" | "sonnet" | "opus";
203
+ severity_score: number | null;
204
+ batch_duration_ms: number;
205
+ prompt_chars: number;
206
+ response_chars: number;
207
+ }>, "many">;
208
+ verdict: z.ZodOptional<z.ZodNullable<z.ZodEnum<["APPROVED", "CHANGES_REQUIRED", "REJECTED"]>>>;
209
+ weighted_score: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
210
+ est_tokens_method: z.ZodLiteral<"chars-div-3.5">;
211
+ mode_warning: z.ZodOptional<z.ZodNullable<z.ZodObject<{
212
+ code: z.ZodEffects<z.ZodString, string, string>;
213
+ message: z.ZodEffects<z.ZodString, string, string>;
214
+ }, "strip", z.ZodTypeAny, {
215
+ code: string;
216
+ message: string;
217
+ }, {
218
+ code: string;
219
+ message: string;
220
+ }>>>;
221
+ }, "strip", z.ZodTypeAny, {
222
+ files_count: number;
223
+ status: "aborted" | "in_flight" | "completed";
224
+ agents: {
225
+ name: import("../config/ownership-matrix.js").AgentName;
226
+ score: number | null;
227
+ model: "haiku" | "inherit" | "sonnet" | "opus";
228
+ severity_score: number | null;
229
+ batch_duration_ms: number;
230
+ prompt_chars: number;
231
+ response_chars: number;
232
+ }[];
233
+ mode: "quick" | "normal" | "deep";
234
+ id: string;
235
+ invocation: "debug" | "review" | "task" | "implement" | "question" | "brainstorm";
236
+ schema_version: 1;
237
+ started_at: string;
238
+ mode_source: "user" | "auto";
239
+ git_ref: {
240
+ value: string;
241
+ kind: "head" | "diff_base" | "pr_head";
242
+ } | null;
243
+ est_tokens_method: "chars-div-3.5";
244
+ work_type?: "Feature" | "Bug Fix" | "Refactor" | "Performance" | "Security" | "Business Rule" | undefined;
245
+ duration_ms?: number | undefined;
246
+ weighted_score?: number | null | undefined;
247
+ completed_at?: string | undefined;
248
+ verdict?: "APPROVED" | "CHANGES_REQUIRED" | "REJECTED" | null | undefined;
249
+ mode_warning?: {
250
+ code: string;
251
+ message: string;
252
+ } | null | undefined;
253
+ }, {
254
+ files_count: number;
255
+ status: "aborted" | "in_flight" | "completed";
256
+ agents: {
257
+ name: import("../config/ownership-matrix.js").AgentName;
258
+ score: number | null;
259
+ model: "haiku" | "inherit" | "sonnet" | "opus";
260
+ severity_score: number | null;
261
+ batch_duration_ms: number;
262
+ prompt_chars: number;
263
+ response_chars: number;
264
+ }[];
265
+ mode: "quick" | "normal" | "deep";
266
+ id: string;
267
+ invocation: "debug" | "review" | "task" | "implement" | "question" | "brainstorm";
268
+ schema_version: 1;
269
+ started_at: string;
270
+ mode_source: "user" | "auto";
271
+ git_ref: {
272
+ value: string;
273
+ kind: "head" | "diff_base" | "pr_head";
274
+ } | null;
275
+ est_tokens_method: "chars-div-3.5";
276
+ work_type?: "Feature" | "Bug Fix" | "Refactor" | "Performance" | "Security" | "Business Rule" | undefined;
277
+ duration_ms?: number | undefined;
278
+ weighted_score?: number | null | undefined;
279
+ completed_at?: string | undefined;
280
+ verdict?: "APPROVED" | "CHANGES_REQUIRED" | "REJECTED" | null | undefined;
281
+ mode_warning?: {
282
+ code: string;
283
+ message: string;
284
+ } | null | undefined;
285
+ }>;
286
+ export type RunRecord = z.infer<typeof runRecordSchema>;
287
+ export type AgentMetrics = z.infer<typeof AgentMetricsSchema>;
288
+ export type GitRef = z.infer<typeof GitRefSchema>;
289
+ export type RunStatus = z.infer<typeof StatusEnum>;
290
+ export type RunInvocation = z.infer<typeof InvocationEnum>;
291
+ export type RunVerdict = z.infer<typeof VerdictEnum>;
292
+ export { runRecordSchema, WorkTypeEnum };
293
+ /** Test-only: clear the per-process cache. Production code MUST NOT call this. */
294
+ export declare function __resetRunsStoreCacheForTests(): void;
295
+ /**
296
+ * Generate a fresh run id. Date.now() base36 prefix + 6 chars from
297
+ * [a-z0-9] (36^6 = 2.18B unique values per millisecond — collision
298
+ * chance is effectively zero across realistic concurrent writers in
299
+ * the same ms).
300
+ */
301
+ export declare function generateRunId(): string;
302
+ /**
303
+ * Read all run records from the JSONL file. Returns `[]` if the file does
304
+ * not exist (fresh repo, first run). Corrupt lines are quarantined to a
305
+ * timestamped sibling file and logged once; the surviving entries return
306
+ * in append order.
307
+ *
308
+ * Unknown `schema_version` rows are quarantined too — readers must NEVER
309
+ * silently include rows they don't understand. The quarantine file is
310
+ * `.squad/runs.jsonl.corrupt-<ts>.jsonl` alongside the source.
311
+ */
312
+ export declare function readRuns(workspaceRoot: string, options?: {
313
+ configuredPath?: string;
314
+ }): Promise<RunRecord[]>;
315
+ /**
316
+ * Append one RunRecord. Validates against Zod, then enforces
317
+ * MAX_RECORD_BYTES (post-serialisation) before acquiring the file lock.
318
+ * Oversize records throw `RECORD_TOO_LARGE` — no silent split, no soft
319
+ * truncation. The caller (the squad skill) is responsible for keeping
320
+ * `mode_warning.message` capped and the agent list short enough that
321
+ * realistic records stay well under the cap.
322
+ */
323
+ export declare function appendRun(workspaceRoot: string, record: RunRecord, options?: {
324
+ configuredPath?: string;
325
+ }): Promise<{
326
+ filePath: string;
327
+ record: RunRecord;
328
+ }>;