edgegate-mcp 0.1.2 → 0.2.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/README.md +1 -0
- package/dist/client.d.ts +3 -1
- package/dist/client.js +6 -0
- package/dist/client.js.map +1 -1
- package/dist/server.js +10 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/compare_runs.d.ts +35 -0
- package/dist/tools/compare_runs.js +409 -0
- package/dist/tools/compare_runs.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/edgegate-status.md +4 -0
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ See [docs/tools.md](./docs/tools.md) for the full tool reference. Quick list:
|
|
|
67
67
|
| `edgegate_get_report` | List recent runs |
|
|
68
68
|
| `edgegate_get_audit_report` | Fetch the signed audit PDF |
|
|
69
69
|
| `edgegate_setup_github_action` | Generate the GitHub Actions workflow + secret commands |
|
|
70
|
+
| `edgegate_compare_runs` | Diff two runs — gate flips, metric deltas, per-device breakdown, REGRESSION / IMPROVEMENT / NEUTRAL verdict |
|
|
70
71
|
|
|
71
72
|
## Skills
|
|
72
73
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { APIKeyCreateResponse, Pipeline, RunBundle, RunDetail, RunSummary, Workspace, WorkflowTemplate } from "./types.js";
|
|
1
|
+
import type { APIKeyCreateResponse, Pipeline, RunBundle, RunComparison, RunDetail, RunSummary, Workspace, WorkflowTemplate } from "./types.js";
|
|
2
2
|
export interface EdgeGateClientOptions {
|
|
3
3
|
apiUrl: string;
|
|
4
4
|
apiKey: string;
|
|
@@ -60,6 +60,8 @@ export declare class EdgeGateClient {
|
|
|
60
60
|
}): Promise<RunSummary>;
|
|
61
61
|
getRun(workspaceId: string, runId: string): Promise<RunDetail>;
|
|
62
62
|
listRuns(workspaceId: string, limit?: number): Promise<RunSummary[]>;
|
|
63
|
+
listRunsByPipeline(workspaceId: string, pipelineId: string, limit?: number): Promise<RunSummary[]>;
|
|
64
|
+
getRunDiff(workspaceId: string, runId: string): Promise<RunComparison>;
|
|
63
65
|
getRunBundle(workspaceId: string, runId: string): Promise<RunBundle>;
|
|
64
66
|
getWorkflowTemplate(workspaceId: string): Promise<WorkflowTemplate>;
|
|
65
67
|
private request;
|
package/dist/client.js
CHANGED
|
@@ -48,6 +48,12 @@ export class EdgeGateClient {
|
|
|
48
48
|
async listRuns(workspaceId, limit = 20) {
|
|
49
49
|
return this.request("GET", `/v1/workspaces/${workspaceId}/runs?limit=${limit}`);
|
|
50
50
|
}
|
|
51
|
+
async listRunsByPipeline(workspaceId, pipelineId, limit = 20) {
|
|
52
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/runs?pipeline_id=${pipelineId}&limit=${limit}`);
|
|
53
|
+
}
|
|
54
|
+
async getRunDiff(workspaceId, runId) {
|
|
55
|
+
return this.request("GET", `/v1/workspaces/${workspaceId}/runs/${runId}/diff`);
|
|
56
|
+
}
|
|
51
57
|
async getRunBundle(workspaceId, runId) {
|
|
52
58
|
return this.request("GET", `/v1/workspaces/${workspaceId}/runs/${runId}/bundle`);
|
|
53
59
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -11,6 +11,7 @@ import { checkStatusHandler, checkStatusInputSchema } from "./tools/check_status
|
|
|
11
11
|
import { getReportHandler, getReportInputSchema } from "./tools/get_report.js";
|
|
12
12
|
import { getAuditReportHandler, getAuditReportInputSchema } from "./tools/get_audit_report.js";
|
|
13
13
|
import { setupGithubActionHandler, setupGithubActionInputSchema, } from "./tools/setup_github_action.js";
|
|
14
|
+
import { compareRunsHandler, compareRunsInputSchema, } from "./tools/compare_runs.js";
|
|
14
15
|
const TOOLS = [
|
|
15
16
|
{
|
|
16
17
|
name: "edgegate_setup_workspace",
|
|
@@ -60,6 +61,15 @@ const TOOLS = [
|
|
|
60
61
|
schema: setupGithubActionInputSchema,
|
|
61
62
|
handler: setupGithubActionHandler,
|
|
62
63
|
},
|
|
64
|
+
{
|
|
65
|
+
name: "edgegate_compare_runs",
|
|
66
|
+
description: "Diff two EdgeGate runs in the same pipeline — metrics delta, gate flips (✓→✗ regressions " +
|
|
67
|
+
"and ✗→✓ recoveries), per-device breakdown, and an overall verdict (REGRESSION / IMPROVEMENT / " +
|
|
68
|
+
"NEUTRAL / NO BASELINE). When baseline_run_id is omitted, auto-selects the most recent " +
|
|
69
|
+
"PASSED run from the same pipeline as the baseline.",
|
|
70
|
+
schema: compareRunsInputSchema,
|
|
71
|
+
handler: compareRunsHandler,
|
|
72
|
+
},
|
|
63
73
|
];
|
|
64
74
|
function getClient() {
|
|
65
75
|
const apiUrl = process.env.EDGEGATE_API_URL ?? "https://edgegateapi.frozo.ai";
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* edgegate_compare_runs — run-over-run diff with smart auto-baseline selection.
|
|
3
|
+
*
|
|
4
|
+
* When baseline_run_id is omitted:
|
|
5
|
+
* 1. Fetch candidate run's pipeline_id
|
|
6
|
+
* 2. List last 20 runs in that pipeline
|
|
7
|
+
* 3. Pick the most recent PASSED run with a bundle (excluding candidate itself)
|
|
8
|
+
* 4. Fallback: most recent completed run (any status) excluding candidate
|
|
9
|
+
* 5. If nothing found: "NO BASELINE" response
|
|
10
|
+
*
|
|
11
|
+
* The backend already exposes GET /v1/workspaces/{id}/runs/{run_id}/diff which
|
|
12
|
+
* returns the pre-computed, signed diff embedded in the evidence bundle (commit
|
|
13
|
+
* 41167a6). We call that endpoint for the candidate run — it internally uses
|
|
14
|
+
* the baseline the Celery task stored at completion time. When the user
|
|
15
|
+
* explicitly provides a baseline_run_id that differs from what the backend
|
|
16
|
+
* stored, we fall back to client-side diff from both runs' detail endpoints.
|
|
17
|
+
*/
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
import { EdgeGateClient } from "../client.js";
|
|
20
|
+
import type { ToolResult } from "./setup_workspace.js";
|
|
21
|
+
export declare const compareRunsInputSchema: z.ZodObject<{
|
|
22
|
+
workspace_id: z.ZodString;
|
|
23
|
+
run_id: z.ZodString;
|
|
24
|
+
baseline_run_id: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
workspace_id: string;
|
|
27
|
+
run_id: string;
|
|
28
|
+
baseline_run_id?: string | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
workspace_id: string;
|
|
31
|
+
run_id: string;
|
|
32
|
+
baseline_run_id?: string | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export type CompareRunsInput = z.infer<typeof compareRunsInputSchema>;
|
|
35
|
+
export declare function compareRunsHandler(client: EdgeGateClient, input: CompareRunsInput): Promise<ToolResult>;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* edgegate_compare_runs — run-over-run diff with smart auto-baseline selection.
|
|
3
|
+
*
|
|
4
|
+
* When baseline_run_id is omitted:
|
|
5
|
+
* 1. Fetch candidate run's pipeline_id
|
|
6
|
+
* 2. List last 20 runs in that pipeline
|
|
7
|
+
* 3. Pick the most recent PASSED run with a bundle (excluding candidate itself)
|
|
8
|
+
* 4. Fallback: most recent completed run (any status) excluding candidate
|
|
9
|
+
* 5. If nothing found: "NO BASELINE" response
|
|
10
|
+
*
|
|
11
|
+
* The backend already exposes GET /v1/workspaces/{id}/runs/{run_id}/diff which
|
|
12
|
+
* returns the pre-computed, signed diff embedded in the evidence bundle (commit
|
|
13
|
+
* 41167a6). We call that endpoint for the candidate run — it internally uses
|
|
14
|
+
* the baseline the Celery task stored at completion time. When the user
|
|
15
|
+
* explicitly provides a baseline_run_id that differs from what the backend
|
|
16
|
+
* stored, we fall back to client-side diff from both runs' detail endpoints.
|
|
17
|
+
*/
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
import { EdgeGateError } from "../client.js";
|
|
20
|
+
export const compareRunsInputSchema = z.object({
|
|
21
|
+
workspace_id: z.string().uuid(),
|
|
22
|
+
run_id: z.string().uuid().describe("Candidate run to evaluate"),
|
|
23
|
+
baseline_run_id: z
|
|
24
|
+
.string()
|
|
25
|
+
.uuid()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Baseline to compare against. When omitted, auto-selects the most recent " +
|
|
28
|
+
"PASSED run from the same pipeline (excluding the candidate itself), " +
|
|
29
|
+
"or the most recent completed run as a fallback."),
|
|
30
|
+
});
|
|
31
|
+
// Metrics where lower is better (high delta% is bad)
|
|
32
|
+
const LOWER_IS_BETTER = new Set(["inference_time_ms", "peak_memory_mb", "latency_ms"]);
|
|
33
|
+
// Threshold for "significant regression" in lower-is-better metrics
|
|
34
|
+
const REGRESSION_THRESHOLD_PCT = 25;
|
|
35
|
+
export async function compareRunsHandler(client, input) {
|
|
36
|
+
try {
|
|
37
|
+
const { workspace_id, run_id, baseline_run_id } = input;
|
|
38
|
+
// --- Fetch candidate run detail (need pipeline_id for auto-baseline) ---
|
|
39
|
+
let candidateRun;
|
|
40
|
+
try {
|
|
41
|
+
candidateRun = await client.getRun(workspace_id, run_id);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err instanceof EdgeGateError) {
|
|
45
|
+
return {
|
|
46
|
+
isError: true,
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: "text",
|
|
50
|
+
text: `Could not fetch candidate run ${run_id}: ${err.detail}`,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
// --- Try the backend /diff endpoint first (Scenario A fast path) ---
|
|
58
|
+
// The backend stores the diff from the previous pipeline run at completion.
|
|
59
|
+
// If the caller did NOT supply a baseline_run_id (or it matches what the
|
|
60
|
+
// backend would pick), use the pre-computed signed diff directly.
|
|
61
|
+
if (!baseline_run_id) {
|
|
62
|
+
try {
|
|
63
|
+
const comparison = await client.getRunDiff(workspace_id, run_id);
|
|
64
|
+
// Backend returned a diff — render it
|
|
65
|
+
return { content: [{ type: "text", text: renderComparison(comparison, candidateRun) }] };
|
|
66
|
+
}
|
|
67
|
+
catch (diffErr) {
|
|
68
|
+
if (diffErr instanceof EdgeGateError && diffErr.status === 404) {
|
|
69
|
+
// No server-side diff yet: either first run or still in flight.
|
|
70
|
+
// Attempt client-side auto-baseline selection.
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Unexpected error — propagate
|
|
74
|
+
if (diffErr instanceof EdgeGateError) {
|
|
75
|
+
return {
|
|
76
|
+
isError: true,
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: "text",
|
|
80
|
+
text: `EdgeGate returned ${diffErr.status} fetching diff: ${diffErr.detail}`,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
throw diffErr;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// --- Auto-baseline or explicit baseline: client-side path ---
|
|
90
|
+
let resolvedBaselineId = baseline_run_id ?? null;
|
|
91
|
+
if (!resolvedBaselineId) {
|
|
92
|
+
// Auto-select: list recent runs in the same pipeline
|
|
93
|
+
resolvedBaselineId = await pickAutoBaseline(client, workspace_id, candidateRun);
|
|
94
|
+
if (!resolvedBaselineId) {
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: formatNoBaseline(candidateRun),
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Fetch baseline run detail
|
|
106
|
+
let baselineRun;
|
|
107
|
+
try {
|
|
108
|
+
baselineRun = await client.getRun(workspace_id, resolvedBaselineId);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err instanceof EdgeGateError) {
|
|
112
|
+
return {
|
|
113
|
+
isError: true,
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: `Could not fetch baseline run ${resolvedBaselineId}: ${err.detail}`,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
// Build client-side diff
|
|
125
|
+
const comparison = buildClientSideDiff(candidateRun, baselineRun);
|
|
126
|
+
return { content: [{ type: "text", text: renderComparison(comparison, candidateRun) }] };
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (err instanceof EdgeGateError) {
|
|
130
|
+
return {
|
|
131
|
+
isError: true,
|
|
132
|
+
content: [{ type: "text", text: `EdgeGate returned ${err.status}: ${err.detail}` }],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// ─── Auto-baseline selection ───────────────────────────────────────────────
|
|
139
|
+
async function pickAutoBaseline(client, workspaceId, candidateRun) {
|
|
140
|
+
const pipelineId = candidateRun.pipeline_id;
|
|
141
|
+
let runs;
|
|
142
|
+
try {
|
|
143
|
+
runs = await client.listRunsByPipeline(workspaceId, pipelineId, 20);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Fall back to listing all runs if pipeline filter fails
|
|
147
|
+
try {
|
|
148
|
+
runs = await client.listRuns(workspaceId, 20);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Filter to same pipeline, excluding candidate itself
|
|
155
|
+
const eligible = runs.filter((r) => r.id !== candidateRun.id && r.pipeline_id === pipelineId);
|
|
156
|
+
// Priority 1: most recent PASSED with a bundle
|
|
157
|
+
// (RunSummary doesn't have bundle_artifact_id, but passed status implies a bundle)
|
|
158
|
+
const passedRun = eligible.find((r) => r.status === "passed");
|
|
159
|
+
if (passedRun)
|
|
160
|
+
return passedRun.id;
|
|
161
|
+
// Priority 2: most recent completed run (any terminal status)
|
|
162
|
+
const completedRun = eligible.find((r) => ["passed", "failed", "error"].includes(r.status));
|
|
163
|
+
if (completedRun)
|
|
164
|
+
return completedRun.id;
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
// ─── Client-side diff construction ────────────────────────────────────────
|
|
168
|
+
function buildClientSideDiff(candidate, baseline) {
|
|
169
|
+
const candidateMetrics = candidate.normalized_metrics ?? {};
|
|
170
|
+
const baselineMetrics = baseline.normalized_metrics ?? {};
|
|
171
|
+
// Metric deltas
|
|
172
|
+
const allMetricKeys = new Set([
|
|
173
|
+
...Object.keys(candidateMetrics),
|
|
174
|
+
...Object.keys(baselineMetrics),
|
|
175
|
+
]);
|
|
176
|
+
const metric_deltas = {};
|
|
177
|
+
for (const k of allMetricKeys) {
|
|
178
|
+
const cur = candidateMetrics[k] ?? null;
|
|
179
|
+
const prev = baselineMetrics[k] ?? null;
|
|
180
|
+
const delta = cur !== null && prev !== null ? cur - prev : null;
|
|
181
|
+
const delta_pct = delta !== null && prev !== null && prev !== 0 ? (delta / prev) * 100 : null;
|
|
182
|
+
metric_deltas[k] = { current: cur, previous: prev, delta, delta_pct };
|
|
183
|
+
}
|
|
184
|
+
// Gate flips
|
|
185
|
+
const candidateGates = candidate.gates_eval?.gates ?? [];
|
|
186
|
+
const baselineGates = baseline.gates_eval?.gates ?? [];
|
|
187
|
+
const prevByMetric = new Map(baselineGates.map((g) => [g.metric, g]));
|
|
188
|
+
const currByMetric = new Map(candidateGates.map((g) => [g.metric, g]));
|
|
189
|
+
const allGateMetrics = new Set([...prevByMetric.keys(), ...currByMetric.keys()]);
|
|
190
|
+
const gate_flips = [];
|
|
191
|
+
for (const m of [...allGateMetrics].sort()) {
|
|
192
|
+
const prev = prevByMetric.get(m) ?? null;
|
|
193
|
+
const curr = currByMetric.get(m) ?? null;
|
|
194
|
+
let transition;
|
|
195
|
+
if (!prev)
|
|
196
|
+
transition = "new";
|
|
197
|
+
else if (!curr)
|
|
198
|
+
transition = "removed";
|
|
199
|
+
else {
|
|
200
|
+
const p = prev.passed;
|
|
201
|
+
const c = curr.passed;
|
|
202
|
+
if (c && p)
|
|
203
|
+
transition = "unchanged";
|
|
204
|
+
else if (c && !p)
|
|
205
|
+
transition = "improved";
|
|
206
|
+
else if (!c && p)
|
|
207
|
+
transition = "regressed";
|
|
208
|
+
else
|
|
209
|
+
transition = "still_failing";
|
|
210
|
+
}
|
|
211
|
+
gate_flips.push({
|
|
212
|
+
metric: m,
|
|
213
|
+
transition,
|
|
214
|
+
previous: prev
|
|
215
|
+
? {
|
|
216
|
+
passed: prev.passed,
|
|
217
|
+
threshold: prev.threshold,
|
|
218
|
+
operator: prev.operator,
|
|
219
|
+
actual_value: prev.actual_value,
|
|
220
|
+
}
|
|
221
|
+
: null,
|
|
222
|
+
current: curr
|
|
223
|
+
? {
|
|
224
|
+
passed: curr.passed,
|
|
225
|
+
threshold: curr.threshold,
|
|
226
|
+
operator: curr.operator,
|
|
227
|
+
actual_value: curr.actual_value,
|
|
228
|
+
}
|
|
229
|
+
: null,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
current_run_id: candidate.id,
|
|
234
|
+
previous_run_id: baseline.id,
|
|
235
|
+
diff_sha256: null, // client-side, not signed
|
|
236
|
+
diff: {
|
|
237
|
+
current_run_id: candidate.id,
|
|
238
|
+
previous_run_id: baseline.id,
|
|
239
|
+
current_commit: {},
|
|
240
|
+
previous_commit: {},
|
|
241
|
+
current_completed_at: candidate.completed_at,
|
|
242
|
+
previous_completed_at: baseline.completed_at,
|
|
243
|
+
metric_deltas,
|
|
244
|
+
gate_flips,
|
|
245
|
+
per_device: null,
|
|
246
|
+
per_cell: null,
|
|
247
|
+
is_baseline: false,
|
|
248
|
+
},
|
|
249
|
+
created_at: new Date().toISOString(),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// ─── Rendering ─────────────────────────────────────────────────────────────
|
|
253
|
+
function renderComparison(comparison, candidateRun) {
|
|
254
|
+
const diff = comparison.diff;
|
|
255
|
+
const lines = [];
|
|
256
|
+
// Header
|
|
257
|
+
lines.push(`## Run Comparison`, ``, `**Pipeline:** ${candidateRun.pipeline_name} (${candidateRun.pipeline_id})`, `**Candidate:** \`${comparison.current_run_id}\` ` +
|
|
258
|
+
`(${diff.current_completed_at ?? "in flight"})`, `**Baseline:** \`${comparison.previous_run_id ?? "—"}\` ` +
|
|
259
|
+
`(${diff.previous_completed_at ?? "—"})`, ``);
|
|
260
|
+
if (diff.is_baseline) {
|
|
261
|
+
lines.push(`> **NO BASELINE** — this is the first completed run in this pipeline.`);
|
|
262
|
+
lines.push(``);
|
|
263
|
+
return lines.join("\n");
|
|
264
|
+
}
|
|
265
|
+
// Commit context (only if server-side diff has it)
|
|
266
|
+
const cc = diff.current_commit;
|
|
267
|
+
const pc = diff.previous_commit;
|
|
268
|
+
if (cc?.sha || pc?.sha) {
|
|
269
|
+
lines.push(`### Commit Context`);
|
|
270
|
+
if (cc?.sha)
|
|
271
|
+
lines.push(`**Candidate:** \`${cc.sha}\` — ${cc.message ?? ""}`);
|
|
272
|
+
if (pc?.sha)
|
|
273
|
+
lines.push(`**Baseline:** \`${pc.sha}\` — ${pc.message ?? ""}`);
|
|
274
|
+
lines.push(``);
|
|
275
|
+
}
|
|
276
|
+
// Metrics
|
|
277
|
+
const metricKeys = Object.keys(diff.metric_deltas).sort();
|
|
278
|
+
if (metricKeys.length > 0) {
|
|
279
|
+
lines.push(`### Metrics`);
|
|
280
|
+
lines.push(`| Metric | Baseline | Candidate | Delta | Direction |`);
|
|
281
|
+
lines.push(`|---|---|---|---|---|`);
|
|
282
|
+
for (const k of metricKeys) {
|
|
283
|
+
const m = diff.metric_deltas[k];
|
|
284
|
+
const pct = m.delta_pct !== null ? `${m.delta_pct > 0 ? "+" : ""}${m.delta_pct.toFixed(1)}%` : "—";
|
|
285
|
+
const arrow = m.delta === null ? "" : m.delta > 0 ? "↑" : m.delta < 0 ? "↓" : "→";
|
|
286
|
+
const direction = m.delta === null ? "—" : buildDirectionLabel(k, m.delta);
|
|
287
|
+
lines.push(`| ${k} | ${fmt(m.previous)} | ${fmt(m.current)} | ${fmtDelta(m.delta)} (${pct}) ${arrow} | ${direction} |`);
|
|
288
|
+
}
|
|
289
|
+
lines.push(``);
|
|
290
|
+
}
|
|
291
|
+
// Gate flips
|
|
292
|
+
if (diff.gate_flips.length > 0) {
|
|
293
|
+
lines.push(`### Gate Status`);
|
|
294
|
+
lines.push(`| Gate | Baseline | Candidate | Status |`);
|
|
295
|
+
lines.push(`|---|---|---|---|`);
|
|
296
|
+
for (const gf of diff.gate_flips) {
|
|
297
|
+
const baseIcon = gateIcon(gf.previous?.passed ?? null);
|
|
298
|
+
const candIcon = gateIcon(gf.current?.passed ?? null);
|
|
299
|
+
const statusLabel = flipLabel(gf.transition);
|
|
300
|
+
lines.push(`| ${gf.metric} | ${baseIcon} | ${candIcon} | ${statusLabel} |`);
|
|
301
|
+
}
|
|
302
|
+
lines.push(``);
|
|
303
|
+
}
|
|
304
|
+
// Per-device breakdown
|
|
305
|
+
if (diff.per_device && Object.keys(diff.per_device).length > 0) {
|
|
306
|
+
lines.push(`### Per-Device Breakdown`);
|
|
307
|
+
for (const [device, metrics] of Object.entries(diff.per_device)) {
|
|
308
|
+
lines.push(`**${device}**`);
|
|
309
|
+
for (const [k, m] of Object.entries(metrics)) {
|
|
310
|
+
const pct = m.delta_pct !== null ? `${m.delta_pct > 0 ? "+" : ""}${m.delta_pct.toFixed(1)}%` : "—";
|
|
311
|
+
lines.push(` - ${k}: ${fmt(m.previous)} → ${fmt(m.current)} (${pct})`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
lines.push(``);
|
|
315
|
+
}
|
|
316
|
+
// Verdict
|
|
317
|
+
const verdict = computeVerdict(diff.gate_flips, diff.metric_deltas);
|
|
318
|
+
lines.push(`### Verdict`);
|
|
319
|
+
lines.push(``);
|
|
320
|
+
lines.push(verdictBadge(verdict));
|
|
321
|
+
lines.push(``);
|
|
322
|
+
// Audit trail
|
|
323
|
+
lines.push(`### Audit Trail`);
|
|
324
|
+
if (comparison.diff_sha256) {
|
|
325
|
+
lines.push(`Diff SHA-256: \`${comparison.diff_sha256}\` (signed, embedded in evidence bundle)`);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
lines.push(`Diff computed client-side (no SHA-256 — backend diff not yet available for this run)`);
|
|
329
|
+
}
|
|
330
|
+
if (candidateRun.bundle_artifact_id) {
|
|
331
|
+
lines.push(`Candidate bundle artifact: \`${candidateRun.bundle_artifact_id}\``);
|
|
332
|
+
}
|
|
333
|
+
if (comparison.previous_run_id) {
|
|
334
|
+
lines.push(`Baseline run ID: \`${comparison.previous_run_id}\``);
|
|
335
|
+
}
|
|
336
|
+
return lines.join("\n");
|
|
337
|
+
}
|
|
338
|
+
function formatNoBaseline(candidateRun) {
|
|
339
|
+
return [
|
|
340
|
+
`## Run Comparison`,
|
|
341
|
+
``,
|
|
342
|
+
`**Pipeline:** ${candidateRun.pipeline_name} (${candidateRun.pipeline_id})`,
|
|
343
|
+
`**Candidate:** \`${candidateRun.id}\``,
|
|
344
|
+
``,
|
|
345
|
+
`> **NO BASELINE** — this is the first completed run in pipeline "${candidateRun.pipeline_name}", ` +
|
|
346
|
+
`or no prior completed runs were found. There is nothing to compare against yet.`,
|
|
347
|
+
``,
|
|
348
|
+
`**Verdict: NO BASELINE**`,
|
|
349
|
+
].join("\n");
|
|
350
|
+
}
|
|
351
|
+
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
352
|
+
function fmt(v) {
|
|
353
|
+
return v === null ? "—" : v.toFixed(2);
|
|
354
|
+
}
|
|
355
|
+
function fmtDelta(v) {
|
|
356
|
+
if (v === null)
|
|
357
|
+
return "—";
|
|
358
|
+
return `${v > 0 ? "+" : ""}${v.toFixed(2)}`;
|
|
359
|
+
}
|
|
360
|
+
function gateIcon(passed) {
|
|
361
|
+
if (passed === null)
|
|
362
|
+
return "—";
|
|
363
|
+
return passed ? "✓" : "✗";
|
|
364
|
+
}
|
|
365
|
+
function flipLabel(transition) {
|
|
366
|
+
switch (transition) {
|
|
367
|
+
case "regressed": return "**REGRESSION** ✓→✗";
|
|
368
|
+
case "improved": return "RECOVERY ✗→✓";
|
|
369
|
+
case "unchanged": return "passing";
|
|
370
|
+
case "still_failing": return "still failing";
|
|
371
|
+
case "new": return "new gate";
|
|
372
|
+
case "removed": return "removed";
|
|
373
|
+
default: return transition;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function buildDirectionLabel(metric, delta) {
|
|
377
|
+
if (delta === 0)
|
|
378
|
+
return "no change";
|
|
379
|
+
const lowerBetter = LOWER_IS_BETTER.has(metric);
|
|
380
|
+
if (lowerBetter) {
|
|
381
|
+
return delta > 0 ? "worse ↑" : "better ↓";
|
|
382
|
+
}
|
|
383
|
+
return delta > 0 ? "better ↑" : "worse ↓";
|
|
384
|
+
}
|
|
385
|
+
function computeVerdict(gateFlips, metricDeltas) {
|
|
386
|
+
const hasRegression = gateFlips.some((gf) => gf.transition === "regressed");
|
|
387
|
+
const hasRecovery = gateFlips.some((gf) => gf.transition === "improved");
|
|
388
|
+
// Also flag metric-only regression even if no gate flip
|
|
389
|
+
const significantMetricRegression = Object.entries(metricDeltas).some(([k, m]) => {
|
|
390
|
+
if (!LOWER_IS_BETTER.has(k))
|
|
391
|
+
return false;
|
|
392
|
+
return m.delta_pct !== null && m.delta_pct >= REGRESSION_THRESHOLD_PCT;
|
|
393
|
+
});
|
|
394
|
+
if (hasRegression || significantMetricRegression)
|
|
395
|
+
return "REGRESSION";
|
|
396
|
+
if (hasRecovery && !hasRegression)
|
|
397
|
+
return "IMPROVEMENT";
|
|
398
|
+
return "NEUTRAL";
|
|
399
|
+
}
|
|
400
|
+
function verdictBadge(verdict) {
|
|
401
|
+
switch (verdict) {
|
|
402
|
+
case "REGRESSION": return `**REGRESSION** — one or more gates regressed or a lower-is-better metric increased by ≥${REGRESSION_THRESHOLD_PCT}%.`;
|
|
403
|
+
case "IMPROVEMENT": return `**IMPROVEMENT** — previously-failing gates now pass; no regressions.`;
|
|
404
|
+
case "NEUTRAL": return `**NEUTRAL** — no gate flips and no significant metric regressions.`;
|
|
405
|
+
case "NO BASELINE": return `**NO BASELINE** — no prior run to compare against.`;
|
|
406
|
+
default: return `**${verdict}**`;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=compare_runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare_runs.js","sourceRoot":"","sources":["../../src/tools/compare_runs.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -89,3 +89,46 @@ export interface AuditReport {
|
|
|
89
89
|
url?: string;
|
|
90
90
|
generated_at?: string;
|
|
91
91
|
}
|
|
92
|
+
export interface MetricDelta {
|
|
93
|
+
current: number | null;
|
|
94
|
+
previous: number | null;
|
|
95
|
+
delta: number | null;
|
|
96
|
+
delta_pct: number | null;
|
|
97
|
+
}
|
|
98
|
+
export interface GateFlip {
|
|
99
|
+
metric: string;
|
|
100
|
+
/** "unchanged" | "improved" | "regressed" | "still_failing" | "new" | "removed" */
|
|
101
|
+
transition: string;
|
|
102
|
+
previous: {
|
|
103
|
+
passed: boolean | null;
|
|
104
|
+
threshold: number | null;
|
|
105
|
+
operator: string | null;
|
|
106
|
+
actual_value: number | null;
|
|
107
|
+
} | null;
|
|
108
|
+
current: {
|
|
109
|
+
passed: boolean | null;
|
|
110
|
+
threshold: number | null;
|
|
111
|
+
operator: string | null;
|
|
112
|
+
actual_value: number | null;
|
|
113
|
+
} | null;
|
|
114
|
+
}
|
|
115
|
+
export interface RunDiffPayload {
|
|
116
|
+
current_run_id: UUID;
|
|
117
|
+
previous_run_id: UUID | null;
|
|
118
|
+
current_commit: Record<string, string | null>;
|
|
119
|
+
previous_commit: Record<string, string | null> | null;
|
|
120
|
+
current_completed_at: string | null;
|
|
121
|
+
previous_completed_at: string | null;
|
|
122
|
+
metric_deltas: Record<string, MetricDelta>;
|
|
123
|
+
gate_flips: GateFlip[];
|
|
124
|
+
per_device: Record<string, Record<string, MetricDelta>> | null;
|
|
125
|
+
per_cell: unknown[] | null;
|
|
126
|
+
is_baseline: boolean;
|
|
127
|
+
}
|
|
128
|
+
export interface RunComparison {
|
|
129
|
+
current_run_id: UUID;
|
|
130
|
+
previous_run_id: UUID | null;
|
|
131
|
+
diff_sha256: string | null;
|
|
132
|
+
diff: RunDiffPayload;
|
|
133
|
+
created_at: string;
|
|
134
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
2
|
-
export declare const USER_AGENT = "edgegate-mcp/0.
|
|
1
|
+
export declare const VERSION = "0.2.0";
|
|
2
|
+
export declare const USER_AGENT = "edgegate-mcp/0.2.0";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -12,3 +12,7 @@ The user wants to know how a run is doing.
|
|
|
12
12
|
3. Render the result. If the run is FAILED, lead with the violating gate and the actual value — don't bury it.
|
|
13
13
|
|
|
14
14
|
For PASSED runs, briefly summarize the metrics so the user has the numbers handy for a PR comment.
|
|
15
|
+
|
|
16
|
+
## "Is this run a regression?"
|
|
17
|
+
|
|
18
|
+
If the user asks whether a run is a regression, or wants to see how it compares to the previous one, call `edgegate_compare_runs` with the `run_id` (and optionally a `baseline_run_id`). The tool auto-selects the baseline from the same pipeline when no explicit baseline is given. Read the **Verdict** section of the output — REGRESSION means at least one gate flipped ✓→✗ or a lower-is-better metric increased by ≥ 25%.
|