Architecture
The approach: a spec before code, everything as data, deterministic engines with the model at the edges, invariants enforced by tools, and an evaluation that shares no code with what it scores.
Five layers, every arrow pointing up: read-only sources, data files, deterministic engines, agents, the human gate. Nothing points down or out.
Everything a person might change is data: clients, rules, desks, connectors, policy. A change is an attributed log entry, replayable to any past moment.
A model composes and reads at the edges; it never decides. The prototype runs every step deterministically and says on each screen which step a model would own.
The layers
Where the model sits, and where it never does
The engines in the middle are deterministic: the same facts always produce the same verdict, so a past decision can be replayed against the rules as they stood. A model is allowed at three edges, drawn dashed. It reads free text into facts, it phrases what an engine decided, and it rewrites a query and reranks passages. It never decides eligibility, rank, regime or a verdict, and a dependency rule stops the engines importing a model client. The prototype makes no model calls: each screen says which step a model would own.
The data path: read from the systems of record, never written to
Relay is a layer beside the firm's systems, not on top of them. The CRM, the custodian, the planning tool and the archive stay the systems of record and are read only. Relay keeps its own store of what it computed and what people decided, and that store never writes back. An accepted note is a draft the advisor sends from their own tools; an accepted task lands on the follow-up list; a disposition is a log entry. In the prototype the store is the data folder shipped with the page; in production it is a database of Relay's own, fed by a read replica or change feed from each source.
Sources: read replica or change feed
Each connector reads a replica or a change-data-capture stream, never the production tables, so Relay cannot lock, slow or alter a system of record. Coverage says which sources are connected and healthy; a rule that needs an absent source reports cannot evaluate.
Relay's own store: documents and an append-only log
One document per client, rule, desk and connector, as the data folder is today, and an append-only log of findings, dispositions and rule changes. The log is what replay reads. Nothing in it is ever updated in place.
Retrieval: an index beside the documents
The firm's documents are indexed for search with a reason per score and a floor. In production the index adds embeddings for recall; the floor, the citation and the refusal stay in code.
The approach, in the order it was applied
- Write the spec before the codeA build spec names every surface, the data model, each engine's responsibility, the demo path and the tests. Decisions made while building are written back, numbered.
- Make everything a person might change into dataA client is a file. A rule is JSON with a condition tree the console edits at runtime. A desk and a connector are entries. A validator fails the build on anything inconsistent.
- Keep the engines deterministic; put the model at the edgesThe same facts produce the same verdict, so a past decision can be replayed. Where a model would compose or read free text, the deterministic version is built and the screen says which step a model owns.
- Enforce the invariants with tools, and see each guard fail firstNever sends, the model never decides, nothing clears its own findings, design tokens only, no client data in code. Each is a dependency rule or a test, and each was seen failing on a planted violation.
- Read the output before writing the testMost defects were found by reading engine output and screenshots, not by the passing suite. Each became a test.
- Evaluate against an expected side that shares no codeA 300-household corpus, an expected side with its own reader and arithmetic, hand-reviewed labels, precision and recall per rule, a golden file enforced in the check suite.
- Tighten only, at every layerFirm, segment, advisor, client. Preferences resolve most-specific-wins; rules and desks resolve strictest-wins; the learning loop and the proposer suggest and never apply.
The stack
Next.js, TypeScript strict, Tailwind on tokens
A static export with no server and no database; the whole product runs from the data folder in the browser.
Vitest, dependency-cruiser, Playwright
Unit and invariant tests, architecture rules over every import path, and a browser suite at five widths.
No model client, no network client
There is nothing to send with. The content security policy blocks any request to another host, and the browser suite proves it on every run.
Where to read further
- ARCHITECTURE.md: the overview, and links to the three detailed architecture documents
- BUILD-SPEC.md: every surface, the data model, engine responsibilities, the demo path
- evals/README.md: the corpus, how the expected side is built, what the eval has caught
Next: How it works, the loop, every morning.