From daed5db908ffe16eed2c6b0c84ae74c871fc3f8c Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Tue, 23 Jun 2026 18:19:49 +0200 Subject: [PATCH] =?UTF-8?q?test:=20rename=20'fake'=20test=20agent=20?= =?UTF-8?q?=E2=86=92=20'sample'=20(lighter,=20less=20loaded)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'fake' carries a broad/negative association. Rename the test-double agent and all its references to 'sample' (it emits a canned sample of pi-format JSONL): - scripts/fake-pi-agent.py → scripts/sample-pi-agent.py (git mv, mode kept) - pi_spawn_live.rs: sample-pi-agent.py, pane label 'sample-pi' - socket.rs: fn sample_agent_stdout_stream_updates_glasspane, labels, 'pi-sample' - live_socket_check.rs: sample_agent; colibri.rs: /tmp/sample-agent - glasspane/spawner doc comments: 'sample JSONL readers' - docs (ISO-SERVICE-LAYOUT, PRIORITY-HANDOFF, ISO-ACCEPTANCE-RUNBOOK) Pure rename; no behavior change. ./scripts/ci-checks.sh green. Stacks on #158. Co-Authored-By: Claude Opus 4.8 --- crates/colibri-client/src/bin/colibri.rs | 8 ++--- .../colibri-client/tests/live_socket_check.rs | 21 +++++++----- crates/colibri-daemon/src/socket.rs | 12 +++---- crates/colibri-daemon/src/spawner.rs | 2 +- crates/colibri-daemon/tests/pi_spawn_live.rs | 15 +++++---- crates/colibri-glasspane/src/lib.rs | 16 +++++----- docs/ISO-ACCEPTANCE-RUNBOOK.md | 2 +- docs/ISO-SERVICE-LAYOUT.md | 2 +- docs/PRIORITY-HANDOFF-ISO-SPAWN-COST.md | 32 +++++++++---------- .../{fake-pi-agent.py => sample-pi-agent.py} | 2 +- 10 files changed, 60 insertions(+), 52 deletions(-) rename scripts/{fake-pi-agent.py => sample-pi-agent.py} (90%) diff --git a/crates/colibri-client/src/bin/colibri.rs b/crates/colibri-client/src/bin/colibri.rs index 2936999..e5cf06e 100644 --- a/crates/colibri-client/src/bin/colibri.rs +++ b/crates/colibri-client/src/bin/colibri.rs @@ -700,7 +700,7 @@ mod tests { assert_eq!( parsed(&[ "spawn-local", - "/tmp/fake-agent", + "/tmp/sample-agent", "--session-id", "s1", "--system-prompt", @@ -710,7 +710,7 @@ mod tests { socket_path: default_socket_path(), command: Command::SpawnAgent { provider: "local".to_string(), - model: "/tmp/fake-agent".to_string(), + model: "/tmp/sample-agent".to_string(), session_id: Some("s1".to_string()), system_prompt: Some("hello".to_string()), jail: None, @@ -847,7 +847,7 @@ mod tests { assert_eq!( parsed(&[ "spawn-local", - "/tmp/fake-agent", + "/tmp/sample-agent", "--jail-name", "proof0", "--jail-root", @@ -857,7 +857,7 @@ mod tests { socket_path: default_socket_path(), command: Command::SpawnAgent { provider: "local".to_string(), - model: "/tmp/fake-agent".to_string(), + model: "/tmp/sample-agent".to_string(), session_id: None, system_prompt: None, jail: Some(colibri_client::JailConfig { diff --git a/crates/colibri-client/tests/live_socket_check.rs b/crates/colibri-client/tests/live_socket_check.rs index 0099d72..a1aec38 100644 --- a/crates/colibri-client/tests/live_socket_check.rs +++ b/crates/colibri-client/tests/live_socket_check.rs @@ -90,10 +90,10 @@ async fn wait_for_state(client: &DaemonClient, expected: AgentState) -> String { } #[tokio::test] -async fn daemon_client_live_socket_check_with_local_fake_agent() { +async fn daemon_client_live_socket_check_with_local_sample_agent() { let config = check_config(); tokio::fs::create_dir_all(&config.data_dir).await.unwrap(); - let fake_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); + let sample_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); let state: SharedState = Arc::new(DaemonState::new(config.clone())); let shutdown = state.shutdown_rx.resubscribe(); @@ -113,7 +113,12 @@ async fn daemon_client_live_socket_check_with_local_fake_agent() { assert!(empty_snapshot.panes.is_empty()); let spawn = client - .spawn_agent("local", fake_agent, Some("test-session".to_string()), None) + .spawn_agent( + "local", + sample_agent, + Some("test-session".to_string()), + None, + ) .await .unwrap(); let agent_id = spawn["agent_id"].as_str().unwrap().to_string(); @@ -202,12 +207,12 @@ async fn colibri_cli_task_commands_use_socket_api() { #[tokio::test] async fn poll_tasks_spawns_agent_for_claimed_task() { let mut config = check_config(); - let fake_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); + let sample_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); // Set COLIBRI_AGENT_BINARY so poll_tasks uses the test agent binary config.data_dir = std::env::temp_dir().join(format!("colibri-poll-tasks-test-{}", Uuid::new_v4())); tokio::fs::create_dir_all(&config.data_dir).await.unwrap(); - std::env::set_var("COLIBRI_AGENT_BINARY", fake_agent); + std::env::set_var("COLIBRI_AGENT_BINARY", sample_agent); let state: SharedState = Arc::new(DaemonState::new(config.clone())); let shutdown = state.shutdown_rx.resubscribe(); @@ -310,7 +315,7 @@ async fn poll_tasks_spawns_agent_for_claimed_task() { async fn harness_double_spawn_session_isolation() { let config = check_config(); tokio::fs::create_dir_all(&config.data_dir).await.unwrap(); - let fake_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); + let sample_agent = env!("CARGO_BIN_EXE_colibri-test-agent"); let state: SharedState = Arc::new(DaemonState::new(config.clone())); let shutdown = state.shutdown_rx.resubscribe(); @@ -326,7 +331,7 @@ async fn harness_double_spawn_session_isolation() { client .spawn_agent( "local", - fake_agent, + sample_agent, Some("harness-session-a".to_string()), None, ) @@ -335,7 +340,7 @@ async fn harness_double_spawn_session_isolation() { client .spawn_agent( "local", - fake_agent, + sample_agent, Some("harness-session-b".to_string()), None, ) diff --git a/crates/colibri-daemon/src/socket.rs b/crates/colibri-daemon/src/socket.rs index e38cb24..14b0e44 100644 --- a/crates/colibri-daemon/src/socket.rs +++ b/crates/colibri-daemon/src/socket.rs @@ -1088,7 +1088,7 @@ mod tests { let state: SharedState = Arc::new(DaemonState::new(test_config())); state.glasspane.write().await.attach_pane_at( "pane-a", - "fake-agent", + "sample-agent", SystemTime::UNIX_EPOCH, ); state.glasspane.write().await.ingest_line_at( @@ -1106,16 +1106,16 @@ mod tests { } #[tokio::test] - async fn fake_agent_stdout_stream_updates_glasspane() { + async fn sample_agent_stdout_stream_updates_glasspane() { let state: SharedState = Arc::new(DaemonState::new(test_config())); - let pane_id = "fake-agent-pane".to_string(); + let pane_id = "sample-agent-pane".to_string(); state.glasspane.write().await.attach_pane_at( pane_id.clone(), - "fake-agent", + "sample-agent", SystemTime::UNIX_EPOCH, ); - let script = r#"printf '%s\n' '{"type":"session","id":"pi-fake","cwd":"/tmp"}' '{"type":"turn_start"}' '{"type":"turn_end"}'"#; + let script = r#"printf '%s\n' '{"type":"session","id":"pi-sample","cwd":"/tmp"}' '{"type":"turn_start"}' '{"type":"turn_end"}'"#; let mut child = Command::new(PathBuf::from("/bin/sh")) .arg("-c") .arg(script) @@ -1139,7 +1139,7 @@ mod tests { .find(|pane| pane.id == pane_id) .unwrap(); assert_eq!(pane.state, colibri_glasspane::AgentState::Done); - assert_eq!(pane.session_id.as_deref(), Some("pi-fake")); + assert_eq!(pane.session_id.as_deref(), Some("pi-sample")); } #[tokio::test] diff --git a/crates/colibri-daemon/src/spawner.rs b/crates/colibri-daemon/src/spawner.rs index ca182af..60bbe33 100644 --- a/crates/colibri-daemon/src/spawner.rs +++ b/crates/colibri-daemon/src/spawner.rs @@ -9,7 +9,7 @@ //! 3. Anthropic (fallback) //! //! `Provider::Local` is intentionally excluded from fallback routing and API-key -//! checks. It exists for deterministic daemon/client startup checks with fake +//! checks. It exists for deterministic daemon/client startup checks with sample //! Pi-JSONL agents and for future local-only tools. use std::collections::HashMap; diff --git a/crates/colibri-daemon/tests/pi_spawn_live.rs b/crates/colibri-daemon/tests/pi_spawn_live.rs index 21fde46..ecab6c4 100644 --- a/crates/colibri-daemon/tests/pi_spawn_live.rs +++ b/crates/colibri-daemon/tests/pi_spawn_live.rs @@ -1,7 +1,7 @@ //! Pi spawn path proof — integration test. //! //! Validates: Colibri spawns agent → reads JSONL stdout → glasspane ingests → snapshot correct. -//! Uses scripts/fake-pi-agent.py which emits the colibri-pi-events JSONL taxonomy. +//! Uses scripts/sample-pi-agent.py which emits the colibri-pi-events JSONL taxonomy. //! //! With real Pi binary (when installed): //! COLIBRI_AGENT_BINARY=pi cargo test -p colibri-daemon --test pi_spawn_live -- --nocapture @@ -22,20 +22,23 @@ async fn pi_spawn_path_produces_correct_glasspane_state() { .parent() .unwrap() .join("scripts") - .join("fake-pi-agent.py"); + .join("sample-pi-agent.py"); - assert!(script.exists(), "fake-pi-agent.py not found at {script:?}"); + assert!( + script.exists(), + "sample-pi-agent.py not found at {script:?}" + ); let mut supervisor = colibri_glasspane::PaneSupervisor::new(); let pane_id = "pi-spawn-proof"; - supervisor.attach_pane_at(pane_id, "fake-pi", SystemTime::now()); + supervisor.attach_pane_at(pane_id, "sample-pi", SystemTime::now()); let mut child = Command::new(PathBuf::from("python3")) .arg(&script) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() - .expect("failed to spawn fake-pi-agent.py"); + .expect("failed to spawn sample-pi-agent.py"); let stdout = child.stdout.take().expect("no stdout"); let mut reader = BufReader::new(stdout).lines(); @@ -60,7 +63,7 @@ async fn pi_spawn_path_produces_correct_glasspane_state() { } let status = child.wait().await.expect("child wait failed"); - assert!(status.success(), "fake-pi-agent.py exited with {status}"); + assert!(status.success(), "sample-pi-agent.py exited with {status}"); assert!( accepted >= 5, "expected >=5 accepted JSONL lines, got {accepted}" diff --git a/crates/colibri-glasspane/src/lib.rs b/crates/colibri-glasspane/src/lib.rs index 2b4a687..59670e3 100644 --- a/crates/colibri-glasspane/src/lib.rs +++ b/crates/colibri-glasspane/src/lib.rs @@ -9,7 +9,7 @@ //! Phase 3 starts the supervision layer: Colibri-owned pane ids are distinct //! from Pi session ids, ingestion is streaming, `last_event_at` is kept as real //! time internally, and `stalled` is derived from event silence. Live PTY launch -//! is scaffolded with `portable-pty`; tests use fake JSONL readers until the +//! is scaffolded with `portable-pty`; tests use sample JSONL readers until the //! FreeBSD validation lane exercises real terminals. use std::{ @@ -240,7 +240,7 @@ pub struct PaneReaderStats { /// Stateful streaming ingestor for Pi `--mode json` JSONL. /// /// This is intentionally independent from PTY/process ownership: tests can feed -/// fake readers, while live panes can wire PTY stdout to the same API later. +/// sample readers, while live panes can wire PTY stdout to the same API later. #[derive(Debug, Clone, PartialEq, Eq)] pub struct PiJsonlIngestor { state: AgentState, @@ -465,7 +465,7 @@ impl PaneSupervisor { self.get_mut(pane_id)?.ingest_line_at(line, observed_at) } - /// Test-first Phase-3 path: feed a fake/recorded JSONL reader through the + /// Test-first Phase-3 path: feed a sample/recorded JSONL reader through the /// same streaming API that a PTY stdout reader will use. pub fn ingest_jsonl_reader_at( &mut self, @@ -505,7 +505,7 @@ impl PaneSupervisor { /// Drain a JSONL reader into an already-attached pane using wall-clock time. /// -/// This is the Phase-3.1 bridge between fake JSONL readers and real PTY stdout: +/// This is the Phase-3.1 bridge between sample JSONL readers and real PTY stdout: /// both paths feed the same streaming ingestor and update the same supervisor. pub fn run_pane_reader( supervisor: &mut PaneSupervisor, @@ -550,7 +550,7 @@ where } /// Minimal portable-pty launch spec. Live FreeBSD validation is intentionally -/// later; this keeps the process/PTY seam explicit while tests use fake readers. +/// later; this keeps the process/PTY seam explicit while tests use sample readers. #[derive(Debug, Clone, PartialEq, Eq)] pub struct PtyLaunchSpec { pub program: String, @@ -578,7 +578,7 @@ pub struct PtyPane { } /// Spawn a command under a native PTY. The caller owns wiring `reader` into -/// [`PiJsonlIngestor`] / [`PaneSupervisor`]. Not exercised by CI yet; fake JSONL +/// [`PiJsonlIngestor`] / [`PaneSupervisor`]. Not exercised by CI yet; sample JSONL /// readers cover the supervision state model first. pub fn spawn_pty_command( spec: &PtyLaunchSpec, @@ -606,7 +606,7 @@ pub fn spawn_pty_command( /// Drain the reader side of a live PTY-backed pane into the supervisor. /// /// The caller owns spawning/waiting/killing the child; this function only folds -/// stdout JSONL into Glasspane state. CI still covers this through fake readers. +/// stdout JSONL into Glasspane state. CI still covers this through sample readers. pub fn run_pty_pane_reader( supervisor: &mut PaneSupervisor, pane_id: &str, @@ -851,7 +851,7 @@ mod tests { } #[test] - fn supervisor_fake_jsonl_reader_uses_streaming_api() { + fn supervisor_sample_jsonl_reader_uses_streaming_api() { let jsonl = [ r#"{"type":"session","id":"pi-s","cwd":"/repo"}"#, "not json", diff --git a/docs/ISO-ACCEPTANCE-RUNBOOK.md b/docs/ISO-ACCEPTANCE-RUNBOOK.md index 1b4546a..b3e018c 100644 --- a/docs/ISO-ACCEPTANCE-RUNBOOK.md +++ b/docs/ISO-ACCEPTANCE-RUNBOOK.md @@ -99,7 +99,7 @@ colibri snapshot Expected: valid JSON snapshot. It may have no panes before an agent is spawned. -Optional local fake-agent check if `colibri-test-agent` is included: +Optional local sample-agent check if `colibri-test-agent` is included: ```sh colibri spawn-local /usr/local/bin/colibri-test-agent --session-id iso-check diff --git a/docs/ISO-SERVICE-LAYOUT.md b/docs/ISO-SERVICE-LAYOUT.md index a6b2e62..e0340ce 100644 --- a/docs/ISO-SERVICE-LAYOUT.md +++ b/docs/ISO-SERVICE-LAYOUT.md @@ -15,7 +15,7 @@ ``` /usr/local/bin/colibri-daemon ← daemon binary (foreground, no self-daemonize) /usr/local/bin/colibri ← CLI client (status, create-task, etc.) -/usr/local/bin/colibri-test-agent ← test agent (fake Pi JSONL) +/usr/local/bin/colibri-test-agent ← test agent (sample Pi JSONL) /usr/local/etc/rc.d/colibri_daemon ← rc.d service script /usr/local/etc/colibri/ rc.conf.sample ← service config template diff --git a/docs/PRIORITY-HANDOFF-ISO-SPAWN-COST.md b/docs/PRIORITY-HANDOFF-ISO-SPAWN-COST.md index 3edb3d2..a5d71c3 100644 --- a/docs/PRIORITY-HANDOFF-ISO-SPAWN-COST.md +++ b/docs/PRIORITY-HANDOFF-ISO-SPAWN-COST.md @@ -129,14 +129,14 @@ to state transitions before it can be validated. ### What exists -| Capability | Location | Status | -| ------------------- | ------------------------------------------ | ---------------------------------------------------------- | -| `Spawner::spawn()` | `crates/colibri-daemon/src/spawner.rs:585` | done — provider routing, jail wrap, retry/backoff | -| `AgentHandle` | `crates/colibri-daemon/src/spawner.rs:465` | done — tracks child, stdout for glasspane, kill, poll_exit | -| `take_stdout()` | `crates/colibri-daemon/src/spawner.rs:500` | done — hands stdout to glasspane supervision | -| Jail confinement | `crates/colibri-daemon/src/spawner.rs:332` | done — named/ephemeral, staged env payload, priv modes | -| `fake-pi-agent.py` | `scripts/fake-pi-agent.py` | exists — emits JSONL events for testing | -| Glasspane ingestion | `crates/colibri-glasspane/` | done — ingests JSONL, tracks pane state | +| Capability | Location | Status | +| -------------------- | ------------------------------------------ | ---------------------------------------------------------- | +| `Spawner::spawn()` | `crates/colibri-daemon/src/spawner.rs:585` | done — provider routing, jail wrap, retry/backoff | +| `AgentHandle` | `crates/colibri-daemon/src/spawner.rs:465` | done — tracks child, stdout for glasspane, kill, poll_exit | +| `take_stdout()` | `crates/colibri-daemon/src/spawner.rs:500` | done — hands stdout to glasspane supervision | +| Jail confinement | `crates/colibri-daemon/src/spawner.rs:332` | done — named/ephemeral, staged env payload, priv modes | +| `sample-pi-agent.py` | `scripts/sample-pi-agent.py` | exists — emits JSONL events for testing | +| Glasspane ingestion | `crates/colibri-glasspane/` | done — ingests JSONL, tracks pane state | ### What's missing @@ -150,7 +150,7 @@ to state transitions before it can be validated. - Hand stdout to glasspane 2. **End-to-end integration test.** - Using `scripts/fake-pi-agent.py` (or a Rust mock binary): + Using `scripts/sample-pi-agent.py` (or a Rust mock binary): - Start daemon - Create a task + intake it - Wait for scheduler tick + spawn @@ -178,13 +178,13 @@ to state transitions before it can be validated. - `crates/colibri-daemon/src/daemon.rs:242` — `session_rotation()` (working, good reference for how other background loops iterate state) - `crates/colibri-daemon/src/spawner.rs:585` — `Spawner::spawn()` (working) - `crates/colibri-daemon/src/socket.rs` — socket command dispatch (check for spawn commands) -- `scripts/fake-pi-agent.py` — test agent that emits JSONL +- `scripts/sample-pi-agent.py` — test agent that emits JSONL - `crates/colibri-glasspane/src/` — JSONL ingestion + pane state machine ### Suggested owner Rust lane (Hermes on Linux). Can implement and test fully on Linux with -`fake-pi-agent.py`. FreeBSD validation confirms jail path works. +`sample-pi-agent.py`. FreeBSD validation confirms jail path works. --- @@ -303,11 +303,11 @@ wiring, no platform-specific behavior. ## Summary table -| # | Item | Blocks | Linux-doable | Effort | -| --- | --------------------------- | ------------------- | --------------------------- | ------ | -| 1 | ISO boot/runtime validation | Gate 1 | no (needs FreeBSD boot) | small | -| 2 | Pi spawn end-to-end | Gate 2 | yes (with fake-pi-agent.py) | medium | -| 3 | Cost mode enforcement | core design promise | yes (pure logic) | medium | +| # | Item | Blocks | Linux-doable | Effort | +| --- | --------------------------- | ------------------- | ----------------------------- | ------ | +| 1 | ISO boot/runtime validation | Gate 1 | no (needs FreeBSD boot) | small | +| 2 | Pi spawn end-to-end | Gate 2 | yes (with sample-pi-agent.py) | medium | +| 3 | Cost mode enforcement | core design promise | yes (pure logic) | medium | All three are medium effort and can be worked in parallel. None require FreeBSD to implement — only to validate the final result. diff --git a/scripts/fake-pi-agent.py b/scripts/sample-pi-agent.py similarity index 90% rename from scripts/fake-pi-agent.py rename to scripts/sample-pi-agent.py index 9c88154..cb8f20b 100755 --- a/scripts/fake-pi-agent.py +++ b/scripts/sample-pi-agent.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Fake Pi agent — emits JSONL in the colibri-pi-events format. +"""Sample Pi agent — emits JSONL in the colibri-pi-events format. Used by Colibri integration tests to validate the spawn → JSONL → glasspane path. """ import sys -- 2.45.3