CODING PLANNER

Documentation · AR Labs

System reference · Part 3

Containers

How a container splits work, waits for its children and checks the assembled result, and how the coverage ledger turns each promised scenario into a test.

A container does not write code. It splits work, waits for its children, and then checks the assembled result.

The root's design steps

The root enters the pipeline from a clarification interview that precedes the pipeline proper and produces an approved brief. The manifest's declared entry step is create-prp, not the first step on the root route. generate-design is declared ahead of it because that is its place in the process, but it has no pipeline wiring — nothing records that it ran and nothing refuses the next step if it did not — so it is skippable in practice. Declaring a step does not make it a gate. refine-design is the post-requirements design revisit; it dispatches the same instructions with the requirements document as added context, and exists as its own step value because the step field is a program counter and must be able to say whether the requirements document has happened yet.

to-issues — the fan-out

An agent splits the node into children. The floor checks the birth facts of that fan-out: the sanctioned child set is recorded by id at the moment of the split, along with a timestamp that marks the node as a container. Recording the child set matters because the next step compares against it.

delegate

The container's middle slot, kept separate from a leaf's implement so that two unrelated dispatch actions stop sharing one name. It declares no command file yet. Its floor is children_terminal: leaving delegate requires every child closed, with blocked children named separately because they defer the parent; every closed child that is itself a container already carrying its own review; the live child set unchanged since the fan-out sanctioned it; and coverage still conserved.

That last clause about the unchanged child set is what makes the recorded birth facts load-bearing rather than decorative. Without it, a child quietly added or removed after the split would pass unnoticed.

integrate

The up-leg: integrated acceptance plus design reconciliation, in one step. It is terminal on both container routes. Its floors are integrated_acceptance — every scenario the node owns has a tagged test under the campaign's declared test paths, and the campaign's declared suite command exits zero on the integrated result — plus file_exists on the reconciliation document, whose content a human then judges.

Integrate declares a human gate, and the driver consults a terminal step's gate before anything else, so a node at integrate rests and waits for a person unless its autonomy level relaxes the gate, which only deep does and only when the campaign has an integration branch; there the driver finalises it. It never dispatches, and it never advances on silence. The reconciliation is authored by a fresh sub-agent context rather than by the orchestrating session, by owner ruling: the context that ran the work is not the context that should write the account of it.

Whether a container then delivers is an open question, deliberately unruled, so no successor is declared after integrate.

The coverage ledger — how a promise becomes a proof

Two of the floors above ask for something this document has not yet explained. The fan-out floor wants coverage conserved; the integration floor wants integrated scenario coverage. Both are questions about one ledger that runs the length of a campaign, and the plain version of it is short: a campaign opens by promising a list of behaviours, and it may not close until every one of those promises can be pointed at a test carrying its name.

The promise. The requirements document written at create-prp states its acceptance criteria as Gherkin scenarios — Given, When, Then, one behaviour each — and gives each one a short identifier, S1 through S9 on a campaign with nine of them. A scenario's prose can be rewritten later; its identifier is meant not to be. That identifier is the handle everything downstream holds.

The claim. At to-issues the campaign records the whole set on itself and each child records the subset it undertakes to deliver, both in the same reserved field, pipeline.scenarios. Siblings may claim the same scenario when they deliver it jointly, and every child claims at least one, because a slice carrying no promised behaviour is mis-scoped rather than empty. The fan-out floor then does arithmetic: the union of the children's claims must equal the parent's set exactly, nothing dropped and nothing invented. A split that quietly loses a scenario is caught by comparing two sets rather than by someone reading the fan-out attentively.

The token. At implement, each test that discharges a scenario carries that scenario's identifier in its own name — test_s3_<something>. This piece of bookkeeping exists for one reason: it makes the promise mechanically findable later. Nothing else in the tree ties a line of test code back to the sentence in the requirements document it was written to satisfy.

The re-check. delegate asks the conservation question a second time, at the other end of the children's work rather than at their creation, which is what stops a child being added or re-scoped in between.

The audit. integrate then does two separate things, and keeping them separate is the point.

The first is an existence audit. For each scenario the node owns, the floor searches the campaign's declared test paths for a test carrying that identifier: the identifier must sit on a line that declares a test, inside a file whose name or directory marks it as a test. A comment, a constant in source code or a line of prose does not count, and a scenario nothing carries refuses the step by name, listing the files where its identifier was found out of position. This is the check that catches a promise which quietly never became a test at all, and that failure is invisible to a test suite: a suite reports on the tests that exist and says nothing whatever about the test nobody wrote.

The second is one suite run. The campaign's declared suite command runs on the integrated result and must exit zero. This is the first moment the combined work exists anywhere — each leaf was developed on its own branch and passed the suite there, in its siblings' absence, so until the branches are assembled nothing has ever run them together.

It is existence plus a green suite, and deliberately not per-scenario pass attribution. The floor never claims to know which test proved which scenario. The existence half cannot tell a thorough test from a trivial one; it matches one line at a time and ignores case, so it counts the identifier anywhere on a declaring line, not only in the test's name; and a skipped test still carries its identifier. Those are known limits, asserted as limits in the floor's own tests. The honest claim is that no promise reached the end of the campaign unrepresented and the assembled work is green — not that every scenario was individually demonstrated.

The configuration. The audit needs two values it cannot derive: pipeline.suite_cmd, the command that runs the whole suite, and pipeline.test_paths, the directories holding tests. They are facts about the project, not about the campaign, so they live once on the campaign root and every node below reads them from there. Paths resolve against the VOX repository root, so a project extracted to a repository of its own declares them in the ../<repo>/... form. When either is unset the floor escalates rather than refuses, which is the distinction from Part 1 doing its job: missing machinery is not incomplete work, and absence is never approval.

The set-config verb writes both, on the campaign root only (set-config --campaign <root> --suite-cmd <cmd> --test-paths <paths>). It is ungated but audited, and it refuses test paths that name no existing directory. generate-spec records them from its test-infrastructure sweep, and init warns while they are unset.

The stage-field adoption campaign of September 2026 ran the whole chain: nine scenarios promised in its requirements document, one child claiming all nine, every identifier present as a token in the committed tests, and the suite green on the first attempt once a person had set the two configuration values.