Two root causes found via truss:
1. Bare command names (sudo, jexec) unresolved under daemon(8) PATH
→ fixed by resolve_program() in PR #131
2. Jail staging directory owned by root, unwritable by clawdie
→ fixed by chmod 777 <jail_root>/var/run/colibri-stage
Trace saved at /tmp/daemon.truss (1964 lines, successful spawn).
Move the backoff spawn operation into a named async helper so older tooling does not trip over || async syntax, and add a jail sudo wrapping unit test. Document sudo as an interim validated-host privilege mode.\n\nValidation: ./scripts/check-format.sh; cargo fmt --check; cargo check -p colibri-daemon; cargo test -p colibri-daemon jail_tests -- --nocapture.
1. VAULT-PROVISION-FIRST-PROOF.md — refresh to the clean CLI now that the
three gaps are closed (#101/#102 via PR #107; #92 via PR #119):
- Step 3: raw SQLite INSERT →
- Step 4: raw JSON →
- Status header: mark all three closed; note the proof validates the
production deployment pattern (bare-metal Clawdie service runs this model)
- Chain-resolution section: document the #92/#119 containment guard
(canonicalize + assert under COLIBRI_JAIL_ROOT_BASE before any write)
- Follow-ups: record what landed vs. what's still open (no delete-tenant
verb; CI runner intermittently down)
2. Sweep markdown corruption introduced by #126 (merged while CI runner was
down, so the prettier gate never ran):
- AGENTS.md — prettier reflow
- COLIBRI-SKILLS-PLAN.md — Ownership table had a row split across two
lines ('consumer.' orphan + a duplicated Agents row); restored to 5
clean logical rows
Checks: npx prettier@3 --check across all docs + AGENTS.md + README.md →
0 warnings; cargo fmt --check clean.
Co-Authored-By: Hermes & Sam <hello@clawdie.si>
PR #124 applied the positive-instruction-framing convention across docs but
was self-merged without the markdown format gate, leaving 6 files failing
prettier and a few structural defects. This repairs them:
- prettier --write on the 6 files that failed ./scripts/check-format.sh
(AGENTS.md, CLAWDIE-STUDIO-PROPOSAL, COLIBRI-SKILLS-PLAN, HEADROOM-SIDECAR,
MULTI-AGENT-HOST-PLAN, VAULT-PROVISION-FIRST-PROOF).
- COLIBRI-SKILLS-PLAN.md: fix a table row split across two lines by a stray
newline injected mid-cell.
- CLAWDIE-STUDIO-PROPOSAL.md: remove an orphaned "together." left dangling
by a reworded sentence; restore the editor-bridge (MCP) guardrail bullet
that was dropped, reworded positively; restore the guardrail list structure.
- CLAWDIE-STUDIO-PROPOSAL.md: plain-language the three implementation
guardrails (MCP foundation, opt-in/guarded tools, set-cost-mode scope).
./scripts/check-format.sh -> green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Convert 'do not', 'cannot', 'never', 'avoid', 'don't' patterns across
AGENTS.md, README.md, and 11 docs/*.md files into positive,
actionable instructions that tell the reader what TO do.
Preserved: hard safety constraints (MUST NOT agent boundaries,
vault credential confinement intent) — these are enforceable
guardrails where the prohibition IS the instruction.
docs/MULTI-AGENT-HOST-PLAN.md and docs/README.md had table-column formatting
drift that fails the markdown CI gate (prettier --check '**/*.md') on main.
Formatting only — pure table-padding re-alignment, no content change. Unblocks
the markdown job so the CI pipeline goes green again.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Correct the raw socket spawn example to use the bootstrapped colibri-test-agent in the jail instead of the default remote-provider agent binary. Use a harmless FIRST_PROOF_KEY item for the throwaway collection.\n\nAlso convert packaging/freebsd/colibri-agent-loop.md to normal Markdown so the repository formatting gate passes.\n\nChecks: ./scripts/check-format.sh; git diff --check
Documents how to prove the spawn -> vault-provision -> .env chain live on osa,
honestly surfacing that it isn't CLI-drivable yet:
- the chain is wired + unit-tested, but tenant registration is raw-SQLite-only
(#101) and jailed spawn is raw-socket-JSON-only (#102)
- runbook uses the interim manual path (sqlite insert + raw spawn-agent JSON)
- scratch jail + test collection per first-proof policy; bootstrap creds never
enter the jail
- documents exact resolution: collection name = tenant_id, jail_root must match
Continues an osa-agent investigation (verified against origin/main).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New doc: docs/MULTI-AGENT-HOST-PLAN.md — gap analysis of the multi-host
coordination stack after PR #83 (socat bridge + Python pollers). Defines 5
phases: Phase 1 (multi-agent task-board tests), Phase 2 (merge CLI surface
gaps), Phase 3 (agent presence schema, deferred), Phase 4 (polling workflow
test, deferred), Phase 5 (TCP bridge validation, FreeBSD-only).
Immediate scope: Phases 1-2, all Linux-testable.
Updated PRIORITY-HANDOFF-ISO-SPAWN-COST.md to mark Priorities 2 (poll_tasks)
and 3 (cost mode enforcement) as done, fix stale test count (164 → 211), and
cross-reference the new plan as the next sprint.
211 tests pass, clippy clean, fmt clean.
Return an error from the socket server when another daemon owns the Unix socket or bind setup fails, and broadcast shutdown so the daemon does not stay alive without a control socket. Also format the PR docs.\n\nChecks: cargo fmt --check; ./scripts/check-format.sh; git diff --check; cargo test -p colibri-daemon clear_stale_socket -- --nocapture; cargo test -p colibri-daemon --test sigterm_shutdown -- --nocapture.
Six bugs found in deep-dive analysis of FreeBSD rc.d/rc.conf after the
live-copy-safe fix (7d23905):
1. colibri_cost_mode → colibri_daemon_cost_mode: naming broke rc.subr
${name}_ convention — operator setting colibri_daemon_cost_mode=fast
in rc.conf was silently ignored. Fixed in rc.d, staging script,
rc.conf.sample, and all docs.
2. Removed redundant chmod 660 on socket in poststart: Rust code already
sets 0770 with documented rationale. The poststart override to 0660
was conflicting, fragile, and had no comment.
3. Removed unnecessary chmod 644 on pidfile in poststart: pidfile lives
in a 0750 directory — world-readable permission is pointless and
security-negative.
4. Fixed ISO-SERVICE-LAYOUT.md: socket perms were wrong (said 750, actual
770), colibri-daemon.pid was labeled supervisor pidfile (it's the
child), supervisor pidfile was missing entirely, shutdown behavior
didn't mention custom stop_cmd targeting the supervisor.
5. health_cmd now checks for non-empty daemon response instead of just
connectvity — a hung daemon accepting connections but returning
garbage was reported healthy.
6. rc.conf.sample hostname path: $ (hostname) → $(/bin/hostname) for
consistency with rc.d script and early-boot PATH safety.
Checks: sh -n OK, cargo fmt --check OK, cargo clippy clean,
cargo test --workspace 207 passed.
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.
The layered-soul skills importer globbed skills/**/*.md, pulling references/ and
templates/ in as separate skills. Import each skills/**/SKILL.md instead
(frontmatter name/description, category 'soul'); supporting files are not skills.
Verified against the populated layered-soul: 9 skills imported, idempotent,
curated memory deferred. Doc updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the docs to the shipped staged-env code: add the JailConfig root_path
field, a 'Staged env payloads' section (prepare_spawn_command writes env.sh/
launch.sh under /var/run/colibri-stage/<id>/), resolve the mdo-env-passthrough
open item, and add root_path to the external-MCP example.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add real FreeBSD 15 read-only validation output and the hardening findings so Linux-side reviewers can evaluate the installer follow-up without needing host access.\n\nChecks: ./scripts/check-format.sh; git diff --check
Use the clawdie service user in the generated FreeBSD rc.d script, chown state directories after the user is created, and reject unknown existing ZFS pools before rendering/applying a plan. Update the FreeBSD validation handoff to cover these checks.\n\nFreeBSD checks: cargo fmt --check; ./scripts/check-format.sh; git diff --check; cargo test -p clawdie -- --nocapture; cargo clippy -p clawdie --all-targets -- -D warnings; cargo build -p clawdie --release; target/release/clawdie discover; target/release/clawdie plan; target/release/clawdie apply --pool zroot (dry-run); target/release/clawdie plan --pool does-not-exist (expected error).
Codex validates the disk-touching + service-install paths (zfs/zpool create,
pw/rc.d service) that can't be exercised off-host. Includes read-only checks,
destructive provisioning steps for a scratch pool, teardown, and acceptance
criteria.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wires clawdie/layered-soul (the portable identity/context source) into Colibri.
scripts/import-layered-soul.sh reads its reviewed skills/**/*.md into the existing
`skills` catalog (mirrors import-clawdie-skills.sh; idempotent, frontmatter
name/description, category from the skill's parent dir).
Honest scope: only skills are wired. The adapter's "Layered Memory Fabric"
(system_brain / system_ops + a richer system_skills) is design-only
(COLIBRI-SKILLS-PLAN.md), so curated memory is reported-but-not-imported and the
gap is documented in docs/INTEGRATION-LAYERED-SOUL.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both were written as proposals; the decisions are now working code, so slim them
to plain "how it works" docs (code is the source of truth).
- ADR-agent-harness-consolidation: Proposed -> Accepted/implemented; drop the
migration plan + gates (all shipped), fold in the pi-demotion correction, and
drop the dangling CLAWDIE-AGENT-WIKI reference (deleted in #34). 116 -> ~55 lines.
- COLIBRI-JAILED-AGENT-SPAWN-DESIGN: proposal -> implemented; describe the shipped
spawner (name-vs-path lifecycle, command= syntax, PrivMode mdo/helper, socket
wiring, external-MCP reuse) instead of the original code sketch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per cleanup decision: HERDR-HUB-RUNBOOK.md is stale (Herdr is now an optional
Linux UI only, not a hub), and T1.4-CACHE-WARMING-DESIGN.md is superseded (cache
warming is implemented via config flags). Also drops the now-dangling link to the
latter from COLIBRI-TOKENOMICS-TRIFECTA.md.
Kept (still useful): ISO-INTEGRATION-PLAN.md, CLAWDIE-STUDIO-PROPOSAL.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Salvages the non-stale part of docs/colibri-socket-name-cleanup. The daemon's
wire types are ColibriCommand/ColibriResponse (renamed from Herdr* long ago), but
COLIBRI-DAEMON-GLASSPANE-INTEGRATION.md still documented the old Herdr* names.
(The branch's other edit touched docs/CLAWDIE-BUILD.md, which #34 deleted, so it
is dropped.)
Co-authored-by: Sam & Codex (docs/colibri-socket-name-cleanup)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the canonical ADR referenced by build.cfg and the consolidation work
(from docs/adr-agent-harness-consolidation, which merges clean). Prepends a
dated Update note: the ADR's "remove Pi" guidance is superseded — Pi is DEMOTED
to a spawnable backend (kept on-image, Node stays), zot is the primary harness,
per docs/COLIBRI-JAILED-AGENT-SPAWN-DESIGN.md. Original record preserved.
Co-authored-by: Sam & Claude (original ADR)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
External MCP servers are arbitrary third-party binaries — at least as untrusted
as the agents the spawner already jails — but the #36 prototype spawned them
directly on the host. Close that gap by reusing the existing confinement
primitive instead of growing a second one.
- ExternalMcpServer gains `jail: Option<JailConfig>` (#[serde(default)]).
- ExternalMcpSession::start routes Command::new through
colibri_daemon::spawner::jail_wrap with the shared COLIBRI_JAIL_PRIV_MODE
policy (mdo live / helper deploy). No jail => unchanged. stdio (incl. the
piped JSON-RPC stdin/stdout) flows through jexec/jail/mdo unaffected.
- docs/COLIBRI-EXTERNAL-MCP-PROTOTYPE: document the `jail` field + confinement.
- 3 tests (no-jail passthrough, jexec wrap, registry jail deserialize).
colibri-mcp already depends on colibri-daemon, so no new dep. Build/test/clippy/
fmt green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A prettier-style pass in #36 mangled the jailed-spawn design doc — `mac_do`
became `mac*do` (eating the underscore and opening stray italics) and the
`_which_` / `_not_` emphasis turned into broken `\_which*` / `\_not*`. Restore
the text and wrap `mac_do` in backticks so a future formatter leaves it alone.
Also correct the README status line ("11 crates" → "10 crates") to match the
workspace table; clawdie was removed in #34 and #36 added no new crate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds stdio external MCP server registry support to colibri-mcp with read-only discovery by default and explicit COLIBRI_MCP_EXTERNAL_CALL gating for proxying external tools. Also smooths the merged jail-spawn formatting/FreeBSD command parameter edge so repository gates pass.\n\nChecks: cargo test -p colibri-mcp --all-targets; cargo fmt --check; ./scripts/check-format.sh; git diff --check; fake stdio MCP server smoke via colibri-mcp --external-config --external-call
The `clawdie` crate (Telegram+DeepSeek mini-agent over the control-plane core)
was an experimental operator-lane candidate. Per the agent-harness
consolidation, the live USB runs colibri_daemon + the zot agent, and the
deployed `service clawdie` is a reserved name, not this binary — so the
mini-binary is dead weight. Remove it and its now-orphaned docs.
- delete crates/clawdie (leaf crate; nothing depended on it)
- delete packaging/freebsd/clawdie.in (its rc.d candidate)
- delete docs/CLAWDIE-AGENT-WIKI.md + docs/CLAWDIE-BUILD.md (only described it)
- drop it from workspace members + Cargo.lock; tidy the strip-profile comment
- README: 11 → 10 crates, remove the clawdie row
- COLIBRI-TOKENOMICS-TRIFECTA: drop the stale clawdie-lane scope note
No "relay" existed in this repo (already gone). zot is untouched. The Clawdie
brand, the clawdie operator user, and the reserved deployed `service clawdie`
name are unaffected — this only removes the experimental Rust mini-binary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Colibri already spawns pi (spawner.rs) and captures its JSONL for glasspane;
this documents adding optional jail confinement to that existing path rather
than touching zot (whose swarm is self-only + no isolation — keeps the mirror
clean).
Covers: JailConfig + jail_wrap at the Command::new site, jail-aware teardown,
and the privilege decision for the root-only jexec step —
- live USB → `mdo -u root` (reuses mac_do; daemon == operator trust domain)
- deployed → setuid/Capsicum helper (narrow root surface on exposed hosts)
mac_do rules are identity-based (gid=0>uid=0), not command-filtered, so mdo
grants the daemon full root; that's acceptable on the single-operator live USB
but not on a deployed/exposed box, hence the split. Selected via PrivMode at
daemon config time so one spawner serves both.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cleans stale Herdr socket/API naming after the Colibri socket rename, preserves Herdr as an optional Linux/macOS display client, marks the clawdie mini-binary service as experimental rather than ISO/deployed-service contract, and removes old internal session logs.\n\nChecks: ./scripts/check-format.sh; cargo fmt --check; git diff --check; sh -n packaging/freebsd/colibri_daemon.in packaging/freebsd/clawdie.in
Remove the transition-era docs that no longer guide anyone and just pollute
context: MIGRATION-INVENTORY, CALLER-INVENTORY, GATE5-MIGRATION-GRAPH,
COLIBRI-CUTOVER-PLAN, and the rolling .agent-handoff.md. (History stays in git.)
Fix references in kept docs: drop the cutover/caller pointers (README,
COLIBRI-DAEMON-GLASSPANE-INTEGRATION), and repoint handoff mentions (AGENTS,
tools/README, MULTIAGENT-WORKFLOW-IMPROVEMENTS) to the ephemeral per-task
`doc/<FEATURE>-HANDOFF.md` convention. Dated session logs left as historical
record. Markdown gate green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
colibri had no Prettier config or gate, so its markdown drifted freely (22/31
files failed Prettier). Mirror the clawdie-iso gate so docs stay consistent:
- .prettierrc: same as clawdie-iso — proseWrap=preserve, printWidth=80, and
embeddedLanguageFormatting=off for *.md so fenced code (JSON/mermaid/shell in
the graph + design docs) is left exactly as written.
- .prettierignore: target/, scratch dirs, CHANGELOG.
- scripts/check-format.sh: `prettier@3 --check '**/*.md'` (run before pushing).
- AGENTS.md: "Markdown Formatting Gate" section documenting the workflow.
- One-shot `prettier --write` across all markdown. Pure formatting — only
emphasis-marker (*x* -> _x_), list-bullet, table-padding, and blank-line
normalization; no prose/command/code-fence content changed.
Gate now green (`./scripts/check-format.sh` → all matched files pass).
Docs-only + tooling — no Rust touched, no rebuild.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Run Prettier on the PR #15 tokenomics doc after the clawdie scope and model-name fixes.\n\nChecks: npx --yes prettier@3 --check docs/COLIBRI-TOKENOMICS-TRIFECTA.md; cargo fmt --check; git diff --check.
Per Claude review: the tokenomics doc implied cost-modes/metering as
universal Colibri behaviour, but the clawdie lane deliberately strips
all of it. Added explicit scope block referencing CLAWDIE-AGENT-WIKI.md.
Also aligned example model name deepseek-v4-flash with harness docs.