Skip to content
GitHub
Decisions

Overview

Architecture Decision Records (ADRs)

How we keep decisions and domain docs

Two forward design genres. ADRs capture a researched decision — the choice, why, and the rejected alternatives — written only when a choice warranted weighing options. The Codex (apps/docs-codex/) documents the domain and its behaviors — the broad design; most of it has no ADR. Both are authored before code and seed the backlog.

One current version. Each ADR states the decision as it stands now. When a decision changes, rewrite it in place — no supersession chains, no per-decision tombstones, no narrative of how it changed. Git holds the past.

Keep the why, drop the changelog. An ADR keeps its rationale and rejected alternatives, so settled questions stay settled. It does not record how we got here.

Realization lives in the tracker, not the docs. ADRs and the Codex are the design; Linear / the milestone says how much is built. No status field on ADRs — a doc can legitimately run ahead of the code during a build window.

Two checkpoints. At authoring, validate against the live corpus (coherence; no contradiction with other current decisions). At close — folded into “verify before closing” — reconcile the governing ADR and the Codex pages you touched against the built code: matches → it stands; the build taught us better → rewrite the doc; the doc was right → fix the code.

Reversed → rewrite. Abandoned → delete.

Format

Every ADR is a markdown file named NNN-short-title.md holding the decision, its rationale, and the alternatives considered. The number is a stable handle for cross-references, not a chronology.

Discipline rule

Any decision that shapes more than one epic or more than one file deserves an ADR. This is a default, not a ceiling — write an ADR whenever the reasoning is worth preserving for a future reader who joins after the context has evaporated.

  • Prefer one ADR per cohesive decision. If a decision bundles several related sub-decisions (as ADR-012 does with four dev-tooling choices), keep them together rather than splitting into separate ADRs that always have to be read as a set.
  • Link ADRs from the Linear issue that prompted them and from the Codex page that documents the resulting system behavior. ADRs are why; Codex is what; Linear is when.
  • A decision changes → rewrite its ADR in place to the new current state. A decision is abandoned → delete its ADR. There are no Supersedes:/Amends:/Status: headers, no supersession pointers, no “Retired/folded into” notes — in the ADR, the index, or anywhere. Git holds the past. (See §“How we keep decisions” above.)
  • Discipline reminders for day-to-day work live in AGENTS.md at the repo root.

Adding a new ADR

  1. Pick the next unused number (ls docs/decisions/ and take the highest + 1; numbers skip over retired-and-deleted ADRs).
  2. Copy _template.md to NNN-short-title.md and rename.
  3. Fill in Context, Decision, Alternatives Considered, and Consequences.
  4. If this decision replaces a prior one, don’t write a “superseding” ADR: rewrite the existing ADR in place to the new current state, or — if the prior decision is wholly abandoned — delete its file and sweep live references to the current decision. No Supersedes: header, no addendum, no tombstone.
  5. Add a row to the Index below (number + linked title). Remove the row of any ADR you deleted.
  6. Land the ADR in the same change as the code it governs when possible — the ADR and its first consumer ship together.

Index

#TitleSummary
001Three-context architecture (worlds, platform, core)The package boundary is the context boundary; inter-context isolation + Clean-Architecture layers enforced by the architecture validator.
006API versioning and RESTful conventionsRESTful conventions for the API surface — resource shape, status codes, error envelope, router structure.
007LangGraph agent architectureLangGraph is the agent orchestration framework; the closed-over-DI tool-factory pattern.
012Dev tooling — Biome, git-cliff, tiered commit hooks, ruff TD rulesBiome, git-cliff release notes, tiered commit hooks, ruff TODO-comment rules.
015SystemCard protocol with authority and authority versionThe SystemCard protocol carries an authority + authority_version convention across the context boundary.
018Memory system — three tiers, world signal pathA three-tier agent-memory architecture with a signal path into Worlds.
022Eval generation architectureHow evaluation sets are generated and structured.
025System card authority basisThe basis on which a system card asserts authority.
026World model version as unit of authorityA published world-model version is the unit of decision authority.
029US Individual Tax Preparation as the first world-model domainThe first dogfood domain is US individual (1040) tax preparation.
030Authority version as metadata-only across the context boundaryAuthority version crosses the context boundary as metadata only, not a typed dependency.
031Single-library Python package with per-app leaf namespacesOne installable library package (spectral) under src/spectral/; apps are leaf namespaces.
032Storage topology — single Supabase project, three application schemasOne Supabase project; three application schemas plus core; forward-only migrations.
033Tenancy enforcement layeringApp-layer tenancy filtering is primary; RLS is the backstop; operator access is assumed-identity act-as.
034Frontend data access via API proxyFrontends reach data only through the API proxy; no direct browser→Supabase SDK.
035LLM stack — in-process control planeThe in-process LLM control plane and the call boundary.
036Observability stack — OTel substrate; three-stream LLMOpenTelemetry substrate; a three-stream model for LLM observability.
037Secrets management — provisioning scriptSecrets resolve through the provisioning-script seam; BYOK reserved.
038Embedding model + hybrid retrievalThe embedding model choice and hybrid (dense + lexical) retrieval.
039Supabase Auth confirmation + hardeningSupabase Auth is the auth substrate, with confirmation + hardening measures.
040Disaster recovery — Supabase-native managed backups + PITRDR is Supabase’s managed backups + PITR on a regenerable alpha; no self-run pipeline.
041Connection pooling architecturepsycopg3 async; session-pooler vs direct-connection strategy.
042Data retention — four-state lifecycleA four-state data-retention lifecycle.
043Agent conversation persistenceConversation-persistence patterns via the LangGraph checkpointer.
044Event substrate — LISTEN/NOTIFY + outboxThe event substrate: a transactional outbox with LISTEN/NOTIFY delivery.
045Test Supabase instance lifecycleHow the test Supabase instance is reset and seeded across the suite (no DB mocks).
046Foundational alpha decisions — subdomains, frontend, auth pattern, dev tooling, SupabaseSubdomain layout, TanStack Start, Pattern-A JWKS auth, build/dev orchestration, supply-chain pin, Supabase.
047Operations as a separate deployableThe operations console is a separate deployable surface.
049Container build strategy — repo Dockerfiles, debian-slim-trixie base, one deployed app containerBuild from repo Dockerfiles (digest + lockfile pinned); the deployed runtime is one collapsed app container; backup container retired.
050TanStack Start + frontend SPA disciplineTanStack Start frontends render in SPA mode at alpha; SPA discipline.
051Python type checker — ty primary, ruff ANN backfillty is the primary type checker; ruff ANN rules backfill annotations.
052Cloudflare edge — DNS, TLS, proxied hostnames, WAF postureCloudflare is the edge: DNS, TLS, all product hostnames proxied (incl. api.), per-key rate limiting + WAF, codex Pages-Function JWKS, cookie discipline.
053CD pipeline — fast-forward production-branch deployA fast-forward push of production fires the reusable GitHub-Actions deploy engine; one container deploy; /health smoke go/no-go; forward-fix rollback.
054DLQ + retry semanticsDead-letter-queue and retry semantics for the event substrate.
055Curation → Worlds interface contractThe interface contract from curation into Worlds.
058World Agent memory + agent-memory primitivesWorld Agent memory and the agent-memory primitives.
060Agent tool invocation, framework-layer composition, and LLM-mediated error handlingThe cross-cutting agent tool-invocation contract — error taxonomy, LLM-mediated handling, approval payload, DI composition.
061LLM testing strategyThe cassette-based record/replay testing strategy for LLM calls.
062CI secrets handlingCI secrets handling, fork-PR safety, and Environment scoping.
063Inter-context access pattern — no SQL grantsInter-context access is mediated, never via cross-schema SQL grants.
064Notification-shaped reads — event-driven local replicaNotification-shaped reads served from an event-driven local replica.
065Contract surface — admission rules and payload patternspectral.core admission rules + the opaque-payload contract pattern (producer-typed payloads, consumer ACL).
066Snapshot-based contract testing with syrupyContract tests use syrupy snapshots over model_json_schema().
068Pragmatic methods on kernel value typesKernel value types may carry pragmatic methods (clarifies the admission rule).
069Trigger-driven spectral.core re-auditThe killer-test kernel re-audit is trigger-driven (not scheduled) — audit-candidate signals, the procedure, and tracked records.
070Inter-context mechanism selection — simplest-fit ladderA simplest-fit ladder for choosing the inter-context mechanism.
071Flat application module placementApplication modules sit flat under the context, not nested by feature.
074Retire the scan pipelineThe scan pipeline and its tournament/holdout machinery are retired.
075Retire customer-facing eval generationCustomer-facing eval generation is retired; evals are an internal world asset.
076Platform pillar as decision-module hostThe platform pillar hosts decision modules.
077Decision API surface — /api/decide and MCPThe decision API surface: /api/decide plus the MCP binding.
078Retire the Spectral AgentThe standalone Spectral Agent is retired; the surviving topology is the single World Agent.
079Retire the memory-tier signal path to WorldsThe T3-memory→Worlds signal path is retired.
080Decision-module integrity — content hash and operator approvalModule integrity via content hash + operator approval.
081World Agent role expansion and session boundaryThe World Agent’s expanded role and its session boundary.
082System Card and World Model Card under the in-band shiftThe System Card / World Model Card model under the in-band decision-support shift.
083Decision-module execution sandbox — layered defense, language-agnosticLayered, language-agnostic sandbox defense for executing decision modules.
084Multi-tenant noisy-neighbor handlingRate limiting and per-tenant observability for noisy-neighbor handling.
085Module store consistency — content-addressed storage with event-driven projectionContent-addressed bundles on the core.storage object store; commit-then-signal upload; honor-or-refuse; event-projected routing.
086Tenancy hierarchy — org and domainThe org/domain tenancy hierarchy and naming.
087Subject-identity delegationJWT shape, act claim, lifetimes, revocation, and issuance for subject-identity delegation.
088MCP surface — tool shape, resource shape, auth, decision-module bindingThe MCP surface specifics.
089Action discoverability endpointOpenAPI 3.x action discovery per (org, domain), with version pinning.
090World Agent positioning and the world-model evolution workflowWorld Agent positioning and the world-model evolution workflow.
091API versioning — date-based, key-pinned, additive-onlyAPI versioning is date-based, key-pinned, and additive-only.
092read:actions scope — action-registry read accessThe read:actions scope for action-registry reads; module approval is operator-only.
097Architecture-validator rule registryThe canonical slugged rule set for the architecture validator + kernel dependency-direction discipline.
098Domain and world as distinct entities with a one-to-one linkDomain and world are distinct entities under a 1:1 link; the active version is world-owned.
099Core infrastructure zoneIn-kernel infrastructure implementations of core contracts (the core/<area>/infrastructure/ zone).
100Rule-provenance model — four axes and authoritative-source taxonomyThe rule-provenance model: four axes and the authoritative-source taxonomy.
101Alpha agent topology — one agent (the World Agent)One agent (the World Agent), serving operators directly.
102LLM execution stack — LangGraph orchestration + LangChain structured-stepLangGraph orchestration + LangChain with_structured_output; DSPy deferred post-alpha.
103Decision-authority positioning and the alpha product vocabularyDecide-and-prove positioning; Workspace/Ruleset vocabulary; “world” internal-only; lifecycle labels; verify-at-review; publish-and-deploy.
104Action registry and per-action module deploymentA world declares a real action set; one content-addressed module per action; the wildcard catch-all retired.
105Tenancy authority & ownership modelOwner owns tenancy (operator participates, never owns); ≥1-owner invariant; self-service org provisioning + cold-start REST contract.
106Rule-outcome model and winner_takes_all aggregationA rule emits a static four-state outcome; severity is a sort/suppression axis under winner_takes_all.
107The action’s canonical input ontology, reconciled at publishAn action carries a persisted canonical input ontology; a publish-time reconciliation converges its rules’ divergent input names onto it (published inputs frozen, enshrined-unpublished rules freely rewritten).
108Behavioral-completeness publish gateAn independent behavioral spec → discriminating tests → predicate-to-pass → mutation gate enforces behavioral completeness at publish.
109Cloudflare hosting topology — one app container, predicate in-process, Supabase lockedOne Cloudflare app container (API + workers entrypoints), predicate in-process, World Agent in workers, outbox over the session pooler, generation-stamped deploy.
110Provisioning by config resolution + GitHub Actions deploy — no Terraformprovision.sh resolves an environment (infra/environments.toml + 1Password) into a GitHub Environment; GitHub Actions deploys and reconciles vendor resources via wrangler + CLIs.

TA-N spike identifiers

References to “TA-1,” “TA-3,” “TA-5,” “TA-19,” etc. inside ADRs in the 032–065 range are spike identifiers from the 0.3.0 Tech Arch Review (TAR), which ran approximately TA-1 through TA-27. Each spike’s disposition produced one of the ADRs in this set. The TA-N → ADR mapping is preserved in the corresponding Linear issues and in git history; it is not reproduced here. A future reader landing on a TA-N reference inside an ADR can treat it as the spike-era identifier for that ADR’s disposition.