OXYGENHUB
# f7986cb07b0e spectra / docs / implementation-prompt.md
14.5 KiB · Markdown · last changed Specification Draft 0.3 and the implementation prompt 2 days ago renderedsource blame history raw
1
# Implementation prompt: Spectra 0.1
2
3
This is the prompt to hand to the implementing agent (Opus 5.5) to start Spectra. Paste everything below the line.
4
5
---
6
7
You are implementing **Spectra**, an agentic control plane in Rust, from its specification. You are working for Andy, in `~/development/spectra`, which is an Oxygen repository (not Git). Read these before writing any code, in this order:
8
9
1. `~/development/spectra/docs/spec.md`, Draft 0.3, the whole thing. It is the source of truth. Where it says MUST, do that; where it is silent, follow Oxygen.
10
2. `~/development/oxygen/`: the project Spectra must feel identical to. Read `README.md`, `Cargo.toml`, `Makefile`, `build.rs`, `scripts/changelog-check.sh`, `.flow/pipeline.kdl`, `.oxyignore`, `.oxyattributes`, `CHANGELOG.md` (the first 60 lines), `docs/plan.md`, `src/main.rs`, `src/cli/mod.rs`, `src/cli/ui.rs`, `src/cli/json.rs`, `crates/oxy-core/src/mcp.rs`, `crates/oxy-core/src/identity.rs` (identities, delegates, composite signatures, `sign_challenge`), the deterministic CBOR encoding in `oxy-core`, `docs/ai_native_agent_workflows.md` §2, and `tests/cli_json.rs` and `tests/cli_mcp.rs`.
11
3. `~/development/oxygenhub/`: `Makefile`, `rustfmt.toml`, `crates/hub/src/{main.rs,config.rs,bus.rs,live.rs}`, `crates/hub/src/db/`, one template under `templates/` and `templates/base.html`, and one test under `crates/hub/tests/`. The hub is the reference for axum, sqlx, askama, the event bus, SSE and the test harness that starts a server on a loopback port.
12
13
## The one rule about shape
14
15
**If it looks like something in Oxygen, it must look the same in Spectra.** A developer who moves from `oxygen` or `oxygenhub` to `spectra` must find every file where they expect it, with the same name, the same targets, the same flags and the same conventions. When you are about to invent a file, a target, a flag, a directory, a test helper or an output format, first look for how Oxygen does it and copy that. Concretely:
16
17
| In Oxygen | In Spectra |
18
|---|---|
19
| `Cargo.toml` workspace with `[workspace.package]` (version, edition 2021, license `MIT OR Apache-2.0`), members `crates/*` and `.`, the binary package at the root with `src/main.rs`, `default-run`, `mimalloc`, `clap` derive, `clap_complete`, `clap_mangen` | The same, package `spectra`, binary `spectra`, version `0.1.0`, members `crates/spectra-core`, `crates/spectra-mcp`, `crates/spectra-api`, `crates/radar`, `.` |
20
| `crates/oxy-core` (library, no CLI concerns) | `crates/spectra-core`, which depends on `oxy-core` (by path during development, pinned as a subrepo under `deps/` as the hub pins its dependencies) for identities, signatures, deterministic CBOR and hashing. Never reimplement those |
21
| `oxy-core::mcp` (hand-rolled JSON-RPC 2.0, `Tool`, `ToolOutput`, `PROTOCOL_VERSIONS`, nothing on stdout but protocol) | `crates/spectra-mcp` starts from a copy of that module's shape and adds the stateless Streamable HTTP endpoint and `server/discover` (spec §15.1); keep the names `Tool`, `ToolOutput`, `read_only`, `destructive` |
22
| `src/cli/mod.rs` (clap tree), `src/cli/ui.rs` (colour, glyphs, spinners, `--plain`, `NO_COLOR`, non-TTY detection), `src/cli/json.rs` (`--json` printing one document) | Copy `ui.rs` and `json.rs` as they are, with the names changed; every listing command takes `--json` and `--plain` exactly as `oxy` does |
23
| `build.rs` and `OXY_BUILD` (the build identity from `oxy describe` in `--version`) | `build.rs` and `SPECTRA_BUILD`, the same mechanism; `spectra version --json` as `oxy version --json` |
24
| `Makefile` | The targets of **oxygenhub's** Makefile (`build`, `check: changelog fmt clippy test`, `changelog`, `fmt`, `clippy`, `test`, `run`, `ts`) plus **oxygen's** `install` target (release build with the build identity, symlink into `~/.local/bin`, print `--version`). `run` is `cargo run -- --data data serve`. `ts` writes `crates/spectra-api/ts/index.d.ts` the way `hub-api` does |
25
| `scripts/changelog-check.sh` | Copy verbatim |
26
| `scripts/dist.sh` | Copy and adapt the names; the artifact list is `spectra-<os>-<arch>.tar.gz`, `spectra_<arch>.deb`, `spectra-src.tar.gz`, `SHA256SUMS` |
27
| `.flow/pipeline.kdl`, `.flow/warm-target.sh` | Copy; the jobs are `fmt`, `clippy`, `test` (nextest with llvm-cov, junit and coverage artifacts), `build`, `dist`; `s/oxy/spectra/`; keep the sandbox definitions and the comments explaining them; drop `riscv64` for now |
28
| `rustfmt.toml` (oxygenhub's: `max_width = 140`, `use_small_heuristics = "Max"`) | Copy |
29
| `.oxyignore` (`/target`, `*.tmp`, `/.claude`), `.oxyattributes` (`CHANGELOG.md merge=union` with its comment) | Copy |
30
| `LICENSE` (MIT or Apache-2.0 at your option, both texts) | Copy with the names changed |
31
| `CHANGELOG.md`: `## Unreleased` at the top, one bold line per change (`**Added:`/`Changed`/`Fixed`/`Security`), the issue number, versions change only at release | The same; your first entries go under `## Unreleased` |
32
| `README.md`: one-paragraph description linking `docs/spec.md`, Status, Install (later), Building, Quick start, Layout table, Licence | The same sections; the existing `README.md` is the start of it |
33
| `docs/plan.md`: the overnight loop ("pick the first unchecked item, implement with tests, run the gated checks, commit with oxy, tick the box with a one-line note, commit again"), a Rules section, Items as checkboxes, a Log | Create it with the 0.1 items from this prompt, and work the loop |
34
| `tests/cli_*.rs`: integration tests that run the built binary against a scratch directory, hermetic (`OXY_HOME`), never touching `~/.config` | `tests/cli_*.rs` with `SPECTRA_DATA` pointing at a temp directory; a `hermetic()` helper with the same name and shape |
35
| oxygenhub `crates/hub/tests/*.rs`: start the server on a loopback port, drive it with a real client, fetch pages | `crates/radar` and `crates/spectra-mcp` tests do the same: start `spectra serve` in-process on a temporary socket and port 0, call tools over the socket with signed requests, fetch pages |
36
| `oxy` output: colour and glyphs on a UTF-8 terminal, plain when piped, `--plain`, `NO_COLOR`; errors on stderr, non-zero exit; `--json` is one document on stdout and nothing else | Identical |
37
| Doc comments: a module comment at the top of every file saying what it is and why, in prose, with the issue or spec section in brackets | Identical; cite spec sections as `(spec §14.1)` |
38
39
Where Oxygen has no counterpart (the event log, tasks, rules, Radar's pages), follow the spec and the hub's idioms (sqlx migrations under `migrations/`, one module per table group under `db/`, askama templates under `templates/` with `base.html`, the stylesheet compiled in, the bus in `bus.rs`, SSE in `live.rs`).
40
41
## Rules (as in `oxygen/docs/plan.md`)
42
43
- **Never run `git init` here and never push this project anywhere but its `oxygenhub` remote.** The repository is tracked with `oxy`; commit with `oxy commit -m "..." PATHS..` (name the paths, as `oxy mcp` makes you). Read `oxygen/docs/mcp.md` if you use `oxy mcp`.
44
- **Tests are hermetic.** Nothing touches `~/.local/share/spectra`, `~/.config` or the network. Every test uses a temporary data directory and port 0.
45
- **Gate every commit** on `make check`: the changelog check, `cargo fmt --all -- --check`, `cargo clippy --workspace --all-targets -- -D warnings`, `cargo test --workspace`. A commit that fails the gate does not happen.
46
- **Every code change adds a CHANGELOG.md line** under `## Unreleased`, or sets `NO_CHANGELOG=1` for a change users will not notice.
47
- **The spec is updated when behaviour the spec describes changes**, with a line in its §27 changelog and a Draft bump. If the spec is wrong or ambiguous, make the smallest decision that keeps it consistent, record it in §26 or the changelog, and carry on; do not stop to ask unless the decision would change the data model.
48
- No new external services, no publishing, no front-end build, no JavaScript framework. Radar is askama plus one hand-written stylesheet plus a small vendored script, as the hub.
49
- Dependencies: prefer what Oxygen and OxygenHub already use (`tokio`, `axum`, `axum-server`, `sqlx` with SQLite, `askama`, `serde`, `serde_json`, `blake3`, `rand`, `clap`, `console`, `indicatif`, `tracing`, `pulldown-cmark`, `ammonia`, `reqwest` in tests). Add a crate only when nothing in that set does the job; `ulid` and `cron` are expected additions. Pin versions the way the two workspaces do.
50
51
## What to build: milestone 0.1, "Talk"
52
53
From spec §25, 0.1 is done when: *Claude Code in `oxygen` and Antigravity in `oxygenhub` each call `brief`, post in `#general`, and see each other's messages via `wait` within a second; the owner watches it on Live.* Work in this order, one plan item per iteration, each with tests, the gate, and an `oxy` commit:
54
55
1. **Skeleton.** The workspace, crates, `Makefile`, scripts, `.flow`, `rustfmt.toml`, `.oxyignore`, `.oxyattributes`, `LICENSE`, `CHANGELOG.md`, `docs/plan.md`, `build.rs`; `spectra version [--json]` and `spectra --help` work; `make check` passes on an empty project. Commit.
56
2. **The ledger** (spec §9, §9.5): `spectra-core::store` opens `<data>/spectra.db` (WAL, `synchronous=NORMAL`, foreign keys), applies migrations, appends events in one transaction with gap-free `seq`, ULID `id`, `at_ms`, `hlc` (hybrid logical clock with the five-minute drift bound), `prev`, `hash` (deterministic CBOR through `oxy-core`, domain-separated BLAKE3) and `auth`, and publishes to the bus after commit. Checkpoints signed by the instance key every 256 events and ten minutes. `spectra admin verify` recomputes the chain and every proof from the ledger alone. The envelope is frozen: write the test that asserts its field set, and the test that an edited row breaks verification. `spectra admin check` and `admin rebuild`.
57
3. **Principals** (§8): `spectra init` reads the owner's identity from their `OXY_HOME` and makes the instance identity; `spectra agent add --home DIR` makes the agent's key pair in its own home and refuses to finish until the owner's identity delegates to it; ownership shown everywhere as `NAME · OWNER's agent`; expiry and revocation honoured from the delegation; `spectra agent list|disable`; `spectra project add|list` reading `.oxy/` and `.oxymodules`; presence as a projection; sessions.
58
4. **Channels and messages** (§10): `#general`, `#humans`, `#system`, one per project, direct on first use; messages with kinds, threads, mentions, refs, the 64 KiB limits, redaction; the `inbox` projection; FTS5 on messages.
59
5. **Tuner over HTTP** (§15.1, §15.2): `POST /mcp` speaking 2026-07-28 (headers validated, `server/discover`, `subscriptions/listen`, `ttlMs` on lists, deterministic tool order, no sessions) and 2025-11-25 (`initialize` accepted); the Unix socket with peer credentials and signed requests (`Spectra-Key`, `Spectra-Time`, `Spectra-Nonce`, `Spectra-Signature`) verified against the ledger's identities and delegations, the assurance level on every event (§8.5), bearer tokens only behind `[security] allow_tokens`; tools `brief`, `rules` (site layer only), `agents`, `status`, `say`, `read`, `inbox`, `wait`, `ack`, `search`, `redact`, with the `_meta` fields, the rules-version line, the idle-`wait` guard (§14.1) and `tool.called` events. Test every tool over the socket with signed requests; fuzz the JSON-RPC parser with random and mutated bodies (as oxygen's CBOR tests do) and assert it never panics.
60
6. **The stdio shim** (§15.1): `spectra mcp --agent NAME`, signing each forwarded request with the agent's key from its home and forwarding over the socket; `tests/cli_mcp.rs` drives it over pipes as oxygen's does.
61
7. **Radar** (§17): `base.html`, the stylesheet (start from oxygenhub's `templates/style.css` tokens and the GitHub-like look; Spectra's mark in `assets/icons/spectra.svg`), the Live (with each agent's owner), Channels, thread and Log pages (the Log with each event's hash and proof, and the head's hash and last verification at the top), the owner's level-2 sign-in through the `--open` one-time link signed by the CLI key (§8.3; the passkey is 0.2), with its banner, CSRF, CSP, `Origin` validation, and `/api/v1/events?follow=1` as the SSE stream with the pages re-fetching fragments. Every page renders without JavaScript.
62
8. **JSON API** (§18) for what exists: `/brief`, `/agents`, `/projects`, `/channels`, `/channels/{name}/messages`, `/threads/{id}`, `/inbox`, `/search`, `/events`, `/health`, `/version`; `spectra-api` types with `serde` and JSON Schema derives; `make ts`.
63
9. **CLI for the human** (§19): `spectra say`, `spectra inbox [--follow]`, `spectra search`, each signing with the owner's key from `OXY_HOME`, with `--json` and `--plain`.
64
10. **Docs**: README sections filled in, `docs/plan.md` ticked with notes and timings, spec §27 bumped for anything you changed, `CHANGELOG.md` under `## Unreleased`. Then run the 0.1 acceptance test by hand against two real clients and record the result in `plan.md`'s Log.
65
66
Not in 0.1: the passkey and the assurance policy (0.2), committed rules and `ref.verified` (0.3), checkpoints into OxygenHub's transparency log (0.5), tasks, claims, decisions, rule layers beyond `site.md`, hooks, `spectra trigger`, the channel shim, schedules, webhooks, the uplink, SpectraHub, the extensions. Do not start them; leave the modules' names in place as empty files with a comment only if a 0.1 piece needs a seam.
67
68
## Quality bar
69
70
- `cargo clippy --workspace --all-targets -- -D warnings` clean; `cargo fmt` clean; every public function in `spectra-core` has a doc comment.
71
- Tests: unit tests beside the code; integration tests under `tests/` and each crate's `tests/`; the projection-equality test (append a random mix of events, rebuild, compare every table) runs after every scenario; a server test per tool; a page test per Radar page.
72
- Performance targets of spec §24 for what exists: measure `brief` and `say` with a thousand events and record the numbers in `plan.md`'s Log, as oxygen's plan records its benchmarks.
73
- Output and errors read like `oxy`'s: short, declarative, naming the thing and what to do.
74
75
## How to work
76
77
Work the loop in `docs/plan.md` exactly as oxygen's: one unchecked item per iteration; implement with tests; `make check`; `oxy commit` naming the paths; tick the item with a one-line note and the time; commit again; append a Log line. If an item cannot be finished in two iterations, note why under it and move on. Write the plan first, as the first commit of the skeleton, and keep it honest.
78
79
Never weaken what §5 promises to make a test pass: if a security rule in the spec is impractical, stop and say so rather than skip it.
80
81
When done with 0.1, stop and report: what is built, what the acceptance test showed, every decision you recorded in the spec, and the measured numbers.