Architectural decision records

2,800 words · 2 diagrams

Decisions that are expensive to reverse. Each records the context, the decision, the alternatives that were rejected, and the consequences — including the ones that turned out to be costs.

Implementation records carry measurements; accepted direction can precede implementation and states that limitation in its status.

# Decision Status One-line summary
0001 Universe coordinates accepted Int32 sector index + float64 offset in a 2^40 m sector. Sub-millimeter anywhere in 249,000 ly.
0002 Reference frames accepted Frames carry the semantics of motion, not precision — the coordinates already handle that.
0003 Render coordinates accepted Floating origin on a power-of-two grid, plus logarithmic depth compression that preserves angular size.
0004 Entity addressing accepted Identity is a path through containment, and that path is also the seed path.
0005 Procedural seeds accepted Hierarchical derivation, never a shared stream. xoshiro128** over exact integer ops.
0006 Simulation clock accepted 64 Hz fixed timestep, because 1/64 is exact in binary. Wall clock decides only how many.
0007 Persistence accepted A save stores the seed, tick, input versions and dynamic state; generated content stays out.
0008 Multiplayer partitions proposed Partition derivation and local authority are implemented; remote authority, replication and handoff remain proposed.
0009 Issue-ordinal addressing accepted A body index is the ordinal it was issued at, not its orbital position — so real astronomy can add a planet without renaming every world outward of it.
0010 Cinematic director accepted Scripted scenes are presentation borrowed from a running world and returned intact — the camera overridden, nothing canonical written, time from the tick.
0011 Application shell and modes accepted The canvas lives outside every route; the mode is a pure function of the path; the camera has one precedence order — cutscene, observatory, ship.
0012 Dockable panels accepted Panels move between four zones. The layout is a value and the moves are property-tested arithmetic; the drag library is only an input device.
0013 Measured figures accepted A body gravity never rounded off carries its measured figure as a radius grid, and the generated case and the measured case are the same case.
0014 The record with holes in it accepted A field nothing has measured is a row saying so, with the reason — written in the universe's voice, never the engine's.
0015 Terrain level of detail accepted A restricted, morphing quadtree over a detail floor measured from the field — and the morph closes one level, which is why the tree is restricted at all.
0016 Documentation as a mode accepted The docs are a mode of the application, rendered at build and fetched at runtime — TypeDoc's model drawn by our components, so the reference is one site with the rest.
0017 The lens accepted The camera carries focal length, gauge, aperture, focus and gain; the field of view is derived. One producer, under the pose's own precedence.
0018 The instrument accepted The aim is an offset on the pose; compositions are one list with two placers; the keymap has one dispatcher and contexts that may share a chord; preferences are a registry with one storage call site.
0019 The geology accepted Terrain is a grammar derived from body facts, a per-body sketch, and a band stack of shares that sum to one; maxElevation is a strength limit rather than a dial; craters are placed on a cubic lattice in ℝ³; one field at every level, because the morph is exact only if two patches evaluate the same function.
0020 The face accepted The ground carries a cover record a vertex — four bytes then, eight since 0026 — for what a shader cannot derive; the palette is ratios against the body's own color; a mapped body's terrain wears its published map and the invented channels switch off; deposits are layered rather than splatted, and everything shades in body-fixed axes.
0021 The ground accepted The drawn field is the canonical one plus a presentational tail, 1.25 m at worst; the tail's amplitude is above the refinement tolerance, which is the only reason the detail floor moves; a rock is an address, and it wears the ground's own material.
0022 The timeline accepted Canonical code emits to a timeline and cannot read one — Span.end returns void; the host capability is a port and one file names the platform APIs; two APIs behind a three-valued level, off by default because feature detection cannot be a typeof; the phases tile the engine step from one clock read per boundary.
0023 The GPU producer accepted The GPU produces the drawn heightfield tiles and the CPU function stays canon and fallback; the precision lives in a float64-packed per-tile frame, not in the float; a source is a port the pool also implements; the tolerance is a test on the physical adapter, per body and per band.
0024 The type system accepted The Record and Instrument registers are the IBM Plex pair — one program, matched x-height, true italics; the mathematical operators are vendored Plex subsets under the same family names and the sigils are Noto subsets, all unicode-range-gated, with ☉ and ⊕ still uncovered; the display face stays Archivo, hand-kerned at poster size.
0025 The rails accepted A coasting entity's state at any tick is the two-body propagation of a canonical epoch, so a frame jumps the ticks nothing integrates; eligibility is physical, never the warp; sphere-of-influence tests run at fixed boundaries and are skipped by a triangle-inequality bound; the clock plans and settles rather than budgets.
0026 The liquid accepted; valleys and the sea's datum superseded by 0043 A sea is a liquid the ground temperature admits; valleys are the zero-level strip of a warped noise cut to a depth that shallows toward the datum; the coast is a C¹ remap either side of it; the sea is a sheet over a seabed the heightfield now carries, refracting the frame behind it; a world is drawn in families off its seed; every per-pixel octave is a fetch of one baked 3D texture; the sphere wears two cube maps the ground material bakes, its reflectance and its relief; and the surface has four named levers.
0027 The rings accepted A ring system's character — architecture, particle albedo and tint — is drawn once from the seed with the host only leaning it, because a ring is the debris of one event; Sol's seven mapless systems are looked up in a table keyed by address and held to the catalog both ways; the profile peaks at one so the record's optical depth means the densest band; ω₀ is 0.9 with the darkening living in the strip; the strip is mipmapped against a moiré that crawls; and the axial-tilt tail is stretched, which owes a SYSTEM_ALGORITHM bump that is deliberately deferred.
0028 Client tasks accepted The shared registry is what every host serves, and a host's own worker entry registers what only it needs: the game's serves render.bakeAtmosphere over the pure bake in rendering, which the same-layer workers package cannot import; the response is arrays, transferred, and converted where the GPU is; a shell whose tables are in flight draws a vacuum for those frames rather than a stalled frame.
0029 The sensor spine accepted The sensor owns the frame for everyone: one RenderPipeline around the scene pass and the house curve, MSAA on the pass and the canvas single-sampled; the pass is keyed on the render call rather than three's own frame counter, so a measured frame is a frame; the chain restores the renderer around the quad, because RenderPipeline.render swaps it and a throw from the scene left the picture one transfer too dark for good; and a frame drawn against a pipeline the warm-up is still building draws nothing for it. Level with the baseline at five operating points, two of them at Proxima Centauri d.
0030 three r185 accepted The renderer tracks the three release the upscaler's peer range starts at, and carries no patch to it: r185's renderer gates the draw on Pipelines.isReady, so the guard ADR-0029 patched in is dead code and is dropped; a compile yields through scheduler.yield, which the harness installs from Node and the app shims where a browser has none; the warm-up hands one renderable at a time to compileAsync, because the material's setup reads the live render target after the first yield; and the node type aliases are the typings' own.
0031 The sensor response accepted The measured Natural/Direct baseline records optical calibration, ACES diagnostics and resource ownership. ADR-0037 governs current camera modes; P3 requires matching canvas and encoder declarations.
0032 The stellar field accepted Field conventions, linear photometry and calibration history; ADR-0038 supersedes the preview restriction and initial cache configuration with the active population.
0033 Portable presets accepted A shared JSON format stores the camera, lens and photographic time without rewinding canonical simulation state.
0034 The drop accepted A figure dragged onto a world aims a ballistic entry the camera flies to the ground: the conic holds 1 − e rather than e because a drop from far out is within 1e-13 of radial, the schedule is logarithmic in height, and the aid is scene geometry placed in the body's own frame — a point put through its own compression sinks inside the sphere it is meant to lie on.
0035 Searching the volume accepted Worlds are found by a predicate over generated bodies rather than an index, because nothing exists until its seed is expanded; the sweep streams as 32-system worker batches since a job has no partial-result message, keeps the nearest thousand and counts the rest.
0036 The pointer holds the rope accepted The hand end stays on the pointer, gravity chooses the landing site, and a damped spring chain connects them. Release reads the same destination the scene draws.
0037 The Enhanced camera implemented; acceptance completed Enhanced composes the default bright-world and faint-sky image; Automatic and Manual share photographic processing. Physical surface light, exposure continuity and compatibility are verified; the camera completion record holds inspected images, transitions and measured limits. Display output remains independent.
0038 Stars and diffuse sky accepted Bounded luminosity levels, GPU projection, shared dust, progressive physical cubes and temporal radiance history.
0039 The shell before the scene accepted Astro pre-renders the complete page shell. One browser runtime adds the scene, and React Router preserves its engine and canvas across navigation.
0040 Body-fixed structures accepted Durable surface placements share body-relative poses, rendering, support surfaces, and save records across game modes.
0041 The guide requests the view accepted; narration superseded by 0042 An optional Planetarium guide proposes bounded, sourced actions; the observatory executes them and the application gates narration on current receipts. Its execution boundary stands; ADR-0042 supersedes its two-model narration and server session store.
0042 The guide speaks in one voice accepted; listening pending; authorization amended by 0048 One voice speaks and one model thinks through Responses delegation; the browser runs the tool loop over the WebRTC data channel and keeps the clock, and the server holds only the key and the password. Supersedes ADR-0041's director, clips, socket, and Durable Objects.
0043 The rivers drain accepted A body's rivers are a graph built once per body on the CPU — a jittered cube-sphere lattice flooded from the sea, steepest descent, a floor that never rises downstream — and the field cuts the ground to its floors through segments in cells; standing water is a level per vertex, the sea a lake at the datum on the nodes it reaches, and a basin the sea never reached is dry. Terrain is algorithm version 5. Supersedes ADR-0026's valley strip and its sea drawn wherever the ground is under the datum.
0044 The reconstructed display accepted One picture record combines edges and render scale; the sensor runs FSR before display-size optics, with reversed floating-point WebGPU depth, declared history cuts and a logarithmic WebGL fallback.
0045 The disposable terrain cache accepted; amended Complete versioned input keys and producer namespaces validate generated heightfields in bounded SQLite and IndexedDB stores; failure regenerates, and caches remain separate from saves. One archive per store owns the epoch and writes, and a fingerprint holds the CPU revision.
0046 The check is a graph accepted One runner runs every check as a graph under a core budget and stamps passes by the tree's content; the thirteen presets are the regression fixture as a headless ledger in pnpm test and a plate comparison through the renderer; shipping runs no gate because CI runs the graph, from a cached terrain archive.
0047 Surface characters accepted Canonical characters walk in a body-fixed frame at 64 Hz; trusted session permission gates flight, explicit pointer lock enters gameplay, and first-person and third-person cameras use the existing player arm.
0048 Accounts accepted Clerk signs a visitor in — pages from the menu, a modal inside a mode — and the Worker verifies the bearer session token; the guide is granted by admin or tour in the account's private metadata, read by the Worker.

How they connect

flowchart TB
    A1["<b>0001</b><br/>universe coordinates"]
    A2["<b>0002</b><br/>reference frames"]
    A3["<b>0003</b><br/>render coordinates"]
    A4["<b>0004</b><br/>entity addressing"]
    A5["<b>0005</b><br/>procedural seeds"]
    A6["<b>0006</b><br/>simulation clock"]
    A7["<b>0007</b><br/>persistence"]
    A8["<b>0008</b><br/>multiplayer partitions"]
    A9["<b>0009</b><br/>issue-ordinal addressing"]
    A10["<b>0010</b><br/>cinematic director"]
    A11["<b>0011</b><br/>application shell"]
    A12["<b>0012</b><br/>dockable panels"]
    A13["<b>0013</b><br/>measured figures"]
    A14["<b>0014</b><br/>the record with holes"]
    A15["<b>0015</b><br/>terrain level of detail"]
    A16["<b>0016</b><br/>documentation as a mode"]
    A17["<b>0017</b><br/>the lens"]
    A18["<b>0018</b><br/>the instrument"]
    A19["<b>0019</b><br/>the geology"]
    A20["<b>0020</b><br/>the face"]
    A21["<b>0021</b><br/>the ground"]
    A22["<b>0022</b><br/>the timeline"]
    A23["<b>0023</b><br/>the GPU producer"]
    A24["<b>0024</b><br/>the type system"]
    A25["<b>0025</b><br/>the rails"]
    A26["<b>0026</b><br/>the liquid"]
    A27["<b>0027</b><br/>the rings"]
    A28["<b>0028</b><br/>client tasks"]
    A29["<b>0029</b><br/>the sensor spine"]

    A1 -->|"precision already solved,<br/>so frames are free to be<br/>about motion"| A2
    A1 -->|"canonical → GPU"| A3
    A2 -->|"anchor frames"| A3
    A4 -->|"the address<br/>is the seed path"| A5
    A5 -->|"content is derivable,<br/>so it is not stored"| A7
    A4 -->|"a save stores<br/>references"| A7
    A6 -->|"state is a function<br/>of tick count"| A7
    A2 -->|"gravitational coupling<br/>bounds authority"| A8
    A7 -->|"replicate what a client<br/>cannot derive"| A8
    A4 -->|"amended: orbital order<br/>is not identity"| A9
    A5 -->|"the catalog version<br/>joins the manifest"| A9
    A3 -->|"the scene is built<br/>around one eye"| A10
    A6 -->|"scene time derives<br/>from the tick"| A10
    A10 -->|"a second producer<br/>of the same eye"| A11
    A4 -->|"the address is<br/>what a URL carries"| A11
    A11 -->|"a mode made<br/>of panels"| A12
    A9 -->|"the debris is issued<br/>after every planet"| A13
    A3 -->|"the drawn radius is<br/>what a mesh normalizes to"| A13
    A13 -->|"null means round,<br/>never unknown"| A14
    A12 -->|"the panel that<br/>reads the record"| A14
    A5 -->|"the field decides<br/>where refining stops"| A15
    A3 -->|"a patch rides the body's<br/>own compression"| A15
    A4 -->|"a patch is addressed<br/>before it exists"| A15
    A11 -->|"a fifth mode, over<br/>the same canvas"| A16
    A11 -->|"the optics follow<br/>the pose's precedence"| A17
    A15 -->|"the refinement predicate<br/>was reading a guess"| A17
    A17 -->|"a lens nothing<br/>could operate"| A18
    A12 -->|"the panels the eye<br/>is operated from"| A18
    A7 -->|"a preference is not<br/>part of the universe"| A18
    A10 -->|"a shot carries<br/>its own lens"| A17
    A15 -->|"the quadtree wanted<br/>something to draw"| A19
    A5 -->|"a grammar is a pure<br/>function of the seed"| A19
    A14 -->|"the geology is a claim<br/>about the place"| A19
    A19 -->|"a shape wants<br/>a face"| A20
    A17 -->|"the detail fades against<br/>the lens's pixel angle"| A20
    A13 -->|"the published map<br/>is not negotiable"| A20
    A20 -->|"a face wants a meter<br/>scale under it"| A21
    A15 -->|"the floor is measured<br/>from the drawn field,<br/>not the canonical one"| A21
    A4 -->|"a rock is an<br/>o: address"| A21
    A6 -->|"the wall clock may be<br/>written to, never read"| A22
    A12 -->|"one definition of<br/>over budget, two consumers"| A22
    A15 -->|"the streamer is what<br/>the frame is made of"| A22
    A19 -->|"the band stack gets<br/>a second producer"| A23
    A21 -->|"the drawn field is made<br/>where it is drawn; the<br/>canon stays on the CPU"| A23
    A22 -->|"gpu heightfields<br/>on the Terrain track"| A23
    A16 -->|"the reading room the<br/>italics and coverage serve"| A24
    A6 -->|"the tick stays the unit;<br/>a coast is jumped, not stepped"| A25
    A7 -->|"the epoch is canonical<br/>and rides in the save"| A25
    A19 -->|"the landform the<br/>valleys are cut into"| A26
    A14 -->|"a stated optical depth<br/>has to mean one ring"| A27
    A26 -->|"the material a ring<br/>is drawn beside"| A27
    A21 -->|"the floor's task, then<br/>the bake's, off the<br/>arrival frame"| A28
    A22 -->|"a worker's cost lands<br/>on the Tasks track"| A28
    A21 -->|"the seabed is the drawn<br/>ground under the sheet"| A26
    A17 -->|"the image the lens<br/>forms lands on a sensor"| A29
    A11 -->|"the shell owns the canvas;<br/>the chain owns the frame"| A29

    style A1 fill:#0369a1,stroke:#0c4a6e,color:#fff
    style A8 fill:#334155,stroke:#1e293b,color:#94a3b8,stroke-dasharray: 5 5
    style A9 fill:#0e7490,stroke:#155e75,color:#fff
    style A11 fill:#0e7490,stroke:#155e75,color:#fff
    style A13 fill:#0e7490,stroke:#155e75,color:#fff
    style A14 fill:#0e7490,stroke:#155e75,color:#fff
    style A15 fill:#0e7490,stroke:#155e75,color:#fff
    style A17 fill:#0e7490,stroke:#155e75,color:#fff
    style A22 fill:#0e7490,stroke:#155e75,color:#fff

The foundation graph above ends at ADR-0029. The camera, galaxy and shell extensions connect those decisions as follows:

flowchart LR
    S["0029 sensor spine"] --> T["0030 three r185"]
    S --> C["0031 sensor response"]
    C --> E["0037 Enhanced camera"]
    L["0017 lens"] --> P["0033 photographic presets"]
    P --> E
    I["0018 instrument"] --> D["0034 drop"]
    I --> R["0036 pointer rope"]
    A["0004 addresses + 0005 seeds"] --> Q["0035 volume search"]
    F["0032 stellar field preview"] --> G["0038 active population and diffuse sky"]
    E --> G
    A --> G
    H["0011 shell + 0016 docs mode"] --> B["0039 shell before scene"]

ADR-0037 owns current camera processing over ADR-0031's optical record. ADR-0038 supersedes ADR-0032's preview restriction and initial cache configuration. ADR-0039 amends the shell and documentation host boundary while retaining the persistent scene and route-derived modes.

ADR-0044 joins the render-coordinate and sensor decisions: depth must preserve distance precision while supporting temporal reconstruction. ADR-0045 joins persistence and the heightfield source: complete keys permit reuse without making generated data part of a save. ADR-0047 joins body-fixed frames, canonical saves, the shared keymap, and the player camera arm while keeping the observatory passive. ADR-0048 fills the account routes ADR-0011 reserved, inside its background-location contract, and puts the verdict on who is asking in the Worker.

Four dependencies are worth noticing because they are not obvious:

  • 0001 → 0002. Because coordinates are precise everywhere, frames did not have to be a precision mechanism, which is the opposite of how most engines at this scale are built. That freed frames to be about the semantics of motion.
  • 0005 + 0004 → 0007. Determinism plus stable identity is what makes a save compact references instead of stored generated content. Persistence did not need a clever format; it needed the other two decisions to have been made correctly.
  • 0004 → 0009. ADR-0004's own consequences section admitted that bodies are addressed by orbital index and that changing the layout renames them. That was acceptable while the only thing changing the layout was us. It stops being acceptable when real astronomy is a generation input, which is what 0009 corrects — and it is free to correct only while there is no save corpus.
  • 0010 → 0011. The cinematic director needed one thing from the renderer: an eye that is not the ship's. Having built that seam, the planetarium was a second producer of the same shape rather than a new mechanism — which is why a whole mode cost a nullable field and six lines of precedence.

Writing a new one

Add an ADR when a decision would be expensive for a future engineer to reverse, or when they would otherwise have to reverse-engineer why from the code.

Keep the four headings: Context, Decision, Alternatives considered, Consequences. The alternatives section is the one that ages best — it is the difference between a record and a rationalization.

Prefer real numbers over adjectives. "0.24 mm anywhere in 249,000 ly" is a decision record; "very precise" is a mood.