feat(rc): rename test agent and load provider env (Sam & Codex)
Rename the local deterministic launch helper from colibri-smoke-agent to colibri-test-agent, update CLI/TUI/tests/docs, and teach the FreeBSD rc.d service to source /usr/local/etc/colibri/provider.env plus set a service PATH for local spawns.\n\nChecks: cargo fmt --check; ./scripts/check-format.sh; git diff --check; cargo check -p colibri-daemon -p colibri-client -p colibri-glasspane-tui; cargo check -p colibri-client --bins; cargo test -p colibri-client --test live_socket_check -- --nocapture.
This commit is contained in:
parent
c967698ea2
commit
9891d06144
22 changed files with 97 additions and 85 deletions
|
|
@ -52,7 +52,7 @@ colibri-daemon (always-on Unix socket server)
|
|||
├── session — append-only JSONL sessions, 3-region prompt assembly
|
||||
└── spawner — agent subprocess management (retry/backoff, FreeBSD jail confinement)
|
||||
|
||||
colibri-client — CLI tools (colibri, colibri_smoke_agent)
|
||||
colibri-client — CLI tools (colibri, colibri-test-agent)
|
||||
colibri-glasspane-tui— ratatui dashboard
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ name = "colibri"
|
|||
path = "src/bin/colibri.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "colibri-smoke-agent"
|
||||
path = "src/bin/colibri_smoke_agent.rs"
|
||||
name = "colibri-test-agent"
|
||||
path = "src/bin/colibri_test_agent.rs"
|
||||
|
||||
[dependencies]
|
||||
colibri-daemon = { path = "../colibri-daemon" }
|
||||
|
|
|
|||
|
|
@ -74,12 +74,12 @@ Socket defaults to COLIBRI_DAEMON_SOCKET, then the daemon's configured default.
|
|||
|
||||
Examples:
|
||||
colibri status
|
||||
colibri --socket /tmp/colibri-smoke/colibri.sock snapshot
|
||||
colibri spawn-local target/release/colibri-smoke-agent
|
||||
colibri create-task --title "verify OSA smoke" --description "manual follow-up"
|
||||
colibri --socket /tmp/colibri-test/colibri.sock snapshot
|
||||
colibri spawn-local target/release/colibri-test-agent
|
||||
colibri create-task --title "verify OSA check" --description "manual follow-up"
|
||||
colibri intake-task --title "triage watchdog" --capability freebsd
|
||||
colibri list-tasks --status queued
|
||||
colibri register-skill freebsd-smoke --description "Live USB smoke test" --category freebsd
|
||||
colibri register-skill freebsd-check --description "Live USB startup check" --category freebsd
|
||||
colibri list-skills
|
||||
"#
|
||||
}
|
||||
|
|
@ -483,14 +483,14 @@ mod tests {
|
|||
parsed(&[
|
||||
"create-task",
|
||||
"--title",
|
||||
"check smoke",
|
||||
"check agent",
|
||||
"--description",
|
||||
"from cli",
|
||||
]),
|
||||
Options {
|
||||
socket_path: default_socket_path(),
|
||||
command: Command::CreateTask {
|
||||
title: "check smoke".to_string(),
|
||||
title: "check agent".to_string(),
|
||||
description: Some("from cli".to_string()),
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use std::{
|
|||
|
||||
fn usage() -> &'static str {
|
||||
r#"Usage:
|
||||
colibri-smoke-agent [--session-id ID] [--cwd PATH] [--step-ms MS] [--hold-secs SECONDS]
|
||||
colibri-test-agent [--session-id ID] [--cwd PATH] [--step-ms MS] [--hold-secs SECONDS]
|
||||
|
||||
Emits deterministic Pi-compatible JSONL for local colibri-daemon smoke tests.
|
||||
Emits deterministic Pi-compatible JSONL for local colibri-daemon startup checks.
|
||||
"#
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ struct Options {
|
|||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
session_id: "manual-smoke".to_string(),
|
||||
session_id: "manual-test".to_string(),
|
||||
cwd: env::current_dir()
|
||||
.ok()
|
||||
.and_then(|path| path.into_os_string().into_string().ok())
|
||||
|
|
@ -135,7 +135,7 @@ fn main() -> ExitCode {
|
|||
Ok(options) => match emit_jsonl(&options) {
|
||||
Ok(()) => ExitCode::SUCCESS,
|
||||
Err(e) => {
|
||||
eprintln!("colibri-smoke-agent: {e}");
|
||||
eprintln!("colibri-test-agent: {e}");
|
||||
ExitCode::FAILURE
|
||||
}
|
||||
},
|
||||
|
|
@ -10,8 +10,8 @@ use colibri_daemon::{socket, DaemonConfig, DaemonState, SharedState};
|
|||
use colibri_glasspane::AgentState;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn smoke_config() -> DaemonConfig {
|
||||
let data_dir = std::env::temp_dir().join(format!("colibri-live-smoke-{}", Uuid::new_v4()));
|
||||
fn check_config() -> DaemonConfig {
|
||||
let data_dir = std::env::temp_dir().join(format!("colibri-live-test-{}", Uuid::new_v4()));
|
||||
DaemonConfig {
|
||||
socket_path: data_dir.join("colibri.sock"),
|
||||
data_dir: data_dir.clone(),
|
||||
|
|
@ -23,7 +23,7 @@ fn smoke_config() -> DaemonConfig {
|
|||
openrouter_endpoint: "https://openrouter.ai/api/v1/chat/completions".to_string(),
|
||||
anthropic_api_key: None,
|
||||
anthropic_endpoint: "https://api.anthropic.com/v1/messages".to_string(),
|
||||
host: "live-smoke-host".to_string(),
|
||||
host: "live-test-host".to_string(),
|
||||
max_context_tokens: 128_000,
|
||||
cost_mode: "smart".to_string(),
|
||||
scheduler_prompt_injection: false,
|
||||
|
|
@ -90,10 +90,10 @@ async fn wait_for_state(client: &DaemonClient, expected: AgentState) -> String {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn daemon_client_live_socket_smoke_with_local_fake_agent() {
|
||||
let config = smoke_config();
|
||||
async fn daemon_client_live_socket_check_with_local_fake_agent() {
|
||||
let config = check_config();
|
||||
tokio::fs::create_dir_all(&config.data_dir).await.unwrap();
|
||||
let fake_agent = env!("CARGO_BIN_EXE_colibri-smoke-agent");
|
||||
let fake_agent = env!("CARGO_BIN_EXE_colibri-test-agent");
|
||||
|
||||
let state: SharedState = Arc::new(DaemonState::new(config.clone()));
|
||||
let shutdown = state.shutdown_rx.resubscribe();
|
||||
|
|
@ -107,13 +107,13 @@ async fn daemon_client_live_socket_smoke_with_local_fake_agent() {
|
|||
|
||||
let status = client.status().await.unwrap();
|
||||
assert_eq!(status["daemon"], "colibri-daemon");
|
||||
assert_eq!(status["host"], "live-smoke-host");
|
||||
assert_eq!(status["host"], "live-test-host");
|
||||
|
||||
let empty_snapshot = client.glasspane_snapshot().await.unwrap();
|
||||
assert!(empty_snapshot.panes.is_empty());
|
||||
|
||||
let spawn = client
|
||||
.spawn_agent("local", fake_agent, Some("smoke-session".to_string()), None)
|
||||
.spawn_agent("local", fake_agent, Some("test-session".to_string()), None)
|
||||
.await
|
||||
.unwrap();
|
||||
let agent_id = spawn["agent_id"].as_str().unwrap().to_string();
|
||||
|
|
@ -130,7 +130,7 @@ async fn daemon_client_live_socket_smoke_with_local_fake_agent() {
|
|||
.iter()
|
||||
.find(|pane| pane.id == agent_id)
|
||||
.unwrap();
|
||||
assert_eq!(pane.pi_session_id.as_deref(), Some("manual-smoke"));
|
||||
assert_eq!(pane.pi_session_id.as_deref(), Some("manual-test"));
|
||||
assert!(pane.cwd.is_some());
|
||||
|
||||
let kill = client.kill_agent(agent_id).await.unwrap();
|
||||
|
|
@ -143,7 +143,7 @@ async fn daemon_client_live_socket_smoke_with_local_fake_agent() {
|
|||
|
||||
#[tokio::test]
|
||||
async fn colibri_cli_task_commands_use_socket_api() {
|
||||
let config = smoke_config();
|
||||
let config = check_config();
|
||||
tokio::fs::create_dir_all(&config.data_dir).await.unwrap();
|
||||
|
||||
let state: SharedState = Arc::new(DaemonState::new(config.clone()));
|
||||
|
|
@ -201,9 +201,9 @@ async fn colibri_cli_task_commands_use_socket_api() {
|
|||
|
||||
#[tokio::test]
|
||||
async fn poll_tasks_spawns_agent_for_claimed_task() {
|
||||
let mut config = smoke_config();
|
||||
let fake_agent = env!("CARGO_BIN_EXE_colibri-smoke-agent");
|
||||
// Set COLIBRI_AGENT_BINARY so poll_tasks uses the smoke agent binary
|
||||
let mut config = check_config();
|
||||
let fake_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();
|
||||
|
|
@ -230,7 +230,7 @@ async fn poll_tasks_spawns_agent_for_claimed_task() {
|
|||
// Create and claim a task directly in the store
|
||||
let task = {
|
||||
let store = state.store.lock().unwrap();
|
||||
let task = store.create_task("poll-tasks-smoke", None).unwrap();
|
||||
let task = store.create_task("poll-tasks-check", None).unwrap();
|
||||
let agent = store.list_agents().unwrap();
|
||||
let agent_id = &agent[0].id;
|
||||
store.claim_task(&task.id, agent_id).unwrap();
|
||||
|
|
@ -245,7 +245,7 @@ async fn poll_tasks_spawns_agent_for_claimed_task() {
|
|||
"task should be claimed before poll_tasks"
|
||||
);
|
||||
|
||||
// Call poll_tasks — should spawn the smoke agent for this claimed task
|
||||
// Call poll_tasks — should spawn the test agent for this claimed task
|
||||
poll_tasks(&state).await;
|
||||
|
||||
// Verify an agent handle was created
|
||||
|
|
@ -278,7 +278,7 @@ async fn poll_tasks_spawns_agent_for_claimed_task() {
|
|||
"session should be created for task"
|
||||
);
|
||||
|
||||
// Glasspane should observe the full lifecycle: the smoke agent runs
|
||||
// Glasspane should observe the full lifecycle: the test agent runs
|
||||
// through Idle → Working → Blocked → Working → Done quickly (10ms steps).
|
||||
// Wait for Done — the terminal state — which proves the whole path worked:
|
||||
// poll_tasks spawned the agent, stdout streamed to glasspane, and the
|
||||
|
|
@ -292,7 +292,10 @@ async fn poll_tasks_spawns_agent_for_claimed_task() {
|
|||
assert!(
|
||||
Instant::now() < deadline,
|
||||
"agent did not reach Done — snapshot: {:?}",
|
||||
snap.panes.iter().map(|p| (p.id.clone(), p.state)).collect::<Vec<_>>()
|
||||
snap.panes
|
||||
.iter()
|
||||
.map(|p| (p.id.clone(), p.state))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
|
@ -305,9 +308,9 @@ async fn poll_tasks_spawns_agent_for_claimed_task() {
|
|||
|
||||
#[tokio::test]
|
||||
async fn harness_double_spawn_session_isolation() {
|
||||
let config = smoke_config();
|
||||
let config = check_config();
|
||||
tokio::fs::create_dir_all(&config.data_dir).await.unwrap();
|
||||
let fake_agent = env!("CARGO_BIN_EXE_colibri-smoke-agent");
|
||||
let fake_agent = env!("CARGO_BIN_EXE_colibri-test-agent");
|
||||
|
||||
let state: SharedState = Arc::new(DaemonState::new(config.clone()));
|
||||
let shutdown = state.shutdown_rx.resubscribe();
|
||||
|
|
@ -359,14 +362,14 @@ async fn harness_double_spawn_session_isolation() {
|
|||
let snap = client.glasspane_snapshot().await.unwrap();
|
||||
assert_eq!(snap.panes.len(), 2);
|
||||
|
||||
// Both smoke agents default to "manual-smoke" unless --session-id is passed
|
||||
// Both test agents default to "manual-test" unless --session-id is passed
|
||||
let pane_a = &snap.panes[0];
|
||||
let pane_b = &snap.panes[1];
|
||||
assert_eq!(pane_a.state, AgentState::Done);
|
||||
assert_eq!(pane_b.state, AgentState::Done);
|
||||
assert_ne!(pane_a.id, pane_b.id);
|
||||
|
||||
// Verify session isolation: both share the same session_id (smoke agent default)
|
||||
// Verify session isolation: both share the same session_id (test agent default)
|
||||
assert_eq!(pane_a.pi_session_id, pane_b.pi_session_id);
|
||||
|
||||
// Kill one agent — snapshot may still include stopped panes briefly
|
||||
|
|
@ -337,7 +337,7 @@ pub async fn poll_tasks(state: &SharedState) {
|
|||
}
|
||||
|
||||
let binary = std::env::var("COLIBRI_AGENT_BINARY")
|
||||
.unwrap_or_else(|_| "colibri-smoke-agent".to_string());
|
||||
.unwrap_or_else(|_| "colibri-test-agent".to_string());
|
||||
|
||||
let agent_config = crate::spawner::AgentSpawnConfig {
|
||||
binary: binary.clone(),
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ mod tests {
|
|||
let state: SharedState = Arc::new(crate::daemon::DaemonState::new(config));
|
||||
let mut scheduler = Scheduler::new();
|
||||
scheduler.submit(TaskRequest {
|
||||
title: "intake smoke".to_string(),
|
||||
title: "intake check".to_string(),
|
||||
description: Some("must become a task".to_string()),
|
||||
required_capabilities: Vec::new(),
|
||||
});
|
||||
|
|
@ -547,7 +547,7 @@ mod tests {
|
|||
|
||||
let tasks = state.store.lock().unwrap().list_tasks(None).unwrap();
|
||||
assert_eq!(tasks.len(), 1);
|
||||
assert_eq!(tasks[0].title, "intake smoke");
|
||||
assert_eq!(tasks[0].title, "intake check");
|
||||
|
||||
let _ = std::fs::remove_dir_all(data_dir);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 smoke tests with fake
|
||||
//! checks. It exists for deterministic daemon/client startup checks with fake
|
||||
//! Pi-JSONL agents and for future local-only tools.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Regression test for the bug a 2026-05-27 osa FreeBSD smoke caught:
|
||||
//! Regression test for the bug a 2026-05-27 osa FreeBSD check caught:
|
||||
//! `main.rs` started the socket server but never spawned `daemon::run_loop`, so
|
||||
//! an `intake-task` reported `queued` over the socket yet was never drained into
|
||||
//! the SQLite coordination store.
|
||||
|
|
@ -20,7 +20,7 @@ use tokio::net::UnixStream;
|
|||
async fn intake_task_over_socket_drains_to_sqlite_via_run_loop() {
|
||||
// Isolated temp paths — never touch production /var/db or /var/run.
|
||||
let data_dir =
|
||||
std::env::temp_dir().join(format!("colibri-intake-smoke-{}", uuid::Uuid::new_v4()));
|
||||
std::env::temp_dir().join(format!("colibri-intake-check-{}", uuid::Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&data_dir).expect("create temp data dir");
|
||||
|
||||
let mut config = DaemonConfig::from_env();
|
||||
|
|
@ -52,7 +52,7 @@ async fn intake_task_over_socket_drains_to_sqlite_via_run_loop() {
|
|||
wait_for_socket(&socket_path).await;
|
||||
|
||||
// Submit an intake task over the socket; it should be accepted + queued.
|
||||
const TITLE: &str = "intake-smoke-task";
|
||||
const TITLE: &str = "intake-check-task";
|
||||
let response = send_command(
|
||||
&socket_path,
|
||||
&format!(
|
||||
|
|
|
|||
|
|
@ -172,10 +172,10 @@ impl App {
|
|||
async fn spawn_agent(&mut self) {
|
||||
let result = self
|
||||
.client
|
||||
.spawn_agent("local", "colibri-smoke-agent", None, None)
|
||||
.spawn_agent("local", "colibri-test-agent", None, None)
|
||||
.await;
|
||||
match result {
|
||||
Ok(_) => self.set_status("spawned colibri-smoke-agent"),
|
||||
Ok(_) => self.set_status("spawned colibri-test-agent"),
|
||||
Err(e) => self.set_status(format!("spawn failed: {e}")),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ JSON-RPC process — trivial to implement in Rust.
|
|||
- Create intake tasks from current file/docs context
|
||||
- Query queued tasks and blocked panes
|
||||
- Summarize active sessions
|
||||
- Trigger smoke tests or scheduler runs
|
||||
- Trigger startup checks or scheduler runs
|
||||
- Ask "what's the system doing right now?" and get a real answer
|
||||
|
||||
**Why highest leverage:**
|
||||
|
|
@ -160,7 +160,7 @@ Agent spawn/kill tools are stronger than normal writes and should require a sepa
|
|||
|
||||
```sh
|
||||
COLIBRI_MCP_SPAWN=1
|
||||
COLIBRI_MCP_SPAWN_ALLOWLIST=/usr/local/bin/pi,/usr/local/bin/colibri-smoke-agent
|
||||
COLIBRI_MCP_SPAWN_ALLOWLIST=/usr/local/bin/pi,/usr/local/bin/colibri-test-agent
|
||||
```
|
||||
|
||||
Phase 2 MCP tools (after basics proven):
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ colibri-mcp --external-call
|
|||
This is intentionally separate from `COLIBRI_MCP_WRITE=1`. A Colibri write tool
|
||||
and an external MCP tool are different trust surfaces.
|
||||
|
||||
## Quick smoke shape
|
||||
## Quick check shape
|
||||
|
||||
From an MCP client:
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ After both builds, these must exist (the ISO preflight checks each):
|
|||
```sh
|
||||
ls -l colibri/target/release/colibri-daemon \
|
||||
colibri/target/release/colibri \
|
||||
colibri/target/release/colibri-smoke-agent
|
||||
colibri/target/release/colibri-test-agent
|
||||
ls -l zot/bin/zot
|
||||
# colibri-tui is optional (staged if present)
|
||||
```
|
||||
|
|
@ -113,14 +113,14 @@ ls -l /usr/local/bin/colibri /usr/local/bin/colibri-daemon
|
|||
ls -l /usr/local/etc/rc.d/colibri_daemon
|
||||
sysrc colibri_daemon_enable
|
||||
|
||||
# lifecycle + smoke
|
||||
# lifecycle + checks
|
||||
service colibri_daemon start
|
||||
colibri status # paths, cost.mode, scheduler, tasks
|
||||
colibri create-task --title "iso smoke"
|
||||
colibri list-tasks --status queued # contains "iso smoke"
|
||||
colibri intake-task --title "iso intake smoke" --capability freebsd
|
||||
colibri create-task --title "iso check"
|
||||
colibri list-tasks --status queued # contains "iso check"
|
||||
colibri intake-task --title "iso intake check" --capability freebsd
|
||||
sleep 35 # one scheduler tick (~30s)
|
||||
colibri list-tasks --status queued # contains "iso intake smoke"
|
||||
colibri list-tasks --status queued # contains "iso intake check"
|
||||
service colibri_daemon stop # socket gone, SQLite remains
|
||||
service colibri_daemon start && colibri list-tasks --status queued # persistence
|
||||
```
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ Current daemon timeout: 5 seconds per sidecar request.
|
|||
a `HeadroomSidecar`; it is not a global daemon-wide replacement for existing
|
||||
cost-mode compaction.
|
||||
- Keep `COLIBRI_HEADROOM_ENABLED=0` for ISO/live-USB defaults unless Headroom is
|
||||
staged and smoke-tested on the target image.
|
||||
staged and validated on the target image.
|
||||
- FreeBSD: upstream `headroom-ai` may require local packaging work because some
|
||||
ONNX/ORT-backed extras do not have FreeBSD prebuilt binaries. Use a known-good
|
||||
Python environment and validate `scripts/headroom-sidecar.py` directly before
|
||||
|
|
|
|||
|
|
@ -67,20 +67,20 @@ scheduler.interval_secs
|
|||
|
||||
Confirm `cost.mode` matches `colibri_cost_mode` from rc.conf.
|
||||
|
||||
## 3. Task board smoke
|
||||
## 3. Task board check
|
||||
|
||||
```sh
|
||||
colibri create-task --title "iso smoke" --description "direct CLI task"
|
||||
colibri create-task --title "iso check" --description "direct CLI task"
|
||||
colibri list-tasks --status queued
|
||||
```
|
||||
|
||||
Expected: list contains `iso smoke` with status `queued`.
|
||||
Expected: list contains `iso check` with status `queued`.
|
||||
|
||||
## 4. Scheduler/intake smoke
|
||||
## 4. Scheduler/intake check
|
||||
|
||||
```sh
|
||||
colibri intake-task \
|
||||
--title "iso intake smoke" \
|
||||
--title "iso intake check" \
|
||||
--description "scheduler should persist this" \
|
||||
--capability freebsd
|
||||
|
||||
|
|
@ -89,9 +89,9 @@ sleep 35
|
|||
colibri list-tasks --status queued
|
||||
```
|
||||
|
||||
Expected: list contains `iso intake smoke`.
|
||||
Expected: list contains `iso intake check`.
|
||||
|
||||
## 5. Glasspane smoke
|
||||
## 5. Glasspane check
|
||||
|
||||
```sh
|
||||
colibri snapshot
|
||||
|
|
@ -99,10 +99,10 @@ colibri snapshot
|
|||
|
||||
Expected: valid JSON snapshot. It may have no panes before an agent is spawned.
|
||||
|
||||
Optional local fake-agent smoke if `colibri-smoke-agent` is included:
|
||||
Optional local fake-agent check if `colibri-test-agent` is included:
|
||||
|
||||
```sh
|
||||
colibri spawn-local /usr/local/bin/colibri-smoke-agent --session-id iso-smoke
|
||||
colibri spawn-local /usr/local/bin/colibri-test-agent --session-id iso-check
|
||||
sleep 4
|
||||
colibri snapshot
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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-smoke-agent ← smoke test agent (fake Pi JSONL)
|
||||
/usr/local/bin/colibri-test-agent ← test agent (fake Pi JSONL)
|
||||
/usr/local/etc/rc.d/colibri_daemon ← rc.d service script
|
||||
/usr/local/etc/colibri/
|
||||
rc.conf.sample ← service config template
|
||||
|
|
@ -59,9 +59,9 @@ service colibri_daemon status
|
|||
# Socket health (nc must be available)
|
||||
service colibri_daemon health
|
||||
|
||||
# CLI smoke
|
||||
# CLI check
|
||||
colibri status
|
||||
colibri create-task --title "iso-smoke"
|
||||
colibri create-task --title "iso-check"
|
||||
colibri list-tasks --status queued
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -27,17 +27,17 @@ Gate 1 (passive service) is unproven.
|
|||
|
||||
### What's done (build wiring)
|
||||
|
||||
| Artifact / step | Location | Status |
|
||||
| -------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
|
||||
| staging script | `scripts/stage-colibri-iso.sh` | done — copies `colibri-daemon`, `colibri`, `colibri-smoke-agent`, rc.d, newsyslog, creates dirs |
|
||||
| rc.d script | `packaging/freebsd/colibri_daemon.in` | done — `start_precmd`, pidfile, daemon(8) wrapper, `COLIBRI_COST_MODE` propagation |
|
||||
| newsyslog config | `packaging/freebsd/newsyslog-colibri.conf` | done |
|
||||
| rc.conf.sample | generated by staging script | done |
|
||||
| acceptance runbook | `docs/ISO-ACCEPTANCE-RUNBOOK.md` | done |
|
||||
| build integration | clawdie-iso `build.sh::install_colibri_service` | done — calls `stage-colibri-iso.sh` against the image root |
|
||||
| `colibri` user/group | clawdie-iso `build.sh` (`pw useradd colibri`) | done — created in the image during build |
|
||||
| service enable | clawdie-iso `build.sh` (`colibri_daemon_enable`) | done — written into image rc.conf |
|
||||
| prebuilt binaries | build-host Rust toolchain (preflight-gated) | done — `build.sh` stages prebuilt release binaries and fails preflight if missing |
|
||||
| Artifact / step | Location | Status |
|
||||
| -------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
|
||||
| staging script | `scripts/stage-colibri-iso.sh` | done — copies `colibri-daemon`, `colibri`, `colibri-test-agent`, rc.d, newsyslog, creates dirs |
|
||||
| rc.d script | `packaging/freebsd/colibri_daemon.in` | done — `start_precmd`, pidfile, daemon(8) wrapper, `COLIBRI_COST_MODE` propagation |
|
||||
| newsyslog config | `packaging/freebsd/newsyslog-colibri.conf` | done |
|
||||
| rc.conf.sample | generated by staging script | done |
|
||||
| acceptance runbook | `docs/ISO-ACCEPTANCE-RUNBOOK.md` | done |
|
||||
| build integration | clawdie-iso `build.sh::install_colibri_service` | done — calls `stage-colibri-iso.sh` against the image root |
|
||||
| `colibri` user/group | clawdie-iso `build.sh` (`pw useradd colibri`) | done — created in the image during build |
|
||||
| service enable | clawdie-iso `build.sh` (`colibri_daemon_enable`) | done — written into image rc.conf |
|
||||
| prebuilt binaries | build-host Rust toolchain (preflight-gated) | done — `build.sh` stages prebuilt release binaries and fails preflight if missing |
|
||||
|
||||
### What's missing (boot/runtime validation)
|
||||
|
||||
|
|
@ -50,9 +50,9 @@ Gate 1 (passive service) is unproven.
|
|||
```sh
|
||||
service colibri_daemon start
|
||||
colibri status
|
||||
colibri create-task --title "iso smoke"
|
||||
colibri create-task --title "iso check"
|
||||
colibri list-tasks --status queued
|
||||
colibri intake-task --title "iso intake smoke" --capability freebsd
|
||||
colibri intake-task --title "iso intake check" --capability freebsd
|
||||
# wait one scheduler tick
|
||||
colibri list-tasks --status queued
|
||||
service colibri_daemon stop
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ load_rc_config $name
|
|||
: ${colibri_daemon_socket:="${colibri_daemon_run_dir}/colibri.sock"}
|
||||
: ${colibri_daemon_db_path:="${colibri_daemon_data_dir}/colibri.sqlite"}
|
||||
: ${colibri_daemon_logfile:="/var/log/colibri/daemon.log"}
|
||||
: ${colibri_daemon_provider_env:="/usr/local/etc/colibri/provider.env"}
|
||||
: ${colibri_daemon_host:="$(/bin/hostname)"}
|
||||
: ${colibri_cost_mode:="smart"}
|
||||
|
||||
|
|
@ -89,6 +90,14 @@ colibri_daemon_prestart()
|
|||
# root/corrupt manual start.
|
||||
rm -f "${colibri_daemon_socket}" "${pidfile}" "${supervisor_pidfile}"
|
||||
|
||||
# Provider keys are optional. Keep them in a root-owned env file instead of
|
||||
# rc.conf so they are easy to rotate and not world-readable.
|
||||
if [ -r "${colibri_daemon_provider_env}" ]; then
|
||||
set -a
|
||||
. "${colibri_daemon_provider_env}"
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Config is passed to the child via the environment.
|
||||
export COLIBRI_DAEMON_DATA_DIR="${colibri_daemon_data_dir}"
|
||||
export COLIBRI_DAEMON_SOCKET="${colibri_daemon_socket}"
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ echo "=== Glasspane Stress Test ==="
|
|||
echo "Socket: $SOCKET"
|
||||
echo ""
|
||||
|
||||
# 1. Concurrent multi-spawn — spawn 3 smoke agents at once
|
||||
# 1. Concurrent multi-spawn — spawn 3 test agents at once
|
||||
echo "--- Concurrent spawn (3 agents) ---"
|
||||
for _ in 1 2 3; do
|
||||
printf '{"cmd":"spawn-agent","provider":"local","model":"/usr/local/bin/colibri-smoke-agent"}\n' | timeout 5 $NC >/dev/null 2>&1 &
|
||||
printf '{"cmd":"spawn-agent","provider":"local","model":"/usr/local/bin/colibri-test-agent"}\n' | timeout 5 $NC >/dev/null 2>&1 &
|
||||
done
|
||||
wait
|
||||
sleep 2
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ mkdir -p "$BIN_DIR" "$RC_DIR" "$ETC_DIR" "$NEWSYSLOG_DIR" "$DB_DIR" "$RUN_DIR" "
|
|||
|
||||
copy_bin colibri-daemon
|
||||
copy_bin colibri
|
||||
copy_bin colibri-smoke-agent
|
||||
copy_bin colibri-test-agent
|
||||
|
||||
if [ "${COLIBRI_STAGE_INCLUDE_TUI:-1}" != "0" ] && [ -x "$TARGET/colibri-tui" ]; then
|
||||
copy_bin colibri-tui
|
||||
|
|
@ -85,7 +85,7 @@ Runtime validation:
|
|||
|
||||
service colibri_daemon start
|
||||
colibri status
|
||||
colibri create-task --title "iso smoke"
|
||||
colibri create-task --title "iso check"
|
||||
colibri list-tasks --status queued
|
||||
service colibri_daemon stop
|
||||
EOF
|
||||
|
|
@ -102,7 +102,7 @@ Staged Colibri into: $DESTDIR
|
|||
Installed:
|
||||
/usr/local/bin/colibri-daemon
|
||||
/usr/local/bin/colibri
|
||||
/usr/local/bin/colibri-smoke-agent
|
||||
/usr/local/bin/colibri-test-agent
|
||||
/usr/local/etc/rc.d/colibri_daemon
|
||||
/usr/local/etc/colibri/rc.conf.sample
|
||||
/usr/local/etc/newsyslog.conf.d/colibri.conf
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Cross-platform smoke test matrix for Colibri
|
||||
// Cross-platform startup check matrix for Colibri
|
||||
//
|
||||
// Validates that core functionality works identically across all platforms
|
||||
// (FreeBSD, Linux) and catches platform-specific regressions early.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ cargo build --release --bin proof-gate-tracker
|
|||
|
||||
## Platform Matrix Tests
|
||||
|
||||
Cross-platform smoke tests are located in `tests/platform-matrix.rs`.
|
||||
Cross-platform startup checks are located in `tests/platform-matrix.rs`.
|
||||
|
||||
### Usage
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue