Fix 10 OpenAPI review items for HITL, run outputs, and verifications

Addresses agreed items from the openapi-hitl-and-run-outputs review:
rename retrieveRunDiff operationId, add 409s to steer/preview, bound
expires_in_secs, add selected_option_keys for multi-select end-to-end,
document skip/na semantics, add slug and require type on
RunVerificationControl, require file on CodeLocation, and remove the
checkpoint "all" sentinel in favor of omitting the parameter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-06 15:13:06 -05:00
parent a519124532
commit 72c0c8e257
16 changed files with 175 additions and 96 deletions

View file

@ -14,7 +14,7 @@ import type { Route } from "./+types/run-compare";
export const handle = { wide: true };
export async function loader({ request, params }: Route.LoaderArgs) {
const data = await apiJson<RunCompare>(`/runs/${params.id}/compare?checkpoint=all`, { request });
const data = await apiJson<RunCompare>(`/runs/${params.id}/compare`, { request });
return data;
}

View file

@ -946,7 +946,6 @@ mod runs {
pub fn compare() -> RunCompare {
RunCompare {
checkpoints: vec![
FileCheckpoint { id: "all".into(), label: "All changes".into() },
FileCheckpoint { id: "cp-4".into(), label: "Checkpoint 4 — Apply Changes".into() },
FileCheckpoint { id: "cp-3".into(), label: "Checkpoint 3 — Review Changes".into() },
FileCheckpoint { id: "cp-2".into(), label: "Checkpoint 2 — Propose Changes".into() },
@ -1454,7 +1453,7 @@ mod verifications {
name: &'static str,
slug: &'static str,
description: &'static str,
type_: Option<VerificationType>,
type_: VerificationType,
mode: VerificationMode,
f1: Option<f64>,
pass_at_1: Option<f64>,
@ -1640,7 +1639,7 @@ mod verifications {
ControlDef {
name: "Motivation", slug: "motivation",
description: "Origin of proposal identified",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.87), pass_at_1: Some(0.82),
evaluations: &[P, P, F, P, P, P, P, F, P, P],
run_status: VerificationResult::Pass,
@ -1653,7 +1652,7 @@ mod verifications {
ControlDef {
name: "Specifications", slug: "specifications",
description: "Requirements written down",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.83), pass_at_1: Some(0.78),
evaluations: &[P, F, P, P, P, F, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1666,7 +1665,7 @@ mod verifications {
ControlDef {
name: "Documentation", slug: "documentation",
description: "Developer and user docs added",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.79), pass_at_1: Some(0.74),
evaluations: &[P, P, P, F, P, P, F, P, P, F],
run_status: VerificationResult::Pass,
@ -1679,7 +1678,7 @@ mod verifications {
ControlDef {
name: "Minimization", slug: "minimization",
description: "No extraneous changes",
type_: Some(VerificationType::Ai), mode: VerificationMode::Evaluate,
type_: VerificationType::Ai, mode: VerificationMode::Evaluate,
f1: Some(0.72), pass_at_1: Some(0.68),
evaluations: &[P, F, P, F, P, P, F, P, P, P],
run_status: VerificationResult::Pass,
@ -1698,7 +1697,7 @@ mod verifications {
ControlDef {
name: "Formatting", slug: "formatting",
description: "Code layout matches standard",
type_: Some(VerificationType::Automated), mode: VerificationMode::Active,
type_: VerificationType::Automated, mode: VerificationMode::Active,
f1: Some(0.99), pass_at_1: Some(0.98),
evaluations: &[P, P, P, P, P, P, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1711,7 +1710,7 @@ mod verifications {
ControlDef {
name: "Linting", slug: "linting",
description: "Linter issues resolved",
type_: Some(VerificationType::Automated), mode: VerificationMode::Active,
type_: VerificationType::Automated, mode: VerificationMode::Active,
f1: Some(0.98), pass_at_1: Some(0.97),
evaluations: &[P, P, P, P, P, P, P, P, F, P],
run_status: VerificationResult::Pass,
@ -1724,7 +1723,7 @@ mod verifications {
ControlDef {
name: "Style", slug: "style",
description: "House style applied",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.81), pass_at_1: Some(0.76),
evaluations: &[P, F, P, P, P, P, F, P, P, P],
run_status: VerificationResult::Pass,
@ -1743,7 +1742,7 @@ mod verifications {
ControlDef {
name: "Completeness", slug: "completeness",
description: "Implementation covers requirements",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.76), pass_at_1: Some(0.71),
evaluations: &[P, P, F, P, F, P, P, P, F, P],
run_status: VerificationResult::Pass,
@ -1756,7 +1755,7 @@ mod verifications {
ControlDef {
name: "Defects", slug: "defects",
description: "Potential or likely bugs remediated",
type_: Some(VerificationType::AiAnalysis), mode: VerificationMode::Active,
type_: VerificationType::AiAnalysis, mode: VerificationMode::Active,
f1: Some(0.84), pass_at_1: Some(0.79),
evaluations: &[P, P, P, F, P, P, P, P, P, F],
run_status: VerificationResult::Pass,
@ -1769,7 +1768,7 @@ mod verifications {
ControlDef {
name: "Performance", slug: "performance",
description: "Hot path impact identified",
type_: Some(VerificationType::Ai), mode: VerificationMode::Evaluate,
type_: VerificationType::Ai, mode: VerificationMode::Evaluate,
f1: Some(0.69), pass_at_1: Some(0.63),
evaluations: &[F, P, P, F, P, F, P, P, F, P],
run_status: VerificationResult::Pass,
@ -1788,7 +1787,7 @@ mod verifications {
ControlDef {
name: "Test Coverage", slug: "test-coverage",
description: "Production code exercised by unit tests",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.95), pass_at_1: Some(0.93),
evaluations: &[P, P, P, P, P, P, F, P, P, P],
run_status: VerificationResult::Pass,
@ -1801,7 +1800,7 @@ mod verifications {
ControlDef {
name: "Test Quality", slug: "test-quality",
description: "Tests are robust and clear",
type_: Some(VerificationType::Ai), mode: VerificationMode::Evaluate,
type_: VerificationType::Ai, mode: VerificationMode::Evaluate,
f1: Some(0.71), pass_at_1: Some(0.65),
evaluations: &[P, F, F, P, P, F, P, F, P, P],
run_status: VerificationResult::Fail,
@ -1814,7 +1813,7 @@ mod verifications {
ControlDef {
name: "E2E Coverage", slug: "e2e-coverage",
description: "Browser automation exercises UX",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.91), pass_at_1: Some(0.88),
evaluations: &[P, P, P, F, P, P, P, P, P, P],
run_status: VerificationResult::Na,
@ -1833,7 +1832,7 @@ mod verifications {
ControlDef {
name: "Architecture", slug: "architecture",
description: "Layering and dependency graph meets design",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.88), pass_at_1: Some(0.84),
evaluations: &[P, P, P, P, F, P, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1846,7 +1845,7 @@ mod verifications {
ControlDef {
name: "Interfaces", slug: "interfaces",
description: "",
type_: None, mode: VerificationMode::Disabled,
type_: VerificationType::Ai, mode: VerificationMode::Disabled,
f1: None, pass_at_1: None,
evaluations: &[],
run_status: VerificationResult::Pass,
@ -1859,7 +1858,7 @@ mod verifications {
ControlDef {
name: "Duplication", slug: "duplication",
description: "Similar and identical code blocks identified",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.96), pass_at_1: Some(0.94),
evaluations: &[P, P, P, P, P, P, P, F, P, P],
run_status: VerificationResult::Pass,
@ -1872,7 +1871,7 @@ mod verifications {
ControlDef {
name: "Simplicity", slug: "simplicity",
description: "Extra review for reducing complexity",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.74), pass_at_1: Some(0.69),
evaluations: &[P, F, P, P, F, P, P, F, P, P],
run_status: VerificationResult::Pass,
@ -1885,7 +1884,7 @@ mod verifications {
ControlDef {
name: "Dead Code", slug: "dead-code",
description: "Unexecuted code and dependencies removed",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.93), pass_at_1: Some(0.90),
evaluations: &[P, P, P, P, P, F, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1904,7 +1903,7 @@ mod verifications {
ControlDef {
name: "Vulnerabilities", slug: "vulnerabilities",
description: "Security issues are remediated",
type_: Some(VerificationType::AiAnalysis), mode: VerificationMode::Active,
type_: VerificationType::AiAnalysis, mode: VerificationMode::Active,
f1: Some(0.86), pass_at_1: Some(0.81),
evaluations: &[P, P, F, P, P, P, P, P, F, P],
run_status: VerificationResult::Pass,
@ -1917,7 +1916,7 @@ mod verifications {
ControlDef {
name: "IaC Scanning", slug: "iac-scanning",
description: "",
type_: None, mode: VerificationMode::Disabled,
type_: VerificationType::Automated, mode: VerificationMode::Disabled,
f1: None, pass_at_1: None,
evaluations: &[],
run_status: VerificationResult::Pass,
@ -1930,7 +1929,7 @@ mod verifications {
ControlDef {
name: "Dependency Alerts", slug: "dependency-alerts",
description: "Known CVEs are patched",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.97), pass_at_1: Some(0.95),
evaluations: &[P, P, P, P, P, P, P, P, P, F],
run_status: VerificationResult::Pass,
@ -1943,7 +1942,7 @@ mod verifications {
ControlDef {
name: "Security Controls", slug: "security-controls",
description: "Organization standards applied",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.80), pass_at_1: Some(0.75),
evaluations: &[P, P, F, P, P, F, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1962,7 +1961,7 @@ mod verifications {
ControlDef {
name: "Compatibility", slug: "compatibility",
description: "Breaking changes are avoided",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.89), pass_at_1: Some(0.85),
evaluations: &[P, P, P, P, F, P, P, P, P, P],
run_status: VerificationResult::Pass,
@ -1975,7 +1974,7 @@ mod verifications {
ControlDef {
name: "Rollout / Rollback", slug: "rollout-rollback",
description: "Known rollback plan if deploy fails",
type_: Some(VerificationType::Ai), mode: VerificationMode::Evaluate,
type_: VerificationType::Ai, mode: VerificationMode::Evaluate,
f1: Some(0.66), pass_at_1: Some(0.60),
evaluations: &[F, P, F, P, F, P, P, F, P, F],
run_status: VerificationResult::Fail,
@ -1988,7 +1987,7 @@ mod verifications {
ControlDef {
name: "Observability", slug: "observability",
description: "Logging, metrics, tracing instrumented",
type_: Some(VerificationType::Ai), mode: VerificationMode::Evaluate,
type_: VerificationType::Ai, mode: VerificationMode::Evaluate,
f1: Some(0.73), pass_at_1: Some(0.67),
evaluations: &[P, F, P, F, P, P, F, P, F, P],
run_status: VerificationResult::Fail,
@ -2001,7 +2000,7 @@ mod verifications {
ControlDef {
name: "Cost", slug: "cost",
description: "Tech ops costs estimated",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Evaluate,
type_: VerificationType::Analysis, mode: VerificationMode::Evaluate,
f1: Some(0.78), pass_at_1: Some(0.72),
evaluations: &[P, P, F, P, F, P, P, F, P, P],
run_status: VerificationResult::Pass,
@ -2020,7 +2019,7 @@ mod verifications {
ControlDef {
name: "Change Control", slug: "change-control",
description: "Separation of Duties policy met",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.94), pass_at_1: Some(0.91),
evaluations: &[P, P, P, P, P, P, P, P, F, P],
run_status: VerificationResult::Pass,
@ -2033,7 +2032,7 @@ mod verifications {
ControlDef {
name: "AI Governance", slug: "ai-governance",
description: "AI involvement was acceptable",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.85), pass_at_1: Some(0.80),
evaluations: &[P, P, P, F, P, P, P, P, P, P],
run_status: VerificationResult::Pass,
@ -2046,7 +2045,7 @@ mod verifications {
ControlDef {
name: "Privacy", slug: "privacy",
description: "PII is identified and handled to standards",
type_: Some(VerificationType::Ai), mode: VerificationMode::Active,
type_: VerificationType::Ai, mode: VerificationMode::Active,
f1: Some(0.77), pass_at_1: Some(0.72),
evaluations: &[P, F, P, P, P, F, P, P, P, F],
run_status: VerificationResult::Pass,
@ -2059,7 +2058,7 @@ mod verifications {
ControlDef {
name: "Accessibility", slug: "accessibility",
description: "Software meets accessibility requirements",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.90), pass_at_1: Some(0.87),
evaluations: &[P, P, P, P, P, F, P, P, P, P],
run_status: VerificationResult::Pass,
@ -2072,7 +2071,7 @@ mod verifications {
ControlDef {
name: "Licensing", slug: "licensing",
description: "Supply chain meets IP policy",
type_: Some(VerificationType::Analysis), mode: VerificationMode::Active,
type_: VerificationType::Analysis, mode: VerificationMode::Active,
f1: Some(0.96), pass_at_1: Some(0.93),
evaluations: &[P, P, P, P, P, P, P, P, P, P],
run_status: VerificationResult::Pass,
@ -2155,7 +2154,7 @@ mod verifications {
.map(|(_, s)| SiblingControl {
name: s.name.into(),
slug: s.slug.into(),
type_: s.type_,
type_: Some(s.type_),
mode: Some(s.mode),
})
.collect();
@ -2170,7 +2169,7 @@ mod verifications {
name: ctrl.name.into(),
slug: ctrl.slug.into(),
description: ctrl.description.into(),
type_: ctrl.type_,
type_: Some(ctrl.type_),
category: CategoryReference { name: cat.name.into() },
},
performance: ControlPerformance {
@ -2206,6 +2205,7 @@ mod verifications {
.iter()
.map(|c| RunVerificationControl {
name: c.name.into(),
slug: c.slug.into(),
description: c.description.into(),
type_: c.type_,
status: c.run_status,

View file

@ -767,30 +767,42 @@ async fn submit_answer(
.into_response();
}
};
let answer = match &req.selected_option_key {
Some(key) => {
let option = interviewer
.pending_questions()
.iter()
.find(|pq| pq.id == qid)
.and_then(|pq| pq.question.options.iter().find(|o| o.key == *key))
.cloned();
match option {
Some(opt) => Answer::selected(key.clone(), opt),
let answer = if let Some(key) = &req.selected_option_key {
let option = interviewer
.pending_questions()
.iter()
.find(|pq| pq.id == qid)
.and_then(|pq| pq.question.options.iter().find(|o| o.key == *key))
.cloned();
match option {
Some(opt) => Answer::selected(key.clone(), opt),
None => {
return ApiError::bad_request("Invalid option key.").into_response();
}
}
} else if !req.selected_option_keys.is_empty() {
let pending = interviewer.pending_questions();
let pq = pending.iter().find(|pq| pq.id == qid);
let mut options = Vec::new();
for key in &req.selected_option_keys {
let opt = pq.and_then(|pq| {
pq.question.options.iter().find(|o| o.key == *key).cloned()
});
match opt {
Some(o) => options.push(o),
None => {
return ApiError::bad_request("Invalid option key.").into_response();
}
}
}
None => match req.value {
Some(v) => Answer::text(v),
None => {
return ApiError::bad_request(
"Either value or selected_option_key is required.",
)
.into_response();
}
},
Answer::multi_selected(req.selected_option_keys, options)
} else if let Some(v) = req.value {
Answer::text(v)
} else {
return ApiError::bad_request(
"One of value, selected_option_key, or selected_option_keys is required.",
)
.into_response();
};
let accepted = interviewer.submit_answer(&qid, answer);
if accepted {

View file

@ -86,6 +86,7 @@ fn format_answer(answer: &Answer) -> String {
k.clone()
}
}
AnswerValue::MultiSelected(keys) => keys.join(", "),
AnswerValue::Skipped => "Skipped".to_string(),
AnswerValue::Timeout => "Timed out".to_string(),
}

View file

@ -255,6 +255,7 @@ fn answer_text(answer: &Answer) -> String {
match &answer.value {
AnswerValue::Text(t) => t.clone(),
AnswerValue::Selected(s) => s.clone(),
AnswerValue::MultiSelected(keys) => keys.join(", "),
AnswerValue::Yes => "yes".to_string(),
AnswerValue::No => "no".to_string(),
AnswerValue::Skipped => "skipped".to_string(),

View file

@ -16,6 +16,7 @@ impl Interviewer for AutoApproveInterviewer {
|first| Answer {
value: AnswerValue::Selected(first.key.clone()),
selected_option: Some(first.clone()),
selected_options: Vec::new(),
text: None,
},
)

View file

@ -28,6 +28,7 @@ fn find_matching_option(response: &str, options: &[super::QuestionOption]) -> Op
return Some(Answer {
value: AnswerValue::Selected(opt.key.clone()),
selected_option: Some(opt.clone()),
selected_options: Vec::new(),
text: None,
});
}
@ -39,6 +40,7 @@ fn find_matching_option(response: &str, options: &[super::QuestionOption]) -> Op
return Some(Answer {
value: AnswerValue::Selected(opt.key.clone()),
selected_option: Some(opt.clone()),
selected_options: Vec::new(),
text: None,
});
}
@ -89,6 +91,7 @@ fn ask_select_interactive(question: &Question) -> Answer {
Answer {
value: AnswerValue::Selected(opt.key.clone()),
selected_option: Some(opt.clone()),
selected_options: Vec::new(),
text: None,
}
}
@ -111,13 +114,9 @@ fn ask_multi_select_interactive(question: &Question) -> Answer {
match selection {
Ok(Some(indices)) if !indices.is_empty() => {
let idx = indices[0];
let opt = &question.options[idx];
Answer {
value: AnswerValue::Selected(opt.key.clone()),
selected_option: Some(opt.clone()),
text: None,
}
let keys: Vec<String> = indices.iter().map(|&i| question.options[i].key.clone()).collect();
let options: Vec<_> = indices.iter().map(|&i| question.options[i].clone()).collect();
Answer::multi_selected(keys, options)
}
_ => Answer::skipped(),
}

View file

@ -76,6 +76,7 @@ pub enum AnswerValue {
Skipped,
Timeout,
Selected(String),
MultiSelected(Vec<String>),
Text(String),
}
@ -84,42 +85,48 @@ pub enum AnswerValue {
pub struct Answer {
pub value: AnswerValue,
pub selected_option: Option<QuestionOption>,
#[serde(default)]
pub selected_options: Vec<QuestionOption>,
pub text: Option<String>,
}
impl Answer {
#[must_use]
pub const fn yes() -> Self {
pub fn yes() -> Self {
Self {
value: AnswerValue::Yes,
selected_option: None,
selected_options: Vec::new(),
text: None,
}
}
#[must_use]
pub const fn no() -> Self {
pub fn no() -> Self {
Self {
value: AnswerValue::No,
selected_option: None,
selected_options: Vec::new(),
text: None,
}
}
#[must_use]
pub const fn skipped() -> Self {
pub fn skipped() -> Self {
Self {
value: AnswerValue::Skipped,
selected_option: None,
selected_options: Vec::new(),
text: None,
}
}
#[must_use]
pub const fn timeout() -> Self {
pub fn timeout() -> Self {
Self {
value: AnswerValue::Timeout,
selected_option: None,
selected_options: Vec::new(),
text: None,
}
}
@ -129,6 +136,16 @@ impl Answer {
Self {
value: AnswerValue::Selected(key),
selected_option: Some(option),
selected_options: Vec::new(),
text: None,
}
}
pub fn multi_selected(keys: Vec<String>, options: Vec<QuestionOption>) -> Self {
Self {
value: AnswerValue::MultiSelected(keys),
selected_option: None,
selected_options: options,
text: None,
}
}
@ -138,6 +155,7 @@ impl Answer {
Self {
value: AnswerValue::Text(t.clone()),
selected_option: None,
selected_options: Vec::new(),
text: Some(t),
}
}

View file

@ -435,6 +435,7 @@ async fn end_to_end_human_gate_pipeline() {
let answers = VecDeque::from([Answer {
value: AnswerValue::Selected("R".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
}]);
let interviewer = Arc::new(QueueInterviewer::new(answers));
@ -2151,11 +2152,13 @@ async fn human_gate_loops_back() {
Answer {
value: AnswerValue::Selected("F".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
},
Answer {
value: AnswerValue::Selected("A".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
},
]);
@ -6193,6 +6196,7 @@ async fn human_gate_freeform_with_fixed_choice_match() {
let answers = VecDeque::from([Answer {
value: AnswerValue::Selected("A".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
}]);
let interviewer = Arc::new(QueueInterviewer::new(answers));
@ -6434,6 +6438,7 @@ async fn human_gate_freeform_sets_allow_freeform_on_question() {
let answers = VecDeque::from([Answer {
value: AnswerValue::Selected("A".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
}]);
let inner = QueueInterviewer::new(answers);
@ -6542,6 +6547,7 @@ async fn human_gate_without_freeform_sets_allow_freeform_false() {
let answers = VecDeque::from([Answer {
value: AnswerValue::Selected("A".to_string()),
selected_option: None,
selected_options: Vec::new(),
text: None,
}]);
let inner = QueueInterviewer::new(answers);

View file

@ -438,9 +438,9 @@ paths:
/runs/{id}/compare:
get:
operationId: retrieveRunDiff
operationId: retrieveRunCompare
tags: [Run Outputs]
summary: List Run Compare
summary: Retrieve Run Compare
description: Returns file-level diffs produced by the run, optionally filtered to a specific checkpoint.
parameters:
- $ref: "#/components/parameters/RunId"
@ -550,6 +550,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Run is not in a steerable state
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
/runs/{id}/preview:
post:
@ -578,6 +584,12 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"409":
description: Run has no active sandbox
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
# ── Workflows ─────────────────────────────────────────────────────────
@ -1174,10 +1186,9 @@ components:
name: checkpoint
in: query
required: false
description: Filter file diffs to a specific checkpoint. Defaults to all changes.
description: Filter to a specific checkpoint ID. Omit to include all changes.
schema:
type: string
default: "all"
example: cp-3
PageLimit:
@ -1506,7 +1517,9 @@ components:
- confirmation
SubmitAnswerRequest:
description: Request body for submitting an answer to a pending question.
description: >
Request body for submitting an answer to a pending question.
At least one of `value`, `selected_option_key`, or `selected_option_keys` must be provided.
type: object
properties:
value:
@ -1515,8 +1528,14 @@ components:
example: "Yes, proceed with the changes."
selected_option_key:
type: string
description: Key of the selected option (for multiple-choice questions).
description: Key of the selected option (for single-select multiple-choice questions).
example: option_a
selected_option_keys:
type: array
items:
type: string
description: Keys of selected options (for multi-select questions).
example: ["option_a", "option_b"]
ErrorResponseEntry:
description: A single error entry in an error response.
@ -1676,6 +1695,8 @@ components:
CodeLocation:
description: A file and line location in the codebase.
type: object
required:
- file
properties:
file:
type: string
@ -2228,7 +2249,10 @@ components:
# ── Verification Schemas ─────────────────────────────────────────────
VerificationResult:
description: Outcome of a verification control evaluation.
description: >
Outcome of a verification control evaluation.
`skip`: evaluation was intentionally skipped (e.g., control is disabled).
`na`: control does not apply to this run (e.g., Python lint on a Rust-only change).
type: string
enum:
- pass
@ -2250,13 +2274,19 @@ components:
type: object
required:
- name
- slug
- description
- type
- status
properties:
name:
type: string
description: Human-readable control name.
example: Motivation
slug:
type: string
description: URL-safe slug for linking to verification detail page.
example: motivation
description:
type: string
description: Short description of what the control verifies.
@ -2318,6 +2348,8 @@ components:
expires_in_secs:
type: integer
description: Time-to-live for the preview URL in seconds.
minimum: 1
maximum: 86400
example: 3600
PreviewUrlResponse:
@ -2409,6 +2441,7 @@ components:
- name
- slug
- description
- type
properties:
name:
type: string

View file

@ -87,15 +87,15 @@ export const RunOutputsApiAxiosParamCreator = function (configuration?: Configur
},
/**
* Returns file-level diffs produced by the run, optionally filtered to a specific checkpoint.
* @summary List Run Compare
* @summary Retrieve Run Compare
* @param {string} id Unique run identifier (ULID).
* @param {string} [checkpoint] Filter file diffs to a specific checkpoint. Defaults to all changes.
* @param {string} [checkpoint] Filter to a specific checkpoint ID. Omit to include all changes.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
retrieveRunDiff: async (id: string, checkpoint?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
retrieveRunCompare: async (id: string, checkpoint?: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'id' is not null or undefined
assertParamExists('retrieveRunDiff', 'id', id)
assertParamExists('retrieveRunCompare', 'id', id)
const localVarPath = `/runs/{id}/compare`
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
@ -198,16 +198,16 @@ export const RunOutputsApiFp = function(configuration?: Configuration) {
},
/**
* Returns file-level diffs produced by the run, optionally filtered to a specific checkpoint.
* @summary List Run Compare
* @summary Retrieve Run Compare
* @param {string} id Unique run identifier (ULID).
* @param {string} [checkpoint] Filter file diffs to a specific checkpoint. Defaults to all changes.
* @param {string} [checkpoint] Filter to a specific checkpoint ID. Omit to include all changes.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async retrieveRunDiff(id: string, checkpoint?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RunCompare>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.retrieveRunDiff(id, checkpoint, options);
async retrieveRunCompare(id: string, checkpoint?: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<RunCompare>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.retrieveRunCompare(id, checkpoint, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['RunOutputsApi.retrieveRunDiff']?.[localVarOperationServerIndex]?.url;
const localVarOperationServerBasePath = operationServerMap['RunOutputsApi.retrieveRunCompare']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
@ -246,14 +246,14 @@ export const RunOutputsApiFactory = function (configuration?: Configuration, bas
},
/**
* Returns file-level diffs produced by the run, optionally filtered to a specific checkpoint.
* @summary List Run Compare
* @summary Retrieve Run Compare
* @param {string} id Unique run identifier (ULID).
* @param {string} [checkpoint] Filter file diffs to a specific checkpoint. Defaults to all changes.
* @param {string} [checkpoint] Filter to a specific checkpoint ID. Omit to include all changes.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
retrieveRunDiff(id: string, checkpoint?: string, options?: RawAxiosRequestConfig): AxiosPromise<RunCompare> {
return localVarFp.retrieveRunDiff(id, checkpoint, options).then((request) => request(axios, basePath));
retrieveRunCompare(id: string, checkpoint?: string, options?: RawAxiosRequestConfig): AxiosPromise<RunCompare> {
return localVarFp.retrieveRunCompare(id, checkpoint, options).then((request) => request(axios, basePath));
},
/**
* Returns token and cost usage broken down by stage and model for a specific run.
@ -287,14 +287,14 @@ export class RunOutputsApi extends BaseAPI {
/**
* Returns file-level diffs produced by the run, optionally filtered to a specific checkpoint.
* @summary List Run Compare
* @summary Retrieve Run Compare
* @param {string} id Unique run identifier (ULID).
* @param {string} [checkpoint] Filter file diffs to a specific checkpoint. Defaults to all changes.
* @param {string} [checkpoint] Filter to a specific checkpoint ID. Omit to include all changes.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
public retrieveRunDiff(id: string, checkpoint?: string, options?: RawAxiosRequestConfig) {
return RunOutputsApiFp(this.configuration).retrieveRunDiff(id, checkpoint, options).then((request) => request(this.axios, this.basePath));
public retrieveRunCompare(id: string, checkpoint?: string, options?: RawAxiosRequestConfig) {
return RunOutputsApiFp(this.configuration).retrieveRunCompare(id, checkpoint, options).then((request) => request(this.axios, this.basePath));
}
/**

View file

@ -21,7 +21,7 @@ export interface CodeLocation {
/**
* File path.
*/
'file'?: string;
'file': string;
/**
* Line number in the file.
*/

View file

@ -28,11 +28,15 @@ export interface RunVerificationControl {
* Human-readable control name.
*/
'name': string;
/**
* URL-safe slug for linking to verification detail page.
*/
'slug': string;
/**
* Short description of what the control verifies.
*/
'description': string;
'type'?: VerificationType;
'type': VerificationType;
'status': VerificationResult;
}

View file

@ -15,7 +15,7 @@
/**
* Request body for submitting an answer to a pending question.
* Request body for submitting an answer to a pending question. At least one of `value`, `selected_option_key`, or `selected_option_keys` must be provided.
*/
export interface SubmitAnswerRequest {
/**
@ -23,8 +23,12 @@ export interface SubmitAnswerRequest {
*/
'value'?: string;
/**
* Key of the selected option (for multiple-choice questions).
* Key of the selected option (for single-select multiple-choice questions).
*/
'selected_option_key'?: string;
/**
* Keys of selected options (for multi-select questions).
*/
'selected_option_keys'?: Array<string>;
}

View file

@ -39,7 +39,7 @@ export interface VerificationControl {
* Short description of what the control verifies.
*/
'description': string;
'type'?: VerificationType;
'type': VerificationType;
'mode'?: VerificationMode;
/**
* F1 score of the control\'s AI evaluator.

View file

@ -15,7 +15,7 @@
/**
* Outcome of a verification control evaluation.
* Outcome of a verification control evaluation. `skip`: evaluation was intentionally skipped (e.g., control is disabled). `na`: control does not apply to this run (e.g., Python lint on a Rust-only change).
*/
export const VerificationResult = {