System Handbook · v4 · self-published via the Operus pipeline

Operus

A single-user, Discord-commanded personal operations system on one VM with no inbound ports. Outside data is normalized into one signal hub, scored by an LLM, and turned into reports and pages. A thin reliable Bridge owns the connection, the job runner, and the scheduler; small decoupled tools do the real work and join as data, not code. The autonomous parts can build the system — but never the parts that keep it safe, unsupervised.

Operus Prima Est — the seeing makes the doing.

patterns & core healthy / observable risk / needs attention

01 The Grammar of Operus

Ten named patterns are the whole design. Every part of the system is an application of one of them — learn these and the rest is detail. The first tenet is the one to internalize.

Core Tenet

Tools, Not Scripts — build capability you can call, never steps you re-type

When an action might happen twice, it becomes a tool: a named, tested entry point an agent (or you) invokes by name — a run.sh <verb> --format json subcommand, promoted to a one-line bridge ToolSpec. Never a throwaway shell script an agent has to reproduce from memory. Tools compound: each one is a verb the next agent already knows. Scripts evaporate. If you find yourself writing a script, you've found a missing tool.

Comms Boundary

The Three Channels — the system talks to the world exactly three ways

No fourth is permitted without changing the charter. (1) Voice In — a Discord voice memo is the front door. (2) Reports Out — the bot posts to a Discord channel on a schedule, carrying Cloudflare links to the detail. (3) Forms Back — a Cloudflare form (behind Access) POSTs to a Pages Function that signs it and relays to a private Discord channel; the bot runs only HMAC-verified, allowlisted data-capture. Integrated systems are only Discord (the bus), Cloudflare (the surface), and Fastmail/Todoist (read-only sources, never written). Every channel is outbound-only — no inbound port, no VPN.

The One Seamregistry-as-data

Core ↔ tools coupling is exactly one file: integrations.py → REGISTRY. A tool joins by adding one ToolSpec row (data). No dispatch edits, no new modules.

Propose, Don't Self-Editthe quarantine

Autonomous output is quarantined until a human applies it — !code → a worktree branch you merge; the fitness curator → a reversible overlay; LLM HTML → static, behind Access. The bot can build the system; it can't silently rewrite its own trust boundary.

Deterministic Core, LLM at the Edgesbounded intelligence

Tool logic is deterministic. The LLM appears only as a curator/author at named seams — relevance scoring, page authoring, voice routing, !code — never in the hot path.

One Gatesingle identity

A single authorized-user identity check fronts every command. Everything downstream assumes it passed. New entry points must route through the gate or they bypass it.

Outbound-Onlydial-out

Every external touch dials out — Discord gateway, Cloudflare deploy, collectors pull. There is no server to attack and no inbound port to defend.

CLI as Contractjson over the wire

Tools are standalone and talk only through run.sh … --format json — microservices whose wire protocol is a command line. One shared _lib is the deliberate exception.

Snapshot vs Eventone flag, two shapes

A source is snapshot (overwrite-by-source: weather, tasks, email) or event (append + dedupe: notes, news). One collector flag models both; adding a source is config, not code.

Index, Not Cachethe hub-exception

The hub stores normalized, feed-like signals. When a consumer needs a rich/computed view (a fitness suggestion, an accountability report) it reads the tool directly — flattening would lose information. That's correct, not debt.

Confirm-First for Consequencehuman approves power

High-consequence commands (!code, !page) are proposed from lossy inputs like voice, never auto-run — the bridge hands back a ready command for you to send.

Self-Publishingeat your own pipeline

The system reports through the same Cloudflare pipeline it documents. This handbook ships that way — a static page in local-report/pages/, deployed by publish.


02 System Map

Three layers — collectors feed the hub, the hub feeds the surfaces — with the Bridge as the deterministic core that dispatches everything.

DATA IN ───────────▶ THE HUB ───────────▶ DATA OUT signalstore external pull ┌──────────────┐ Cloudflare Pages (LLM-authored) rss → cloud-native │ signals.db │ ───▶ briefing · accountability · github → releases │ normalize │ career-radar [scheduled 07:00–10] │ + dedupe │ tool harvest (run.sh │ + LLM │ Voice / text (read-only Claude over …--format json) │ score │ ───▶ your data; voiceroute → command) weather·uptime·notes └──────────────┘ email·tasks·milestones ▲ Ad-hoc query !ingest query --min-score the BRIDGE (Discord gateway · job runner · scheduler · registry) ───────── deterministic core; tools join as one REGISTRY row ─────────
BridgeThe reliable core: gateway, async job runner (!job/!code), scheduler, file/log access, the registry. Hand-maintained; never edited by the bot.
signalstoreThe hub — normalized SQLite signal store, dedupe on sha256, dynamic feeds, LLM relevance scoring.
local-reportLLM-authored evolving HTML, plus hand-authored static pages, assembled into one Cloudflare Pages site behind Access.
_lib/claude_clientThe one shared library — a headless-claude CLI wrapper. The deliberate exception to tool decoupling.

03 Command Surface

One auth gate fronts a dispatch ladder: built-in core commands → registry tools → a sync fall-through. No shell anywhere; whitelist matches the first token only.

CommandDoesClass
!ping · !statusliveness; host uptime/disk/mem from /procsafe
!run · !job <name>a whitelisted preset, inline or as a background jobwhitelisted
!jobs · !logs [id]list/inspect jobs; tail a job log or the service journalobservability
!cat <path>read a file, jailed to ~/projects, secret-names blockedname-jailed
!<tool> …registry tools: jot, todoist, fitness, fastmail, weather, accountability, uptime, ingest, voiceroute, ops, metricstools
!ops doctorsystem health in one call — secrets, empty domains, drift, pending branches, egress riskobservability
!intake hereChannel 3 — bind the channel where HMAC-signed Cloudflare-form submissions run (note/metric/check-in)forms back
!page <slug>LLM-author a page and deploy to a public Cloudflare URLpublic egress
!code <proj> <task>autonomous Claude Code in a sparse git worktree, on a branchRCE by design
!reloadhot-reload integrations.py/config.py, AST-validated firstsafe
Voice is a first-class input. A Discord audio memo → local-transcribe (STT) → either a read-only Claude over your data, or — in a !voiceroute here channel — routed to a registered command and run. !code/!page are proposed, not run from voice (Confirm-First for Consequence).

04 Tool Registry

Fifteen registered entries. Each is a self-contained local-* project (own deps, state, run.sh) joined by one ToolSpec. bridge_sync proves the registry matches every tool's declared bridge.json (0 pending).

ToolModeRole
jotcommandnotes; ask/reflect over them (LLM)
todoist · todoist-synccommand · jobopen tasks + completion metrics (by label/project/priority/weekday)
accountabilitycommandmilestones, routines, check-ins → the write-back half
fitness · fitness-curatecommand · jobStrong workout log; LLM catalog curator (reversible overlay)
fastmailcommandread-only inbox + calendar (JMAP)
weathercommandforecast/history/climatology (Open-Meteo)
uptimescheduledendpoint uptime/latency monitor
ingest · ingest-scorescheduled · jobthe signal hub + LLM relevance scoring
voiceroutecommandvoice instruction → registered command (decide-only)
opscommanddoctor (health in one call) · verify (whole-tree tests) · merge (review+ff a !code branch)
metrics · metrics-collectcommand · jobtime-series metric store → a Cloudflare report extra

Supporting: local-report (Cloudflare pipeline), local-transcribe (STT), _lib (Claude client). Archived & recoverable in git: netscan, locascout, rssdigest. 490 tests across 15 suites run green (!ops verify).


05 Components & Versioning

Everything that changes is a codified component with a canonical definition in one registry — operus/registry.json. !ops components lists them and proves no drift (every local-*, the bridge, and _lib is registered); !ops observe attaches live change metrics. The registry is the single source of truth.

Componenta codified unit — the bridge, the hub, each tool, the library, a surface, the meta-tool. Fields: name · dir · kind · version · interface_version · summary.
Kindscorehubsurfacelibrarymetastoretool

The versioning standard

componentsemver MAJOR.MINOR.PATCH — the unit's behavior. Bump in the registry in the same commit as the change.
interfacean integer contract — a tool's run.sh verbs + --format json shape, or the bridge's ToolSpec/dispatch. Bump only on a breaking change; additive verbs keep the same interface_version.
reportan integer per report, auto-incremented in reports.db on each rebuild — shown on the report and on the dashboard.
joban instance, not semver — stamped with the producing component's version; tracked by count + success rate (!jobs --stats).

Page hierarchy & naming standard. The Cloudflare site has a flat, kebab-case slug namespace grouped by page family on the hub (/): doc documentation (/operus, /architecture) · report generated reports (/briefing, /accountability, …) · observe the live dashboard (/observability) · form capture (/capture). /operus is the central docs root; it links to the live dashboard, which tracks every component's version and change count and is regenerated on every publish.


06 Risk Register

Named, not hidden. The trade-offs are correct for a single-operator bot — but a maintainer should know exactly where the power is.

HIGH  !code is unsandboxed RCE, by design. Runs claude -p --dangerously-skip-permissions as the host user. The sparse worktree scopes what's visible, not what's reachable — it can read/write $HOME, hit the network, even push. Contained only by One Gate + Propose-Don't-Self-Edit (it can't target the bridge, its output waits on a branch).

HIGH  !page is public egress. Publishes signal data (email, tasks, calendar) to a Cloudflare URL. LLM-authored, not human-reviewed; the "no-network script" rule for interactive pages is a prompt instruction, not an enforced CSP. Sits behind Cloudflare Access — that gate is load-bearing.

MED  One Gate is the whole perimeter. A single Discord identity is authentication, authorization, and audit. Compromise of that account is total compromise. There is no second factor, no per-command scoping, no action log beyond job history.

MED  Secrets ride into autonomous jobs. !code/!page jobs inherit the bridge's full environment — Cloudflare + Discord tokens, the filesystem. A misbehaving autonomous run has the keys.

LOW  Residual edges. !cat's secret screen is name-based (misses a token inside an innocently-named file). SIGNALSTORE_DB is shared by path-coincidence, not wiring (fragile if a caller ever runs from a different root). calendar/tasks domains are empty until their tokens are set. LLM seams fail-open (kept, not dropped) on a flaky response.


07 Operational Observability

What you can see today, and the gaps. The system is honest about state, but it has no metrics/tracing layer — observability is conversational, pulled on demand.

Built in

Now shipped as tools done

Remaining gaps tools-not-scripts


08 North Stars & Agent Instructions

The single biggest lever on how long and how big an autonomous job can usefully run is the quality of the context it wakes up in. A memory-less !code job in a sparse worktree knows only what it can read relative to its cwd.

What exists. Every project ships VM_LAYOUT.md — a drop-in "where am I?" note an agent reads to orient (it's in a sparse worktree; siblings are read-only by absolute path). This is the seed of the pattern. It tells the agent where it is, not what good looks like.

The charter gap — now filled. Every project ships a CHARTER.md — purpose, invariants (e.g. "read-only; always valid --format json"), definition of done (tests + docs + bridge_sync green), non-goals, and the Grammar patterns it embodies — and the VM_LAYOUT.md notes point at it and at this handbook. A task like "add improvements" is now well-posed: the agent reads the charter first and knows what good looks like, so it runs much further before it needs you.


09 Tooling & Process Improvements

Each "improvement" below is itself a tool to build, not a script to keep — per the tenet.

Built — consolidated into !ops + !metrics done

Processes to adopt


10 Next Steps — a Multi-Agent Setup

Independent tracks, each a focused agent. Ordered by leverage; every track lands a callable tool, never a script (the tenet, applied).

A ✓
!ops doctor shipped — system health in one call, including the CF public-egress risk. Every later track checks its own work with it.
B ✓
!ops merge shipped — tested ff-merge of a !code branch. Its first run resolved the pending code/afb948 branch (24 tests + bridge_sync green → merged).
C ✓
CHARTER.md authored for all 13 projects + a template; VM_LAYOUT.md notes now point at the charter and this Grammar — autonomous jobs wake up with purpose and a definition of done.
D ✓
!ops verify shipped (whole-tree runner, 473 green) and the scheduler now runs todoist-sync (06:45), metrics-collect (06:55), and a 07:30 links-digest posting the Cloudflare report URLs to Discord. The page builds already republish this handbook daily.
E ✓
!jobs --failed shipped — recent failures + an aggregate success rate over jobs.db (and !jobs --stats), with a !logs <id> hint.
F
Remaining — secrets & domains: set the Fastmail calendar URL + Todoist token, run a poll, and confirm the empty calendar/tasks domains fill (!ops doctor verifies). Plus: confirm Cloudflare Access actually fronts the site.

11 Maintenance Runbook

Verify everythingbridge: venv/bin/python -m pytest -q; each tool: python3 -m pytest -q (fastmail/ingest need a venv).
Promote a toolbridge.jsonpython3 bridge_sync.py → paste the ToolSpec!reload.
Apply a gateway editedits to bot.py/voice.py need a service restart!reload only refreshes the registry.
Publish this handbooklocal-report/run.sh publish (or CF_DRY_RUN=1 … to assemble only) → https://scout.pages.dev/praxis.
Secretsone source of truth: the untracked external-command-bridge/.env, mirrored by .env.example, loaded via systemd EnvironmentFile.