feat(insights): split guardrail rejections from tool failures #12

Merged
janpeter merged 3 commits from fix/insights-guardrail-class into main 2026-05-28 15:23:40 +02:00
Owner

Probleem

Het Worker Insights-dashboard telt elke is_error=true MCP tool_result als "tool-fout". Maar veel daarvan zijn bedoelde guardrails die de agent juist moet zien en afhandelen: verify-gate (Plan vereist ALIGNED maar verify gaf DIVERGENT…), MISSING_BASE_SHA, already in terminal state, JOB_CANCELLED, enz. Die vertekenen de error-rate (een tool lijkt kapot terwijl het platform bewust een actie weigerde).

Aanpak (alleen metrics — MCP-server ongewijzigd)

We veranderen is_error in de MCP-server niet (de agent moet die meldingen blijven zien als "fix dit"). In plaats daarvan classificeren we ze in de insights-laag:

  • lib/worker-insights/taxonomy.ts: nieuwe isGuardrailRejection(text) + GUARDRAIL_PATTERNS (met comment die het verschil met classifyError uitlegt).
  • lib/worker-insights/queries.ts: getToolFriction haalt nu ook de fout-teksten op (parallelle query, zelfde join/scoping als de aggregate), classificeert ze, en splitst errors (echte fouten) van rejections (guardrails). errorRate = errors / (calls − rejections) met divide-by-zero-guard; NULL-tool rijen worden symmetrisch onder 'unknown' geteld.
  • components/worker-insights/insights-view.tsx: extra kolom "Rejections (guardrail)" (semantische text-warning-token), error-rate gebruikt de nieuwe noemer. Rejection-volume blijft zichtbaar.

Test

taxonomy.test.ts (6) + uitgebreide queries.test.ts (incl. mixed real+guardrail én all-guardrail → errorRate 0). npm run verify: 206 tests + lint + typecheck groen.

## Probleem Het Worker Insights-dashboard telt elke `is_error=true` MCP tool_result als "tool-fout". Maar veel daarvan zijn **bedoelde guardrails** die de agent juist moet zien en afhandelen: verify-gate (`Plan vereist ALIGNED maar verify gaf DIVERGENT…`), `MISSING_BASE_SHA`, `already in terminal state`, `JOB_CANCELLED`, enz. Die vertekenen de error-rate (een tool lijkt kapot terwijl het platform bewust een actie weigerde). ## Aanpak (alleen metrics — MCP-server ongewijzigd) We veranderen `is_error` in de MCP-server **niet** (de agent moet die meldingen blijven zien als "fix dit"). In plaats daarvan classificeren we ze in de insights-laag: - `lib/worker-insights/taxonomy.ts`: nieuwe `isGuardrailRejection(text)` + `GUARDRAIL_PATTERNS` (met comment die het verschil met `classifyError` uitlegt). - `lib/worker-insights/queries.ts`: `getToolFriction` haalt nu ook de fout-teksten op (parallelle query, zelfde join/scoping als de aggregate), classificeert ze, en splitst `errors` (echte fouten) van `rejections` (guardrails). `errorRate = errors / (calls − rejections)` met divide-by-zero-guard; NULL-tool rijen worden symmetrisch onder `'unknown'` geteld. - `components/worker-insights/insights-view.tsx`: extra kolom "Rejections (guardrail)" (semantische `text-warning`-token), error-rate gebruikt de nieuwe noemer. Rejection-volume blijft zichtbaar. ## Test `taxonomy.test.ts` (6) + uitgebreide `queries.test.ts` (incl. mixed real+guardrail én all-guardrail → errorRate 0). `npm run verify`: 206 tests + lint + typecheck groen.
Adds guardrail pattern matching so intentional rejections (verify-gate,
MISSING_BASE_SHA, terminal-state, JOB_CANCELLED) can be separated from
true tool failures in the insights layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
getToolFriction now fetches error texts in parallel and classifies each
with isGuardrailRejection, counting known intentional rejections separately.
ToolFrictionRow gains `rejections` field; `errors` excludes guardrails;
error-rate is errors / (calls - rejections). The Top-frictie-tools table
gains a "Rejections (guardrail)" column styled in amber.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- queries.ts: use `toolName ?? 'unknown'` sentinel in rejection-counting
  loop to match query-1 bucketing; NULL-tool guardrail rejections are now
  correctly subtracted instead of leaking into the error count
- insights-view.tsx: replace hardcoded `text-amber-600 dark:text-amber-400`
  with semantic `text-warning` token (defined in theme.css @theme inline)
- taxonomy.ts: add comment above GUARDRAIL_PATTERNS clarifying semantic
  difference from classifyError (failures vs intentional non-failures)
- queries.test.ts: add edge test asserting errorRate === 0 when all errors
  for a tool are guardrail rejections (guards the divide-by-zero path)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-workers!12
No description provided.