Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The self-similar shape

Why this exists ends on the coherence problem: self-building platforms accrete one-off pieces, and automatt’s unifying moves only half-worked. Supernova’s answer is structural: every system in the platform has the identical five-part shape, keyed by one canonical name, so every piece of code has an obvious home and an auditable contract. The shape is the contract a new system must satisfy, not a convention it may follow. [built in-repo] — the shape is enforced by a scaffolding validator in the Rust workspace; no Supernova instance is production-deployed.

Five parts, one name

Pick a system name — issue, monitor, vcs — and the name keys everything:

PartWhere it livesWhat it is
Code foldersystems/<name>/the system’s logic and long-running services
Client librarysun_lib/<name>the stateless typed front door
CLI namespacesun <name> ...thin wrappers over the client library
Wiki docsthe system’s wiki foldermandatory index plus requirements, invariants, interfaces
Config section<name>:one top-level key in the single config.yaml, singular canonical name

The governing rule is blunt: “All sun commands fall under a system.” There is no miscellaneous drawer.

A new system inherits the platform for free: bus topics under the event.<system>.<entity>.<verb> convention on the shared Kafka bus, CLI dispatch and namespace registration, a config section with schema validation and hot reload, the docs contract whose requirements/invariants/interfaces (RII) sections make the shape auditable — an undocumented interface is a flaggable gap, enforced by the wiki validator — and, by design, rendering in the shared frontend.

sun_lib: a lens, never a store

Two invariants carry most of the shape’s weight, both from Matt’s 2026-06-04 ruling: sun_lib holds only client/frontend libraries, and it never owns authoritative state. Nova — automatt’s lead agent — produced the formulation that stuck as the platform-wide invariant: “sun_lib is a lens, not a store” — swap, rebuild, or wipe it and nothing authoritative is lost. A client library calls into the system that owns the data; ephemeral convenience (a connection handle, a brief in-call cache) is permitted, persistent state is forbidden. This is the flagship rule on the platform-wide critical list that review checks every patch against.

The frontend falls out of this invariant rather than being designed separately. It is not a system: it is a renderer inside core (2026-06-20, final), “the visual sibling of the CLI.” CLI and UI are two stateless consumers of the same sun_lib — text layer and rendering layer — and each view is owned by and derives its spec from its host system. [supernova design] — the renderer itself is unbuilt; the CLI framework, dispatch, and shape validation are implemented in the workspace.

core itself is the one deliberately different system: horizontal rather than vertical, owning framework concerns (CLI entrypoint, scaffolding, the sun_lib aggregation, the config-schema registry) and never a domain’s rules. It earned system status by accumulating real occupants — Nova: “‘util’ is junk-drawer name; ‘core’ is the same stuff with self-respect.”

The map around the bus

Nineteen systems (the set is open-ended), everything riding one Kafka bus:

flowchart LR
    delivery["delivery loop: issue, workflow, agent, wiki, vcs, project"]
    boundary["external boundary: link, ingest, chat"]
    control["control and proof: monitor, ops, test, review"]
    substrate["substrate and safety: core, config, auth, permission, approval"]
    bus["bus: Kafka substrate + bespoke reactor"]
    delivery -- "emit events" --> bus
    bus -- "reactor dispatches" --> delivery
    boundary -- "inbound events" --> bus
    bus -- "gated outbound" --> boundary
    bus -- "metrics and alerts" --> control
    control -- "actions back onto the bus" --> bus
    substrate -- "config and identity events" --> bus

The groupings are descriptive, not architectural — every system talks to every other system the same way, over bus events and stateless library calls. The one sanctioned exception to “everything rides the bus” is ops’ bus-independent Kafka broker health probe, since the broker cannot report its own death over itself (see the supporting cast).

Adding a system

Adding a system is a defined path, not a redesign. sun system new scaffolds the five parts; the shape validator checks them; the new system inherits topics, dispatch, config, docs contract, and rendering as above. There is no fixed system count — the 2026-06-20 ruling struck the earlier “20 confirmed systems” framing, and the canonical systems doc now reads: “19 systems as of 2026-06-24. The count is descriptive, not a cap.”

The set shrinks by the same discipline it grows: audit folded into monitor, reactor into bus, memory into agent, scheduler into workflow, deploy into ops, and refactor was removed as a system outright, surviving only as the wiki move/rename verbs. Each fold is a recorded ruling in the decision ledger.

Cold start: a hint, not a gate

There is a recommended bring-up order (Matt’s ruling, 2026-06-19): config → permission → auth → bus → approval → workflow → e2e test → the rest, with Sentinel — the monitor’s alert-consuming agent (see the supporting cast) — last. The testing rig stands up immediately after the first safety primitive, so every system built afterward lands with a working way to validate it end-to-end — instead of bolting testing on at the end.

But per D67, encoded as standard S24 (2026-06-20), that order is a hint that minimizes retry churn, not a correctness gate. Every system must start and restart in any order — a system whose dependencies aren’t up yet retries until they are — and any single system must be restartable while the rest of the platform stays stable. The one hard edge: static config must exist before the bus can read it. Order-independence is what makes isolated restart and rolling single-system updates possible; the ordering is a cheap optimization on top.

Build or buy

The default is bespoke carry-over from automatt. Specific calls, from the canonical systems doc — every “buy” is self-hosted on owned hardware, per the owned-infrastructure principle:

ConcernDecisionWhy
Bus transportBuy: self-hosted Kafkathe bespoke Python bus was “consistently painful + slow”
Bus reactorBuildthe event-to-action dispatch arm on top of the bought substrate
Workflow engineBuy: self-hosted Temporaldurability, retries, observability; scheduling = Temporal Schedules
MonitoringRebuild: OTel + Prometheus + Grafanathe stack existed in automatt but was “barely used”; the rebuild wires it end-to-end
StorageBuy: self-hosted Postgrescross-cutting infrastructure, not a system
SecretsBuy candidate: an encrypted-local store (sops/age-style)auth’s storage substrate; Vault and AWS SM were explicitly ruled out as too heavy / off-owned-infra; the identity model above it is bespoke
Issue trackingBuild“a single type in a database”; buying eats lock-in for nothing
WikiBuild, carry-over“I like the way wiki works, no plan to change it”
IngestBuildnothing off the shelf does trust-tiered, injection-contained, two-gate triage
Test harnessBuild: Rust sun-testowned-hardware constraint disqualifies metered CI — no GitHub Actions, no SaaS
Everything elseBuild / carry-overbespoke domain logic; carry-over means no decision was needed, not a pending gate

The pattern: buy the substrate (transport, durability, storage, dashboards, secrets), build every system whose rules are the product.

What this costs

The shape is a uniformity tax. Every system — including trivial ones — pays for five parts: a docs contract with RII sections, a config schema, a CLI namespace, a client library. The bet is that the tax is cheaper than the drift it prevents, but the tax is real and paid up front.

core is a standing junk-drawer risk: a horizontal system that hosts every other system’s CLI and libraries accretes by default. Two invariants guard it (stays thin on domain logic; sun_lib stays a lens), and automatt provides the cautionary precedent of a CLI that grew fat because it became where logic lived. The guard is a review rule, not a law of physics.

The open-ended count cuts both ways: adding a system is cheap by design, which invites sprawl. The fold record shows the pruning pressure works so far — but “so far” is a design corpus plus a workspace, not a platform under years of load.

And the gap: the frontend renderer is design-only, and no part of the shape has been exercised by a standing production deployment. What exists today is the contract, the scaffolding, the validator, and in-repo test evidence — the shape’s real test, a stranger adding a system without asking anyone, hasn’t happened yet.