Expand description
Outcome contracts — the verifiable definition of “done” for a coder session.
A contract is a set of shell commands that must pass inside the worktree.
It is derived from the user’s intent by a model (with a bounded repair loop
mirroring car-builder: generation is an injected closure, so tests run
without inference) and then becomes the trust boundary for the whole
session: whatever engine did the work — the native loop or an external CLI
— the runtime re-runs the checks itself before asking for merge approval.
§What a contract can and cannot assert
The point-in-time assertion vocabulary is
ContractCheck::expect_exit_zero and
ContractCheck::output_contains. The latter normally checks a substring;
its reserved $json:<pointer>=<json> form performs runtime-owned JSON value
equality. That is not the boundary, though: the command is graded on its exit code, so a threshold
against a live system ([ "$(…)" -lt 100000 ]) is a legal check today, and
contract checks are deliberately not de-credentialed, which is why they run
through WorktreeExecutor::run_check_shell rather than the model’s own
run_shell.
Before/after claims are expressible too (Parslee-ai/car#1067). A check
marked ContractCheck::baseline is a capture: it runs once, at session
start, inside evaluate_contract_baseline’s pass over the unmodified
worktree, and its output is kept (BaselineCaptures, built by
collect_baseline_captures). A check carrying a
ContractCheck::differential runs at every later evaluation and its
output is compared against the named capture by the RUNTIME — exhaustively
one of DifferentialExpect::Changed, DifferentialExpect::Unchanged
(the control-group claim), or DifferentialExpect::DeltaWithin (numeric
delta bounds). The command is arbitrary — a row count, a file digest, a
curl body — so the external subject falls out of the command. Checks keep
the model’s policy chain by default; an explicit contract opt-in omits only
DenyCredentialAccess (car#1066). What this adds is the before/after
structure. Both executions are runtime-owned and both results
are stamped into the session’s events (the capture in contract_baseline,
the comparison in check_completed): model claims count for nothing.
What is still missing is an evaluation point past delivery. Every
evaluation is on this side of it:
evaluate_contract_baseline against the unmodified worktree, then
evaluate_contract once per repair round inside the loop, then
evaluate_contract_within as the gate that admits delivery. Only
car code-task runs that gate as a separate pass after the loop, holding
the loop’s own verdict advisory; a daemon session finalizes straight off the
loop’s last evaluation, which is the same call one layer down. Nothing runs
after either way. So a claim about what a DEPLOY changed (“the row count
fell after the deploy”) still belongs to the orchestrator wrapping the
session, which owns the deploy and both sides of that window — the
differential machinery here measures across the session’s work, not
across a deploy the session never performs. See docs/car-code-task.md.
Structs§
- Check
Result - Result of evaluating one
ContractCheck. - Contract
Check - One acceptance check: a shell command run at the worktree root.
- Contract
Draft Request - What one derivation attempt asks of the injected generator: the prompt, plus whether this attempt must be routed to a DIFFERENT model than the last one.
- Differential
Check - A before/after claim: compare this check’s output against a named
baselinecapture. - Outcome
Contract - The verifiable definition of done for a coding session.
Enums§
- Differential
Expect - The differential claims the runtime can decide. Matching is exhaustive everywhere — a new variant must be handled at every site or the build fails, which is the point.
Functions§
- baseline_
cannot_ run - Checks whose COMMAND could not run at all, by name.
- baseline_
gates_ nothing - Whether a baseline run means the contract gates nothing at all.
- clamp_
check_ timeout - The timeout one check may take: its own, never more than the session has left on the wall clock.
- collect_
baseline_ captures - Extract the baseline captures from a session-start baseline pass: the
results of every check the contract marks
ContractCheck::baseline. - derive_
contract - Derive a contract from
intentvia the injectedgenerateclosure, with a bounded validate→repair loop. - evaluate_
contract - Run every check through the worktree shell tool and report results.
- evaluate_
contract_ baseline - Evaluate the contract against the unmodified worktree, before the first edit — the red-green baseline.
- evaluate_
contract_ baseline_ within evaluate_contract_baseline, bounded by a session deadline. Seeevaluate_contract_withinfor why the baseline needs one at all.- evaluate_
contract_ with_ baselines evaluate_contract, with the session-start baseline captures that differential checks compare against. Callers that hold captures (the coder loops) use this; the capture-less signatures delegate here with an empty map, under which a differential check FAILS with a “never captured” message rather than silently passing — fail closed, never open.- evaluate_
contract_ within evaluate_contract, bounded by a session deadline.- evaluate_
contract_ within_ baselines evaluate_contract_within, with baseline captures.- intent_
targets_ tests - Whether the intent is a “the tests fail, make them pass” task — the case where the contract must be grounded in the actually failing tests rather than guessed. Deliberately narrow: the observe-then-derive path runs the test suite, so it only fires when the intent clearly asks for it.
- parse_
test_ failures - Parse pytest’s short-summary
FAILEDlines into node ids (tests/test_x.py::test_name). Best-effort and format-tolerant: the line isFAILED <node id> - <reason>, so the second whitespace token is the id. Deduplicated, order-preserving. Anything unrecognized yields nothing — the caller treats an empty result as “learned nothing”, not “no failures”. - summary_
with_ failures - Fold observed failing tests into the repo summary handed to derivation, so the model’s contract is grounded in what actually fails instead of guessed. Empty input returns the summary unchanged.
Type Aliases§
- Baseline
Captures - Baseline captures by capturing check name — the before-values differential
checks compare against. Built from the session-start baseline pass by
collect_baseline_captures; the capture is the check’sCheckResult, whoseoutput_tail(the 4 KiB tail) is the compared value, so keep a capture command’s output small and deterministic (a count, a digest, a status line — not a full dump).