Expand description
Agent-contract loop (the codiff pattern, graph-extended): the walkthrough
guide (digest + schema + graph-snapshot pin) and the --walkthrough-file
post-validation against the live graph. Public so the schema-emit binary can
derive the guide + validation envelopes.
Agent-contract loop (the codiff pattern, graph-extended).
Closes the steer-the-agent loop. The tool owns the digest + prompt + schema;
the agent owns judgment; fallow post-validates the agent’s judgment against
the LIVE graph + diff. The reentry is the --walkthrough-file path, exactly
as codiff re-resolves hunk ids against the live diff at validation time, but
fallow’s verifier is the deterministic module graph, not a second model.
§LEAD PRINCIPLE: the verifier is the graph, not a second model
Trust comes from deterministic, reproducible, graph-adjudicated post-validation that cannot hallucinate. Two mechanisms enforce it:
- Anti-hallucination (anchoring): every agent judgment MUST cite a
signal_idfallow emitted.DecisionSurface::accept_signal_idis the allowlist; a judgment whose id was never emitted is REJECTED. The agent proposes; the graph disposes. - Staleness refusal (snapshot pin): the digest (the
WalkthroughGuide) carries a deterministicgraph_snapshot_hash, a stable hash of the relevant graph + diff state. The agent echoes it back in its JSON; if the tree moved between the guide emission and the reentry, the current hash differs and the WHOLE payload is REFUSED as stale.
§Injection-resistance by construction
The digest is built ONLY from the deterministic graph
(crate::audit_brief::build_brief_output, pure over the tree). PR prose
NEVER enters the digest. On reentry, the agent’s free-text framing is FENCED
(marked non-deterministic) onto the validation output; it never gates, never
auto-posts, and never folds back into the digest. Treat any PR prose fed to an
agent as untrusted: this loop is injection-resistant because the trusted
surface is the graph, and the untrusted surface is fenced.
Structs§
- Accepted
Judgment - One accepted judgment: the real anchored signal passed through with the agent’s framing FENCED as non-deterministic.
- Agent
Judgment - One agent judgment.
- Agent
Walkthrough - The agent’s returned judgment JSON.
- Change
Anchor - One stable per-hunk CHANGE ANCHOR: a changed region the agent may cite as a
judgment anchor IN ADDITION to a
signal_id. Where asignal_idanchors a graph FINDING (“fallow emitted this exact finding”), a change_anchor anchors only a changed REGION (“fallow confirms this region changed”) , a strictly weaker guarantee, surfaced asanchor_kindon the accepted judgment so a consumer can tell the two apart. Graph/diff-derived; NEVER from prose. - Direction
Unit - One directed review unit projected from the graph: a file the change touches, the concern to check, the out-of-diff consumers it must account for, and the routed expert. Graph-derived only (routing + impact closure), NEVER from prose.
- Rejected
Judgment - One rejected judgment plus the reason it was rejected.
- Review
Direction - The review direction artifact: the order to review in, the coherent units, and per-unit concern lens + out-of-diff + expert. A minimal projection of the EXISTING graph facts (routing units + impact closure); the full weighted-focus engine is a later epic. Graph-derived only (injection-resistant).
- Walkthrough
Validation - The
fallow review --walkthrough-filevalidation envelope: the result of post-validating the agent’s judgment against the live graph. Always exit 0.
Constants§
- INJECTION_
NOTE - The standing injection-resistance note stamped on every guide.
Functions§
- agent_
schema - The default agent schema descriptor.
- build_
direction - Build the review direction. The SPINE is the change itself: every reviewable
focus unit (
review_here+ thedeprioritizedescape hatch), so the direction is never empty when there is code to review. Ownership routing is a LEFT-JOINED overlay for the optionalexpertfield, NOT the spine: sourcing the work-list from routing made it empty on solo / author’s-own-PR changes (no one else to ask), which is exactly the cloud’s dominant case. Each unit carries itsscoring_budget(the focus composite score) so a fan-out spends AI proportional to risk, its per-fileout_of_diffconsumers, and theconcern_lens. Non-source churn is excluded. Units with out-of-diff consumers sort first (load-bearing definitions before mechanical churn), then by budget. - build_
guide_ from_ result - Assemble the walkthrough guide from an
crate::audit::AuditResulton the brief path. Reusesbuild_brief_outputfor the digest (graph-only, pure) and the retained routing + impact closure for the direction. - build_
walkthrough_ guide - Assemble the walkthrough guide from the assembled brief data. Pure over its inputs: the same digest + hash always produce the same guide.
- change_
anchor_ allowlist - Build the change-anchor allowlist from the emitted anchors: every current id
plus every
previous_change_anchor(so a judgment that cited an anchor under a pre-rename path still resolves). - derive_
change_ anchor_ id - Derive a stable, CONTENT-addressed change-anchor id. Hashes ONLY the file
path + the normalized added text + an occurrence ordinal (to disambiguate
byte-identical hunks in one file). Line numbers are deliberately excluded so
the id survives edits above the hunk and whitespace-only changes. Mirrors
crate::audit_decision_surface::derive_signal_idwith achg:namespace. - parse_
agent_ walkthrough - Parse the agent’s judgment JSON from a
--walkthrough-filepath’s contents. A malformed payload yields an emptyAgentWalkthroughwhose default hash ("") will not match any real snapshot hash, so it is refused as stale (the safe direction: a garbled agent file never accepts). - parse_
change_ anchors - Parse a zero-context unified diff (
git diff --unified=0) into per-hunkChangeAnchors. Each hunk’s added (+) lines form one anchor. Rename headers make the anchor rename-durable viaprevious_change_anchor. Pure: the same diff text always yields the same anchors. - validate_
walkthrough - Post-validate the agent’s judgment JSON against the live graph.