re-frame2 Specification¶
Type: Reference Index of the design documents for re-frame2 — a re-frame-flavoured pattern for building SPAs, plus its Clojure/CLJS reference implementation.
The load-bearing decisions live in 000-Vision.md. Each per-area Spec consumes those decisions; downstream Specs do not reshape the foundation. The AI-first practical principles are collected in Principles.md.
How the corpus is organised¶
The directory has two orthogonal axes:
- Bucket axis (normative vs. supporting). Numbered Specs (000–014) are the primary normative bucket — they own pattern-level contract surfaces. The Companion layer (below) is mixed: most companion docs support the contract (rationale, scaffolding, audit, examples), but a small subset are normative companions — they own contract surfaces of their own. The Ownership matrix in Ownership.md is the single source for "which companion owns what."
- Layer axis (foundation / capability / companion). Three explicit layers structure the corpus:
| Layer | What it contains | Role |
|---|---|---|
| Foundation | 000-Vision, 001-Registration, 002-Frames | Load-bearing decisions every other doc consumes — goals, identity primitive, registration grammar, frame model, dispatch envelope, drain semantics. Reshape these and the rest of the corpus moves. |
| Capability | 004-Views, 005-StateMachines, 006-ReactiveSubstrate, 007-Stories, 008-Testing, 009-Instrumentation, 010-Schemas, 011-SSR, 012-Routing, 013-Flows, 014-HTTPRequests, 015-Data-Classification | Per-area normative Specs. Each consumes Foundation; none reshapes it. Optional capabilities (see the host-profile matrix) live here. |
| Companion | API, MIGRATION, Principles, Conventions, Construction-Prompts, Security, AI-Audit, Tool-Pair, Implementor-Checklist, Runtime-Architecture, Cross-Spec-Interactions, Ownership, Spec-Schemas, Conformance Corpus, the Pattern-* docs, worked examples |
Mixed: see the §Normative status within the Companion layer breakdown immediately below. Some companion docs are normative companions (own contract surfaces of their own); the rest are supporting material that scaffolds, validates, or demonstrates the contract owned elsewhere. |
Within the Companion layer, each doc carries a Type (the companion-document genre axis): Reference, Migration, Convention, Construction Prompts, Audit, Schemas, or Pattern. Every doc declares its Type via the > **Type:** header. The Foundation and Capability layers do not carry a Type header — their layer is determined by numbering. The Type vocabulary is closed for v1; new Types require a companion-doc convention update.
Normative status within the Companion layer¶
The Companion layer is mixed-normativity. Some companion docs own pattern-level contract surfaces (a normative companion); others cite the owning spec without defining the contract (a supporting companion). The Ownership matrix in Ownership.md is the authoritative split per surface — read this section to understand the categories, then read Ownership.md to see which doc owns which contract surface.
| Companion doc | Status | What it owns (per Ownership.md) |
|---|---|---|
| MIGRATION | Normative companion | Migration rules (re-frame v1.x → re-frame2, CLJS reference). |
| Conventions | Normative companion | Reserved-namespace policy, reserved fx-ids, reserved app-db keys, packaging conventions, cross-MCP indicator-field vocabulary, privacy config-knob naming. |
| Tool-Pair | Normative companion | Pair-tool runtime contract (inspect, dispatch, hot-swap, time-travel, fx-stub, source-map; direct-read privacy posture). |
| Construction-Prompts | Normative companion | Construction-prompt scaffolding templates (per-kind AI-scaffolding shapes). |
| Security | Normative companion | Pattern-level security posture — threat model + behavioural MUSTs + pragmatic stance + decisions log. CLJS-reference specifics live in ../implementation/SECURITY.md under the canonical-homes-outside-/spec rule. |
| conformance/ | Normative companion | Conformance fixtures (canonical interactions and expected emissions, in EDN) — the verification surface for Goal 2 — AI-implementable from the spec alone. |
| API | Projection | Consolidated reference: signatures, status, cross-references. Non-canonical — defers to each per-Spec owner of the surface. |
| Spec-Schemas | Projection | Collected EDN form for each runtime shape. Non-canonical — defers to each per-Spec owner of the shape. |
| Principles | Supporting | Discipline principles + foundational essays; rationale layer. |
| AI-Audit | Supporting | Score of every Spec against the AI-first principles; surfaces gaps. |
| Runtime-Architecture | Supporting | Bird's-eye view of the runtime — eight components + interop + data-flow diagram. Cites owners; defines nothing. |
| Cross-Spec-Interactions | Supporting | Edge cases at boundaries between Specs. Each interaction names which Specs meet and the decided behaviour; defines nothing. |
| Cross-Cutting Designs | Supporting | Inventory of design surfaces that span multiple Specs / tool artefacts / skills. Non-normative; the cited home wins on drift. |
| Implementor-Checklist | Supporting | Decision-ordered companion to 000 §Host-profile matrix. |
| Ownership | Supporting | The "where does X live?" matrix; the authoritative split between normative and supporting companions. Lists owners; defines no contract surfaces of its own. |
Pattern-* (8 docs) |
Supporting | Worked-example conventions — Pattern status, not Spec status. Convention is normative-by-convention but not pattern-level contract. |
| worked examples | Supporting | Browser-runnable apps demonstrating the contract owned elsewhere. |
The rule. A companion doc may own a contract surface when the surface is genuinely cross-cutting (touches multiple numbered Specs) — Conventions owns reserved namespaces because the policy spans every Spec, Tool-Pair owns the pair-tool contract because the surface spans 001/002/006/009 plus the time-travel slice. A companion doc must not redefine a contract surface that has a numbered-Spec owner. Drift detection is the same as for in-tree surfaces — a second normative definition is a corpus bug. Per Ownership.md §Drift rule.
External canonical homes (per §Canonical homes outside /spec below) are the third option — surfaces downstream of the pattern that live with their tool / implementation artefact rather than with the framework spec.
About Spec 003. The numbering 000–014 has one gap: there is no 003-*.md. Slot 003 is reserved for a future Spec on cross-frame composition (frame supervisors, parent/child frame relationships, frame-graph topology) — design work that depends on Specs 002 and 005 being settled. The slot is held open so existing Spec numbers do not need to renumber when 003 lands.
Documents¶
Foundation layer (load-bearing decisions)¶
| # | Title | One-liner |
|---|---|---|
| 000 | Vision | Canonical owner of goals, hard constraints, the pattern's minimal core, scope, retained-from-re-frame. Every other doc consumes this. |
| 001 | Registration | The metadata-map shape that every reg-* accepts. Standard keys; two-form middle slot; source-coord capture via macros (CLJS reference); query API; hot-reload semantics. |
| 002 | Frames | Frame as isolated runtime boundary. Pattern contract: explicit-frame addressing. CLJS reference: React context as an optimisation. Keyword identity, :rf/default fallback, run-to-completion drain, machines-as-event-handlers foundation hooks, id-valued override seam. |
Capability layer (per-area normative Specs)¶
| # | Title | One-liner |
|---|---|---|
| 004 | Views | Pattern view contract: pure (state, props) → render-tree. CLJS reference: reg-view with frame-bound dispatch/subscribe; Form-1 canonical; Form-2/3 escape hatches. SSR-renderable per 011. |
| 005 | State Machines | Transition-table grammar layered on 002's machines-as-event-handlers hooks. |
| 006 | Reactive Substrate | Substrate-agnostic core + adapter contract. Reagent default; plain-atom for JVM/SSR/headless. |
| 007 | Stories, Variants, and Workspaces | Storybook/Histoire/devcards-class tooling. Story / Variant / Workspace split. Builds on 008. |
| 008 | Testing | Owns the testing infrastructure surface. Test fixtures, synchronous triggers, per-test fx/interceptor stubbing, headless sub/machine evaluation, framework adapters, JVM-runnable test suites. 007 cross-references 008 for portable-stories-as-tests. |
| 009 | Instrumentation, Tracing, Performance | Trace event model, listener API, structured error contract, per-frame :on-error policy mechanism, forward-compat with 10x / re-frame-pair. |
| 010 | Schemas (CLJS reference) | Malli-based schemas via :schema; path-based app-db schemas via reg-app-schema; validation timing, dev-vs-prod elision. Schemas are opt-in at the pattern level. |
| 011 | SSR & Hydration | Server frame lifecycle (per-request), pure hiccup → HTML emitter (JVM-runnable), :platforms metadata, :rf/hydrate event, hydration-mismatch detection. |
| 012 | Routing | URL ↔ frame state contract. Routes are registry entries; navigation is an event; :route is a sub. Same handler runs server- and client-side. |
| 013 | Flows | Registered, runtime-toggleable computed-state declarations that materialise into app-db. v2 incarnation of v1's on-changes interceptor — same compute-on-input-change semantics, but registered (not on individual events) and toggleable via :rf.fx/reg-flow / :rf.fx/clear-flow. Convenience for narrow use-cases; not a sub replacement. |
| 014 | HTTP requests | The :rf.http/managed request fx (optional capability) — args-map shape, decode pipeline, :accept step, retry-with-backoff, abort, frame-aware reply addressing, eight-category failure taxonomy under :rf.http/*. Specialises Pattern-AsyncEffect; pins Pattern-RemoteData's lifecycle slice. The CLJS reference ships it on Fetch + JVM HttpClient. |
| 015 | Data Classification | Opt-in path-marked sensitive + large declarations at every reg-* site (plus dedicated add-marks / set-marks for app-db). :rf/redacted and :rf/large {:bytes N :head "..."} display sentinels rendered at observation surfaces (trace bus, Xray, MCP, third-party log sinks); auto-propagation across the dataflow with author-controlled override. Leak-prevention overlay on observability — NOT runtime security. |
Companion layer (rationale, scaffolding, verification, examples)¶
Normative companions (defer to per-Spec doc for design rationale):
| Title | Type | One-liner |
|---|---|---|
| API | Reference | Consolidated reference: signatures, status, cross-references. |
| MIGRATION | Migration | Migration spec for upgrading re-frame v1.x codebases (CLJS reference). |
| Security | Reference | Pattern-level security posture — threat model + behavioural MUSTs + pragmatic stance + decisions log. CLJS-reference specifics (named fns, numeric defaults, JVM-vs-CLJS stub semantics) live in ../implementation/SECURITY.md under the canonical-homes-outside-/spec rule. |
Reference, scaffolding, and audit:
| Title | Type | One-liner |
|---|---|---|
| Principles | Reference | The 9 AI-first discipline principles plus the two foundational essays (the layered constraint, data is code). The yardstick the AI-Audit grades Specs against. |
| Conventions | Convention | Locked runtime conventions: reserved-namespace policy for framework-owned ids, ns-prefix conventions for features, reserved fx-ids and app-db keys. |
| Managed external effects | Reference | The unifying conceptual frame: eight properties every framework-owned managed-effect surface (:rf.http/managed, :rf.ws/*, :spawn / :spawn-all, :rf.server/*, :rf.flow/*) inherits. New surfaces (managed timers, managed background jobs) are graded against the same checklist. |
| Construction Prompts | Construction Prompts | Per-kind AI-scaffolding templates (event, sub, fx, view, machine, feature, route, schema, SSR). Sibling to the migration corpus at ../migration/from-re-frame-v1/. |
| AI Audit | Audit | Score of every Spec against the AI-first discipline principles; surfaces gaps. |
| Runtime-Architecture | Reference | Bird's-eye view of the runtime — the eight components (registrar, frame container, router, drain loop, do-fx, sub-cache, substrate adapter, trace bus) plus the interop layer, with data-flow diagram and per-event lifecycle. Companion to the per-area Specs; redefines nothing. |
| Cross-Spec Interactions | Reference | Edge cases at the boundaries between Specs — frame disposal with active machines, machines under SSR, routing in SSR, plain-fn under non-default frame, machine action throws, hot-reload mid-cascade, etc. Each interaction names which Specs meet, the scenario, the decided behaviour, the reason. |
| Cross-Cutting Designs | Reference | Inventory of design surfaces that span multiple Specs / tool artefacts / skills — wire elision, retro protocol, token budgets, MCP-tool naming, origin tagging. Each entry names the canonical home, the consumers, and the resulting shape. Non-normative; the cited home wins on drift. |
| Privacy | Reference | Cross-artefact index of the privacy + data-classification surface — every imperative + declarative entry point in re-frame.core, re-frame.http, re-frame.schemas, re-frame.epoch, tools/mcp-base, with the composition order from handler exit to off-box wire and a canonical worked example. Cites owning Specs (009 / 010 / 014 / 015 / Tool-Pair / Security / Conventions); redefines nothing. |
| Ownership matrix | Reference | "Where does X live?" — the contract-surface → owning-Spec → companion-citations table. Single source of truth; drift detector when a definition appears in a non-owning doc. |
| Tool-Pair | Reference | Runtime contract for pair-shaped AI tools (re-frame-pair equivalents): inspect, dispatch, hot-swap, time-travel, fx-stub, source-map. |
| Implementor's Checklist | Reference / Companion | Decision-ordered companion to 000 §Host-profile matrix. Part 1 (capability declarations), Part 2 (per-capability technology choices with options-by-host), Part 3 (conformance against the claimed list). The structured form of Goal 2 — AI-implementable from the spec alone. |
| Spec-Internal Schemas | Schemas | Malli (CLJS reference) shape descriptions for the spec's own runtime shapes. Static hosts express the same shapes as types. |
| Conformance Corpus | Reference | Fixture-based test suite: canonical interactions in EDN, expected emissions in EDN. Verifies the "AI can one-shot the implementation in any host" claim. |
Patterns (worked-example conventions, not Specs):
| Title | Type | One-liner |
|---|---|---|
| Pattern — Async Effect | Pattern | The canonical six-step "register fx → return :fx → post work → async reply → dispatch → commit" shape every async-effecting feature follows. Foundational; specific patterns (RemoteData, WebSocket, Boot) cite it. |
| Pattern — Nine States of UI | Pattern | Page-level convention for rendering blank / loading / cardinality / validation / success / terminal states explicitly by composing RemoteData, Forms, and machine/domain state. |
| Pattern — Remote Data | Pattern | Standard request-lifecycle slice + four standard events; SSR-friendly. The HTTP-specific case of Pattern-AsyncEffect. Convention, not Spec. |
| Pattern — Reusable Components | Pattern | The entity-id idiom for parameterised widgets — a customer-card that works against any customer, where the caller supplies the id and the card subscribes and dispatches in terms of it. Multi-identity, adapter-agnostic, placefulness discussion. Convention, not Spec. |
| Pattern — Stateful Components | Pattern | The outer/inner wrapping shape for views that bridge a stateful third-party JavaScript component (D3, Mapbox, CodeMirror, Three.js, GSAP, Framer Motion, ag-grid, Vega-Embed, AmCharts, SpreadJS, …). Outer registered view reads subs and derives props; inner Form-3 / use-effect view owns the library's imperative init / update / dispose lifecycle. Convention, not Spec. |
| Pattern — Forms | Pattern | Standard form slice + seven standard events; per-field error display only on touched. Convention, not Spec. |
| Pattern — Stale Detection | Pattern | The cross-cutting epoch idiom: capture, carry, check, suppress. Used by :after timers, navigation tokens, and any future async-shaped feature. |
| Pattern — Boot | Pattern | Application boot as a chained-async sequence — chained-events form for trivial boots; state-machine canonical form (config → auth → profile → hydrate → route → ready) for non-trivial. SSR handoff and hot-reload rules included. |
| Pattern — WebSocket | Pattern | Long-lived connection lifecycle (WebSocket / SSE / WebRTC peer) as a state machine — :disconnected / :connecting / :authenticating / :connected / :reconnecting / :failed. Worked example of hierarchical states, :after, :always, and :spawn composed. |
| Pattern — Long-Running Work | Pattern | Modernised guidance for handling CPU-intensive work without freezing the UI. Decision tree (offload vs chunk on main thread); state-machine canonical form for chunked work with :always for batch progression and :after 0 for browser yielding; cancellation via state transition; replaces the v1 ^:flush-dom metadata. |
| Pattern — SSR Loaders | Pattern | Parallel data-fetch fan-out for an SSR request — N HTTP fetches spawned via :spawn-all, joined on all-complete, results written to app-db before render-to-string runs. Composes with :rf.server/request cofx (request-derived inputs) and :rf.http/managed (per-child retry / abort / decode). Same machine drives client-side navigation-fetch. |
| Pattern — Form Action | Pattern | Canonical SSR form-POST handling — method="POST" action="/<route>", host adapter parses form-encoded / multipart body, :rf/server-init routes POST to a domain event, action handler validates via :schema, emits 303 See Other on success or re-renders with errors on failure. Covers CSRF, file uploads, progressive enhancement, and the same-handler-tree-both-sides contract. |
Worked examples:
| Title | Type | One-liner |
|---|---|---|
| Worked examples | Reference | Browser-runnable apps spanning the construction-prompt surface across substrates — Reagent: counter, counter_slim_and_fast, counter_with_stories, login, todomvc, routing, ssr, managed_http_counter, state_machine_walkthrough, nine_states, boot, long_running_work, websocket, the 7GUIs cluster (temperature / flight booker / timer / crud / circle drawer / cells), and realworld; UIx: counter, login; Helix: counter, login. Examples are test-free source; their behaviour is covered by CLJS test fixtures (npm run test:cljs) plus three adapter-mount smokes (Reagent / UIx / Helix). The catalogue at examples/README.md maps each example to the Specs it exercises. |
Reading paths¶
The corpus serves three distinct audiences. Pick the track that matches your goal; tracks are intentionally non-overlapping in their primary content.
Track 1 — Canonical (the contract)¶
For implementors and AI agents reading the contract in its normative reading order.
- 000-Vision.md — goals, hard constraints, the minimal-core contract, identity-primitive properties.
- 001-Registration.md — registration grammar; the metadata-map shape every
reg-*accepts. - 002-Frames.md — frames, dispatch envelope, drain semantics, machines-as-event-handlers hooks.
- Capability Specs in numeric order: 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015. Each is independent of the others (with explicit cross-references where needed).
- API.md — consolidated signature reference.
- Spec-Schemas.md — canonical runtime shapes.
- conformance/ — fixtures the contract is verified against.
Track 2 — Background (rationale and design history)¶
For readers wanting the why before (or beside) the what. Optional in the strict sense — every normative claim in Track 1 stands without these — but they make the corpus easier to absorb.
- Optional upstream rationale (re-frame v1 doc set): on-dynamics, data-oriented-design, a-loop, application-state. Why the v1 pattern has the shape it does. Skip if already familiar.
- Principles.md — the 9 AI-first discipline principles + the two foundational essays.
- AI-Audit.md — how each Spec scores against the principles; surfaces gaps.
- Conventions.md — locked runtime conventions (reserved namespaces, fx-ids,
app-dbkeys). - The
Resolved decisionsandOpen questionsappendices in each numbered Spec — design-history records embedded next to the contract.
Track 3 — Implementor (porting to a new host)¶
For implementors taking the pattern to one of the in-scope JS-cross-compile hosts — TypeScript, Melange / ReScript / Reason, Fable (F#), Squint, Scala.js, PureScript, or Kotlin/JS (the CLJS reference being the eighth). The pattern commits to React + VDOM at the render side and to a JS-cross-compile source language per 000 §The pattern and 006 §Abstract; non-React substrates and non-cross-compile-to-JS hosts (server-side Python / Ruby / Rust / Go / Kotlin / Swift / Java) are out of scope as first-class implementation targets. Substantial — most of the artefacts already exist; this track sequences them explicitly.
- 000 §Host-profile matrix — pattern-required vs. host-discretion vs. CLJS-only, row by row. The single source of truth for "must I ship this?"
- Implementor-Checklist.md — the decision-ordered companion to the matrix. Part 1 declares which optional capabilities the implementation includes; Part 2 walks each capability's technology and library choices with options-by-host; Part 3 explains conformance against the claimed list.
- Principles.md — the discipline your implementation should bias toward (especially the "open maps with schemas," "data is code," and "registry-as-truth" essays).
- Spec-Schemas.md — the canonical shapes your runtime must produce. In static hosts, these become types.
- 009 §Error contract — the structured-error trace surface every implementation supplies.
- 011-SSR.md — server/client lifecycle; even non-SSR implementations consume the
:platformsand frame-per-request rules. - Construction-Prompts.md — the user-facing scaffolding surface; adapt to your host's idioms.
- conformance/README.md — fixture-based verification suite. Run the subset matching your declared capabilities (Implementor-Checklist Part 3).
Canonical homes outside /spec¶
Most contract surfaces in re-frame2 have their canonical home in this /spec tree — the language-agnostic pattern lives here, and every other-language port consumes it as the contract. A small, deliberate set of contract surfaces has its canonical home elsewhere, and /spec indexes them via Ownership.md rather than redefining them.
The rule):
- A contract surface MAY live in a canonical home outside
/specwhen it is downstream of the language-agnostic pattern — i.e. it is a tool-shared contract or a CLJS-reference-specific binding of a pattern-level obligation, rather than part of the pattern's minimal core. The home lives with the artefact it ships in (tools/<tool>/spec/...orimplementation/<area>/...). - The pattern-level
/speccorpus remains the single source of truth for whatthe patternis. External homes are valid only for surfaces that are not part of the pattern. - Every external home is indexed in Ownership.md with its canonical-home path made explicit (e.g.
Canonical home speccell pointing attools/mcp-base/spec/README.mdorimplementation/SECURITY.md). The rule for the index is the same as for in-tree owners: exactly one canonical home; other citations are informational. - A new external home requires the same justification as any contract surface — bead-recorded decision, owner identified, drift rule applied.
Currently the rule is exercised by two surfaces:
- Cross-MCP shared primitives — the
:rf.mcp/*+:rf.size/*wire vocabulary, the JSON-RPC error codes, the privacy / elision walkers shared across the MCP triplet, argument coercion, structural diff, overflow-marker shape, and the token-budget cap pipeline — live with the artefact intools/mcp-base/spec/. Indexed in Ownership.md. Tool-shared contracts: a rename here is a wire-protocol break across every MCP server, not a pattern-level decision. - CLJS-reference security specifics — named functions (
re-frame.core/elide-wire-value,re-frame.interop/debug-enabled?, …), numeric defaults (interning cap, timeouts, drain ceilings), JVM-vs-CLJS stub semantics, and the full implementation-side audit trail — live inimplementation/SECURITY.md. The pattern-level threat model + behavioural MUSTs live inSecurity.md; the implementation-side companion carries the host-specific binding (per Security §How to read this doc).
Both homes were sanctioned via beads (rf2-vw4sq for mcp-base; rf2-1g6cj / rf2-ao8a2 for the Security split). The rule itself is recorded at rf2-0hs5t.3 (a).
Why allow external homes at all? /spec is the language-agnostic pattern; cross-MCP wire vocab + the CLJS-reference's concrete function names + numeric defaults are tooling concerns and implementation concerns respectively, not pattern-level. Forcing those into /spec would pollute the abstraction — a TypeScript port reading /spec/Security.md for the pattern doesn't need (and would be confused by) the re-frame.core/elide-wire-value symbol. The split keeps each doc serving one audience cleanly.
Ownership matrix¶
Every contract surface in re-frame2 is owned by exactly one normative spec. The full owner → companion-citations mapping lives in Ownership.md — it is the single source for "where does X live?" Use it to navigate, and to detect drift if a definition ever appears in a non-owning doc. Most owning specs live in this /spec tree; the small set of external canonical homes (per §Canonical homes outside /spec above) is indexed in the same matrix.
Drift rule: if a contract surface acquires a second normative definition (a redefinition rather than a citation), that is a corpus bug. File it as a spec-review bead and resolve by collapsing back to the listed owner.