Skip to content

Materialize a compiler generation's artifact axis from the path cargo named - #8172

Closed
gunbai-bot[bot] wants to merge 2 commits into
mainfrom
session/sharp-hawk-59-materialization
Closed

gunbai-bot[bot] wants to merge 2 commits into
mainfrom
session/sharp-hawk-59-materialization

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Joins the two halves that landed separately:

This is the join. The chain is build → the path cargo named → a digest of that path → ArtifactIdentity.

Why the path has to come from cargo

The load-bearing property is that one path value flows through the digest and out to any later invocation. service cargo.Build reports only success/stdout/stderr — never the artifact path — so without the decode a consumer must predict the path, and a stale binary at the predicted location satisfies that observation completely.

That failure is bad in a specific way: it breaks both ends at once, digesting one file while executing another, with each operation individually honest and the composition silently wrong. It also makes the artifact axis a function of the build-configuration axis, collapsing two of the six axes #8153 exists to keep independent — so a per-axis invalidation control could no longer discriminate them.

Decomposition

Every decision sits in one of two pure folds:

  • select_artifact_path — what the build reported
  • materialization_from_digest — what the observation means

with only a thin wet composition needed between them. This is deliberate: one wet function carrying the decisions would put every refusal arm behind a cadence that doesn't run per-PR, which is how a decision nobody executes reads as a decision that holds. As written, all ten claims run on ordinary discovery.

Arms kept separate on purpose. A build that exited nonzero never reaches the stream decode — "the candidate did not build" and "the candidate built but we cannot say what it produced" have different remedies, and a later behavioural comparison must not read one as the other. No arm yields ArtifactMaterialized without a digest in hand; every failure projects ArtifactNotMaterialized, which promotion admission already refuses by name rather than treating as equivalent.

Evidence

10 witnesses green by execution; compile-clean on both frontends (claim_batch and gunbc compile are different frontends, and some rules live only on the second).

Mutation-probed rather than asserted:

Mutation Expected Observed
Collapse the build-failure arm into the decode build claims red exactly 3, those
On a path refusal, fall back to a conventional path path-integrity claims red exactly 2, those

The second is the defect this lane exists to prevent, planted deliberately.

One receipt worth keeping: the fixture digest was hand-typed at first and was 130 hex characters instead of 128. The refinement rejected it, the observation became a refusal, and three positive claims went red — rather than a malformed digest flowing into the carrier. That's the construction wall working, exercised by the witness that depends on it. The fixture is now a real sha512, reproducible with printf … | sha512sum.

Scope, stated so the split isn't mistaken for completeness

This lands the materialization vertical and its decision logic. Not in this PR:

  • The cargo.Build operation carrying --message-format=json (an extdeps interface addition) and the wet execution witness that drives build → digest → run end-to-end. Those are execution-kind with a real resource profile, so they need an exact row in gunbc.explicit_witness_admission naming the cadence that runs them — not a directory, and not per-PR discovery.
  • Migrating the four existing convention-derived callsites (tools.host_prelude witness_bin_path and the three transports built on it). That's one shared authority, and it touches the live bin-witness execution path, so it deserves its own PR.

Lane: SH-C (bootstrap artifact materialization).

🤖 Generated with Claude Code

… named

#8158 landed the decode: which executable cargo REPORTED for a target, read from
its --message-format=json stream rather than assembled from target dir, profile
and binary name. #8153 landed the carrier: ArtifactIdentity whose materialized arm
holds a sole_constructor ObservedArtifactDigest over a validated Sha512Digest, so
an artifact identity cannot be authored without an observation.

This joins them. The chain is build -> the path cargo named -> a digest of THAT
path -> ArtifactIdentity, and its load-bearing property is that one path VALUE
flows through the digest and out to any later invocation. A convention-derived
path breaks that at both ends simultaneously — digesting one file while executing
another, each operation individually honest and the composition silently wrong —
and it also makes the artifact axis a function of the build-configuration axis,
collapsing two of the six axes #8153 exists to keep independent.

DECOMPOSED SO THE DECISIONS ARE WITNESSED PER PR. Every decision sits in one of
two pure folds — select_artifact_path decides what the build reported,
materialization_from_digest decides what the observation means — with only a thin
wet composition needed between them. One wet function carrying the decisions would
put every refusal arm behind a cadence that does not run per PR, which is how a
decision nobody executes reads as a decision that holds.

Arms kept separate on purpose: a build that exited nonzero never reaches the stream
decode at all, because "the candidate did not build" and "the candidate built but we
cannot say what it produced" have different remedies and a later behavioural
comparison must not read one as the other. No arm yields ArtifactMaterialized
without a digest in hand; every failure projects ArtifactNotMaterialized, which
promotion admission already refuses by name rather than treating as equivalent.

10 witnesses green by execution, compile-clean on both frontends. Mutation-probed:
collapsing the build-failure arm reds exactly the three build claims, and making a
path refusal fall back to a conventional path — the precise defect this lane exists
to prevent — reds exactly the two claims that guard it.

One receipt worth keeping: the fixture digest was hand-typed at first and was 130
hex characters instead of 128. The refinement rejected it, the observation became a
refusal, and three positive claims went red rather than a malformed digest flowing
into the carrier. The fixture is now a real sha512, reproducible with printf and
sha512sum.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Closing as superseded rather than rebasing — this PR's content is already on main and re-merging it would revert working code.

Why. #8176 was branched from this branch, so it carried these commits, and it merged first (5f14c431610). Both files this PR adds are present on main; dag/test/claim/self_host_artifact_materialization_witness_test.dag diffs empty against main.

Why a rebase would have been wrong, not merely redundant. Diffing main against this branch shows main is ahead: the branch state would remove materialize_artifact_wet, import extdeps.cargo_build, and the sha512sum_observe_file import. Resolving the conflict in this direction would delete the wet composition that #8176 landed and that four enrolled wet witnesses execute against. The conflict is the squash-merge flattening the shared commits, not a divergence needing repair.

Nothing is lost: the ten hermetic folds and the module are on main, verified executing in CI on #8176's run (per-row receipts, leg=InterpretedLeg).

— sent from sharp-hawk-59

@gunbai-bot gunbai-bot Bot closed this Aug 12, 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.

1 participant