Skip to content

bind every graph run to the document it loaded (ADR-0030) - #133

Merged
kikashy merged 3 commits into
mainfrom
graph-digest
Aug 24, 2026
Merged

bind every graph run to the document it loaded (ADR-0030)#133
kikashy merged 3 commits into
mainfrom
graph-digest

Conversation

@kikashy

@kikashy kikashy commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Closes #132.

ADR-0030: graphSha256 (bare hex, the payload convention) on the graph suite entry, its validation twin, and the direct single-graph test envelope — the digest of the exact bytes the run decoded, read off the one load. Equality with experimental_get_graph's sha256 proves rows and document describe one revision; the member is absent exactly when the document did not load, beside the detail saying why. Retires the wire client's epoch-gating mitigation with a real binding.

Tests: fixture-digest equality on both walk surfaces; absence with detail on an unloadable document; the validation-side wiring is mutation-verified.

Material-decision impact: public-surface; review: round to be posted on this PR

🤖 Generated with Claude Code

kikashy and others added 3 commits August 24, 2026 08:43
A client can fetch a configured graph document and run its matrix in
two calls with an edit between them, and the matrix payload carried no
digest of the document its run loaded — so a join of rows and structure
could silently span revisions. The suite entry, its validation twin,
and the direct test envelope now carry graphSha256, the bare-hex digest
of the exact bytes the run decoded, read off the one load; equality
with the served document's own sha256 proves one revision, and the
member is absent exactly when the document did not load, beside the
detail that says why. The value existed at the right moment all along —
graph.Load computes it and the lock pins it — and only the wire omitted
it.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
…g test discriminate (review round 1)

- GraphValidation (direct single-graph validate) gains required graphSha256,
  populated from the one load its command performed — the ADR promised the
  validation surface and the direct envelope was missed (round-1 MEDIUM).
- Tests now assert the wire, not the Go field: raw-JSON presence on all four
  payloads, raw-JSON absence (not emptiness) on both failed walk entries, a
  planted impossible digest proving the direct test envelope echoes the handed
  document, and digest retention across a post-load rows failure.
- ADR/changelog narrowed to what ships: matrix runs and validations (evaluate
  composite excluded as before), load at most once per entry, absence beside
  the detail or diagnostics, budget claim qualified to the budgeted paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
@kikashy

kikashy commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Review round 1 — disposition

Reviewer: Codex (codex-cli 0.145.0, OpenAI) · Reviewed SHA: 4e92a5d7f6be241589249b9c6b2904d3ac33ae5a · Fix commit: 7f6ed6b (covered by the dispositioned-finding exception; 0066ad6 is the status flip only)

# Severity Finding Disposition
1 MEDIUM Validation scope incomplete: the direct single-graph GraphValidation envelope was left digest-free while the ADR promises the matrix and validation surfaces. Accepted, fixed. GraphValidation gains required graphSha256 (the payload exists only after its caller's load), populated from the one load at the CLI construction site, asserted in raw JSON on the cycle case — present even on an invalid-but-loaded document, which is exactly the binding's meaning.
2 LOW Tests don't discriminate the wire contract: Go-field asserts miss the direct GraphTest assignment; == "" can't tell omission from emptiness; no rows-failure or validation-walk failure case. Accepted, fixed. All assertions now run on marshaled bytes: presence on all four payloads, absence-of-member (not emptiness) on both failed walk entries, digest retention across a post-load rows failure, and a planted impossible digest proving the direct envelope echoes the handed document rather than re-reading disk. Mutation-verified: rows.go direct assignment, CLI populate, suite testEntry assignment, and omitempty dropped on each entry tag — every mutation fails a test (5/5; the earlier validateEntry mutation was verified pre-push).
3 LOW Budget prose overstates: the validation walk has no report budget. Accepted, fixed. Consequence qualified to the budgeted matrix-test paths, with the reason the validation walk needs none.
4 LOW Documentation broader than implementation: “every graph run” vs the excluded evaluate composite; “loaded once per entry” vs the rowless skip; “the detail” vs validation diagnostics. Accepted, fixed. Title, filename, index row, and changelog narrowed to matrix runs and validations; “at most once per entry”; “detail or diagnostics.”

Reviewer's sandbox could not start go test (read-only FS); the full gate ran on the author side at 7f6ed6b: gofmt/vet clean, full suite green, bundled corpus 20/20.

Six refuted-on-inspection items (single-load provenance, prefix robustness, rows-failure semantics, required/omitempty split, budget accounting, roster/claim drift) recorded in the review log; no action.

ADR-0030 flipped to accepted (0066ad6).

@kikashy
kikashy merged commit 38bf37c into main Aug 24, 2026
6 checks passed
@github-actions

Copy link
Copy Markdown

🎉 Thank you for your contribution to Judgment Pack!

If you’d like another task, choose a path that interests you:

@kikashy kikashy mentioned this pull request Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Carry the graph document digest on graph matrix entries, so a client can bind rows to the document they ran against

1 participant