Concept
The document chain
The document chain links requirements and architecture to the build. Each artefact records what justifies it, what verifies it and which code implements it.
Last updated
The RCF document chain is the set of linked artefacts that runs from product intent to working code: one arm carries intent (PRD, requirements, user stories, acceptance criteria), the other carries architecture (TAD, components, ADRs), and they meet at the build. Every artefact points at its neighbours, so the chain is walkable in both directions.
Documentation often follows authorship rather than purpose, with relationships held in people’s memories. As documents become outdated, they stop explaining why the current code exists.
RCF records these relationships explicitly. Two upstream arms meet at the build:
| The intent arm | The architecture arm |
|---|---|
| PRD → requirements → user stories → acceptance criteria | TAD → components → ADRs |
| What must be true | The system in which it must be true |
The two arms converge at the build chain: build sequence → functional build specification. From there, each in-scope acceptance criterion runs two short lanes side by side: a test suite (and its test cases) that proves it, and a code node that implements it. The FBS is the explicit join point. It pulls in the in-scope ACs from the intent arm and the in-scope TAD components and ADRs from the architecture arm, and turns the two into a buildable slice. This is also the point in the chain where spec-driven development (SDD) typically starts; RCF inherits SDD’s spec-as-primary-artefact framing but anchors the spec earlier, in the requirements layer of the intent arm, so the spec-of-intent runs from PRD all the way through to the FBS rather than appearing only at the build boundary.
The artefacts the chain is built from are listed below in reading order. The PRD and TAD originate upstream of RCF as currently scoped. The scoping page covers what that means and what work is coming to address it. From the PRD-and-TAD-agreed point onwards, the chain runs the same shape on every project.
The intent arm
PRD: the product
The product requirements document starts the intent arm. It describes the product, its users, its behaviour and its exclusions. The out-of-scope section records considered options the team rejected and why. Teams can revisit or reverse those decisions. The record makes each reversal deliberate and preserves an audit trail.
The PRD contains the requirements list. Each requirement states what the product must do, with a category (functional, non-functional or regulatory), priority (must, should or could) and domain (such as auth, billing or search). Requirements specify required outcomes rather than implementation.
User stories: the human shape of a requirement
A requirement on its own is hard to build against. It’s a statement of intent, not a description of behaviour. So each requirement breaks down into user stories, the familiar “as a [role] I want [action] so that [outcome]” shape.
A story gives a requirement an actor and an outcome. OAuth sign-in, for example, can produce stories for first-time signup, returning sign-in, account linking and sign-out. Stories describe the user behaviour needed to satisfy the agreed requirement.
Acceptance criteria: the contract
Each story carries one or more acceptance criteria. A Given/When/Then sentence specifies a precondition, an event and an observable expectation. Each criterion supplies the text for one test suite.
Acceptance criteria make intent verifiable. Most use an automated test suite. Some use a human-attested check, such as inspecting a Kubernetes naming convention or a deployed manifest. Each criterion must be verifiable by a test or by a reviewer checking an artefact against its rule. See Acceptance criteria as the contract.
The architecture arm
The architecture arm runs alongside the intent arm. It defines the system in which the requirements must hold and follows the same linking rules.
TAD: the system the requirements need
The technical architecture document is the top of the architecture arm. It describes the systems and components the product needs: services, data stores, external integrations, the cross-cutting decisions about how data flows and where state lives. One per product, sibling to the PRD.
The TAD supplies the architecture references for each build slice. Other architecture artefacts link to it, as intent artefacts link to the PRD.
TAD components: the moving parts
Under the TAD sit its components: the named services, data
stores, queues, integrations, and shared modules the architecture is made
of. Each one is a technical architecture component, with
its own opaque ID prefixed TAC-, so it sits next to TAD and
ADR in the chain’s ID scheme rather than under an ad-hoc letter of
its own. TACs get referenced from FBSs by ID, the same way ACs do. A TAC
is the architecture-arm equivalent of a story on the intent arm: the
named unit the build slice depends on.
ADRs: the decisions that shaped the system
Architectural Decision Records record significant choices: context, decision, alternatives and consequences. They reference their TAD and the components they constrain. FBSs reference them as build context. See architectural decisions.
The build chain
Both arms feed into the build chain. The FBS is the explicit join: it takes the in-scope ACs from the intent arm and the in-scope TAD components and ADRs from the architecture arm, and turns them into a slice the agent or team can build. From the FBS downwards, the chain is linear again.
Build sequence: the plan
The build sequence is the directed acyclic graph that gets you from nothing to shipped. Each node on the graph is a functional build specification, a slice of the product you can build, test, and ship in one go. Each edge is a dependency: this FBS can’t start until that one is done.
A build sequence should deliver vertical slices that demonstrate working behaviour end to end as early as possible. Building horizontal layers can leave the team without shippable behaviour for weeks.
Functional build specification: where the arms meet
A functional build specification is the brief the worker actually executes against, and the explicit convergence point of the two arms. It pulls together both sides into one buildable slice. From the intent arm: which stories and ACs are in scope, which PRD sections the worker needs to read. From the architecture arm: which TAD components and ADRs the slice depends on, which modules and schemas the work will touch. Plus the surrounding context the worker needs to do the slice well: dependencies on other FBSs that must finish first, the relevant business patterns, standards, style guidelines, and instructions.
The FBS carries a list of testable outcomes, which is the restatement of the in-scope ACs in the worker’s terms. The testable outcomes are the AC-level commitments the slice will be marked against; they’re what makes the AC text actionable inside one build cycle.
The FBS declares the specific PRD sections, TAD components, ADRs, code modules and external documents needed for the slice. This selected context lets a human or agent build without searching the entire codebase for orientation. Its quality strongly affects agent output.
Test suite and test case: where intent becomes behaviour
A test suite hangs off a single user story and lists the acceptance criteria it verifies. The load-bearing binding is one layer down: each test case inside the suite pins to exactly one acceptance criterion. One AC, one test case that proves it. The suite is the container the cases live in; the case is where verification meets a criterion.
The one-to-one rule between AC and test case is what makes traceability possible. Run a single command and you can ask “is AC-042-03 passing” or “which tests would I need to look at if requirement REQ-014 changed.” The answers are mechanical because the structure is mechanical.
Code nodes: where the chain reaches the code
A test suite verifies an acceptance criterion, but does not register the source that implements it. A code node, the eleventh RCF document kind, records that source in the graph.
A code node forks off the acceptance criterion, alongside the test suite
rather than after the test case. Where the test case is what proves the
AC, the code node is what implements it. Its identity is a path,
src/store/validator.js, optionally narrowed to a symbol with
src/store/validator.js#getAjv, and it names the ACs it
implements in an implementsAcIds field, the same way an FBS
anchors through its ACs. This relationship isn’t one-to-one like AC
and test case. Several code nodes can implement one criterion, one node
can implement several, and a node can implement none at all: a utility, a
piece of glue, or wiring with no direct spec anchor is a normal, common
state, not an error.
Code nodes do not link directly to test cases. Both link to the same acceptance criterion, which lets tooling join them and report implemented but uncovered criteria. A direct code-to-test link would duplicate that relationship and become stale when tests are regenerated.
rcf validate checks code node paths and named symbols against the working tree as well
as checking specification references. Moving or deleting a file, or renaming a symbol, produces a
staleCode error that a one-field edit can resolve. This verifies that the source
exists. It does not verify that its behaviour still satisfies the criterion.
Reading the chain end to end
Start with a business decision. The product needs to support exporting user data. On the intent arm, that decision becomes REQ-019 in the PRD, functional, should-have, domain: privacy. REQ-019 generates US-088: as a user I want to download my data so that I can take it elsewhere. US-088 carries three acceptance criteria, AC-088-01 through AC-088-03, covering the happy path, the size cap, and the format.
On the architecture arm, TAD-001 establishes a background job service for long-running work, with ADR-014 recording the decision to route exports through it (alternatives considered: synchronous endpoint, separate worker pool). Components on the arm: the job service, the storage service, the identity service.
The two arms meet at FBS-051. The FBS’s storyScope is { US-088: [AC-088-01, AC-088-02, AC-088-03] }. Its buildContext points to TAD-001 Section 4 (Jobs), the storage service component, and ADR-014. The build sequence places FBS-051 after FBS-016, which stood up the job service. When a worker picks FBS-051 up, they have one document that names what must be true (the ACs) and what system it must be true in (the TAD components and ADR). They write three test suites, then they write the code and record its code nodes against the ACs, then everything goes green, then FBS-051 closes. REQ-019 is now satisfied, and the satisfaction is provable from the chain.
Reading the chain bottom up works just as well, and a code node makes it
a command rather than a manual hunt. Point rcf trace at a
function in the export handler and it resolves the path to its code node,
then walks back: code node → the AC it implements → the story
that holds the AC → the requirement the story serves → the
business decision the requirement encodes. From the same starting point
you can still cross into the architecture arm, through the FBS that named
the slice: which TAD components the code is part of, which ADRs
constrained how it was built. Each step is one hop, and each hop is
mechanical.
Why this many layers and not fewer
Each layer records a decision that the adjacent layers cannot express adequately. The shorthand requirement → test → code describes a three-hop query, but omits those decisions.
On the intent arm: requirements need stories because a requirement is too abstract to test. Stories need ACs because a story is too vague to test directly. ACs need test suites because behaviour needs implementing in code, not in prose.
On the architecture arm: the TAD needs components because the system is made of named parts that get referenced individually. Components need ADRs because the consequential choices about each part need to outlive the conversation that produced them.
In the middle: the build sequence and FBS exist because somebody has to decide what gets built when, with what dependencies, drawing what from each arm, or the work fragments.
Code nodes distinguish implemented criteria from verified criteria. They register the source in the graph so validation can detect references broken by a refactor. An annotation alone cannot provide that check.
Each layer records a specific kind of decision. Combining layers can put decisions in the wrong place, leave them unrecorded or leave the worker to make them during implementation.
The chain supplies context at team scale. Each layer provides the information the next layer needs, so an agent receives the relevant intent at each build stage.
Vocabulary, ID schemes, and what to look up next
Every document type has an opaque ID, such as PRD-001, REQ-014, US-042, AC-042-03, TAD-001, TAC-007, ADR-014, FBS-027, TS-088-01 or CN-006. IDs are never renumbered or reused. Suites reference criteria and work items reference FBSs. Code Nodes also record source paths and the AC IDs they implement. The ID remains the lookup key.
A word about tooling
The chain runs on plain text. The methodology itself is JSON for the documents, markdown for the build specs, and git for the history. Git is the system of record: every artefact, every ID, every state change in the chain lives in commits, and the history of the project is the history of its requirements. Every ID-pointer relationship the chain depends on is greppable from a terminal.
A basic implementation needs a small CRUD CLI to query and validate the chain, plus coding-agent
commands for the build cycle. Managing opaque IDs and one-to-one mappings manually across hundreds
of FBSs is difficult. Stravica publishes this layer as rcf-lite, an Apache-2.0 npm
package providing the rcf CLI. Further tooling can draft artefacts against standards
and identify gaps. Stravica develops these integrations and workflows to support larger projects.
The methodology remains independent of that tooling.