Skip to content

Commit af0b0da

Browse files
schicklingclaude
andcommitted
fix(agents): probe exactly the runner's pty root and expose the ask kind
PTY_SESSION_DIR pointed the probe at a directory st2-managed sessions never use (provable deaths read indeterminate); the probe now shares run::effective_pty_root verbatim. observedState gains the machine-readable ask axis, pinned literals updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 738778b commit af0b0da

2 files changed

Lines changed: 17 additions & 14 deletions

File tree

src/agents.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,11 @@ fn observed_state(
9999
}
100100
}
101101

102-
/// The pty registry root the probe reads. Operator shells rarely export PTY_ROOT, while
103-
/// supervised tasks run under the catalog's own pty root — so the reader derives the runner's
104-
/// default from the catalog, with the ambient overrides still winning.
102+
/// The pty registry root the probe reads: exactly the runner's own resolution, so the reader and
103+
/// the sessions it probes can never disagree. The runner honors `PTY_ROOT` and nothing else — a
104+
/// legacy `PTY_SESSION_DIR` here would point the probe at a directory st2-managed sessions never
105+
/// use, turning provable deaths into indeterminate reads.
105106
pub fn probe_pty_root(catalog_root: &Path) -> PathBuf {
106-
for var in ["PTY_ROOT", "PTY_SESSION_DIR"] {
107-
if let Some(dir) = std::env::var_os(var)
108-
&& !dir.is_empty()
109-
{
110-
return PathBuf::from(dir);
111-
}
112-
}
113107
crate::run::effective_pty_root(catalog_root)
114108
}
115109

@@ -121,6 +115,7 @@ struct ObservedJson<'a> {
121115
state: &'a str,
122116
blocked_on: &'a str,
123117
input_buffer: &'a str,
118+
ask: &'a str,
124119
harness: Option<&'a str>,
125120
since: Option<u64>,
126121
exit: Option<&'a str>,
@@ -133,6 +128,7 @@ impl<'a> ObservedJson<'a> {
133128
state: observed.state.as_str(),
134129
blocked_on: observed.blocked_on.as_str(),
135130
input_buffer: observed.input_buffer.as_str(),
131+
ask: observed.ask.as_str(),
136132
harness: observed.harness.as_deref(),
137133
since: observed.since_ms,
138134
exit: observed.exit.as_deref(),
@@ -341,6 +337,7 @@ mod tests {
341337
state: harness_state::Activity::Idle,
342338
blocked_on: harness_state::BlockedOn::None,
343339
input_buffer: harness_state::InputBuffer::Empty,
340+
ask: harness_state::Ask::None,
344341
harness: Some("codex".to_string()),
345342
since_ms: Some(1784653000000),
346343
exit: None,
@@ -349,26 +346,27 @@ mod tests {
349346

350347
assert_eq!(
351348
to_json(&[wedged.clone()], false),
352-
r#"[{"identity":"hetz.worker","status":"busy","name":null,"description":null,"retired":false,"resources":[],"desiredState":"running","desiredStateReason":null,"observedState":{"state":"idle","blockedOn":"none","inputBuffer":"empty","harness":"codex","since":1784653000000,"exit":null,"reason":null}}]"#
349+
r#"[{"identity":"hetz.worker","status":"busy","name":null,"description":null,"retired":false,"resources":[],"desiredState":"running","desiredStateReason":null,"observedState":{"state":"idle","blockedOn":"none","inputBuffer":"empty","ask":"none","harness":"codex","since":1784653000000,"exit":null,"reason":null}}]"#
353350
);
354351
assert_eq!(
355352
to_json(&[wedged], true),
356-
r#"[{"identity":"hetz.worker","status":"busy","name":null,"description":null,"retired":false,"resources":[],"lastActivity":1784653027733.6138,"inbox":0,"desiredState":"running","desiredStateReason":null,"observedState":{"state":"idle","blockedOn":"none","inputBuffer":"empty","harness":"codex","since":1784653000000,"exit":null,"reason":null}}]"#
353+
r#"[{"identity":"hetz.worker","status":"busy","name":null,"description":null,"retired":false,"resources":[],"lastActivity":1784653027733.6138,"inbox":0,"desiredState":"running","desiredStateReason":null,"observedState":{"state":"idle","blockedOn":"none","inputBuffer":"empty","ask":"none","harness":"codex","since":1784653000000,"exit":null,"reason":null}}]"#
357354
);
358355

359356
let mut derived = row("hetz.worker", State::Available, None, false, None, 0);
360357
derived.observed = Some(harness_state::Observed {
361358
state: harness_state::Activity::Unknown,
362359
blocked_on: harness_state::BlockedOn::Unknown,
363360
input_buffer: harness_state::InputBuffer::Unknown,
361+
ask: harness_state::Ask::Unknown,
364362
harness: Some("codex".to_string()),
365363
since_ms: None,
366364
exit: None,
367365
reason: Some("session-dead".to_string()),
368366
});
369367
assert_eq!(
370368
to_json(&[derived], false),
371-
r#"[{"identity":"hetz.worker","status":"available","name":null,"description":null,"retired":false,"resources":[],"desiredState":"running","desiredStateReason":null,"observedState":{"state":"unknown","blockedOn":"unknown","inputBuffer":"unknown","harness":"codex","since":null,"exit":null,"reason":"session-dead"}}]"#
369+
r#"[{"identity":"hetz.worker","status":"available","name":null,"description":null,"retired":false,"resources":[],"desiredState":"running","desiredStateReason":null,"observedState":{"state":"unknown","blockedOn":"unknown","inputBuffer":"unknown","ask":"unknown","harness":"codex","since":null,"exit":null,"reason":"session-dead"}}]"#
372370
);
373371
}
374372
}

tests/doctor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,12 @@ fn observed_harness_state_arms_are_advisory_except_a_fresh_live_record() {
475475
);
476476

477477
// A fresh live record is a passing check.
478-
let mut writer = Writer::new(&agent_dir, "h.worker", "codex", None);
478+
let mut writer = Writer::new(
479+
&agent_dir,
480+
"h.worker",
481+
"codex",
482+
Some("h.worker".to_string()),
483+
);
479484
writer
480485
.observe(Observation::new(
481486
Activity::Active,

0 commit comments

Comments
 (0)