Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions robosoft/robots/core-integration.robot.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,18 @@ export default {
// may be "failed" (the probe manifest has findings) — that is a REAL Core
// evaluation, which is exactly what proves the round-trip.
const data = unwrap(r.body);
check('Core returns a real evaluation verdict (gates evaluated)', r.body?.success === true && Array.isArray(data.gates), {
detail: Array.isArray(data.gates) ? summarizeVerdict(data) : r.body?.error?.message || 'no gates',
// `results.gate`, NOT `gates`. The Core's canonical EvaluationResult nests
// per-kind results under `results` (`gate`, `artifact`, `compliance`); it is
// the TRACKER's own DTO that flattens them to `gates`, and this robot talks
// to the Core through the gateway, so it gets the canonical shape.
//
// Asserting the flattened key made this step report "no gates" against a
// Core that had evaluated six of them — a defect in the instrument that read
// as a defect in the product. Measured against a captured REST response:
// `data.gates` is undefined, `data.results.gate` has 6 entries.
const gates = gatesOf(data);
check('Core returns a real evaluation verdict (gates evaluated)', r.body?.success === true && Array.isArray(gates), {
detail: Array.isArray(gates) ? summarizeVerdict(data) : r.body?.error?.message || 'no gates',
});
}

Expand Down Expand Up @@ -177,8 +187,16 @@ function parseMcpInner(body) {
}

/** One-line summary of an evaluation verdict from the Core's `data` payload. */
/** The canonical EvaluationResult nests gates under `results.gate`. */
function gatesOf(data) {
return Array.isArray(data?.results?.gate) ? data.results.gate : undefined;
}

function summarizeVerdict(data) {
const gates = Array.isArray(data.gates) ? data.gates : [];
const failed = gates.filter((g) => String(g.verdict).toLowerCase() === 'failed').length;
const gates = gatesOf(data) ?? [];
// The Core emits `FAIL`, not `failed`. Comparing against 'failed' reported
// zero failures on a run where all six gates had failed — a green-looking
// summary over a red result, which is worse than no summary.
const failed = gates.filter((g) => /^fail/i.test(String(g.verdict))).length;
return `gates=${gates.length} · failed=${failed}`;
}
Loading