diff --git a/docs/wiki/agent-harness.md b/docs/wiki/agent-harness.md new file mode 100644 index 0000000..0226fff --- /dev/null +++ b/docs/wiki/agent-harness.md @@ -0,0 +1,51 @@ +# Agent harness: zot + Colibri + +← [index](./index.md) + +## Decision + +Two binaries, not one (Sam rejected merging them, 2026-06-13): + +- **zot** — _the agent_ (front door to the model). Go binary; acts. +- **Colibri** — _the control plane_ (supervisor). Rust; watches agents via + glasspane, runs the task board, owns cost. It **observes** zot/pi; it does not + contain them. + +Canonical statement: `AGENTS.md` (lines ~18–32). `clawdie-ai` (TS) is being +pruned; surviving features move to zot/Colibri. + +> There is **no** `ADR-agent-harness-consolidation.md` despite references to it +> in `clawdie-iso/scripts/stage-colibri-iso.sh`. Treat `AGENTS.md` as the ADR. + +## Runtimes + +Glasspane normalizes events from both harnesses into one taxonomy via +`AgentRuntime { Pi, Zot, Local }` — `crates/colibri-glasspane/src/lib.rs` +(`zot_event_type()` maps zot's events onto the pi-style names). + +## Autospawn + the RPC driver (colibri#143) + +The spawner's contract: spawn the agent, read stdout JSONL. + +- **pi** self-drives (`pi --mode json`) with `stdin` null — fits directly. +- **zot**'s only structured persistent mode is `zot rpc`, a request/response + peer that **reads stdin**. So the spawner pipes stdin for RPC agents and the + daemon sends the prompt over an `RpcSender`. + +Where it lives: + +- spawn contract + `rpc_stdin` + `RpcSender`: `crates/colibri-daemon/src/spawner.rs` +- autospawn binary-aware argv (`zot → rpc`, pi → `--mode json`): + `crates/colibri-daemon/src/socket.rs` (`default_agent_args`, + `autospawn_agent_if_configured`) +- wire format (verified against real zot): [ZOT-RPC-TRANSCRIPT](../ZOT-RPC-TRANSCRIPT.md) +- end-to-end proof: `crates/colibri-daemon/tests/zot_rpc_smoke.rs` + (`#[ignore]`, `ZOT_BIN`-gated) + +OOTB default harness is **zot**; pi remains a supported fallback +(`COLIBRI_AUTOSPAWN_BINARY=pi`). + +## See also + +- [naming-decisions](./naming-decisions.md) — the `pi → zot` neutral-naming work +- [quality-gates](./quality-gates.md) — how a half-finished rename reached `main` diff --git a/docs/wiki/index.md b/docs/wiki/index.md new file mode 100644 index 0000000..0f5e502 --- /dev/null +++ b/docs/wiki/index.md @@ -0,0 +1,56 @@ +# Colibri Wiki + +A small, agent-maintained knowledge base for Colibri's **decisions and +architecture** — based on Andrej Karpathy's +[LLM Wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f). + +This is a **pilot**. It deliberately covers a few decision-dense areas, not the +whole repo. + +## Why this exists + +Stale decisions accumulate faster than anyone hand-audits them: a rename that +was only half-applied, a doc that still describes the old design, a default +left over from a superseded choice. Several recent passes were spent finding +exactly that (`pi → zot`, `usb_nodes → hive_nodes`, `fake → sample`). This wiki +makes the bookkeeping near-zero-cost: one place that records _what was decided_, +links to _where it lives in code_, and can be **linted** for drift. + +## Conventions (the schema) + +These rules keep the wiki a maintainable artifact, not a second source of truth: + +1. **Code is the source of truth.** Pages describe _decisions_ and _where_ they + live; they link to code/docs rather than re-explaining implementation. When a + decision ships, slim its page to "how it works + link." +2. **Link, don't duplicate.** Reference code as `path/to/file.rs:line` and other + wiki pages with relative links (`[label](./page.md)`) — Forge-clickable, the + equivalent of Obsidian `[[wikilinks]]` adapted to a repo. +3. **One decision per page** where practical; cross-link liberally. +4. **Flag, don't silently overwrite.** When new code contradicts a page, note + the contradiction (and resolve it) rather than quietly editing history. +5. **Lint, don't trust.** A page is a claim to be checked against code, not a + guarantee. + +## Lint workflow (the point of the pilot) + +`lint` = an agent pass that reads each page and checks it against the current +code: stale names, dangling references, contradictions, decisions that shipped +but whose page still says "planned." Output is a **report**, not auto-edits — +advisory first, until the signal is trusted. (Tool TBD — pilot step 2.) + +Open drift already noted by hand: + +- `stage-colibri-iso.sh` (clawdie-iso) and a guardrail comment reference + `ADR-agent-harness-consolidation.md`, which **does not exist** in either repo. + The real architecture statement is `AGENTS.md`. → see [agent-harness](./agent-harness.md). + +## Pages + +| Page | What it covers | +| ----------------------------------------- | ------------------------------------------------------------------------ | +| [agent-harness](./agent-harness.md) | The zot (agent) + Colibri (control plane) split; autospawn + RPC driver | +| [naming-decisions](./naming-decisions.md) | Ledger of harness-neutral / architecture renames — shipped and in-flight | +| [quality-gates](./quality-gates.md) | `ci-checks.sh` as the pre-merge gate; why drift reached `main` before | + +_Pending: a `mother-hive` page once the mother MCP infra lands (colibri #161)._ diff --git a/docs/wiki/naming-decisions.md b/docs/wiki/naming-decisions.md new file mode 100644 index 0000000..4a27c3f --- /dev/null +++ b/docs/wiki/naming-decisions.md @@ -0,0 +1,43 @@ +# Naming decisions ledger + +← [index](./index.md) + +A living record of renames driven by superseded assumptions, so future drift is +checkable against one list. "Shipped" means merged to `main`; verify against the +linked code before trusting a row. + +## Shipped + +| Old → New | Why | Anchor | +| ------------------------------------------------ | -------------------------------------------------------------------- | ---------------------------------------------- | +| `COLIBRI_AUTOSPAWN_PI` → `COLIBRI_AUTOSPAWN` | Harness-neutral (default agent is zot, not pi) | `crates/colibri-daemon/src/socket.rs` | +| `COLIBRI_PI_BINARY` → `COLIBRI_AUTOSPAWN_BINARY` | same | `socket.rs` (`autospawn_agent_if_configured`) | +| `pi_session_id` → `session_id` | zot agents have session ids too; `#[serde(alias)]` keeps back-compat | `crates/colibri-glasspane/src/lib.rs` (`Pane`) | +| `fake-pi-agent.py` → `sample-pi-agent.py` | "fake" too loaded; it emits a canned _sample_ | `scripts/sample-pi-agent.py` | +| non-local spawn default `hermes-agent` → `zot` | `hermes-agent` was a nonexistent leftover binary | `socket.rs` (`default_agent_args`) | + +## In-flight + +| Old → New | Status | Anchor | +| -------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------ | +| `usb_nodes` → `hive_nodes` | colibri #161 (a node is any host that joined the hive, not only a USB boot; `+node_type` column) | `packaging/mother/mother_schema.sql` | + +## Known residue (not yet actioned) + +| Item | Note | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `pi_type` | pi-era name for "normalized event type"; **internal only**, not serialized. Optional rename → `event_type`. `crates/colibri-glasspane/src/lib.rs` | +| `FEATURE_COLIBRI` | `AGENTS.md`/README imply "no separate feature flag," but the build keeps it (default YES, "internal escape hatch"). Reconcile wording or flag. (clawdie-iso) | +| `clawdie-startx` | README teaches `clawdie-gui`; `startx` kept as the internal wrapper — documented transition, verify the user-facing launcher leads with `gui`. (clawdie-iso) | +| `ADR-agent-harness-consolidation.md` | Referenced but does not exist; `AGENTS.md` is the real anchor. See [agent-harness](./agent-harness.md). | + +## Structural decisions + +| Decision | Why / lesson | Anchor | +| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| Single home for mother infra = colibri | The mother MCP scripts were copied into both colibri and clawdie-iso; the iso copy drifted to an **SQL-injectable** `node-register-mcp` on `main`. Same script in two repos drifts — a lint pass should flag cross-repo duplicates. | colibri `packaging/mother/`; iso removal in iso PR #129 | + +## See also + +- [agent-harness](./agent-harness.md) +- [quality-gates](./quality-gates.md) — the gate that should catch these at PR time diff --git a/docs/wiki/quality-gates.md b/docs/wiki/quality-gates.md new file mode 100644 index 0000000..353992c --- /dev/null +++ b/docs/wiki/quality-gates.md @@ -0,0 +1,42 @@ +# Quality gates + +← [index](./index.md) + +## Decision + +A change is not "done" until the gate passes locally: + +```sh +./scripts/ci-checks.sh # cargo fmt --check, clippy -D warnings, cargo test, markdown gate +``` + +`.forgejo/workflows/ci.yml` encodes the same checks, but **no Forgejo Actions +runner is registered**, so nothing enforces them server-side. Until a runner is +active, `ci-checks.sh` passing locally is the only gate. Stated as mandatory in +`AGENTS.md`. + +## Why this page exists + +A compile break (`pi_binary` undefined, from a half-finished rename) reached +`main` because the gate was skipped _and_ unenforced. The same audit found both +gates were effectively red on `main` at the time: + +- `clippy -D warnings` failed on a pre-existing lint → the Rust gate would have + failed for anyone who ran it. +- the markdown gate failed on prettier-dirty docs. + +Both were brought green, so the gate is now actually runnable. The lesson: a +gate nobody runs (and that's red anyway) is the root cause of drift reaching +`main` — more than any individual naming slip. + +## Relationship to this wiki + +The [naming-decisions](./naming-decisions.md) ledger + a future `lint` pass are +the _semantic_ counterpart to `ci-checks.sh`: the compiler/clippy catch broken +_code_, but not a doc that still describes the old design or a name that drifted. +The wiki lint is meant to cover that gap (advisory first). + +## See also + +- [agent-harness](./agent-harness.md) +- [naming-decisions](./naming-decisions.md)