Skip to content

feat(detection): add opt-in structured triage contract - #135

Merged
barisozbas merged 3 commits into
uber:mainfrom
shengqi-gensee:review/structured-triage-contract
Sep 23, 2026
Merged

barisozbas merged 3 commits into
uber:mainfrom
shengqi-gensee:review/structured-triage-contract

Conversation

@shengqi-gensee

Copy link
Copy Markdown
Contributor

Summary

This PR implements the second part of the maintainer's recommended plan in uber/ADR#50: S — structured triage option, following the P2 import-following source-coverage fix.

Add an opt-in structured Tier-1 routing contract while retaining stock text triage as the default, preserving existing behavior when disabled and escalating on invalid structured output.

What changed

  • Add decision_contract: structured_risk_route_v1 under adr_framework.triage_llm. Omitting it preserves stock triage; invalid contract names fail explicitly.
  • Add benchmark-specific ADR-Bench and AgentDojo prompts with explicit BENIGN_EXIT / ESCALATE, scenario/component risk, injection, unsafe plan/action/effect, authorization, provenance-needed, and evidence fields.
  • Validate JSON types, field bounds, duplicate keys, finite confidence, and cross-field/benchmark consistency locally. Invalid responses escalate rather than silently exit benign.
  • Build a bounded Tier-2 handoff from validated enum/boolean fields and, for ADR-Bench, validated framework-provided MCP server names. Free-form model reasoning and evidence are not copied into the trusted handoff slot.
  • Include the ADR-Bench scenario/component versus execution-outcome distinction and security-evidence boundary in the structured handoff.
  • Persist validated structured audit data in an optional structured_triage result field and a per-task debug artifact, before Tier 2 runs. Preserve the artifact even if Tier 2 fails; an audit-write failure does not block escalation.
  • Add unit/integration regression coverage and configuration documentation.

Enable

adr_framework:
  triage_llm:
    decision_contract: structured_risk_route_v1

The stock to_dict() output key set remains unchanged. Opted-in structured results add structured_triage; consumers enforcing an exact JSON schema must accept that optional field. Direct dataclass serialization also exposes the new field when it is None.

Validation

  • Full local Detection test suite: 248 passed.
  • Four offline evaluation checks: frozen request reconstruction, stock prompt parity, structured prompt/schema/handoff parity, and message-adapter parity across all 93 AgentDojo trajectories.
  • Fresh independent code review found no actionable correctness/security regression in the combined feature and audit fix. This is supplementary review, not a substitute for maintainer review.

Evaluation results

Luna low at both tiers, store:false. Final pipeline results:

Dataset Configuration Recall FPR Accuracy
ADR-Bench (303 tasks) Stock ADR/Luna 85.71% (36/42) 15.33% (40/261) 84.82%
ADR-Bench (303 tasks) Structured ADR/Luna 92.86% (39/42) 7.28% (19/261) 92.74%
AgentDojo (93 evaluated tasks) Stock ADR/Luna 100% (38/38) 3.64% (2/55) 97.85%
AgentDojo (93 evaluated tasks) Structured ADR/Luna 100% (38/38) 1.82% (1/55) 98.92%

On AgentDojo, structured triage reduced benign escalations from 41 to 9 and Tier-2 tasks from 79 to 47, retaining all 38 malicious detections. Five structured responses exceeded the evidence-item limit and safely escalated; all five received correct final decisions.

ADR-Bench uses a frozen stock reference and frozen Tier-1 outputs with fresh structured Tier-2 calls; the structured implementation matches this branch. AgentDojo is a fresh paired run on the existing evaluated subset. These are separate development evaluations, not a single matched experiment or proof of generalization. Hosted calls use the Responses evaluation harness with product prompts, parsers, and handoffs, rather than the production Claude CLI transport.

@barisozbas barisozbas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@barisozbas
barisozbas merged commit 0b2821f into uber:main Sep 23, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants