Skip to content

Repair main (layer 3/3): realize REST input_digest as the ContentHash carrier - #7665

Merged
briansrls merged 1 commit into
mainfrom
fix/rest-invocation-digest-seed-bridge
Aug 2, 2026
Merged

briansrls merged 1 commit into
mainfrom
fix/rest-invocation-digest-seed-bridge

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

The third and final layer of #7480 fallout on main. #7656 fixed layer 1 (the rest.dag import), #7663 fixed layer 2 (the bare-string field in the witness fixture). This fixes layer 3, and with it all nine rest_exchange_replay witnesses pass again.

The defect

#7480 made ContentHash a family coproduct in .dag. v1_interpreter.rs rest_bound_invocation_value kept minting the pre-#7480 branded string:

(ctx.sym("input_digest"), Value::Str(input_digest))

So a RestBoundOperationInvocation built in .dag (a ContentHash variant) could never equal one built by the seed (a Value::Str). Fixture lookup compares those two values, so no fixture ever matched.

This is the model↔realization fork DESIGN's open threads name: a primitive modeled as a coproduct and realized as a native Value, reconciled by per-site bridges, so coverage is accidental. #7480 moved the model; this construction site was one of the bridges it did not move with it.

How it was located

Not by reading the diff — by the failure signature. Every witness requiring a fixture to MATCH failed; every witness requiring NO match passed:

requires witness result
match rest_status_and_body_are_persistable FAIL
match rest_success_projects_rest_ok FAIL
match rest_operation_without_outcome_still_refuses FAIL
match rest_transport_failure_is_persistable FAIL
match rest_unreadable_body_is_not_fabricated_empty FAIL
match ×2 rest_replay_duplicate_exact_fixture_refuses FAIL
no match rest_replay_missing_fixture_refuses_without_network_fallback PASS
no match rest_replay_sibling_operation_fixture_cannot_satisfy_subject PASS
n/a rest_replay_binding_does_not_escape_its_frame PASS

That partition is the signature of an equality that is always false, not of a broken lookup — a broken lookup would have disturbed the no-match arm too. It pointed straight at the one field #7480 changed.

Receipts

Baseline. At 9abf6243e98 — the commit immediately before #7480 — all nine witnesses PASS, same binary invocation. So this is a genuine regression against something those witnesses were already pinning, not pre-existing red.

After this change, on a release build of claim_batch:

PASS rest_status_and_body_are_persistable
PASS rest_success_projects_rest_ok
PASS rest_operation_without_outcome_still_refuses
PASS rest_transport_failure_is_persistable
PASS rest_unreadable_body_is_not_fabricated_empty
PASS rest_replay_missing_fixture_refuses_without_network_fallback
PASS rest_replay_duplicate_exact_fixture_refuses
PASS rest_replay_sibling_operation_fixture_cannot_satisfy_subject
PASS rest_replay_binding_does_not_escape_its_frame

9/9 — exactly the pre-#7480 baseline, including both no-match controls still refusing. The discriminating pair is load-bearing: a fix that made everything match would have flipped sibling_operation_fixture_cannot_satisfy_subject and missing_fixture_refuses_without_network_fallback to FAIL. They hold.

What this deliberately does not do

An earlier attempt of mine routed rest_bound_invocation_eq through compare_content_hash in dag/extdeps/transports/rest.dag. It did not fix the six, and it flipped sibling_operation_fixture_cannot_satisfy_subject PASS→FAIL. I reverted it rather than leave a speculative edit in another lane's carrier — and it turns out no .dag change is needed at all: once both sides construct the same coproduct, substrate == compares them structurally. Recording it here so the next person does not re-derive the dead end.

The bridge itself is recovered from closed PR #7650, which had this exact shape right; that PR's ci failed on its wider scope, so the correct piece went down with it.

Hand-Rust disposition

~28 lines of seed Rust, carried in-diff as a doc comment on rest_structural_content_hash_value:

  • Lane: v1 exit (ROADMAP §11 — zero hand-maintained Rust).
  • Row: "Get hand-written Rust in this repository down to zero", authority dag/gunbc/v1_deletion_plan.dag.
  • Dissolution trigger: REST service dispatch is evaluated by the emitted transport handler and this host-side RestBoundOperationInvocation construction is deleted.

No census moves: the diff adds zero tracked-Rust paths (v1_interpreter.rs is M, already tracked and already carrying its disposition), and HandAuthoredLOC is a declared-deferred axis per stage0_rust_honest_frontier_projection_note, so there is no line-grain census to shrink. The alternative was leaving .dag and the seed constructing structurally different values for the same modeled thing — a silent always-false equality, which is the §5 fail-open this closes.

🤖 Generated with Claude Code

… carrier

#7480 made ContentHash a family coproduct in .dag, but the interpreter kept
minting the pre-#7480 branded string at rest_bound_invocation_value, so a
fixture invocation built in .dag could never equal one built by the seed.

Signature: every rest_exchange_replay witness requiring a fixture to MATCH
failed, while the ones requiring NO match passed -- an equality that is always
false, not a broken lookup. Proven by baseline: all 9 pass at 9abf624
(immediately pre-#7480), 6 fail after.

The bridge is recovered from closed PR #7650, which had it right. No .dag
semantic change is needed: with both sides constructing the same coproduct,
substrate == compares structurally.

Verified: 9/9 rest_exchange_replay witnesses PASS.
@briansrls
briansrls merged commit dbc87b2 into main Aug 2, 2026
1 check passed
@briansrls
briansrls deleted the fix/rest-invocation-digest-seed-bridge branch August 2, 2026 03:57
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
…wed-carrier mint on this branch

Main's layer-3 repair realizes input_digest as the ContentHash union
Variant to match main's union-typed field; this branch narrows the field
to Fnv1a64Structural and mints the family record directly via the shared
fnv1a64_structural_value helper (both digest carriers, one mint), so the
union helper does not survive the merge — under the narrowed model it is
dead code of the wrong shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
…7665

The HAND-RUST receipt opened with 'This PR touches v1_interpreter.rs',
which stopped being true when main's piecemeal heal chain (#7656/#7663/
#7665) landed the same repair and the merge dissolved this branch's
inline copy into main's factored helper. The receipt stays as the
program record of the repair's class and triggers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
Refresh onto tip with ContentHash layers repaired (#7656/#7663/#7665).
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
…dration + #7665 seed mint layer)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
@gunbai-bot gunbai-bot Bot mentioned this pull request Aug 2, 2026
6 tasks done
briansrls pushed a commit that referenced this pull request Aug 2, 2026
…uling 2026-08-02) (#7651)

* Generated-file conflict policy: lane charter recording the 2026-08-01 operator ruling

Four-case integration policy (deterministic projection / hand-authored
authority / keyed set-map / roster-naming-outputs), derivation chain with
.gitattributes and git config as projections never authority, commit-writer
admission with the 218dea6 reproduction as lane 1, landing order, and the
hard-reject bars.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* WIP: what is our conflict policy for generated files?

* Address review 46546: state the interim status of the invert-hand-maintained row explicitly

The amendment rides with lane 2's implementation by operator sequencing:
amending the row before the modeled policy lands would make the planning
authority assert an emitted .gitattributes while the tree's file is still
hand-authored. The charter now states the interim so no two-instructions
reading exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 46572: anchor lane 3's carrier in the charter's typed work set

Adds gunbc.stage0_emit_model generated_stage0_files to additional_works —
it exists on main today and is lane 3's subject. Lane 4's keyed-roster
carrier is deliberately NOT cited: it does not exist on main yet, and its
on-main admission surface (commit_gate_roster) is already anchored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 46587: cite the invert-hand-maintained row symbolically

gunbc.plans.invert_hand_maintained invert_hand_maintained_body, not a
line number in the projected markdown — the charter's own §3 rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Encode the operator second-pass acceptance walls per lane and the corrected merge sequence

Lane 1: complete staged-index observation (population equality, observed
classification, bound provenance receipt, forgery REDs), writer bindings
as countable carriers. Lane 2: converge before the first Git consumer;
named countable clone-rollout carrier; typed read-back refusals; derived
stage0 paths feed merge attributes. Lane 3: refusal preserved through
supply->plan->generation->writer; located output-path collision refusal.
Lane 4: a live path-keyed carrier consumes keyed construction end-to-end;
canonical verdict never collapsed to Bool; coordinator sequencing note on
the deleted incident carrier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Charter candidate-scoped gates + atomic landing admission (operator ruling 2026-08-02)

The merge-freshness program the conflict-policy charter named out of
scope: three verified defects (freeze-anchored placement subject with
false law text, missing landing-candidate validation, ProcessExit
evidence collapsed to Bool before FullLedger), the three-subject
observation split, the typed accumulated verdict, the
RunnableProcessExitClaim migration, the MergeQueueOnly/ALLGREEN landing
policy absorbing the existing GatingEnforced trigger, acceptance set
A-F, landing sequence with the queue-first sequencing bar, and the
coordinator's verification receipts and sharpenings. Step 0 recorded as
already discharged (session_dashboard enrolled; #7644 closed unmerged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 46971 (commit vs tree subjects) and repair main's stale ContentHash import

IntegrationCandidate now carries base_commit/candidate_commit as the
ancestry subjects merge-base actually computes over, with candidate_tree
retained separately as the exact-tree admission subject; freeze-law
carriers follow. Also repoints dag/extdeps/transports/rest.dag's
ContentHash import to std.content_hash — main's #7480 re-home left this
module importing from std.types, which breaks main_wet's closure on any
branch (the heal job's failure here); fix identical to #7609's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* WIP: what is our conflict policy for generated files?

* Complete the fleet heal: seed mints the grounded ContentHash, digest.dag enrolls, regen converges

Three coupled repairs riding the charter PR because main is red without
them: (1) v1_interpreter rest_bound_invocation_value minted a bare Str
input_digest while #7480's model requires the Fnv1a64(Fnv1a64Structural)
coproduct arm — every fixture-match replay witness silently failed
(model/realization fork, hidden behind main's compile error); the seed
now mints the coproduct shape (probed empirically: positional field 0).
(2) dag/extdeps/container/oci/digest.dag gains its ExternalModelScope and
scope_carrier_paths enrollment — the unenrolled-file case the operator's
verdict named live; placement gate now ExitSuccess. (3) regenerated
extdeps_container_oci_digest.rs for the new declaration; fixed point
converges. EMITTER DEFECT FLAGGED, not fixed here: the fully-qualified
module-local reference extdeps.container.oci.digest.extdeps_external_authority_anchor
emitted as crate::extdeps_cargo::... (wrong module, E0308) — first
enrolled carrier in the emitted set exposed the dotted-path resolution
class; the declaration uses the module-local spelling and the defect
belongs to the dotted-path emitter bucket.

Local receipts: replay witnesses 9/9 PASS, placement gate ExitSuccess,
dry artifact gate ExitSuccess, regen second pass clean, build 0 errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 47056: tree-kind carrier + HAND-RUST receipt

candidate_tree is now GitTreeObjectId — a kind-refined carrier the
implementation lane introduces in extdeps.git.object_store (which today
types even GitCommitObject.tree as generic GitObjectId; the lane
re-grounds every kind-fixed position, not a charter-local special) so a
blob or tag is unrepresentable as a landing subject. Added the HAND-RUST
GATE receipt for the v1_interpreter rest replay bridge hunk: a
model-conformance repair to an existing seed mint (no new decision
surface; dissolves with the seed's rest transport bridge), checkable by
the 6-red-then-9-green replay witness split.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 47071: DefaultBranchAudit subject is GitTreeObjectId too

Same class as the IntegrationCandidate fix — every audit/admission
subject in the charter is a tree by construction. Swept the doc for
remaining generic GitObjectId type positions; the three other mentions
are prose about the generic carrier itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review 47097: verdict total over both surfaces, subject on the wrapper, receipt names lane + ROADMAP row

ExtdepsScopeVerdict gains DefaultBranchAuditCovered (the audit surface
had no faithful success result) and ExtdepsScopeRefused carries the run's
ExtdepsScopeEvaluation subject once at the wrapper — refusal arms keep
only law-local facts, the six duplicated per-arm candidate fields delete,
and the rendering law now names identities that flow forward rather than
demanding base/tree on arms that never carried them. HAND-RUST receipt
gains the explicit-deferral header naming the v1-exit lane (zero
hand-maintained Rust finish line) and the witness-realization rest-bridge
trigger, matching the compile-clean-forcecheck receipt form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Receipt records its landing vehicle: the interpreter hunk merged via #7665

The HAND-RUST receipt opened with 'This PR touches v1_interpreter.rs',
which stopped being true when main's piecemeal heal chain (#7656/#7663/
#7665) landed the same repair and the merge dissolved this branch's
inline copy into main's factored helper. The receipt stays as the
program record of the repair's class and triggers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant