Architecture Decision Records
Significant architecture decisions for Hakiri live here. Other spec files describe what the system does; ADRs describe why it is shaped that way and what alternatives were rejected.
Why a separate folder
Section titled “Why a separate folder”- The narrative specs (
01-architecture.md…09-access-control.md) and the top-levelPRD.mdread better when freed of “we considered X but chose Y” detours. - Decisions need a stable identifier (
ADR-0004) that’s quoted in PRs and commit messages without dragging in surrounding prose. - A separate file per decision is greppable, diffable, and supersedable. When a decision is overturned, we add a new ADR and mark the old one superseded — we don’t rewrite the original.
| ID | Title | Status | Supersedes |
|---|---|---|---|
| 0001 | WIT + WASM Component Model as the connector contract | Accepted | — |
| 0002 | Parquet + JSON manifest layout, not Iceberg / Delta | Accepted | — |
| 0003 | TOML for humans, JSON for agents, one canonical schema | Accepted | — |
| 0004 | DuckDB as the primary query face; SurrealDB rejected as core | Accepted | — |
| 0005 | Last-write-wins sync with cursor-kind awareness, no CRDTs in v0 | Accepted | — |
| 0006 | Durable Object SQLite over D1 for the Cloudflare catalog | Accepted | — |
| 0007 | RDS Postgres as the AWS catalog; EFS-mounted SQLite rejected | Accepted | — |
| 0008 | Embedded hakiri coord over external etcd/ZooKeeper for clustering | Accepted | — |
| 0009 | Cloudflare and AWS are the only first-class cloud targets in v0 | Accepted | — |
| 0010 | Polars as the transform engine; Python and TypeScript as authoring surfaces | Accepted | — |
| 0011 | trait Catalog semantic invariants pinned across SQLite / DO SQLite / RDS Postgres / DynamoDB | Accepted | — |
| 0012 | Three feature-flagged build profiles (hakiri-core / hakiri-full / hakiri-coord) with CI footprint gates | Accepted | — |
| 0013 | Loro over Automerge for the team-mode config CRDT | Accepted | — |
| 0014 | Cloudflare-first team execution with self-hosted Rust hakiri-control parity | Accepted | — |
| 0015 | Inference zones with Incognito mode, enforced by policy + capability token | Accepted | — |
Template
Section titled “Template”# ADR-NNNN: <short imperative title>
- **Status**: Proposed | Accepted | Superseded by ADR-XXXX | Deprecated- **Date**: YYYY-MM-DD- **Deciders**: <names or roles>- **Related specs**: links into specs/
## Context
What forces are at play? What constraints, requirements, or principlesmake this decision necessary? Keep it to the facts a reader needs tojudge whether the decision still applies.
## Decision
The choice, stated as a single declarative sentence followed by theshape of the implementation.
## Consequences
- Positive: what this unlocks.- Negative: what this costs.- Neutral: what it makes structurally different but not better or worse.
## Alternatives considered
For each rejected alternative: one paragraph on what it would havelooked like and the specific reason it lost. Do not paste a featurematrix — that belongs in the body of the decision if it's trulyload-bearing.
## References
- Links to PRs, design docs, conversations, external articles, or prior ADRs that informed the decision.Authoring rules
Section titled “Authoring rules”- One decision per ADR. “TOML + JSON dual format” is one decision. “Connector contract” is one decision. Bundling unrelated choices makes them hard to supersede individually.
- Past tense for the decision, present tense for consequences. “We chose X” / “X means Y is true today.”
- No churn. Once Accepted, do not edit the Context / Decision / Alternatives sections. Add a new ADR that supersedes this one.
- Link from the spec, not vice versa. Specs cite ADRs (
See [ADR-0004](./adr/0004-...)); ADRs cite specs by section anchor. Single direction keeps the graph clean. - Number monotonically. Never reuse a number, even for a deleted ADR.