Commit graph

111 commits

Author SHA1 Message Date
a42e6b76ff feat: add local_args to spawn-agent for argv-capable Pi spawn
Adds local_args field to HerdrCommand::SpawnAgent, enabling the
Local provider to pass argv to the agent binary without a wrapper
script. Backward-compatible — local_args defaults to None.

Real Pi spawn on FreeBSD is now:
  spawn-agent provider=local model=pi local_args=['--mode','json','--no-tools','-p','task']

Previously required a wrapper script because only an executable
path was accepted. This closes the OSA wrapper caveat from PR #9.

Build: pass | Tests: workspace green
2026-05-31 17:21:25 +02:00
ad5e03f1dc Merge pull request 'docs: record OSA real Pi binary proof' (#9) from docs/osa-real-pi-binary-proof into main 2026-05-31 17:15:23 +02:00
69c61cb189 docs: record OSA real Pi binary proof (Sam & Codex)
Validation: real pi 0.76.0 executed via colibri-daemon spawn-local wrapper; glasspane reached done with pi_session_id.
2026-05-31 17:10:55 +02:00
44865f3e39 Merge pull request 'feat: scheduler prompt injection (T1.4 PR3a)' (#8) from feat/t14-pr3a-scheduler-injection into main 2026-05-31 17:05:45 +02:00
1f550a4b5c feat: scheduler prompt injection (T1.4 PR3a)
When scheduler_prompt_injection is enabled and a session_id is
provided on spawn-agent, the daemon builds a PromptAssembly from
the session, serializes it as COLIBRI_SESSION_CONTEXT env var,
and passes COLIBRI_COST_MODE to the spawned agent process.

Config-gated (default: disabled) via COLIBRI_SCHEDULER_PROMPT_INJECTION.
No cache warming — that's PR3b (separate).

Build: pass | Tests: workspace green | Clippy: clean | Fmt: clean
2026-05-31 17:05:32 +02:00
8f08643c69 Merge pull request 'feat: ISO service hardening — rc.d + log rotation + layout docs' (#7) from feat/iso-service-hardening into main 2026-05-31 16:49:00 +02:00
3235f8c00e feat: ISO service hardening — rc.d + log rotation + layout docs
Hardens the FreeBSD service for production readiness:

- rc.d: post-start socket health check (waits up to 10s), post-stop
  socket cleanup, 'health' extra command that probes socket with
  a status command via nc.

- newsyslog: log rotation at 1MB, 7 compressed archives,
  colibri:colibri ownership.

- staging: copies newsyslog config into image root, updated
  staging report to list all installed files.

- docs/ISO-SERVICE-LAYOUT.md: filesystem layout, boot/shutdown
  behavior, startup validation commands, config knobs, secrets
  policy, log rotation details.

Shell syntax: sh -n clean on both scripts.
Workspace tests: all green.
2026-05-31 16:48:48 +02:00
efdb54dfff Merge pull request 'test: add Pi spawn path proof integration test' (#6) from feat/pi-spawn-proof into main 2026-05-31 16:23:24 +02:00
3c10fc098e test: add Pi spawn path proof integration test
Validates: Colibri spawns agent process (fake-pi-agent.py) → reads
JSONL stdout → glasspane ingests → snapshot shows Done state with
correct session ID.

Uses scripts/fake-pi-agent.py which emits the colibri-pi-events
JSONL taxonomy (session, agent_start, turn_start, turn_end,
agent_end). Proves the spawn→ingest→glasspane pipeline without
requiring the real pi binary.

The real Pi binary path (when installed) follows the same pattern:
pi --mode json is spawned with identical spawner code.

Build: pass | Tests: 1/1 green | Workspace: all green
2026-05-31 16:23:11 +02:00
144c143d77 Merge pull request 'docs: record d360dde post-merge baseline' (#5) from docs/d360dde-baseline into main 2026-05-31 16:19:11 +02:00
040f56316d docs: record d360dde post-merge baseline
Linux + FreeBSD validation green. All 4 PRs merged.
Known caveats: OSA kernel p8 running / p9 pending reboot,
colibri-skills and zot harness are scaffold-only.
2026-05-31 16:18:59 +02:00
d360dde1b9 Merge pull request 'feat: cost-aware trimming + auto-escalation (T1.4 PR 2)' (#4) from t14-pr2-trimming into main 2026-05-31 16:13:29 +02:00
79c15cd4df feat: cost-aware trimming + auto-escalation (T1.4 PR 2)
Behavior changes for cache-first prompt discipline:

- PromptAssembly::trim_to_budget(CostMode): trims volatile scratch
  first, then oldest appendable log entries, to fit within cost mode
  budget. Prefix is never trimmed. Returns count of items removed.

- EscalationTrigger enum: BudgetExceeded + CompactionInsufficient
  variants for auto-escalation decisions.

- auto_escalate(): returns Some(next_mode) if trigger warrants
  escalation, None if already at ceiling or trigger doesn't apply.

- 11 new tests: trim budget scenarios (under/over/deterministic/
  prefix-preserved), escalation chain (fast→smart→max→ceiling),
  compaction triggers.

No scheduler injection, no cache warming — PR 3 follows.

Build: pass | Tests: 51/51 green | Clippy: clean | Fmt: clean
2026-05-31 16:13:11 +02:00
880da14662 Merge pull request 'feat: add zot runtime event normalization scaffold' (#3) from feat/zot-runtime-event-adapter into main 2026-05-31 16:03:51 +02:00
65e304a1e0 Merge pull request 'feat: scaffold colibri-skills crate — split-brain read consumer' (#2) from feat/colibri-skills-scaffold into main 2026-05-31 16:03:12 +02:00
437b2f60b0 Merge pull request 'feat: add PromptAssembly + CacheMetrics structs (T1.4 PR 1)' (#1) from t14-pr1-clean into main
Reviewed-on: #1
2026-05-31 15:54:24 +02:00
7c1a9d886a feat: add PromptAssembly + CacheMetrics structs (T1.4 PR 1)
Structural only — no behavior change. Introduces:

- PromptAssembly: named 3-region wrapper around build_prompt_messages()
  with to_messages(), immutable_prefix, appendable_log, volatile_scratch,
  total_bytes, estimated_tokens.

- CacheMetrics: per-session cache-hit tracking with hit_rate() and
  record().

- Session::build_prompt_assembly() wraps existing build_prompt_messages()
  with no logic change.

- 5 golden tests: assembly structure, empty volatile, hit rate
  calculations, record accumulation.

- Linked T1.4-PROMPT-DISCIPLINE-PLAN.md from COLIBRI-CUTOVER-PLAN.md.

No trimming, no escalation, no scheduler changes — PR 2 and 3 follow.

Parked branches (colibri-skills, zot harness) untouched.

Build: pass | Tests: 41/41 green (+5 new) | Clippy: clean | Fmt: clean
2026-05-31 15:30:38 +02:00
39db0b661b docs: T1.4 cache-first prompt discipline plan
Inventory of current prompt/cache/session code across Colibri:
- cost.rs: CostMode (fast/smart/max), thresholds, escalation (present)
- session.rs: 3-region prompt assembly, compaction (present)
- colibri-deepseek: STABLE_SYSTEM_PREFIX, cache probe (present)
- config.rs: DaemonConfig with cost fields (present)

Plan adds 6 integration items across 3 PRs:
1. PromptAssembly + CacheMetrics structs
2. Cost-aware trimming + auto-escalation
3. Scheduler injection + cache warming

No changes to parked branches (colibri-skills, zot harness).

Build: N/A (docs-only) | Tests: N/A
2026-05-31 15:30:38 +02:00
b0e94fd514 feat: add zot runtime event normalization scaffold
Phase 1 of zot agent harness integration. Adds:

- AgentRuntime enum (Pi, Zot, Local) with serde support
- zot_event_type() — parse zot RPC NDJSON lines to normalized
  Colibri event types. Permissive: handles tool_use_start,
  tool_use_args, tool_use_end in addition to documented events.
- apply_zot_event() / fold_zot_events() — state transitions
  reusing the existing apply_pi_event() logic via normalization.
- Critical: assistant_message does NOT end the pane (zot may
  emit them during tool loops). Only turn_end/done signals
  completion.
- 16 new tests using real captured zot RPC event lines, including
  tool call sequences and error/success response handling.
- PiJsonlIngestor and existing tests unchanged (33/33 green).

No spawner, socket, or process changes — this is the event
taxonomy foundation only. Wrapper + daemon integration follow
in Phase 2.

Build: pass | Tests: 33/33 green | Clippy: clean | Fmt: clean
2026-05-31 15:03:39 +02:00
8b419f79ed docs: align skills plan with scaffold (Sam & Codex)
Validation: cargo fmt --check; cargo clippy -p colibri-skills --all-targets -- -D warnings; cargo test -p colibri-skills; git diff --check.
2026-05-31 14:39:49 +02:00
1da49eac4f fix: satisfy clippy for skill status default (Sam & Codex)
Validation: cargo fmt --check; cargo clippy -p colibri-skills --all-targets -- -D warnings; cargo test -p colibri-skills.
2026-05-31 14:38:28 +02:00
5267f97f52 feat: scaffold colibri-skills crate — split-brain read consumer
Phase 1: structs + type system + 12 tests. No IO, no SQLite yet.
Compiles against full workspace (9 crates now, up from 8).

The colibri-skills crate is the read-only runtime consumer for
skill artifacts authored in Clawdie-AI. It does NOT store or author
skills — it indexes committed, reviewed skill bundles.

Seeded from the astro-howto artifact (PR #6 in clawdie-ai):
  - Skill, SkillManifest, SkillArtifact, SkillChunk structs
  - ArtifactType classifier (document, image, script, transcript, etc.)
  - ImportSummary + SearchResult types
  - SQLite schema documented in doc/COLIBRI-SKILLS-PLAN.md

Build: pass | Tests: 12/12 green | Clippy: pending
2026-05-31 14:36:43 +02:00
99b92caf95 docs: fix stale Codeberg ref in Linux agent constraints (Sam & Hermes) 2026-05-29 11:58:23 +02:00
88e5abee93 docs: switch remote references to Forgejo (Sam & Hermes) 2026-05-29 09:32:45 +02:00
56ffa8e596 docs: cut over Colibri remotes to Forgejo (Sam & Claude)
Validation: docs-only; git diff --check.
2026-05-29 09:03:59 +02:00
123kupola
da31b5c9a0 docs: handoff — Codex to build Colibri release binaries for ISO (Sam & Hermes) 2026-05-27 23:53:47 +02:00
123kupola
e4bd1d92c3 docs: add mandatory post-build cleanup to AGENTS.md (Sam & Hermes)
All agents (Hermes, Claude, Codex) load AGENTS.md. Cleanup rule:
cargo clean + rm /tmp/colibri-* after every session. Platform notes
for FreeBSD tmpfs behavior.
2026-05-27 23:35:18 +02:00
123kupola
6f957d3d72 test: add Slovenian multibyte truncation test (Sam & Hermes)
"Cene že še češnje je" — š/č/ž are 2-byte UTF-8, same family as
German umlauts. Complements the existing CJK+umlaut test. Ensures
compact_tool_result never panics on Slavic diacritics in FreeBSD
locale output, pkg descriptions, and agent logs.
2026-05-27 23:22:10 +02:00
a69d0059b0 docs: consolidate ISO planning docs 2026-05-27 23:17:35 +02:00
4880502d18 docs: tighten Clawdie Studio Zed integration guardrails 2026-05-27 23:13:27 +02:00
aa15654ae2 docs: propose Clawdie Studio — integrated editor + control plane
Proposal for a unified Colibri + Zed experience where the operator
can edit docs/code while simultaneously running and observing agents,
tasks, and scheduler from one visual surface.

Three integration levels:

1. Near-term: Zed as visual shell over colibri-daemon socket
   (sidebar extension, one-app experience, not one binary)

2. Mid-term: colibri-mcp MCP bridge (highest leverage)
   - Zed already supports MCP natively
   - Reuses colibri-client crate directly
   - Editor-agnostic (works with any MCP-capable editor)
   - 7 Phase-1 tools defined (status, snapshot, tasks, intake, etc.)

3. Long-term: true single binary (not recommended now)
   - Colibri must run headless at boot even when editor is closed

Product shape:
  colibri-daemon (service) + colibri-mcp (bridge) + colibri-studio
  (launcher) + Zed extension. Two new thin binaries, no existing
  crates change.

Estimated: ~1 week of focused agent time for MCP Phase 1 + launcher.
2026-05-27 23:11:23 +02:00
0dd7cf70af fix: UTF-8-safe truncation in compact_tool_result
cost.rs:124 sliced at a raw byte boundary which panics on multibyte
UTF-8 characters (ä, ö, ü, CJK, etc). FreeBSD tool output and agent
logs regularly contain non-ASCII.

Fix: use str::floor_char_boundary() to round down to the nearest valid
char boundary before slicing. This never panics and produces valid
UTF-8 output at or below the requested byte limit.

Added test: multibyte truncation with CJK + umlaut input.
2026-05-27 23:09:34 +02:00
f3a221330b docs: add ISO acceptance tracker and staging helper 2026-05-27 22:52:59 +02:00
123kupola
0b24a7c7d1 feat: richer status + cost thresholds in session rotation (Sam & Hermes)
ISO-ready improvements:
- cmd_status now returns paths, cost mode/thresholds, task counts
  by status, pane count, scheduler interval
- session_rotation reads CostMode thresholds instead of static
  DaemonConfig fields — Fast/Smart/Max affect compaction now
- Debug log includes active cost_mode
2026-05-27 22:48:42 +02:00
2b01d8dad8 docs: add ISO integration plan 2026-05-27 22:43:51 +02:00
2883151b5f fix: keep cost mode changes clippy-clean 2026-05-27 22:31:31 +02:00
123kupola
ffee0c655a docs: note set-cost-mode is runtime-only for T1.4 (Sam & Hermes) 2026-05-27 22:29:09 +02:00
123kupola
c97b44ad3e feat: add cost discipline — Fast/Smart/Max modes + escalation (Sam & Hermes)
Phase 5: cache-first prompt discipline. New cost module with:
- CostMode enum: Fast (500K/5 turns/4KB tool cap), Smart (2M/20/16KB), Max (8M/100/none)
- escalate() — Fast→Smart→Max, each step logged visibly
- compact_tool_result() — truncate oversized tool outputs with byte annotation
- set-cost-mode socket command + COLIBRI_COST_MODE env var
- 9 unit tests (defaults, thresholds, escalation path, parsing, compaction)
2026-05-27 22:27:30 +02:00
4c92a387ba docs: record colibri task CLI smoke 2026-05-27 22:24:41 +02:00
eaa2f27680 feat: add colibri task commands 2026-05-27 22:24:16 +02:00
123kupola
12596d1a71 docs: mark T1.3b FreeBSD smoke done, next: Herdr attach or T1.4 (Sam & Hermes) 2026-05-27 22:20:11 +02:00
8d4bb3a916 refactor: rename colibri-ctl binary to colibri (Sam & Claude)
The operator CLI was already a subcommand dispatcher; drop the -ctl suffix so
it reads `colibri status` / `colibri snapshot` / `colibri spawn-local …` — one
`colibri` entrypoint (same single-binary-with-subcommands shape as just, but a
control plane). Renames the bin + its source file, updates usage strings, and
points the forward-looking docs at `colibri`. Dated session/handoff records
are left as historical. (Task-board subcommands intake/create/list are the
follow-up T1.3c slice.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 21:50:36 +02:00
d5744e8414 fix: rc.d colibri_daemon runs under daemon(8) (Sam & Claude)
colibri-daemon runs in the foreground and writes no pidfile, so the previous
`command=/usr/local/bin/colibri-daemon` would hang `service start` and leave
status/stop unable to track it. Run it under daemon(8): -P supervisor pidfile,
-r restart on crash, -u colibri privilege drop, -o logfile for the tracing
stdout. start_precmd recreates the colibri-owned /var/run/colibri (tmpfs),
/var/db/colibri, and the log dir each start. Still review-only / not installed;
needs an on-FreeBSD `service` test (osa-smoke rec #4).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 21:48:47 +02:00
4f81e49983 test: intake-task drains to SQLite via run_loop (Sam & Claude)
Regression guard for the scheduler store deadlock fixed upstream in d760536:
scheduler.tick held a non-reentrant std::sync::Mutex (state.store) across the
match scrutinee, so relocking inside the arm deadlocked the first time any
intake/scheduled task fired.

This test (independently authored on domedog) submits an intake-task over the
real Unix socket, runs run_loop with a fast scheduler tick, and asserts the
task is drained into SQLite. It hangs (>8min) against the pre-fix code and
passes in 0.09s against d760536 — so it cross-validates that fix and guards the
regression. Closes osa-smoke rec #2.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 21:48:47 +02:00
8199e23890 docs: record OSA intake scheduler re-smoke 2026-05-27 21:09:26 +02:00
d760536fe1 fix: avoid scheduler store deadlock on intake drain 2026-05-27 21:02:01 +02:00
af8c0110d7 fix: improve daemon loop wiring — log scheduler interval, join both tasks
Two improvements to Hermes' run_loop wiring (9717ce7):

1. Add scheduler_secs to the daemon loop startup log — the most
   important interval for the OSA re-smoke was missing from the
   heartbeat/rotation/handoff log line.

2. Replace tokio::select! with tokio::join! in main.rs — select!
   returned when the first task finished, leaving the other dangling.
   join! waits for both the socket server and the daemon loop to
   complete before proceeding to shutdown.

89 tests pass, clippy clean.
2026-05-27 20:21:41 +02:00
123kupola
9717ce70f6 fix: start daemon::run_loop from main.rs (Sam & Hermes)
The scheduler tick was wired into daemon::run_loop but main.rs only
started the socket server, never the background loop. intake-task
commands queued into the scheduler's in-memory queue were never
processed. Fix: spawn daemon::run_loop as a second tokio task
alongside the socket server.
2026-05-27 20:16:02 +02:00
61b008ac6a docs: record OSA FreeBSD daemon smoke finding 2026-05-27 20:13:46 +02:00
123kupola
53028a0022 docs: answer Codex handoff questions — colibri-ctl, scheduler, smoke-agent, WAL (Sam & Hermes) 2026-05-27 20:05:47 +02:00