Train
One method, every repo. Three layers, never mixed:
- METHOD - this file. Universal. Identical everywhere. Resist per-repo
variation; divergence between repos is debt, not diversity.
- SUBSTRATE -
.train/config.md in the repo. ONLY facts that cannot be
derived. Everything derivable is re-measured at §1 of every train, because a
stored fact is recall and recall goes stale silently.
- PRIORS - the Second Brain first,
.train/priors.md only for the
genuinely repo-local. Read before dispatch. Appended by retro.
A rule has exactly one authoritative home, and correcting it means enumerating
its READERS. The layers above say where a rule LIVES; this says what happens
when it changes. Every document that restates a rule is a reader - a checklist
that executes it, an agent definition loaded at start-up, a reference doc - and a
correction that updates the nearest copy leaves the rest live. Two copies of one
rule do not diverge loudly. They diverge silently, and the divergence stays
invisible until someone follows the copy that is wrong.
Modes
| Invocation |
Does |
/train |
Run a train. Requires .train/config.md. |
/train init |
Onboard or retrain a repo. Read references/init.md. |
/train retro |
Fold the last train's lessons back. Read references/retro.md. |
No .train/config.md? Stop and run init. Never guess the substrate.
One repo, one remit. A train never spans repositories, and an agent is never
tasked with another repo's init, config, priors or backlog - each repo's agent
owns its own. The method is shared; the work never is. The Second Brain is the
only channel between repos, and it carries lessons, never instructions.
Answer protocol - governs every output below
Applies to the manifest, Stream Reports, QA verdicts, train reports, and
anything said to the operator.
- A1 Ledger. Every number and factual assertion carries the exact command
that produced it and the literal output containing it. Cannot paste output
containing the figure? Label it UNVERIFIED. Ledger at the end, not inline.
- A2 Scope. State the window measured and the window claimed. Absolute
quantifiers - never, always, zero, none, every, "returns nothing" - require a
population-wide command. Measuring 20 commits and claiming 90 days is the
canonical failure. And a population-wide command must prove it SAW the
population: state the denominator, show it is non-empty, and name the AXIS it
covers. A zero, a green or an "all paths" from a scan whose scope is unstated
is UNVERIFIED. An enumeration bounded to one direction of a state transition
has not enumerated the transition - if you fixed every path that ADVANCES, say
so, and say that the paths that reverse or cancel were not examined.
- A3 Recall. Any figure not re-derived this session is recall. A hedge on a
countable quantity - "4,600+", "~", "over", "roughly" - is the tell.
Countable things get counted. A3 governs what is SAID; this governs what is
COMMITTED. A countable figure written into a source file, docstring or
comment must be recomputed by the build, or it does not go in - state the
RELATION the tests enforce and point at the test. A published CONSTANT is
exempt, because a standard's own threshold cannot drift, and that exemption is
the boundary rather than a loophole.
- A4 Falsify. Take the three claims the conclusion leans on hardest and try
to prove each wrong. Say what was tried.
- A5 Subagent claims inherit zero trust; run A1-A4 on them yourself.
- A6 Assume every number will be re-derived downstream.
- A7 Account. A response to an enumerated instruction answers every item BY
NAME - including no-ops, already-done items and items deliberately dropped -
and states the commit it is true at. A crossing revision is recognised by
checking that commit's parent, not by re-reading the instruction. An item that
appears in no line of the answer is an unanswered item, not an implied yes.
- A8 Live figures. Against a running system a baseline is re-measured
immediately before the change, never carried from build time - a figure that
was true four hours ago is recall. A figure that moves against prediction is
attributed by ORIGIN, by joining records to the change's own marker, never by
the size of the delta. A fix is verified through the CONSUMING surface's own
predicate, never a raw field that looks equivalent.
Refer to work by name, not by bare id. "#150, #151, #128" is a wall the
operator has to look up one at a time; "#150 (never-reject violation)" reads at
a glance. The id rides inside the name, never stands in for it.
Absence-of-token claims about source must exclude comments or parse structure -
a grep for a token inside a file that documents that token matches its own
comment.
1. Measure - every train, never recalled
git log --since="90 days ago" --no-merges --name-only --pretty=format: \
| grep -v '^$' | sort | uniq -c | sort -rn | head -20 # hotspots
git log --since="90 days ago" --oneline --no-merges | wc -l # denominator
git branch --list; git worktree list # in-flight state
git status --porcelain # dirty tree
Hotspot share = count / denominator. Anything above ~5% of commits is a
hotspot. Read .train/config.md for what cannot be derived: gate command,
test-isolation mechanism, migration system, deploy invocation, generated
artifacts, CI triggers and runner count.
A derived index - a code graph, symbol index, embedding store, generated map -
is a stored fact under another name: recall goes stale silently, so it is
ASSERTED fresh, never read fresh. Assert against the newest thing the repo
changed (git log -1 --name-only), never against the tool's own status line,
and treat a miss as staleness until proven otherwise - a stale index degrades
into a plausible capability limit ("unsupported file type"), which is exactly
why it survives. .train/config.md names the index and its refresh command.
(method_ext, operator-approved 2026-08-17.)
Refuse to start if the tree is dirty or work is in flight. Land or park it.
Changing integration model with work in flight is how eight-branch pile-ups
happen.
Enter a train with headroom for a whole train. The integrator's own
context is an entry condition budgeted here exactly as §3 budgets spawns:
compact at the boundary, where every input to the manifest is durable and
re-readable, so the compaction costs nothing. Where a train is large enough
that mid-train compaction becomes unavoidable, that is expected - and is
precisely why verdicts, the sha mapping, dispatch rationale and operator
rulings are written to files as they are produced rather than held in
context (§5). (method_ext, operator-approved 2026-08-17.)
2. Decompose - the step most often skipped, and where rework comes from
Produce the train manifest before any dispatch: per item, the predicted file
set, hotspots claimed, migration slot, dependencies, and its blast radius -
whether being wrong here costs money, data, access, or an irreversible external
effect. Most items are cheap to get wrong; the few that are not should be
visible at manifest time, not discovered at review.
Below about three items, it is not a train. One urgent fix runs solo (§7);
two items in a shared tree cost less than the manifest, the worktrees and the
integration. The ceremony has to be earning something.
What makes a correct slice is not its size. A slice is right when its
predicted file set is disjoint from its siblings AND its acceptance evidence is
self-contained - provable without waiting for another stream to land. Size
(~30 min) is a consequence of getting those two right, not the criterion. A
slice that needs a sibling's work to demonstrate itself is one stream, not two.
Predict the file set from co-change history, not from the ticket. The
ticket says what to change; §1's ranking says what historically gets changed
with it. A prediction drawn from reading the ticket alone systematically misses
the test file, the fixture, the registry entry and the doc that always move
together, and those misses are what spend the +2 allowance.
Dispatch order is not manifest order. Enforcement mechanisms go first
(they bind everyone). Then longest-pole first, then descending, because the
train's wall clock is its slowest chain and starting that last idles it.
High-blast-radius items go early too, so a failure surfaces while there is
still time to react rather than at integration. The concurrency cap is the
LOWER of the substrate limit and what the integrator can actually read: N
streams times a report is a context budget, and that ceiling usually arrives
first.
Dropping a stream mid-train is normal. If an item turns out wrong, pull it
from the merge, let teardown delete its branch, and return it to the backlog.
Do not carry a doubtful stream into integration because it is already built.
Hotspots co-queue, they do not exclude. Two items touching the same
hotspot belong in the SAME train, dispatched sequentially inside it - the
second branches off the train head after the first merges. Pushing the second
to a later train adds delay and buys no safety; same-scope changes need to be
tested together, which is where semantic conflicts surface.
Semantic dependency = one stream. If B's correctness depends on A's
behaviour, they are one stream run sequentially, never two. Two streams green
alone can be wrong together.
Sequenced resources couple like hotspots. A single-head migration chain,
an ordered registry, any monotonic sequence - two claimants cannot verify
their link into it from inside their own worktrees, because the sibling's
entry does not exist there. Two claimants on one sequence co-queue: a declared
dispatch order at manifest time, the second based on the first, and that order
IS the integration order - declared up front, not discovered at integration.
(operator-approved.)
A stream that adds an enforcement mechanism constrains every sibling. A
ratchet, tripwire, lint rule, schema constraint or ACL retroactively binds all
other work in the same train - one-to-many, not pairwise, so the dependency
rule above does not catch it. Such a stream is dispatched FIRST with siblings
branching off its merge, or held to the next train. Never concurrent with the
work it will constrain: no sibling's brief can carry a requirement that does
not exist yet at dispatch. The concurrency exemption is judged on PRACTICE,
not file overlap (observed across two consecutive trains, operator-approved): a ratchet policing a practice
- how tests assert, how errors render, how connections resolve - touches every
sibling with zero file overlap, so file-set disjointness never exempts it.
One train invoked the file-overlap reading and paid three same-train recurrences of
the exact class the ratchet banned. Its brief must also enumerate the recognition
axes - what object, spelled how, named or set which ways - and the house
idioms per axis, gathered by grepping before dispatch. Skip this and QA
discovers the shapes one at a time: observed as a 7-round ladder costing ~2.5h
against a 14.9-minute build, 6 rounds of which were greppable upfront. And
it must try to evade its own detector - a guard keyed on a name rather than
a binding is bypassed by shadowing. This is §5's mutation-check applied to a
detector, where the mutation is a bypass shape, not a new rule. And it must
report its PRECISION on the current codebase - every flag it currently
raises, triaged true or false positive. Evading itself tests false negatives;
this tests false positives, and both are acceptance criteria. A detector that
fires 5 times and is wrong 5 times gets ignored within a week, after which the
class it guards is silently unenforced while still looking enforced - worse
than no detector. If it flags by a hand-maintained list, ask what the
vocabulary IS: one that evolves inside this repo (schema columns, route names,
registry entries) must be DERIVED from its source of truth, because a hand
copy of it is the mechanism's own decay. One that is external and fixed (a
language's builtins, another engine's function set) has no in-repo source to
derive from and a hand list is correct - but write down which case you are in
and why, or the next reader cannot tell a justified list from a rotting one.
An investigation is not a build stream. The test is whether you can state
the question precisely NOW - not whether you can answer it. A sharp question
with an unpredictable file set is an investigation; a question you cannot even
phrase sharply is not ready to dispatch at all, and saying so is the honest
answer rather than dispatching a stream to find out. Its file set is unknowable
at dispatch, so §3's predicted-set hard stop and the hotspot rule cannot
protect it. Dispatch it to produce a FINDING plus a proposed brief - read-only,
no fix - and the fix becomes a properly predicted stream in this train or the
next. If it must fix in flight, it declares its file set UNKNOWN and may not
run concurrent with anything touching plausible surface. A manifest cannot
claim "no hotspot collisions predicted" while any
stream's file set is unknown - that is an unfounded absolute, not a
prediction. A ticket's diagnosis is a hypothesis, not a spec. Any stream
whose brief inherits a diagnosis - from a ticket, a prior finding, or the
integrator - verifies that premise against evidence as its first analytical
act, before building on it. A4 covers the stream's own conclusions; this
covers what it was handed. Observed: a "box config" diagnosis was wrong
(nothing had ever seeded the config anywhere), and the correct fix differed;
a brief once named an edit site that was dead code on the live path.
So is the integrator's own prescription. When the integrator directs a
MECHANISM change rather than a defect fix - replace this parser, use that
library's own output, derive it from the source of truth - the brief must
require the stream to enumerate what the OLD mechanism covered and prove the
new one still covers it. A stream complies exactly and loses coverage doing so,
and it cannot easily refuse a direction that arrives with a rationale and a
bound. Observed: replacing a hand-rolled manifest parser with the build tool's
metadata output was sound reasoning and a net -55 lines, and silently stopped
scanning the workspace root manifest, losing coverage in two layers at once.
AND THE INTEGRATOR'S OWN FIGURES CARRY THE LEDGER. The two rules above bind
the STREAM: verify what you were handed. They work - which is exactly why every
stream in one train corrected the ticket that dispatched it, four of them
correcting facts the integrator had supplied as established. That is the method
catching the defect at the last possible moment, at the cost of every stream
doing correction work that should never have been needed. So the obligation runs
upstream too: every figure in a manifest or brief is either re-derived this
session with its command pasted, or labelled RECALL, and a stream may refuse a
brief whose numbers are unlabelled. The population ledger binds what a stream may
CLAIM; nothing bound what the integrator may ASSERT, and that asymmetry pointed
the discipline away from the party with the most reach. When every stream in a
train corrects its own dispatching ticket, that is a decomposition defect, not a
spec-quality problem.
Decisions serialise; execution parallelises. A decision changes what the
remaining work IS, so two decisions resolved in one pass means the second was
made against a stale picture - the same one-to-many shape as the ratchet rule.
Anything whose output is a decision rather than a diff runs one at a time, and
where that decision is the operator's it is never resolved by inference, no
matter how blocked the train is. An agent answering on the operator's behalf
because waiting is expensive has broken the thing the rule protects.
Slice to ~30 min of build. Sharply-briefed streams run far faster than
intuition predicts (observed 3-13 min against 37-75 min unbriefed); the
predicted file set is what bounds exploration. Widen the train, not the slice.
Walk the manifest before dispatching anything. QA walks streams and §8
enumerates integrator SIDE-EFFECTS; nothing otherwise walks integrator
JUDGEMENT, and judgement errors propagate with full authority because streams
comply exactly. Three mechanical checks, costing minutes:
- Every predicted file exists, or is explicitly marked to-be-created.
git ls-tree -r HEAD --name-only | grep -f predicted takes a second.
Observed: a stream dispatched against an asset directory that was not in the
repo at all - it arrived with a later phase's handoff - and halted correctly
having cost a full dispatch.
- Every acceptance criterion names the mutation AND the failure it must
produce. A criterion that cannot be falsified is not a criterion. Observed:
"all six tests must go red" was impossible for one of the six, and a
compliant stream would have contorted a correct test to satisfy it.
- Every figure is a median of >=5 runs with min and max, or is labelled
UNVERIFIED. A single sample may raise a question; it may never settle one.
Observed: one timing sample taken on a machine that was compiling was 7x
wrong and nearly bought an unnecessary optimisation programme. The method
manufactures that contention itself by running N streams on one box.
A tracker's status is not evidence the work is undone. Before an item
becomes a stream, verify it is still open against the SYSTEM, not against its
status field - the defect still reproduces, the row still exists, the path is
still reachable. An item that cannot be shown still open is an investigation at
most, and possibly a close. The premise check further down fires INSIDE a
stream, which is after the stream is paid for.
Show the operator the manifest with its ledger. Do not wait for approval
unless a hotspot claim is contested or an item needs an operator input.
3. Dispatch - every stream gets all of this or it does not launch
Agent spawns are a consumable session resource - budget them. A train
costs roughly 2N+ spawns (a carriage and a walker per stream, plus ratchet,
classifier and content roles), and runtimes cap spawns per SESSION
cumulatively, not concurrently. Reaping idle agents does not help: the counter
counts spawns, never live agents. .train/config.md records the cap and the
observed per-train cost; when a session's remaining budget is under two trains'
worth, start a fresh session rather than degrading mid-train.
Prefer resuming a finished agent over spawning a fresh one for repeat roles
- a walker already matched to a surface has performed as well or better than a
new spawn. Never force a context-exhausted agent; retire it and start one.
Resuming spends the agent's context instead of the spawn odometer - the two
are currencies for the same purchase, and a resume economy that works perfectly
hides the exhaustion until it fails all at once. Six consecutive trains ran on
zero fresh spawns and then walked into a wall with no warning.
The runtime cap is a runaway backstop, never the budget. Set it high enough
that it cannot bind, and do the budgeting in config where it is visible and
measured. A ceiling you are steering by is a ceiling that will surprise you.
THE POPULATION LEDGER - declare the slots BEFORE the work. Folded after the train that measured it
(operator, 2026-08-20) after E2 failed six times in one train on the class it
was written for. You cannot detect a missing check by inspecting a report,
because the omission removes the claim and its evidence together - so the slot
must exist before the report does. The brief enumerates every population claim
this stream will have to make:
| trigger |
slot |
| the stream ADDS A CHECK |
denominator + axis |
| the stream CENSUSES or claims completeness |
one slot per search route, minimum two of DIFFERENT KIND |
| the stream WRITES EXISTING ROWS |
dry-run query + its output |
| the stream returns a NULL RESULT |
the population that WOULD have contained the thing |
| the stream asserts any ABSOLUTE |
denominator + axis |
"Different KIND" is load-bearing and the brief must say so in these words.
Two greps against the same index is ONE route wearing two hats, and that is
exactly how that missed file was missed. The census that worked used three
genuinely different kinds - ORM attribute, raw SQL string, and
instance-reads-by-holder - and only the third found the file no prior list
named.
The brief must also state, in the brief itself, that UNKNOWN is blameless.
Not in the method, not in a prior - in the text the stream reads. A mechanism
that punishes empty slots without offering an honest unknown manufactures
evidence, and the first stream that cannot reach live will invent a number
rather than write that it could not determine one.
EMISSION is required everywhere. IDENTITY is preferred where the stream
controls both sides - make the claim and the check the same statement, as a
migration whose dry-run and write share one population constant does, or a rule
with one implementation and several callers rather than a restatement in a
second language. Identity cannot diverge; emission can only be checked.
Its own git worktree and a local branch off the current train head. Never the
shared tree. Never a push to origin unless config says otherwise.
Verifying the base is the stream's FIRST act, before any edit. Worktree
tooling spawns at a main-line sha, not necessarily the branch you declared -
observed failing 3 of 3 times. The brief states the expected base sha; the
stream asserts it, ff/resets if wrong, and says so in its report. Without
this, co-queueing silently builds the second claimant on the wrong file state
and every "clean merge" is luck.
A base that was AMENDED or rewritten - not merely advanced - rebases with
rebase --onto <new-base> <old-base>. A plain rebase replays the superseded
base commit itself into the stream. When the integrator rewrites a base, the
grant states BOTH shas and the stream asserts the old one is its ancestor
before rebasing. (operator-approved.)
Brief: goal, acceptance evidence required, predicted file set, migration slot
or "none", isolated substrate handles (test DB port/namespace per config, and
any singleton resource - browser, REPL, shared session, shared dev or staging
database - budgeted exactly like a port), model tier, the relevant lines
from .train/priors.md, and a statement that a SUBSTANTIATED NULL RESULT -
already fixed, premise false, defect unreachable - is an acceptable
deliverable. A stream that manufactures a fix to fill its slot has done worse
than nothing, because the fix will be walked, merged and believed.
Every operator input - screenshot, ruling, credential, sign-off - is
requested at manifest time in one batched list. Never discovered mid-build.
Hard stops; report and halt rather than work around: config-owned data the
operator owns, a production write, a side-effectful external retry, the same
test failing three times, the file set exceeding predicted + 2, running out
of working context - stop honestly with a clean tree and an explicit list of
what remains (observed: two streams did exactly this and a fresh agent completed
each first try; a stream that pushes on with spent context ships unverifiable
work), or needing a new dependency - installed packages are near-always shared state (a symlinked
virtualenv, a hoisted node_modules, a vendor dir), so one stream's install
silently changes what every sibling's gate is testing against. Nothing fails;
the results just stop meaning what they say.
4. Stream exit - the gate is mechanical, runs ONCE, by the stream
Run the repo's exact gate command from .train/config.md, in the worktree,
against its own test substrate. Do not run a second overlapping suite behind it.
Mutation proof runs LEFT, at build time, by the builder (observed across two consecutive trains,
operator-approved): before the gate, the stream reverts each of its fixes in
turn and pastes its own new tests going red, then restores. QA replays rather
than discovers; a stream whose tests were never proven red ships tests that
cannot fail, which one train measured as the dominant defect class (9+ instances,
7 streams). A mutation must vary exactly ONE thing - changing two validates
the test instead of the code (a stream's false proof). A red that fails for the
wrong reason (syntax error, import break) is not a proof; report failed
mutation attempts as what they were.
The Stream Report is what QA and the integrator read instead of the diff. Cap
it at ~40 lines: branch and sha, file list with line counts, gate commands
with pass/fail counts pasted, the repo's pre-ship questions answered with
evidence, the live evidence that will prove it after deploy, what any embedded tunable
constant selects against live data at the value being shipped - a threshold,
cutoff, rate limit, retry count or page size is a judgement call encoded as a
number, and nobody can review a number without seeing what it picks; paste the
read-only result so the decision is operator-visible BEFORE it ships, not
inferred from the diff - anything
UNVERIFIED, any file outside the predicted set, every population-ledger slot
the brief declared, each filled FILLED / UNKNOWN / N-A - FILLED means the
literal command and its literal output, never a summary of the output; UNKNOWN
means could-not-determine with the reason, and is blameless; N-A means it does
not apply, with the reason - and the claim ledger. Full
evidence goes to STREAM-REPORT.md in the worktree, at a path the repo
gitignores, with the path cited. Report artifacts never ride a merge - two
streams writing the same tracked path is an add/add conflict at integration.
Untracked-by-convention is not enough; git add -A defeats it, so the ignore
line is the enforcement and .train/config.md names the path.
An investigation or design stream writes its finding to the FILE first and
returns a summary second - the reverse of a build stream. A build stream's work
survives in its commit whatever happens to the agent. An investigation stream has
no commit: the finding IS the return message, so an idled session loses the
entire result. The durable artifact must never be the ephemeral one - the same
reasoning as the population ledger and the QA verdict file, and the same rule as
§7's detector clause: the thing that proves the work has to survive independently
of the party reporting it.
Every stream report also answers "what did you notice that the brief did not
decide?" - answered, or explicitly NONE. Same three fills as the population
ledger. The ledger forces a stream to emit its EVIDENCE so a claim cannot outrun
it; this forces a stream to emit its UNASKED QUESTIONS so a brief's blind spot
surfaces while the author is still in the code. It is the one question a stream
can always answer and a reviewer usually cannot.
5. QA - adversarial only, concurrent, one instance per stream
QA GATES EVERY PUSH. NO STREAM SHIPS UNWALKED, EVER. Operator law, restated
2026-08-20 after it lapsed for two consecutive trains. It is not a per-train
judgement and does not lapse because a batch is small, urgent, bug-only or
obviously fine. If you find yourself reasoning that a particular stream does
not need a walk, that reasoning is the defect.
The gate is not a substitute. The repo-level rule this mirrors used to read
"run a QA pass (or the full suite)", and that parenthetical is how the law
lapsed: the suite ran, so the rule read as satisfied while nothing independent
looked at the diff. A gate proves the code does what its tests say. QA asks
whether the tests say the right thing - which is the only question that catches
a stream shipping exactly to a brief that was wrong.
QA WRITES ITS OWN VERDICT FILE. A verdict that exists only as an agent's
return message does not exist. One file per stream, on disk, at a path the
train names before dispatch. This is the same rule as the durable-artifact rule
for investigation streams, and it exists because two entire trains' QA verdicts
were lost: they had only ever been chat turns.
A train cannot close until the per-stream verdict count is asserted BY COMMAND
and its output pasted, exactly as section 7 requires of worktree and branch
counts. UNKNOWN is an allowed and visible value; a missing file is not. Without
this, QA's absence is undetectable - which is precisely how it went unnoticed
across two trains, two close-outs and two retros.
Spawned by that stream's completion, not batched by the integrator. QA
for a finished stream runs while other streams are still building. Each QA
instance holds its own test substrate handle.
Walkers dominate the spawn bill - typically 9-11 of a ~15-spawn train. When
budget is tight, one walker may take several streams SEQUENTIALLY: independence
survives, because a walker is independent of the builders whichever streams it
takes, and only concurrency is lost. That is usually cheap, since walks run
under build time. Declare it when you do it, and retire the walker before its
context degrades - a walker on its fourth stream is not the walker that did the
first. Never consolidate a walker across a stream it built.
Does NOT re-run a suite the stream already ran green. That is duplicated
compute and a collision risk.
The QA brief NAMES its hunt classes, derived at brief-generation time from
.train/priors.md plus the stream's own risk surface - the priors file is the
standing class list, so seeding from it is mechanical, not judgement. A defect
found in round 2 whose class was NOT named is a brief gap, not a QA win: that
is what makes the §8 split falsifiable instead of self-flattering. A
first-occurrence exemption - "no prior existed to seed from" - holds only if
the class was underivable from the stream's RISK SURFACE too, since hunt
classes come from both sources; absent-from-priors alone is not enough, or
every gap becomes a first occurrence. One exemption per class, and the class
enters priors the same day. A hunt list
that names everything is not a hunt list - padding it to avoid gaps is itself
a finding.
QA is held to the same evidence standard as the stream: a check that was
attempted but did not take effect is not a check. Three specifics follow
from that one rule, and every one of them was learned the hard way -
- Walk the named classes in the diff. Declaring them beforehand is what
makes "QA caught it" falsifiable after.
- Mutation-check that new tests fail without the fix, scoped to the tests
the stream added. For a guard written after an incident, the mutation is
RESTORING THE DEFECT IT WAS WRITTEN FOR, in the shape that defect actually
had - never a synthetic restatement, never by breaking a helper. To prove a
guard is INVOKED, delete the CALL: breaking the helper proves only that the
helper is reachable from somewhere. The guard must fail INDEPENDENTLY for
every member of the population it claims to cover, restoring clean between
each - one red proves one member, never the set. And assert the LOCATION of
an effect, not only its occurrence: a test proving something was written
passes when the write lands in the wrong place. Verify the mutation LANDED
before its result counts: re-read the value, re-import the module, check the diff. A probe
that silently no-ops (an edit landing in a docstring instead of a table
value, a patch applied to a copy) reads as "fix confirmed" and once nearly
closed a real finding. Commit before mutating - reverting with a
working-tree checkout against uncommitted changes destroys the FIX rather
than the mutation, observed twice in one sitting.
- Mutation proves a test CAN fail. It does not prove the test fails for the
REASON CLAIMED, and that gap has let two defects through. Assert the
expected failure, not merely a failure. Two mechanical halves:
- Proof of arrival. A test must demonstrate it reached the code it
claims to exercise. If it can pass without the function under test being
entered, it is testing something else. Observed: a test failed under
mutation because a validation layer IN FRONT of the target refused the
input, so the target was never entered - it was exercising the guard in
front of the guard.
- Failure specificity. Assert the reason, never a substring that a
generic or default message also contains. Observed: a permanent guard kept
passing because a different error message happened to contain the asserted
substring, so the guard survived the thing it documented being removed.
- The same applies one level up to any test justified as "this proves we
chose X over Y": ask what it would report if Y were implemented. If the
answer is "the same", it never entered the discriminating region and is
decoration. Observed: 2 of 3 tests passed against the rejected
implementation until one asserted it had entered that region.
- Rehearse data migrations by EXECUTING them against a scratch database
built at the pre-merge head. A read-only SELECT proves which rows would be
selected, never that the migration runs - driver type-binding, transaction
semantics and the migration's own code are only exercised by running it.
Production-shaped data where a backup restore is available; an empty schema
proves syntax, not behaviour. A corrective sweep's cutoff derives from the
DEFECT'S WRITE WINDOW - the last moment before the fix's first possible
write - never from the deploy or run moment, which re-destroys post-fix
truth on any re-run. Rehearsal executes the migration TWICE: a sweep that
is not idempotent against post-fix rows is not finished. (operator-approved,
operator-approved.)
Then: run A4 against the stream's ledger, and hunt the absence cases.
For claims of the class that keeps failing (absolutes), prefer 2-3 verifiers
each given a different slice of context, with disagreement as the trigger,
over one verifier with everything.
Verdict is PASS or a specific failure with file:line. Fixes are re-walked as
a delta - never a "smalls" round that lands unwalked. The verdict is
written to .train/t<N>-verdicts.log the moment it is produced (gitignored;
one line: stream, sha, PASS/FAIL, walker) - a verdict that exists only in
conversation is destroyed by compaction and by any session boundary, and the
loss is silent because integration proceeds on a remembered PASS.
(method_ext, operator-approved 2026-08-17.)
The same holds for EVERY artifact handed between agents - a patch, a
finding, a census, not only a verdict. It is written to a file at the moment it
is produced; conversation is not storage, and neither is a scratch directory
the session owns. The reason was never specific to verdicts, and a verified
patch was lost exactly this way.
When the integrator carries a departed stream's work itself, it declares
that exactly like an inline walk, and proves the transplant by CONTENT
EQUALITY of the diff at source and destination - never by inspection.
If a QA walk exceeds its stream's build time, say so in the train report: the
walk is doing work the gate should own.
At-cap protocol, and it must be declared. Out of spawn budget: first resume
a finished walker for a bounded delta it already owns; only as a last resort
does the integrator walk inline. An inline walk is DEGRADED review - the same
party that dispatched the work is now judging it, which is the independence the
method exists to preserve - so the report names every stream walked inline
rather than letting it count as a proper walk. A silently degraded walk is
worse than a skipped one, because it still reads as reviewed.
6. Integrate - the integrator's only build-adjacent job
- An EMPTY population-ledger slot blocks the merge. The check is mechanical -
for each slot the brief declared, does the report carry one of the three fills?
That is a lookup, not attention, and it is the whole conversion: "did you
verify" is unanswerable from absence, "is slot 3 empty" is not. A stream that
discovers a claim the brief did not anticipate ADDS a slot and says so; that
addition is a brief gap and is counted as one.
- Merge order: dependencies first, hotspot-carriers last.
- ff-merge each green stream onto the train branch. Never hand-resolve a
source conflict - mechanical resolution is how duplicate imports ship. A
generated-file conflict is discarded and regenerated; a source conflict means
the losing stream rebases and re-runs its own gate.
- The integrator owns every
down_revision at merge. A stream cannot resolve
its migration's parent from inside its own worktree, because the parent exists
only in a sibling's - the migration tool then fails, the DB suites need a
migrated database, and so the stream cannot gate AT ALL with the correct
parent in place. Left unstated, every stream invents the same workaround (gate
against the real head, flip the line before handover), which ships a commit
containing a line no gate ever ran: the gated-tree-is-not-the-committed-tree
class arriving by construction rather than by carelessness. So: the stream
commits with the parent that exists in ITS OWN worktree and marks the line with
its allotted slot and intended parent; the integrator repoints at merge, where
the integrated gate proves it immediately. The stream's commit stays valid
whichever way the sibling's migration goes.
- Two streams that share no files can still collide. File-level disjointness
is necessary, not sufficient: streams also contend over SHARED OBJECTS no diff
shows - a constraint or enum whose full membership each re-declares, a registry
both enumerate, a linear namespace both draw from. Where each rebuilds a set
from its own snapshot, whichever runs second silently deletes the other's
additions, with no error until first use, and per-stream substrate guarantees
neither stream's own gate can see it. Only the integrated gate can. A rebase also re-runs the
derived-artifact and staleness checks over the files the stream did NOT
write - that is the moment foreign changes arrive under its assumptions, and
its own gate does not interrogate them.
- Regenerate the generated layer once, on the merged tree.
- Run the full gate once on the integrated result. This is the only run that
proves the batch; green-alone proves nothing about the train.
- Semantic-conflict hunt: for each pair of streams whose work COUPLES - shared
symbols, shared TABLES or stores, shared sequences and registries, or a shared
PRACTICE one of them now enforces - name the specific way they could break
together (new caller plus renamed callee, registry entry plus registry
tripwire, template plus copy ratchet, two writers on one table, a ratchet that
retroactively binds a sibling's diff) and check that specific thing. §2 alread
…(truncated)
1---2name: train3description: Run a batch of work as a merge train - N streams building concurrently in isolated worktrees, each self-verifying to green, integrated once and shipped once. Use for ANY multi-item batch of work in ANY repo, in place of building serially in the shared tree. Modes - "init" to onboard or retrain a repo (measures its substrate first), "retro" to fold a finished train's lessons back into the method. Triggers - "run a train", "train init", "train retro", "parallel streams", "batch this work".4---56# Train78One method, every repo. Three layers, never mixed:910- **METHOD** - this file. Universal. Identical everywhere. Resist per-repo11 variation; divergence between repos is debt, not diversity.12- **SUBSTRATE** - `.train/config.md` in the repo. ONLY facts that cannot be13 derived. Everything derivable is re-measured at §1 of every train, because a14 stored fact is recall and recall goes stale silently.15- **PRIORS** - the Second Brain first, `.train/priors.md` only for the16 genuinely repo-local. Read before dispatch. Appended by retro.1718**A rule has exactly one authoritative home, and correcting it means enumerating19its READERS.** The layers above say where a rule LIVES; this says what happens20when it changes. Every document that restates a rule is a reader - a checklist21that executes it, an agent definition loaded at start-up, a reference doc - and a22correction that updates the nearest copy leaves the rest live. Two copies of one23rule do not diverge loudly. They diverge silently, and the divergence stays24invisible until someone follows the copy that is wrong.2526## Modes2728| Invocation | Does |29|---|---|30| `/train` | Run a train. Requires `.train/config.md`. |31| `/train init` | Onboard or retrain a repo. Read `references/init.md`. |32| `/train retro` | Fold the last train's lessons back. Read `references/retro.md`. |3334**No `.train/config.md`? Stop and run init.** Never guess the substrate.3536**One repo, one remit.** A train never spans repositories, and an agent is never37tasked with another repo's init, config, priors or backlog - each repo's agent38owns its own. The method is shared; the work never is. The Second Brain is the39only channel between repos, and it carries lessons, never instructions.4041## Answer protocol - governs every output below4243Applies to the manifest, Stream Reports, QA verdicts, train reports, and44anything said to the operator.4546- **A1 Ledger.** Every number and factual assertion carries the exact command47 that produced it and the literal output containing it. Cannot paste output48 containing the figure? Label it UNVERIFIED. Ledger at the end, not inline.49- **A2 Scope.** State the window measured and the window claimed. Absolute50 quantifiers - never, always, zero, none, every, "returns nothing" - require a51 population-wide command. Measuring 20 commits and claiming 90 days is the52 canonical failure. **And a population-wide command must prove it SAW the53 population**: state the denominator, show it is non-empty, and name the AXIS it54 covers. A zero, a green or an "all paths" from a scan whose scope is unstated55 is UNVERIFIED. An enumeration bounded to one direction of a state transition56 has not enumerated the transition - if you fixed every path that ADVANCES, say57 so, and say that the paths that reverse or cancel were not examined.58- **A3 Recall.** Any figure not re-derived this session is recall. A hedge on a59 countable quantity - "4,600+", "~", "over", "roughly" - is the tell.60 Countable things get counted. **A3 governs what is SAID; this governs what is61 COMMITTED.** A countable figure written into a source file, docstring or62 comment must be recomputed by the build, or it does not go in - state the63 RELATION the tests enforce and point at the test. A published CONSTANT is64 exempt, because a standard's own threshold cannot drift, and that exemption is65 the boundary rather than a loophole.66- **A4 Falsify.** Take the three claims the conclusion leans on hardest and try67 to prove each wrong. Say what was tried.68- **A5** Subagent claims inherit zero trust; run A1-A4 on them yourself.69- **A6** Assume every number will be re-derived downstream.70- **A7 Account.** A response to an enumerated instruction answers every item BY71 NAME - including no-ops, already-done items and items deliberately dropped -72 and states the commit it is true at. A crossing revision is recognised by73 checking that commit's parent, not by re-reading the instruction. An item that74 appears in no line of the answer is an unanswered item, not an implied yes.75- **A8 Live figures.** Against a running system a baseline is re-measured76 immediately before the change, never carried from build time - a figure that77 was true four hours ago is recall. A figure that moves against prediction is78 attributed by ORIGIN, by joining records to the change's own marker, never by79 the size of the delta. A fix is verified through the CONSUMING surface's own80 predicate, never a raw field that looks equivalent.8182**Refer to work by name, not by bare id.** "#150, #151, #128" is a wall the83operator has to look up one at a time; "#150 (never-reject violation)" reads at84a glance. The id rides inside the name, never stands in for it.8586Absence-of-token claims about source must exclude comments or parse structure -87a grep for a token inside a file that documents that token matches its own88comment.8990## 1. Measure - every train, never recalled9192```93git log --since="90 days ago" --no-merges --name-only --pretty=format: \94 | grep -v '^$' | sort | uniq -c | sort -rn | head -20 # hotspots95git log --since="90 days ago" --oneline --no-merges | wc -l # denominator96git branch --list; git worktree list # in-flight state97git status --porcelain # dirty tree98```99100Hotspot share = count / denominator. Anything above ~5% of commits is a101hotspot. Read `.train/config.md` for what cannot be derived: gate command,102test-isolation mechanism, migration system, deploy invocation, generated103artifacts, CI triggers and runner count.104105A derived index - a code graph, symbol index, embedding store, generated map -106is a stored fact under another name: recall goes stale silently, so it is107ASSERTED fresh, never read fresh. Assert against the newest thing the repo108changed (`git log -1 --name-only`), never against the tool's own status line,109and treat a miss as staleness until proven otherwise - a stale index degrades110into a plausible capability limit ("unsupported file type"), which is exactly111why it survives. `.train/config.md` names the index and its refresh command.112(method_ext, operator-approved 2026-08-17.)113114**Refuse to start if the tree is dirty or work is in flight.** Land or park it.115Changing integration model with work in flight is how eight-branch pile-ups116happen.117118**Enter a train with headroom for a whole train.** The integrator's own119context is an entry condition budgeted here exactly as §3 budgets spawns:120compact at the boundary, where every input to the manifest is durable and121re-readable, so the compaction costs nothing. Where a train is large enough122that mid-train compaction becomes unavoidable, that is expected - and is123precisely why verdicts, the sha mapping, dispatch rationale and operator124rulings are written to files as they are produced rather than held in125context (§5). (method_ext, operator-approved 2026-08-17.)126127## 2. Decompose - the step most often skipped, and where rework comes from128129Produce the train manifest before any dispatch: per item, the predicted file130set, hotspots claimed, migration slot, dependencies, and its **blast radius** -131whether being wrong here costs money, data, access, or an irreversible external132effect. Most items are cheap to get wrong; the few that are not should be133visible at manifest time, not discovered at review.134135- **Below about three items, it is not a train.** One urgent fix runs solo (§7);136 two items in a shared tree cost less than the manifest, the worktrees and the137 integration. The ceremony has to be earning something.138- **What makes a correct slice is not its size.** A slice is right when its139 predicted file set is disjoint from its siblings AND its acceptance evidence is140 self-contained - provable without waiting for another stream to land. Size141 (~30 min) is a consequence of getting those two right, not the criterion. A142 slice that needs a sibling's work to demonstrate itself is one stream, not two.143- **Predict the file set from co-change history, not from the ticket.** The144 ticket says what to change; §1's ranking says what historically gets changed145 with it. A prediction drawn from reading the ticket alone systematically misses146 the test file, the fixture, the registry entry and the doc that always move147 together, and those misses are what spend the +2 allowance.148- **Dispatch order is not manifest order.** Enforcement mechanisms go first149 (they bind everyone). Then longest-pole first, then descending, because the150 train's wall clock is its slowest chain and starting that last idles it.151 High-blast-radius items go early too, so a failure surfaces while there is152 still time to react rather than at integration. The concurrency cap is the153 LOWER of the substrate limit and what the integrator can actually read: N154 streams times a report is a context budget, and that ceiling usually arrives155 first.156- **Dropping a stream mid-train is normal.** If an item turns out wrong, pull it157 from the merge, let teardown delete its branch, and return it to the backlog.158 Do not carry a doubtful stream into integration because it is already built.159160- **Hotspots co-queue, they do not exclude.** Two items touching the same161 hotspot belong in the SAME train, dispatched sequentially inside it - the162 second branches off the train head after the first merges. Pushing the second163 to a later train adds delay and buys no safety; same-scope changes need to be164 tested *together*, which is where semantic conflicts surface.165- **Semantic dependency = one stream.** If B's correctness depends on A's166 behaviour, they are one stream run sequentially, never two. Two streams green167 alone can be wrong together.168- **Sequenced resources couple like hotspots.** A single-head migration chain,169 an ordered registry, any monotonic sequence - two claimants cannot verify170 their link into it from inside their own worktrees, because the sibling's171 entry does not exist there. Two claimants on one sequence co-queue: a declared172 dispatch order at manifest time, the second based on the first, and that order173 IS the integration order - declared up front, not discovered at integration.174 (operator-approved.)175- **A stream that adds an enforcement mechanism constrains every sibling.** A176 ratchet, tripwire, lint rule, schema constraint or ACL retroactively binds all177 other work in the same train - one-to-many, not pairwise, so the dependency178 rule above does not catch it. Such a stream is dispatched FIRST with siblings179 branching off its merge, or held to the next train. Never concurrent with the180 work it will constrain: no sibling's brief can carry a requirement that does181 not exist yet at dispatch. **The concurrency exemption is judged on PRACTICE,182 not file overlap** (observed across two consecutive trains, operator-approved): a ratchet policing a practice183 - how tests assert, how errors render, how connections resolve - touches every184 sibling with zero file overlap, so file-set disjointness never exempts it.185 One train invoked the file-overlap reading and paid three same-train recurrences of186 the exact class the ratchet banned. **Its brief must also enumerate the recognition187 axes** - what object, spelled how, named or set which ways - and the house188 idioms per axis, gathered by grepping before dispatch. Skip this and QA189 discovers the shapes one at a time: observed as a 7-round ladder costing ~2.5h190 against a 14.9-minute build, 6 rounds of which were greppable upfront. **And191 it must try to evade its own detector** - a guard keyed on a name rather than192 a binding is bypassed by shadowing. This is §5's mutation-check applied to a193 detector, where the mutation is a bypass shape, not a new rule. **And it must194 report its PRECISION on the current codebase** - every flag it currently195 raises, triaged true or false positive. Evading itself tests false negatives;196 this tests false positives, and both are acceptance criteria. A detector that197 fires 5 times and is wrong 5 times gets ignored within a week, after which the198 class it guards is silently unenforced while still looking enforced - worse199 than no detector. If it flags by a hand-maintained list, ask what the200 vocabulary IS: one that evolves inside this repo (schema columns, route names,201 registry entries) must be DERIVED from its source of truth, because a hand202 copy of it is the mechanism's own decay. One that is external and fixed (a203 language's builtins, another engine's function set) has no in-repo source to204 derive from and a hand list is correct - but write down which case you are in205 and why, or the next reader cannot tell a justified list from a rotting one.206- **An investigation is not a build stream.** The test is whether you can state207 the question precisely NOW - not whether you can answer it. A sharp question208 with an unpredictable file set is an investigation; a question you cannot even209 phrase sharply is not ready to dispatch at all, and saying so is the honest210 answer rather than dispatching a stream to find out. Its file set is unknowable211 at dispatch, so §3's predicted-set hard stop and the hotspot rule cannot212 protect it. Dispatch it to produce a FINDING plus a proposed brief - read-only,213 no fix - and the fix becomes a properly predicted stream in this train or the214 next. If it must fix in flight, it declares its file set UNKNOWN and may not215 run concurrent with anything touching plausible surface. **A manifest cannot216 claim "no hotspot collisions predicted" while any217 stream's file set is unknown** - that is an unfounded absolute, not a218 prediction. **A ticket's diagnosis is a hypothesis, not a spec.** Any stream219 whose brief inherits a diagnosis - from a ticket, a prior finding, or the220 integrator - verifies that premise against evidence as its first analytical221 act, before building on it. A4 covers the stream's own conclusions; this222 covers what it was handed. Observed: a "box config" diagnosis was wrong223 (nothing had ever seeded the config anywhere), and the correct fix differed;224 a brief once named an edit site that was dead code on the live path.225 **So is the integrator's own prescription.** When the integrator directs a226 MECHANISM change rather than a defect fix - replace this parser, use that227 library's own output, derive it from the source of truth - the brief must228 require the stream to enumerate what the OLD mechanism covered and prove the229 new one still covers it. A stream complies exactly and loses coverage doing so,230 and it cannot easily refuse a direction that arrives with a rationale and a231 bound. Observed: replacing a hand-rolled manifest parser with the build tool's232 metadata output was sound reasoning and a net -55 lines, and silently stopped233 scanning the workspace root manifest, losing coverage in two layers at once.234 **AND THE INTEGRATOR'S OWN FIGURES CARRY THE LEDGER.** The two rules above bind235 the STREAM: verify what you were handed. They work - which is exactly why every236 stream in one train corrected the ticket that dispatched it, four of them237 correcting facts the integrator had supplied as established. That is the method238 catching the defect at the last possible moment, at the cost of every stream239 doing correction work that should never have been needed. So the obligation runs240 upstream too: **every figure in a manifest or brief is either re-derived this241 session with its command pasted, or labelled RECALL**, and a stream may refuse a242 brief whose numbers are unlabelled. The population ledger binds what a stream may243 CLAIM; nothing bound what the integrator may ASSERT, and that asymmetry pointed244 the discipline away from the party with the most reach. When every stream in a245 train corrects its own dispatching ticket, that is a decomposition defect, not a246 spec-quality problem.247- **Decisions serialise; execution parallelises.** A decision changes what the248 remaining work IS, so two decisions resolved in one pass means the second was249 made against a stale picture - the same one-to-many shape as the ratchet rule.250 Anything whose output is a decision rather than a diff runs one at a time, and251 where that decision is the operator's it is never resolved by inference, no252 matter how blocked the train is. An agent answering on the operator's behalf253 because waiting is expensive has broken the thing the rule protects.254- **Slice to ~30 min of build.** Sharply-briefed streams run far faster than255 intuition predicts (observed 3-13 min against 37-75 min unbriefed); the256 predicted file set is what bounds exploration. Widen the train, not the slice.257- **Walk the manifest before dispatching anything.** QA walks streams and §8258 enumerates integrator SIDE-EFFECTS; nothing otherwise walks integrator259 JUDGEMENT, and judgement errors propagate with full authority because streams260 comply exactly. Three mechanical checks, costing minutes:261 1. **Every predicted file exists**, or is explicitly marked to-be-created.262 `git ls-tree -r HEAD --name-only | grep -f predicted` takes a second.263 Observed: a stream dispatched against an asset directory that was not in the264 repo at all - it arrived with a later phase's handoff - and halted correctly265 having cost a full dispatch.266 2. **Every acceptance criterion names the mutation AND the failure it must267 produce.** A criterion that cannot be falsified is not a criterion. Observed:268 "all six tests must go red" was impossible for one of the six, and a269 compliant stream would have contorted a correct test to satisfy it.270 3. **Every figure is a median of >=5 runs with min and max, or is labelled271 UNVERIFIED.** A single sample may raise a question; it may never settle one.272 Observed: one timing sample taken on a machine that was compiling was 7x273 wrong and nearly bought an unnecessary optimisation programme. The method274 manufactures that contention itself by running N streams on one box.275- **A tracker's status is not evidence the work is undone.** Before an item276 becomes a stream, verify it is still open against the SYSTEM, not against its277 status field - the defect still reproduces, the row still exists, the path is278 still reachable. An item that cannot be shown still open is an investigation at279 most, and possibly a close. The premise check further down fires INSIDE a280 stream, which is after the stream is paid for.281- Show the operator the manifest with its ledger. Do not wait for approval282 unless a hotspot claim is contested or an item needs an operator input.283284## 3. Dispatch - every stream gets all of this or it does not launch285286- **Agent spawns are a consumable session resource - budget them.** A train287 costs roughly 2N+ spawns (a carriage and a walker per stream, plus ratchet,288 classifier and content roles), and runtimes cap spawns per SESSION289 cumulatively, not concurrently. Reaping idle agents does not help: the counter290 counts spawns, never live agents. `.train/config.md` records the cap and the291 observed per-train cost; when a session's remaining budget is under two trains'292 worth, start a fresh session rather than degrading mid-train.293 **Prefer resuming a finished agent over spawning a fresh one** for repeat roles294 - a walker already matched to a surface has performed as well or better than a295 new spawn. Never force a context-exhausted agent; retire it and start one.296 **Resuming spends the agent's context instead of the spawn odometer** - the two297 are currencies for the same purchase, and a resume economy that works perfectly298 hides the exhaustion until it fails all at once. Six consecutive trains ran on299 zero fresh spawns and then walked into a wall with no warning.300 **The runtime cap is a runaway backstop, never the budget.** Set it high enough301 that it cannot bind, and do the budgeting in config where it is visible and302 measured. A ceiling you are steering by is a ceiling that will surprise you.303- **THE POPULATION LEDGER - declare the slots BEFORE the work.** Folded after the train that measured it304 (operator, 2026-08-20) after E2 failed six times in one train on the class it305 was written for. You cannot detect a missing check by inspecting a report,306 because the omission removes the claim and its evidence together - so the slot307 must exist before the report does. The brief enumerates every population claim308 this stream will have to make:309310 | trigger | slot |311 |---|---|312 | the stream ADDS A CHECK | denominator + axis |313 | the stream CENSUSES or claims completeness | one slot per search route, **minimum two of DIFFERENT KIND** |314 | the stream WRITES EXISTING ROWS | dry-run query + its output |315 | the stream returns a NULL RESULT | the population that WOULD have contained the thing |316 | the stream asserts any ABSOLUTE | denominator + axis |317318 **"Different KIND" is load-bearing and the brief must say so in these words.**319 Two greps against the same index is ONE route wearing two hats, and that is320 exactly how that missed file was missed. The census that worked used three321 genuinely different kinds - ORM attribute, raw SQL string, and322 instance-reads-by-holder - and only the third found the file no prior list323 named.324325 **The brief must also state, in the brief itself, that UNKNOWN is blameless.**326 Not in the method, not in a prior - in the text the stream reads. A mechanism327 that punishes empty slots without offering an honest unknown manufactures328 evidence, and the first stream that cannot reach live will invent a number329 rather than write that it could not determine one.330331 EMISSION is required everywhere. **IDENTITY is preferred where the stream332 controls both sides** - make the claim and the check the same statement, as a333 migration whose dry-run and write share one population constant does, or a rule334 with one implementation and several callers rather than a restatement in a335 second language. Identity cannot diverge; emission can only be checked.336- Its own git worktree and a local branch off the current train head. Never the337 shared tree. Never a push to origin unless config says otherwise.338- **Verifying the base is the stream's FIRST act, before any edit.** Worktree339 tooling spawns at a main-line sha, not necessarily the branch you declared -340 observed failing 3 of 3 times. The brief states the expected base sha; the341 stream asserts it, ff/resets if wrong, and says so in its report. Without342 this, co-queueing silently builds the second claimant on the wrong file state343 and every "clean merge" is luck.344- **A base that was AMENDED or rewritten - not merely advanced - rebases with345 `rebase --onto <new-base> <old-base>`.** A plain rebase replays the superseded346 base commit itself into the stream. When the integrator rewrites a base, the347 grant states BOTH shas and the stream asserts the old one is its ancestor348 before rebasing. (operator-approved.)349- Brief: goal, acceptance evidence required, predicted file set, migration slot350 or "none", isolated substrate handles (test DB port/namespace per config, and351 any singleton resource - browser, REPL, shared session, shared dev or staging352 database - budgeted exactly like a port), model tier, the relevant lines353 from `.train/priors.md`, and **a statement that a SUBSTANTIATED NULL RESULT -354 already fixed, premise false, defect unreachable - is an acceptable355 deliverable.** A stream that manufactures a fix to fill its slot has done worse356 than nothing, because the fix will be walked, merged and believed.357- **Every operator input - screenshot, ruling, credential, sign-off - is358 requested at manifest time in one batched list.** Never discovered mid-build.359- Hard stops; report and halt rather than work around: config-owned data the360 operator owns, a production write, a side-effectful external retry, the same361 test failing three times, the file set exceeding predicted + 2, **running out362 of working context** - stop honestly with a clean tree and an explicit list of363 what remains (observed: two streams did exactly this and a fresh agent completed364 each first try; a stream that pushes on with spent context ships unverifiable365 work), or **needing a new dependency** - installed packages are near-always shared state (a symlinked366 virtualenv, a hoisted node_modules, a vendor dir), so one stream's install367 silently changes what every sibling's gate is testing against. Nothing fails;368 the results just stop meaning what they say.369370## 4. Stream exit - the gate is mechanical, runs ONCE, by the stream371372Run the repo's exact gate command from `.train/config.md`, in the worktree,373against its own test substrate. Do not run a second overlapping suite behind it.374375**Mutation proof runs LEFT, at build time, by the builder** (observed across two consecutive trains,376operator-approved): before the gate, the stream reverts each of its fixes in377turn and pastes its own new tests going red, then restores. QA replays rather378than discovers; a stream whose tests were never proven red ships tests that379cannot fail, which one train measured as the dominant defect class (9+ instances,3807 streams). A mutation must vary exactly ONE thing - changing two validates381the test instead of the code (a stream's false proof). A red that fails for the382wrong reason (syntax error, import break) is not a proof; report failed383mutation attempts as what they were.384385The Stream Report is what QA and the integrator read instead of the diff. **Cap386it at ~40 lines**: branch and sha, file list with line counts, gate commands387with pass/fail counts pasted, the repo's pre-ship questions answered with388evidence, the live evidence that will prove it after deploy, **what any embedded tunable389constant selects against live data at the value being shipped** - a threshold,390cutoff, rate limit, retry count or page size is a judgement call encoded as a391number, and nobody can review a number without seeing what it picks; paste the392read-only result so the decision is operator-visible BEFORE it ships, not393inferred from the diff - anything394UNVERIFIED, any file outside the predicted set, **every population-ledger slot395the brief declared, each filled FILLED / UNKNOWN / N-A** - FILLED means the396literal command and its literal output, never a summary of the output; UNKNOWN397means could-not-determine with the reason, and is blameless; N-A means it does398not apply, with the reason - and the claim ledger. Full399evidence goes to `STREAM-REPORT.md` in the worktree, **at a path the repo400gitignores**, with the path cited. Report artifacts never ride a merge - two401streams writing the same tracked path is an add/add conflict at integration.402Untracked-by-convention is not enough; `git add -A` defeats it, so the ignore403line is the enforcement and `.train/config.md` names the path.404405**An investigation or design stream writes its finding to the FILE first and406returns a summary second - the reverse of a build stream.** A build stream's work407survives in its commit whatever happens to the agent. An investigation stream has408no commit: the finding IS the return message, so an idled session loses the409entire result. The durable artifact must never be the ephemeral one - the same410reasoning as the population ledger and the QA verdict file, and the same rule as411§7's detector clause: the thing that proves the work has to survive independently412of the party reporting it.413414**Every stream report also answers "what did you notice that the brief did not415decide?" - answered, or explicitly NONE.** Same three fills as the population416ledger. The ledger forces a stream to emit its EVIDENCE so a claim cannot outrun417it; this forces a stream to emit its UNASKED QUESTIONS so a brief's blind spot418surfaces while the author is still in the code. It is the one question a stream419can always answer and a reviewer usually cannot.420421## 5. QA - adversarial only, concurrent, one instance per stream422423**QA GATES EVERY PUSH. NO STREAM SHIPS UNWALKED, EVER.** Operator law, restated4242026-08-20 after it lapsed for two consecutive trains. It is not a per-train425judgement and does not lapse because a batch is small, urgent, bug-only or426obviously fine. **If you find yourself reasoning that a particular stream does427not need a walk, that reasoning is the defect.**428429**The gate is not a substitute.** The repo-level rule this mirrors used to read430"run a QA pass (or the full suite)", and that parenthetical is how the law431lapsed: the suite ran, so the rule read as satisfied while nothing independent432looked at the diff. A gate proves the code does what its tests say. QA asks433whether the tests say the right thing - which is the only question that catches434a stream shipping exactly to a brief that was wrong.435436**QA WRITES ITS OWN VERDICT FILE. A verdict that exists only as an agent's437return message does not exist.** One file per stream, on disk, at a path the438train names before dispatch. This is the same rule as the durable-artifact rule439for investigation streams, and it exists because two entire trains' QA verdicts440were lost: they had only ever been chat turns.441442**A train cannot close until the per-stream verdict count is asserted BY COMMAND443and its output pasted**, exactly as section 7 requires of worktree and branch444counts. UNKNOWN is an allowed and visible value; a missing file is not. Without445this, QA's absence is undetectable - which is precisely how it went unnoticed446across two trains, two close-outs and two retros.447448- **Spawned by that stream's completion**, not batched by the integrator. QA449 for a finished stream runs while other streams are still building. Each QA450 instance holds its own test substrate handle.451 **Walkers dominate the spawn bill** - typically 9-11 of a ~15-spawn train. When452 budget is tight, one walker may take several streams SEQUENTIALLY: independence453 survives, because a walker is independent of the builders whichever streams it454 takes, and only concurrency is lost. That is usually cheap, since walks run455 under build time. Declare it when you do it, and retire the walker before its456 context degrades - a walker on its fourth stream is not the walker that did the457 first. Never consolidate a walker across a stream it built.458- Does NOT re-run a suite the stream already ran green. That is duplicated459 compute and a collision risk.460- **The QA brief NAMES its hunt classes**, derived at brief-generation time from461 `.train/priors.md` plus the stream's own risk surface - the priors file is the462 standing class list, so seeding from it is mechanical, not judgement. A defect463 found in round 2 whose class was NOT named is a brief gap, not a QA win: that464 is what makes the §8 split falsifiable instead of self-flattering. A465 first-occurrence exemption - "no prior existed to seed from" - holds only if466 the class was underivable from the stream's RISK SURFACE too, since hunt467 classes come from both sources; absent-from-priors alone is not enough, or468 every gap becomes a first occurrence. One exemption per class, and the class469 enters priors the same day. A hunt list470 that names everything is not a hunt list - padding it to avoid gaps is itself471 a finding.472- **QA is held to the same evidence standard as the stream: a check that was473 attempted but did not take effect is not a check.** Three specifics follow474 from that one rule, and every one of them was learned the hard way -475476 - *Walk the named classes* in the diff. Declaring them beforehand is what477 makes "QA caught it" falsifiable after.478 - *Mutation-check* that new tests fail without the fix, scoped to the tests479 the stream added. For a guard written after an incident, the mutation is480 **RESTORING THE DEFECT IT WAS WRITTEN FOR, in the shape that defect actually481 had** - never a synthetic restatement, never by breaking a helper. To prove a482 guard is INVOKED, delete the CALL: breaking the helper proves only that the483 helper is reachable from somewhere. The guard must fail INDEPENDENTLY for484 every member of the population it claims to cover, restoring clean between485 each - one red proves one member, never the set. And assert the LOCATION of486 an effect, not only its occurrence: a test proving something was written487 passes when the write lands in the wrong place. **Verify the mutation LANDED488 before its result counts**: re-read the value, re-import the module, check the diff. A probe489 that silently no-ops (an edit landing in a docstring instead of a table490 value, a patch applied to a copy) reads as "fix confirmed" and once nearly491 closed a real finding. **Commit before mutating** - reverting with a492 working-tree checkout against uncommitted changes destroys the FIX rather493 than the mutation, observed twice in one sitting.494 - *Mutation proves a test CAN fail. It does not prove the test fails for the495 REASON CLAIMED*, and that gap has let two defects through. Assert the496 **expected failure**, not merely a failure. Two mechanical halves:497 - **Proof of arrival.** A test must demonstrate it reached the code it498 claims to exercise. If it can pass without the function under test being499 entered, it is testing something else. Observed: a test failed under500 mutation because a validation layer IN FRONT of the target refused the501 input, so the target was never entered - it was exercising the guard in502 front of the guard.503 - **Failure specificity.** Assert the reason, never a substring that a504 generic or default message also contains. Observed: a permanent guard kept505 passing because a different error message happened to contain the asserted506 substring, so the guard survived the thing it documented being removed.507 - The same applies one level up to any test justified as "this proves we508 chose X over Y": ask what it would report if Y were implemented. If the509 answer is "the same", it never entered the discriminating region and is510 decoration. Observed: 2 of 3 tests passed against the rejected511 implementation until one asserted it had entered that region.512 - *Rehearse data migrations by EXECUTING them* against a scratch database513 built at the pre-merge head. A read-only SELECT proves which rows would be514 selected, never that the migration runs - driver type-binding, transaction515 semantics and the migration's own code are only exercised by running it.516 Production-shaped data where a backup restore is available; an empty schema517 proves syntax, not behaviour. A corrective sweep's cutoff derives from the518 DEFECT'S WRITE WINDOW - the last moment before the fix's first possible519 write - never from the deploy or run moment, which re-destroys post-fix520 truth on any re-run. Rehearsal executes the migration TWICE: a sweep that521 is not idempotent against post-fix rows is not finished. (operator-approved,522 operator-approved.)523524 Then: run A4 against the stream's ledger, and hunt the absence cases.525- For claims of the class that keeps failing (absolutes), prefer 2-3 verifiers526 each given a *different slice* of context, with disagreement as the trigger,527 over one verifier with everything.528- Verdict is PASS or a specific failure with file:line. Fixes are re-walked as529 a delta - never a "smalls" round that lands unwalked. **The verdict is530 written to `.train/t<N>-verdicts.log` the moment it is produced** (gitignored;531 one line: stream, sha, PASS/FAIL, walker) - a verdict that exists only in532 conversation is destroyed by compaction and by any session boundary, and the533 loss is silent because integration proceeds on a remembered PASS.534 (method_ext, operator-approved 2026-08-17.)535 **The same holds for EVERY artifact handed between agents** - a patch, a536 finding, a census, not only a verdict. It is written to a file at the moment it537 is produced; conversation is not storage, and neither is a scratch directory538 the session owns. The reason was never specific to verdicts, and a verified539 patch was lost exactly this way.540- **When the integrator carries a departed stream's work itself, it declares541 that** exactly like an inline walk, and proves the transplant by CONTENT542 EQUALITY of the diff at source and destination - never by inspection.543- If a QA walk exceeds its stream's build time, say so in the train report: the544 walk is doing work the gate should own.545- **At-cap protocol, and it must be declared.** Out of spawn budget: first resume546 a finished walker for a bounded delta it already owns; only as a last resort547 does the integrator walk inline. An inline walk is DEGRADED review - the same548 party that dispatched the work is now judging it, which is the independence the549 method exists to preserve - so the report names every stream walked inline550 rather than letting it count as a proper walk. A silently degraded walk is551 worse than a skipped one, because it still reads as reviewed.552553## 6. Integrate - the integrator's only build-adjacent job554555- **An EMPTY population-ledger slot blocks the merge.** The check is mechanical -556 for each slot the brief declared, does the report carry one of the three fills?557 That is a lookup, not attention, and it is the whole conversion: "did you558 verify" is unanswerable from absence, "is slot 3 empty" is not. A stream that559 discovers a claim the brief did not anticipate ADDS a slot and says so; that560 addition is a brief gap and is counted as one.561- Merge order: dependencies first, hotspot-carriers last.562- ff-merge each green stream onto the train branch. **Never hand-resolve a563 source conflict** - mechanical resolution is how duplicate imports ship. A564 generated-file conflict is discarded and regenerated; a source conflict means565 the losing stream rebases and re-runs its own gate.566- **The integrator owns every `down_revision` at merge.** A stream cannot resolve567 its migration's parent from inside its own worktree, because the parent exists568 only in a sibling's - the migration tool then fails, the DB suites need a569 migrated database, and so **the stream cannot gate AT ALL** with the correct570 parent in place. Left unstated, every stream invents the same workaround (gate571 against the real head, flip the line before handover), which ships a commit572 containing a line no gate ever ran: the gated-tree-is-not-the-committed-tree573 class arriving by construction rather than by carelessness. So: the stream574 commits with the parent that exists in ITS OWN worktree and marks the line with575 its allotted slot and intended parent; the integrator repoints at merge, where576 the integrated gate proves it immediately. The stream's commit stays valid577 whichever way the sibling's migration goes.578- **Two streams that share no files can still collide.** File-level disjointness579 is necessary, not sufficient: streams also contend over SHARED OBJECTS no diff580 shows - a constraint or enum whose full membership each re-declares, a registry581 both enumerate, a linear namespace both draw from. Where each rebuilds a set582 from its own snapshot, whichever runs second silently deletes the other's583 additions, with no error until first use, and per-stream substrate guarantees584 neither stream's own gate can see it. Only the integrated gate can. **A rebase also re-runs the585 derived-artifact and staleness checks over the files the stream did NOT586 write** - that is the moment foreign changes arrive under its assumptions, and587 its own gate does not interrogate them.588- Regenerate the generated layer once, on the merged tree.589- **Run the full gate once on the integrated result.** This is the only run that590 proves the batch; green-alone proves nothing about the train.591- Semantic-conflict hunt: for each pair of streams whose work COUPLES - shared592 symbols, shared TABLES or stores, shared sequences and registries, or a shared593 PRACTICE one of them now enforces - name the specific way they could break594 together (new caller plus renamed callee, registry entry plus registry595 tripwire, template plus copy ratchet, two writers on one table, a ratchet that596 retroactively binds a sibling's diff) and check that specific thing. §2 alread597598…(truncated)