Skip to content

Witness generic roster staleness and stage current-context entry - #7583

Merged
briansrls merged 12 commits into
mainfrom
session/bold-heron-551-admission-context
Aug 1, 2026
Merged

briansrls merged 12 commits into
mainfrom
session/bold-heron-551-admission-context

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Delivers an executing, generic classification witness for commit-check roster freshness and stages an invocable current-context entry without claiming it is live.

The controls now exercise the shape of a roster change rather than naming a production gate. An otherwise-valid alternative revision reverses the exact live enrollments—same unique members and surfaces—but has a different order-sensitive hash. Its receipt classifies MergeDeniedStaleRoster against current_gate_roster_hash and the identical receipt classifies MergeAdmitted when that alternative revision is supplied as current; a receipt minted under the live roster also admits. This discriminator proves staleness rather than malformed-input rejection.

tools.merge_admission_current_context.main remains staged and invocable, but uninvoked. It can read attempt-scoped V2 wires, fetch the current merge target, and produce the typed verdict; no production caller or V2 wire producers exist yet, so this PR does not call it a live consumer or claim a runtime admission gap is closed.

Why this was recut

The original control reconstructed the 2026-08-01 publication-placement incident by removing PublicationPlacementGate from the live roster. Main commit 05819d525 (#7591) subsequently deleted that gate, its roster, cutover, implementation, and tests by operator ruling. This PR accepts that deletion wholesale and drops its obsolete publication-grant row.

The incident remains motivation, not an execution claim. A regression control naming a volatile roster member is coupled to that member's continued existence; that coupling invalidated this PR when the member disappeared. A control for roster identity must therefore exercise the shape of a roster delta, or its lifetime is bounded by the least stable member it mentions.

The recut is also a direct receipt for the law: #7583 itself was invalidated by an enforcement-set change between its evidence and merge, via deletion rather than addition. The generic pair now detects either direction through roster-hash inequality.

Staging boundaries

The staged-entry boundaries and ordering remain:

  1. Production must capture TestedSubject before the floor and persist it with the post-floor MergeAdmissionReceiptV2 for one WalkAttemptId.
  2. Only after those producers exist may gunbc.ci_failure_class.merge_freshness_gating_status move from GatingComputedDeferred to the existing GatingEnforced arm under operator sign-off and its declared prerequisites.

The later policy-content increment remains separately declared by gate_content_hash_variant_tag_scaffold; this PR does not fire it.

Validation

  • claim_batch on the alternative-refuses, alternative-as-current-admits, and live-admits controls — PASS.
  • gunbc compile --source-root dag --entry dag/tools/merge_admission_current_context.dag --target dag — 0 blocking errors (351 existing advisory diagnostics).
  • cargo build --release --bin claim_batch --bin gunbc — pass.
  • cargo fmt --all --check — pass in commit/push hooks.
  • git diff --check — clean.

@gunbai-bot gunbai-bot Bot changed the title CI admission safety: exact-head evidence coverage, then heal revalidation (two sequential PRs, one owner) Consume merge admission evidence against current wall set Aug 1, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 1, 2026 10:35
@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Review 46238 is correct: tools.merge_admission_current_context is currently an invocable wet entry, not a production-executed consumer. CI still invokes only tools.merge_admission_gate, and the V2 tested-subject/floor-receipt wires expected by the new entry have no live producers. The current carrier wording therefore overstates the rung. I have stopped and escalated the missing production binding because the operator explicitly reserved the required-check/manual-merge bind point; wiring it here without that authority would silently choose load-bearing admission policy. This REQUEST_CHANGES remains open until the operator either authorizes the full production path or recuts this increment as honest staging. — sent from bold-heron-551

@gunbai-bot gunbai-bot Bot changed the title Consume merge admission evidence against current wall set Witness stale wall-set admission and stage current-context entry Aug 1, 2026
@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Addressed review 46238 in 14650f64f19. The carrier no longer calls the entry a live consumer or claims the runtime gap is closed. It now separates the executing discovery-corpus incident witness from the staged, invocable-but-uninvoked wet entry and records two ordered blockers: production V2 subject/receipt writers first, then the existing GatingEnforced transition under operator sign-off and its declared prerequisites. The PR title and body are recut to the same honest rung. — sent from bold-heron-551

@gunbai-bot gunbai-bot Bot mentioned this pull request Aug 1, 2026
6 tasks
gunbc-ci-auto-heal added 2 commits August 1, 2026 17:30
@gunbai-bot gunbai-bot Bot changed the title Witness stale wall-set admission and stage current-context entry Witness generic roster staleness and stage current-context entry Aug 1, 2026
@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Review 46460 correctly observes that merge_admission_current_context_staging_note retains the original incident-specific sentence while the executing control pair is now synthetic. I am not changing that declaration in this recut because the adoption mandate explicitly made the staged-entry notes non-negotiable: preserve the invocable-but-uninvoked boundary and both ordered dissolution triggers unchanged from orphan head 1008287cb.

The executable proof's current authority is test.claim.merge_admission_attempt_witness.roster_staleness_control_recut_note. It explicitly says the 2026-08-01 incident is motivation rather than an execution reconstruction, describes the surface-less synthetic enrollment, and records why a roster-identity control must exercise change shape rather than a volatile member. The PR body repeats that distinction.

Changing the protected staging declaration would violate the assigned scope even though rewriting its final control-pair sentence would improve local consistency. I am leaving this as an explicit, review-visible constraint rather than silently overruling the mandate. — sent from still-seal-608

@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Fixed review 46460 in 43984a4e3ce: the staging note now describes the synthetic changed-roster control that actually executes, while preserving every invocable-but-uninvoked boundary and leaving both ordered dissolution triggers unchanged. The recut note now also records that a control-shape description must live with the control or derive from it. Re-ran both discriminators: 2/2 PASS. — sent from still-seal-608

@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026 •

Copy link
Copy Markdown
Contributor Author

CI failure root cause was the main-red primitive-surface census drift: the two failing witnesses were repaired upstream by #7614. Merged current main (also including subsequent measurement-only #7581) in 2ae946d1c33 without adding a branch-local count edit; targeted rerun now passes both the_surface_is_almost_entirely_derived and the_three_denominators_are_derived_and_distinct. — sent from still-seal-608

@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Closed the valid-alternative discriminator at b9dc0d1: the alternative revision is the exact live roster reversed, preserving the same unique members and surfaces. The same receipt admits when that alternative revision is current, and refuses only when evaluated against the live current revision. All three targeted controls pass. — sent from still-seal-608

@gunbai-bot

gunbai-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Recorded the known order-sensitivity consequence at d8f43eb: order participates in roster identity but not validity, so a source-only roster reordering is a real revision that refuses in-flight admissions minted under the prior order. The three targeted controls still pass. — sent from still-seal-608

@briansrls
briansrls merged commit cbf0d21 into main Aug 1, 2026
5 checks passed
@briansrls
briansrls deleted the session/bold-heron-551-admission-context branch August 1, 2026 22:10
gunbai-bot Bot pushed a commit that referenced this pull request Aug 1, 2026
…sync the inert roster

Same merge class as the last push, caught this time BEFORE pushing by running the
whole-tree compile rather than only the marker census.

ContentHash home. Four more files main added import ContentHash from std.types,
which Phase A moved. Repointed onto the family member their values actually
inhabit, not a bare import swap:
  - gunbc.guarantee_measurement probe_set_digest is folded from content_hash_atom
    / content_hash_tagged / content_hash_combine, so it is Fnv1a64Structural. Its
    fold also had to move to the _structural variants, because Phase A DELETED the
    union-level combine and content_hash_tagged takes a structural payload while
    returning the union -- the union simply does not typecheck at this position.
  - gunbc.stage0_rust_honest_frontier_projection and both witnesses carry the same
    manifest_content_identity field as the previous batch; their "witness-abc123"
    String casts became Fnv1a64Structural records with valid 16-hex digests.

Field rename collision. This branch renamed tested_base_tree -> tested_base_tree_hash
and merge_target_tree -> merge_target_tree_hash alongside the GitObjectId retype, and
main's #7583/#7619 lane added new callers on the old names. Updated those call sites
(dag/tools/merge_admission_current_context.dag and main's new tests in
merge_admission_attempt_witness_test.dag). FLAGGING FOR THE OPERATOR: the rename is
incidental to this PR's purpose -- only the retype was required -- and it is what
made these collisions instead of clean merges. It is kept because the record's
sibling field was already base_tree_hash, but it is a fair thing to ask me to revert.

The merge_admission witness import conflict resolved as the UNION: this branch's
three Phase A symbols plus main's two roster helpers and its new commit_workflow
import. All six are used in the file body and all six are declared.

Inert roster re-synced, both directions of the check firing as designed:
  - DownstreamSupportRoster (#7571) is newly inert -- declared, named in plan prose,
    constructed and read by nothing -- so it is rostered.
  - AccessPolicy is no longer inert: main's std.effect_grant effect_grant_policy is a
    real production consumer, so its row was STALE and is DELETED. That is exactly the
    dissolve the row's own trigger specifies, not a hand-edit.
The roster now equals the live inert set exactly.

Verified on a binary rebuilt AFTER the merge (main touched src/v1, so the pre-merge
binary was not a valid oracle): whole-tree compile 0 blocking errors,
regen_divergence_count=0, and green suites -- merge_admission 28/28,
guarantee_measurement 9/9, honest_frontier 7/7, lifecycle_scaffold 28/28,
emitter poles 7/7, roadmap 39/39, c_compilation_unit 24/24, compilation_unit 15/15,
inert_carrier 4/4.
briansrls added a commit that referenced this pull request Aug 2, 2026
…7480)

* Ground ContentHash on hash family (Phase A: carriers + R0 backstop)

Rebased onto main. ContentHash becomes a family coproduct
(Fnv1a64 | Sha256Hash | Sha1Hash) with where-refined hex carriers,
compare_content_hash cross-family refusals, OCI algorithm-qualified digests,
and construction walls (reviews 45496/45505).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review 45522 regressions and CI compile-gate timeout.

- Restore guarantee-ladder and shell→intent authority in design_document.dag
  and guarantee_ladder_nodes/roadmap_focus in roadmap_authority.dag from main;
  keep intentional chash Fnv1a64Structural migration only.
- Remove git_sha1 witness Absent fallback (mint must succeed or test reds).
- Raise v1-compiler-tests compile-gate step budget to 10m (run 30646205825).

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Update DESIGN open-thread row for ContentHash Phase A landing (#7480).

Replace the stale pre-migration §3 residue with Phase A receipts and an
explicit Phase B dissolve-on remainder (union-level == typecheck refusal).

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Move OCI digest algorithm predicates to extdeps.container.oci.digest.

Review 45539 flagged OCI-specific algorithm grammar in std.content_hash as a §3 authority inversion. The predicates and where-refinement entry point now live at the OCI digest authority; infer imports oci_other_digest_algorithm from there and stage0 emits extdeps_container_oci_digest.rs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* fix(stage0): commit emitted extdeps_container_oci_digest seed module

Regen emits the OCI digest module but it was never tracked in git after
rebase, which broke cargo fmt and the build gate on PR #7480.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* fix(oci digest): realign seed parse path and emitter Optional Present arm

Review 45614: use `encoded: encoded` in the other-algorithm parse arm
(oci_encoded_digest returns NonEmptyStr?, not a record). Route split
parts through oci_wire_digest_parts_from_split so the seed types as
String. Fix v1 emitter construction so Present{value: <branded scalar cast>}
lowers to Some(...) instead of Optional::String. Restore extdeps_base
module path for extdeps_container_oci_digest.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: regenerate drifted generated artifacts (ci auto-heal)

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* chore: regenerate drifted generated artifacts (ci auto-heal)

* fix(emit-on-demand-host): refuse crypto ContentHash at structural projection

Review 45661: replace emit_host_identity_structural sentinel collapse with
typed outcome coproducts (EmitHostStructuralIdentityRefusedCrypto,
ResolvedBuildContextIdentityRefusedCrypto, ToolchainIdentityRefusedCrypto).
Distinct Sha256/Sha1 digests no longer share one fnv1a64 cache key. Witness
resolved_build_context_identity_refuses_sha256_observed_tool exercises the
refusal path; structural fixture tests route through outcome helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* test(emitter): fix optional Present witness include/exclude patterns

The exclude Optional::String substring matches lawful return-type emission;
use the broken-body pattern String { value: text instead so the witness
discriminates Some(...) lowering from the generic Optional::String variant path.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(emit-on-demand-host): serialize ContentHash cache path segments

Route native cache workspace path construction through
serialize_content_hash instead of bare as String casts so cache keys
use the canonical wire form (review 45713).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(emit-on-demand-host): drop parallel family field from crypto refusals

ContentHash already carries its family; RefusedCrypto variants now hold
only component and identity. Witness derives family via content_hash_family
(review 45721).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: restore doc-graph construction walls from main (review 45726)

Reverts accidental regression of HandAuthoredDocBind primary_work +
additional_works, merged accelerator-demo-roundtrip row, guarantee-recovery
dual anchors, and doc_reachability construction witnesses (#7486/#7489).

Updates sha256_digest_content_hash_convergence_note to match the
construction-walled bridge (as_content_hash_cryptographic), not wire-form
rendering prose.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Ground ContentHash on its hash family so a cross-family comparison is un

* fix(oci-digest): construction-wall OciOtherDigestEncoded payload

OciOtherDigestBody.encoded is now NonEmptyStr where oci_other_digest_encoded
(descriptor.md charset), not a forgeable bare NonEmptyStr (review 45731).
Infer where-refinement enrollment mirrors oci_other_digest_algorithm.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(oci-digest): emit parse wire path without NonEmptyStr cast panic

Use parts.encoded as OciOtherDigestEncoded after oci_encoded_digest
validates (same pattern as sha512 hex), avoiding emitter panic on
String→NonEmptyStr cast in the OtherDigest parse arm.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(oci-digest): OciOtherDigestEncoded as String where for emit parity

NonEmptyStr where oci_other_digest_encoded made the emitter emit
panic() on String→NonEmptyStr cast in parse_oci_content_digest_wire.
String where oci_other_digest_encoded matches OciSha512DigestHex and
keeps the construction wall (review 45731).

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: gunbc oracle

* WIP: gunbc oracle

* fix(content-hash): project .digest at string boundaries; repair the last floor reds

Three sites where a structural hash reached a String position:

- roadmap_dispatch_actuator dispatch_attempt_key and roadmap_belt_actuate
  belt_uuid_hex32 cast the content_hash_atom / content_hash_combine_structural
  RESULT to String. content_hash_atom returns Fnv1a64Structural (a record) since
  the family grounding, so the cast no longer yields the digest text. Notably this
  is not a typecheck error -- roadmap_belt_actuate's own uuid witnesses passed
  while the value was wrong -- so the only witness that caught it was the one
  comparing a parsed branch against the minted one
  (attempts_parse_roundtrips_the_minted_branch). Both now project .digest, the
  idiom site/moodboard.dag already used. A regex + paren-matching sweep over every
  .dag confirms no structural result is cast directly to a string type anywhere.

- source_integration_landing_spine's witness compared a receipt against the raw
  literal "multiplicity-receipt" after construction moved to
  content_hash_of_value(...), i.e. the field now holds a hash of that string.

Verified by execution: dispatch_attempts 9/9, roadmap_belt_actuate uuid witnesses
3/3, source_integration_landing_spine 22/22. (roadmap_belt_actuate's seven
belt_exec witnesses fail locally with "hermetic mode: no mock_response for
operation Check" -- they shell out to a real host process and never reach hash
code; that is the hermetic runner refusing to fabricate, not a regression.)

* fix(content-hash): re-home ContentHash imports that arrived with the main merge

The floor's dag_compile_clean_gate went red on the merge commit with one hard
diagnostic: name 'ContentHash' not found in module 'std.types'. Two witness files
came in from main still importing ContentHash from std.types and initializing it
from a string literal -- the shape this PR's family grounding removed:

  dag/test/claim/check_coverage_admission_witness_test.dag  (4 rows)
  src/v2/test/claim/walk_plan_schedule_lens_test.dag        (1 row)

Both now import from std.content_hash and mint through content_hash_of_value,
matching their consumers, which take the union ContentHash
(merge_admission check_coverage_admits; the walk-plan target field).

My pre-merge sweep for this class was clean and stayed correct -- these files did
not exist on this branch when it ran. The sweep has to be re-run after each merge,
not once. Re-run now: zero std.types ContentHash imports and zero string-literal
ContentHash initializers corpus-wide.

Verified by execution: whole-tree `gunbc compile --target dag` reports 0 hard
diagnostics (the gate's own check); check_coverage_admission 12/12;
walk_plan_schedule_lens 2/2.

* WIP: gunbc oracle

* revert(v2-node): restore node.dag hash surface to its 2804c8b state

The WIP auto-commit at 8212c2a captured a mid-edit working tree: a speculative
retype of v2.std.node content_hash / symbol_identity_digest / bag_hash_digest /
byte_offset_cache_key_fingerprint to return Hash, snapshotted BEFORE I had fixed
a stray argument label it introduced --

  fn symbol_identity_digest(sym: Symbol) -> Hash {
    structural: content_hash_atom(value: sym)   # not an expression
  }

-- so that broken form went out on the branch. My subsequent `git checkout --`
restored to that bad commit rather than to the intended baseline, which is how it
survived. This restores the file byte-for-byte to 2804c8b.

The retype is reverted on its merits regardless of the label bug: executed against
the three failing classes (Variant-cast, digest-on-String, atom_identity_hash arity)
it fixed NONE of them, so it was an unverified edit to a load-bearing substrate file
with no demonstrated benefit. The real roots are recorded in the PR comment: five
`ContentHash where brand(...)` types that can no longer be cast, and the raw
atom_identity_hash / std.content_hash dual surface in 02_parse and self_host.

* WIP: gunbc oracle

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Project the corrected ContentHash bridge claim into DESIGN.md

sha256_digest_content_hash is the VALIDATING PARTIAL bridge Digest->ContentHash?;
as_content_hash_cryptographic is the TOTAL injection. Regenerated via
tools.generated_artifact_gate main_wet; byte-stable on a second pass.

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

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* WIP: gunbc oracle

* Restore the v1 seed sources an auto-commit reverted to main

The session auto-commit fired while src/v1 was checked out to origin/main for a
control build, snapshotting main's version as this branch's HEAD; a later
'git checkout HEAD -- src/v1/' then restored that poisoned state. Three files
lost their reviewed content and are restored from f9dc5a8:

  00_core.dag     — 'predicate not enforced at compile time' advisory reason
  04_infer.dag    — lower_hex_{16,40,64,128} / oci_other_digest_* where-predicates
                    and the structural content-hash rewrite
  05_emit_rust.dag — variant_surface_name + fn_returns_optional

05_emit_rust.dag is reconstructed onto main's newer revision rather than
overwritten, so main's rust_btree_set_ord name-grain childless gate and its note
are preserved; the result is byte-identical to f9dc5a8 apart from that
addition.

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

* WIP: gunbc oracle

* Remove temporary emitter-probe fixture

Diagnostic scaffold for isolating the optional-payload cast emit defect; the
repro is recorded in the PR discussion, not enrolled as a witness pending a
decision on the emitter fix.

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

* Record the optional-payload cast emit deficit as executing evidence

Three poles, each holding one variable constant, isolate the trigger for the
E0433 that blocks finding 3's oci_encoded_digest shape:

  refined return, no cast   -> lowers to Some(..)      (refined return is harmless)
  plain String? return, cast inside payload -> broken  (the cast alone suffices)
  cast hoisted to a let     -> STILL broken            (refutes the workaround)

The third pole is load-bearing: hoisting does not avoid the defect, so no
respelling both constructs the carrier and lowers correctly, and the emitter
repair is required rather than optional. An earlier draft of this file claimed
the hoist WAS a working scaffold spelling and briefly landed that spelling in
oci_encoded_digest; executing it refuted the claim, and both are reverted --
oci_encoded_digest keeps the reviewed inline shape.

Poles 2 and 3 are known-red receipts: they assert the deficit is present, so
they pass now and red when the emitter is repaired.

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

* WIP: gunbc oracle

* WIP: gunbc oracle

* Repair optional-payload cast lowering; regenerate the seed from the authority

Confirmed name-loss point (by instrumentation, not by reading): the concrete-type
peel in v1.compiler.emit_rust emit_rust_expr_record_lit. A cast reaching an
optional payload gives the literal a concrete resolved type, so the peel replaced
the authored "Present" with the payload's concrete name; emit_typed_record_lit
then missed the optional arm and fabricated "Optional::String { .. }", which is
not a Rust constructor (E0433). A probe printing variant_name/tn/peeled at the
call site showed the authored name arriving intact and being overwritten.

The standing variant_surface_name hypothesis was wrong as a single cause but is a
real SECOND contributor: with the peel fixed, optional_variant still keyed off the
resolved struct name until variant_surface_name reached the seed. Both were
required; neither alone sufficed.

The peel is suppressed only when the authored name is a built-in optional
constructor AND the concrete type does not itself declare a variant of that name,
so a user-defined "Present" still peels (variant_belongs_to_enum finds it) and
ordinary variants are untouched. Variant identity is preserved, never inferred
from the payload type.

Authority is src/v1/05_emit_rust.dag. The seed could not regenerate the fix, so
minimal bootstrap edits were lifted by hand and then PROVEN by regeneration:
regen_stage0 --verify reports regen_divergence_count=0, so committed stage0 is
exactly the fresh self-compile of the authority. Also restores cli_run.rs, the
v1_interpreter R0 cross-family guard, and two more hand-written seed files that
the earlier auto-commit poisoning reverted to main (the R0 guard is merged onto
main's newer interpreter, not overwritten).

Witness flipped from known-red receipt to permanent regression control (DESIGN
section 4b): 6/6 including the Wrap::Holds and user-defined-Present negative
controls. Nested-refinement receipt retains its polarity, 2/2. Whole-tree compile
exit 0.

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

* Declare publication grants for the 17 ungranted added public paths

The Stage-0 visibility guard (tools.publication_placement_gate, run as the Wet
floor runnable publication_placement_gate_passes) diffs the publication cutover
to HEAD and refuses any added public path with no Publish grant. It reported
PublishGuardLocalViolation count=17, which is why the ci floor failed while
build, regen and heal all passed.

Six are this PR's: the OCI digest carrier, its generated stage0 projection, and
the four ContentHash/emitter witness files. The other eleven arrived with main
(the heal-revalidation and source-integration-proof-kernel lanes, ci_heal_dispatch,
extdeps.github.workflows and the preflight emit pair); the guard diffs from the
cutover rather than from the merge base, so it fires on the union and this branch
cannot go green while they are undeclared.

All seventeen are already merged and pushed to the public repository, so granting
records the publication that already happened rather than newly exposing anything.
Flagged rather than silent because eleven of the paths are not this PR's to
classify.

Gate re-run locally: ExitSuccess. publication_placement_gate_test 8/8.

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

* WIP: gunbc oracle

* Converge the fnv1a64 dual surface at the 22 sites the re-key stranded

The floor's discovery corpus surfaced 22 witnesses this PR broke, in two classes,
both instances of the dual surface DESIGN section 3 tracks: v2 code calls the RAW
v1 intrinsics while std.content_hash is the modeled surface over the same
authority. Re-keying v2.std.node.Hash to Fnv1a64Structural made that fork
observable, because a raw intrinsic yields a native String where the modeled
carrier is a record.

Class 1 (18) -- "cannot access field digest on String": raw atom_identity_hash
flowed into Hash positions. Eleven call sites in v2.compiler.02_parse,
v2.compiler.self_host and the parse_table_content_key witness now route through
v2.std.node symbol_identity_digest, the modeled surface those modules already
import. The substitution is value-preserving: content_hash_atom(v) is by
definition structural_content_hash(digest: atom_identity_hash(v)).

Class 2 (2) -- "atom_identity_hash requires exactly one string argument": the
inverse, a structural passed INTO the intrinsic. v2.lens.interface_summary
signature_fingerprint_of_node hashed a node content hash that is now a record; it
projects .digest first. A direct cast was tried and rejected by the interpreter
(cannot cast Record to Fnv1a64Structural), so the original hash-of-hash semantics
are kept rather than changed.

Plus one value mismatch: the live_deploy readiness witness compared
site_artifact_digest(..) as String against the digests the served body embeds,
which now project .digest.

After this the raw intrinsics appear nowhere outside dag/std/content_hash.dag and
the v1 builtin registry, which is the single-authority end state.

Re-run green: parse_table_content_key 5/5, interface_summary_firewall 4/4,
ingest_bridge 9/9, cross_language_add_python_to_typescript 4/4,
inhabitant_neutralization 6/6, parse_table_memo_governed 9/9,
self_host_realized_comparison_floor 6/6, parse_stamp_span_index 2/2,
live_deploy readiness 25/25.

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

* WIP: gunbc oracle

* Address review 2026-08-01: restore roadmap containment wall, narrow optional emitter, correct design authority

Three blocking items from the review, each with executing evidence.

1. Roadmap containment wall (regression against the branch base). My earlier
   merge dropped main's rendered-node containment wall entirely:
   roadmap_rendered_ghost_count, both RED probes, and all three witnesses were
   absent from this head. Restored roadmap_spawner.dag from main wholesale (main
   was a strict superset there) and grafted the import block, note and three
   tests onto roadmap_authority_test.dag while keeping this PR's
   Fnv1a64Structural changes. 38/38 green, the count the review predicted.

2. Optional emitter classification was broader than its stated boundary. The
   fn_returns_optional disjunct is a fact about the ENCLOSING FUNCTION, so a
   user-defined MyOpt::Present built inside a `-> String?` function emitted
   Some(..), overriding an effective_parent that had already resolved correctly.
   Added the negative control the review asked for and CONFIRMED IT RED before
   changing anything. Then executed all seven poles with the function-wide arm
   removed: it was load-bearing for none of them, so it is deleted rather than
   gated -- resolved_type.return_cardinality == CardOptional is the
   expression-local statement of the same fact, and the disjunct was a second
   representation of it. 7/7 green; regen_divergence_count=0.

3. Design authority still described the deleted models. Corrected
   design_document.dag (v2.std.node Hash is Fnv1a64Structural, not
   std.types.ContentHash -- wrong home and wrong type, contradicting the Phase A
   row below it), regenerated DESIGN.md, and corrected both locked plan docs to
   say the unit carries one agnostic identity from which each realization
   derives its spelling. Corpus sweep for the three stale claims is clean.

Also repairs a main red this branch inherited: CompileDiagnosticCensus became an
unrostered inert carrier when main's codex-review-46144 repair deleted
census_rows(c: CompileDiagnosticCensus), its only production consumer. The three
files involved are byte-identical to main, so the red is main's, not this
branch's. Rostered with that reason and the standard dissolve trigger.

* Discharge the CR/NUL control gap: main's Unicode escapes fired its dissolve-on trigger

Round 2 asked for hostile-spelling controls over / \ CR LF NUL and ". CR and NUL
were declared as a coverage BOUNDARY rather than faked, because .dag string
literals had no numeric-escape form: backslash-r lexed as literal backslash-then-r
and the backslash-u brace form lexed as its raw characters, both measured at the
time. The note carried an explicit dissolve-on trigger.

Main landed Unicode string escapes (#7585), so the trigger fired. The escapes were
RE-MEASURED on this head rather than assumed from the commit title: \u{000d} and
\u{0000} each yield exactly one character, of codepoint 13 and 0. CR and NUL are
now DIRECT witnesses (a%00000db, a%000000b) and both join the output-always-safe
control, so the whole requested hostile set is witnessed against the real encoder
with no argument from escape-branch genericity standing in for any member.

The encoder needed no change -- the genericity argument the boundary rested on
turned out to be correct, which is exactly what direct evidence was owed to show.
24/24 green. The note is kept as the receipt that the boundary was declared,
triggered and discharged rather than quietly dropped.

Also merges current main (4 commits). One conflict, in
dag/extdeps/realization/artifact_store_fs.dag: this branch moved ContentHash to
std.content_hash while main added std.access {Permit, Deny} from the access-kernel
change. Resolved as the union -- both wanted, neither superseding the other.

* WIP: gunbc oracle

* Merge main (15 commits): repoint four more ContentHash consumers, re-sync the inert roster

Same merge class as the last push, caught this time BEFORE pushing by running the
whole-tree compile rather than only the marker census.

ContentHash home. Four more files main added import ContentHash from std.types,
which Phase A moved. Repointed onto the family member their values actually
inhabit, not a bare import swap:
  - gunbc.guarantee_measurement probe_set_digest is folded from content_hash_atom
    / content_hash_tagged / content_hash_combine, so it is Fnv1a64Structural. Its
    fold also had to move to the _structural variants, because Phase A DELETED the
    union-level combine and content_hash_tagged takes a structural payload while
    returning the union -- the union simply does not typecheck at this position.
  - gunbc.stage0_rust_honest_frontier_projection and both witnesses carry the same
    manifest_content_identity field as the previous batch; their "witness-abc123"
    String casts became Fnv1a64Structural records with valid 16-hex digests.

Field rename collision. This branch renamed tested_base_tree -> tested_base_tree_hash
and merge_target_tree -> merge_target_tree_hash alongside the GitObjectId retype, and
main's #7583/#7619 lane added new callers on the old names. Updated those call sites
(dag/tools/merge_admission_current_context.dag and main's new tests in
merge_admission_attempt_witness_test.dag). FLAGGING FOR THE OPERATOR: the rename is
incidental to this PR's purpose -- only the retype was required -- and it is what
made these collisions instead of clean merges. It is kept because the record's
sibling field was already base_tree_hash, but it is a fair thing to ask me to revert.

The merge_admission witness import conflict resolved as the UNION: this branch's
three Phase A symbols plus main's two roster helpers and its new commit_workflow
import. All six are used in the file body and all six are declared.

Inert roster re-synced, both directions of the check firing as designed:
  - DownstreamSupportRoster (#7571) is newly inert -- declared, named in plan prose,
    constructed and read by nothing -- so it is rostered.
  - AccessPolicy is no longer inert: main's std.effect_grant effect_grant_policy is a
    real production consumer, so its row was STALE and is DELETED. That is exactly the
    dissolve the row's own trigger specifies, not a hand-edit.
The roster now equals the live inert set exactly.

Verified on a binary rebuilt AFTER the merge (main touched src/v1, so the pre-merge
binary was not a valid oracle): whole-tree compile 0 blocking errors,
regen_divergence_count=0, and green suites -- merge_admission 28/28,
guarantee_measurement 9/9, honest_frontier 7/7, lifecycle_scaffold 28/28,
emitter poles 7/7, roadmap 39/39, c_compilation_unit 24/24, compilation_unit 15/15,
inert_carrier 4/4.

* Merge main #7608: ground the new GitSha1ObjectId fixtures on Sha1Digest

Phase A made GitObjectId's digest a Sha1Digest record rather than a raw hex
String, and main's new commit_writer_admission witness constructs
GitSha1ObjectId { digest: "1111..." } directly. Both fixtures now use the tree's
existing idiom, Sha1Digest { hex: <40 hex> as Sha1DigestHex }, with the carriers
imported from std.content_hash.

The object_store.dag import conflict resolved as the union: this branch's Phase A
content_hash block plus main's two new imports (PositiveInt, repeat_string).

BLOCKED, and NOT worked around: dag/gunbc/commit_workflow.dag fails to compile
with "no field 'path' on type 'T'" at commit_writer_index_entries_for_path. This
is NOT this branch's defect and it is deliberately left alone rather than papered
over with a speculative type annotation (DESIGN section 5: noticing you are
implementing a workaround IS the line-stop signal).

Evidence it is main's:
  - the file is BYTE-IDENTICAL to origin/main here;
  - it reds in its OWN narrow closure, not just whole-tree, so it is a real defect
    rather than a resolution artifact;
  - this branch's only 04_infer changes are where-predicate registrations
    (lower_hex_*, oci_other_digest_*), which cannot affect lambda parameter
    inference;
  - main's CI for #7608 (f3df2ce) was still QUEUED when this merge happened, and
    three of the preceding main commits are outright red, so the commit landed
    unverified.

Hypotheses tested and REFUTED by execution, so the next person does not repeat
them: trailing comma in the parameter list; filter over an imported record type
(both compile clean in an isolated probe); a shadowing filter declaration; a
lambda/parameter name colliding with an imported symbol; cross-call-site
unification collapsing the element type (only two callers, both passing
List<GitIndexEntry>). The sibling flat_map over the same type and the same
`entry` binding compiles, so it is specific to this call.

* WIP: gunbc oracle

* Remove cw_probe.dag: a scratch bisect probe the auto-commit swept into the branch

Not source. It was a copy of commit_workflow.dag under a probe module name, used
to bisect the 'no field path on type T' failure to its cause, and it should never
have been committed.

* Unblock the compile-clean gate: declared scaffold for the filter name capture, two more ContentHash homes

THE BLOCKER, root-caused by bisection rather than guessed. dag/gunbc/commit_workflow.dag
failed with "no field 'path' on type 'T'". src/v2/std/algebra.dag declares
fn filter<T>(xs: FreeMonoid<T>, predicate: fn(T) -> Bool). commit_workflow does NOT
import v2.std.algebra -- but it imports v2.compiler.source_authority, which drags the
whole v2 compiler closure including v2.std.algebra into the module POOL. The bare name
filter then binds to that declaration instead of the builtin, List<GitIndexEntry> does
not unify with FreeMonoid<T>, the lambda parameter stays unbound, and the module reds.

Discriminating measurement: importing v2.std.algebra for `length` ALONE -- never filter
-- reproduces it, and deleting only the source_authority import makes the original
filter form compile. So this is name capture by POOL MEMBERSHIP, not by the import
list: DESIGN #6985 Class B in its inverting direction, and silent -- nothing reports
that filter rebound.

Refuted by execution before landing anything, recorded in the carrier so nobody repeats
them: trailing comma in the parameter list; filter over an imported record type; List
not imported; two filter calls over different element types in one module; a lambda or
parameter name colliding with an imported symbol; cross-call-site unification.

The import cannot be dropped -- ModuleStorageBinding, ParsedFromSource and
ProducedByBehavior are all genuinely used -- so the only local repair routes around the
capture. Per DESIGN section 5 that is a WORKAROUND and may only land as a DECLARED
SCAFFOLD, never a quiet respelling: the body selects with flat_map (the spelling the
sibling function already uses over the same type with the same binding), and
commit_writer_index_filter_capture_scaffold states the root cause, the discriminating
measurement, the refuted hypotheses, why the import cannot be dropped, and the
dissolve-on -- the namespace-only resolution lane, after which the filter spelling is
restored and the row deleted. Behaviour is unchanged: it selects exactly the entries
whose path matches. commit_writer_admission_witness_test 13/13 exercises
admit_commit_writer, which calls this function, so that is verified by execution and
not merely by compiling.

This is NOT this branch's defect. It is fixed here because it reds main itself and
every job on this PR, and main landed #7608 while its own CI was still queued.

Also: two more files from main's #7623 import ContentHash from std.types. Same
manifest_content_identity field as the two prior batches, so same grounding onto
Fnv1a64Structural, with the contract fixture becoming a valid 16-hex digest.

Whole-tree compile 0 blocking errors; regen_divergence_count=0; heal no drift;
commit_writer_admission 13/13; live_rust_observation_contract 12/12.

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <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