@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +7 -4
- package/CHANGELOG.md +92 -0
- package/README.md +41 -35
- package/agents/senior-debugger.md +85 -0
- package/commands/debug.md +22 -0
- package/commands/stats.md +22 -0
- package/dist/config/ownership-matrix.d.ts +1 -1
- package/dist/config/ownership-matrix.js +16 -0
- package/dist/config/ownership-matrix.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/agent-loader.js +1 -0
- package/dist/resources/agent-loader.js.map +1 -1
- package/dist/runs/aggregate.d.ts +166 -0
- package/dist/runs/aggregate.js +378 -0
- package/dist/runs/aggregate.js.map +1 -0
- package/dist/runs/store.d.ts +328 -0
- package/dist/runs/store.js +406 -0
- package/dist/runs/store.js.map +1 -0
- package/dist/tools/list-runs.d.ts +52 -0
- package/dist/tools/list-runs.js +142 -0
- package/dist/tools/list-runs.js.map +1 -0
- package/dist/tools/record-run.d.ts +202 -0
- package/dist/tools/record-run.js +124 -0
- package/dist/tools/record-run.js.map +1 -0
- package/dist/tools/registry.js +15 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/util/path-safety.d.ts +36 -0
- package/dist/util/path-safety.js +76 -0
- package/dist/util/path-safety.js.map +1 -1
- package/package.json +1 -1
- package/skills/brainstorm/SKILL.md +70 -7
- package/skills/debug/SKILL.md +345 -0
- package/skills/question/SKILL.md +73 -1
- package/skills/squad/SKILL.md +83 -0
- 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
|
+
}>;
|