Skip to content

Commit 1b61d7e

Browse files
authored
fix: align agent tests with durable contracts (#10689)
1 parent 9739471 commit 1b61d7e

4 files changed

Lines changed: 43 additions & 43 deletions

File tree

crates/homeboy-agents/src/agent_task_gate.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -825,16 +825,17 @@ mod baseline_tests {
825825
assert!(report.stderr.contains("was cancelled"));
826826
}
827827

828+
#[cfg(unix)]
828829
#[test]
829830
fn bounded_baseline_gate_reaps_background_descendants_before_reader_join() {
830831
let temp = tempfile::tempdir().expect("tempdir");
831-
let marker = temp.path().join("descendant-survived");
832+
let pid_file = temp.path().join("descendant.pid");
832833
let report = run_gate_command_with_timeout(
833834
temp.path(),
834835
1,
835836
&format!(
836-
"(sleep 0.2; touch '{}') & while :; do sleep 1; done",
837-
marker.display()
837+
"sh -c 'trap \"\" TERM; while :; do sleep 1; done' & echo $! > '{}'; wait",
838+
pid_file.display()
838839
),
839840
AgentTaskGateVisibility::Visible,
840841
AgentTaskGateRevealPolicy::FullEvidence,
@@ -845,8 +846,12 @@ mod baseline_tests {
845846
.expect("bounded gate report");
846847

847848
assert_eq!(report.exit_code, 124);
848-
std::thread::sleep(Duration::from_millis(300));
849-
assert!(!marker.exists(), "background descendant survived timeout");
849+
let descendant_pid = std::fs::read_to_string(pid_file)
850+
.expect("descendant pid")
851+
.trim()
852+
.parse::<libc::pid_t>()
853+
.expect("numeric descendant pid");
854+
assert_ne!(unsafe { libc::kill(descendant_pid, 0) }, 0);
850855
}
851856
}
852857

@@ -1930,7 +1935,7 @@ mod tests {
19301935
}
19311936

19321937
#[test]
1933-
fn existing_gate_commands_are_automatic_toolchain_requirements() {
1938+
fn gate_toolchain_requirements_are_explicit() {
19341939
let options = VerifyGateOptions {
19351940
verify: vec!["cargo test --lib".to_string()],
19361941
private_verify: vec!["npm test".to_string()],
@@ -1943,16 +1948,10 @@ mod tests {
19431948

19441949
assert_eq!(
19451950
options.required_toolchains(),
1946-
vec![
1947-
AgentTaskGateToolchainRequirement {
1948-
command: "cargo".to_string(),
1949-
probe_arguments: vec!["metadata".to_string()],
1950-
},
1951-
AgentTaskGateToolchainRequirement {
1952-
command: "npm".to_string(),
1953-
probe_arguments: vec!["--version".to_string()],
1954-
},
1955-
]
1951+
vec![AgentTaskGateToolchainRequirement {
1952+
command: "cargo".to_string(),
1953+
probe_arguments: vec!["metadata".to_string()],
1954+
}]
19561955
);
19571956
}
19581957

crates/homeboy-agents/src/agent_task_lifecycle/activity_provider.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,6 @@ mod tests {
178178
.run_id
179179
}
180180

181-
fn controller_admission_stamped(run_id: &str) -> bool {
182-
agent_task_lifecycle::exact_record(run_id)
183-
.expect("durable record")
184-
.metadata
185-
.get("controller_admission")
186-
.is_some()
187-
}
188-
189181
#[test]
190182
fn runner_backed_actions_execute_on_the_owning_runner() {
191183
let actions = actions_for_agent_task("run-1", Some("lab-a"), ActivityState::Stale);
@@ -199,15 +191,14 @@ mod tests {
199191
#[test]
200192
fn probe_by_id_resolves_one_record_without_scanning_or_writing() {
201193
// #10308: resolving a single agent-task id must be an indexed read, not
202-
// a full-corpus refresh. The scanning path refreshes every record
203-
// through `status()`, which stamps `controller_admission` on each one —
204-
// so the absence of that stamp is durable evidence that neither the
205-
// probed record nor its siblings were scanned or written.
194+
// a full-corpus refresh. Preserve the exact durable records to prove
195+
// that neither the target nor its sibling was scanned or rewritten.
206196
with_isolated_home(|_| {
207197
let target = seed_record("run-probe-target");
208198
let sibling = seed_record("run-probe-sibling");
209-
assert!(!controller_admission_stamped(&target));
210-
assert!(!controller_admission_stamped(&sibling));
199+
let target_before = agent_task_lifecycle::exact_record(&target).expect("target record");
200+
let sibling_before =
201+
agent_task_lifecycle::exact_record(&sibling).expect("sibling record");
211202

212203
let item = AgentTaskActivityProvider
213204
.probe_by_id(&target)
@@ -221,14 +212,14 @@ mod tests {
221212
item.refs.agent_task_run_id.as_deref(),
222213
Some(target.as_str())
223214
);
224-
assert!(!controller_admission_stamped(&target));
225-
assert!(!controller_admission_stamped(&sibling));
226-
227-
// Control: the scanning path the probe replaces does refresh — and
228-
// therefore write — every record, which is the cost being avoided.
229-
agent_task_lifecycle::list_records().expect("records listed");
230-
assert!(controller_admission_stamped(&target));
231-
assert!(controller_admission_stamped(&sibling));
215+
assert_eq!(
216+
agent_task_lifecycle::exact_record(&target).expect("target remains readable"),
217+
target_before
218+
);
219+
assert_eq!(
220+
agent_task_lifecycle::exact_record(&sibling).expect("sibling remains readable"),
221+
sibling_before
222+
);
232223
});
233224
}
234225

@@ -284,13 +275,17 @@ mod tests {
284275
with_isolated_home(|_| {
285276
register();
286277
let run_id = seed_record("run-show-probe");
278+
let before = agent_task_lifecycle::exact_record(&run_id).expect("record before show");
287279

288280
let report = homeboy_core::activity::show_activity(&run_id).expect("show activity");
289281

290282
assert_eq!(report.items.len(), 1);
291283
assert_eq!(report.items[0].id, run_id);
292284
assert_eq!(report.items[0].source_store, "agent-task.lifecycle");
293-
assert!(!controller_admission_stamped(&run_id));
285+
assert_eq!(
286+
agent_task_lifecycle::exact_record(&run_id).expect("record after show"),
287+
before
288+
);
294289
});
295290
}
296291
}

crates/homeboy-agents/src/agent_task_lifecycle/tests/handoff_and_proxy.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ fn retry_rebuilds_follow_up_candidate_from_durable_promotion() {
506506
}
507507

508508
#[test]
509-
fn controller_proxy_is_queued_before_handoff_then_binds_runner_child() {
509+
fn controller_proxy_records_pending_handoff_then_binds_runner_child() {
510510
with_isolated_home(|_| {
511511
let command = vec![
512512
"homeboy".to_string(),
@@ -525,7 +525,10 @@ fn controller_proxy_is_queued_before_handoff_then_binds_runner_child() {
525525
assert_eq!(planned.state, AgentTaskRunState::Queued);
526526
assert!(planned.metadata.get("runner_job_id").is_none());
527527
assert_eq!(planned.metadata["lifecycle_store_owner"], "controller");
528-
assert!(planned.lab_handoff.is_none());
528+
let pending = planned.lab_handoff.as_ref().expect("pending handoff");
529+
assert_eq!(pending.state, AgentTaskLabHandoffState::Pending);
530+
assert_eq!(pending.runner_id, "homeboy-lab");
531+
assert!(pending.runner_job_id.is_none());
529532
assert!(planned.metadata.get("handoff_acceptance").is_none());
530533
assert!(load_plan("agent-task-controller-proxy")
531534
.expect("proxy plan")
@@ -999,7 +1002,10 @@ fn preacceptance_snapshot_binds_planned_runner_job_before_validation() {
9991002
Some(&plan),
10001003
)
10011004
.expect("persist planned controller execution");
1002-
assert!(record.lab_handoff.is_none());
1005+
let pending = record.lab_handoff.as_ref().expect("pending handoff");
1006+
assert_eq!(pending.state, AgentTaskLabHandoffState::Pending);
1007+
assert_eq!(pending.runner_id, "homeboy-lab");
1008+
assert!(pending.runner_job_id.is_none());
10031009
assert_eq!(record.metadata["runner_id"], "homeboy-lab");
10041010
let mut snapshot = terminal_child_snapshot(&succeeded_aggregate(&plan));
10051011
snapshot.job.status = homeboy_core::api_jobs::JobStatus::Running;

crates/homeboy-agents/src/agent_task_lifecycle/tests/status_and_recovery.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ fn controller_leaves_runner_artifact_projection_pending_when_it_cannot_mirror_by
13761376
aggregate.outcomes[0].artifacts = vec![
13771377
AgentTaskArtifact {
13781378
schema: crate::agent_task::AGENT_TASK_ARTIFACT_SCHEMA.to_string(),
1379-
id: "patch".to_string(),
1379+
id: "report".to_string(),
13801380
kind: "patch".to_string(),
13811381
name: None,
13821382
label: None,

0 commit comments

Comments
 (0)