From 8c11dd16f46f000891513d69ce7917e26391a26a Mon Sep 17 00:00:00 2001 From: bellman Date: Thu, 14 May 2026 17:48:02 +0900 Subject: [PATCH] task: preserve startup no-evidence timestamp evidence Lock the startup-no-evidence contract so prompt timestamps remain the original send time while lifecycle and pane timestamps prove timeout ordering. Constraint: task 4 scope limited changes to runtime worker boot/session/startup modules and tests; .omx/ultragoal not mutated. Rejected: CLI-surface changes | runtime evidence contract already exposes the typed worker.startup_no_evidence payload. Confidence: high Scope-risk: narrow Directive: Keep startup timeout evidence timestamps stable across later lifecycle observations. Tested: cargo test -p runtime worker_boot -- --nocapture; cargo check --workspace Not-tested: cargo clippy -p runtime --tests -- -D warnings is blocked by pre-existing runtime warnings in compact.rs, file_ops.rs, policy_engine.rs, and sandbox.rs. --- rust/crates/runtime/src/worker_boot.rs | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/rust/crates/runtime/src/worker_boot.rs b/rust/crates/runtime/src/worker_boot.rs index c56ae6cf..7bdb3c1d 100644 --- a/rust/crates/runtime/src/worker_boot.rs +++ b/rust/crates/runtime/src/worker_boot.rs @@ -1973,6 +1973,45 @@ mod tests { } } + #[test] + fn startup_timeout_preserves_original_prompt_sent_timestamp() { + let registry = WorkerRegistry::new(); + let worker = registry.create("/tmp/repo-prompt-timestamp", &[], true); + + registry + .observe(&worker.worker_id, "Ready for input\n>") + .expect("ready observe should succeed"); + let prompted = registry + .send_prompt( + &worker.worker_id, + Some("Run timestamp-sensitive work"), + None, + ) + .expect("prompt send should succeed"); + let sent_at = prompted + .prompt_sent_at + .expect("prompt send should record a prompt timestamp"); + + let timed_out = registry + .observe_startup_timeout(&worker.worker_id, "claw worker", true, true) + .expect("startup timeout observe should succeed"); + + let event = timed_out + .events + .iter() + .find(|e| e.kind == WorkerEventKind::StartupNoEvidence) + .expect("startup no evidence event should exist"); + + match event.payload.as_ref() { + Some(WorkerEventPayload::StartupNoEvidence { evidence, .. }) => { + assert_eq!(evidence.prompt_sent_at, Some(sent_at)); + assert!(evidence.last_lifecycle_at <= evidence.pane_observed_at); + assert!(evidence.command_started_at <= sent_at); + } + _ => panic!("expected StartupNoEvidence payload"), + } + } + #[test] fn startup_evidence_bundle_serializes_correctly() { let bundle = StartupEvidenceBundle {