Repository navigation
Carry occurrence identity on every semantic v1 Node - #9344
Conversation
…ore exhaustiveness over the two abort-side dispositions MAIN IS RED, and the finding is HOW rather than what. This is a SEMANTIC MERGE CONFLICT between two PRs that were each correct and each green, and NEITHER IS AT FAULT: #9227 cd7cf33 adds dag/gunbc/build_target.dag, which MATCHES over ClaimDisposition #9263 a968415 adds PanickedBeforeVerdict and NotAttemptedAfterAbort TO ClaimDisposition Neither PR touches the other's file. There is no textual conflict, no merge-tree signal, and both merged cleanly. One grows a coproduct, the other adds a match over it, and main refuses at strict preparation the moment they meet: dag/gunbc/build_target.dag:177:3: error: non-exhaustive match: missing variant(s) PanickedBeforeVerdict, NotAttemptedAfterAbort dag/gunbc/build_target.dag:378:3: error: non-exhaustive match: missing variant(s) PanickedBeforeVerdict, NotAttemptedAfterAbort #9263 was genuinely green on its own head (witnesses/build/floor all success, 03:38-04:56Z) and merged at 15:16Z against a main that had meanwhile acquired the match. So this is not a PR that merged on a missing check. NO PER-PR GATE CAN CATCH THIS CLASS BY CONSTRUCTION, because each PR is green against the base it was tested on; the combination is what is untested. That is worth recording separately from this repair, because the repair will look routine in six hours and the gap will not have moved. The compiler catching it the instant the two met is fail-closed working correctly. It is the only thing that did catch it. THE MAPPING IS DECIDED BY THE PARTITION THESE MATCHES ALREADY DRAW, not by severity. blaze_test_status_of_claim_disposition already sorts on DID THE CLAIM RUN -- RuntimeErrored is FAILED because it ran and blew up, while RouteGap, HostToolUnresolved and ObservationUnreadable are all INCOMPLETE because they never ran. So: PanickedBeforeVerdict -> TestStatusFailed it executed and died NotAttemptedAfterAbort -> TestStatusIncomplete it never executed INCOMPLETE is the honest arm here rather than the soft one. Rendering a claim that never ran as FAILED asserts that an assertion failed when no assertion ever executed -- the execution-provenance loss DESIGN forbids, where a stage refused before it ran must not inhabit the same carrier as a stage that ran and found a defect. In claim_disposition_verdict both are StandingUnsatisfied, for the same reason read the other way: neither is a claim that satisfied its standing, and admitting an unattempted claim as satisfied would let an aborted run report a standing it never tested. Verified by compiling dag/gunbc/build_target.dag as an entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ositions The arm-by-arm policy roster enumerated every ClaimDisposition BY HAND, so the two arms this PR adds would have landed with no executing evidence -- the exact specification-without-execution gap DESIGN names, one rung up from the non-exhaustive match that caused the outage. Both dispositions join the roster, and a dedicated witness pins the split that decides them: PanickedBeforeVerdict exports FAILED beside RuntimeErrored (the claim ran and died), NotAttemptedAfterAbort exports INCOMPLETE beside RouteGap (the claim never ran). The INCOMPLETE half is the assertion that earns its keep -- it goes red on precisely the collapse that is tempting to make, where a claim that never executed is reported as one whose assertion failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The 16:20 push and the 16:27 ready-flip should each have fired a witnesses run -- witnesses.yml lists both synchronize and ready_for_review, and carries no draft guard -- and neither produced a run of any kind. Not queued, not failed, not startup_failure: absent. The fleet was dispatching normally throughout that window, so this is specific to this ref rather than the outage pattern seen earlier today. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit 43f5c0c.
# Conflicts: # src/v1/04_resolve.dag # src/v1/stage0/src/v1_compiler_emit_rust.rs # src/v1/stage0/src/v1_compiler_infer.rs # src/v1/stage0/src/v1_compiler_infer_resolve.rs # src/v1/stage0/src/v1_compiler_trait_derive_emit.rs # src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs
# Conflicts: # src/v1/04_infer.dag # src/v1/stage0/src/v1_compiler_infer.rs
# Conflicts: # src/v1/04_infer.dag # src/v1/stage0/src/v1_compiler_emit_rust.rs # src/v1/stage0/src/v1_compiler_infer.rs # src/v1/stage0/src/v1_std_core.rs
# Conflicts: # src/v1/04_infer.dag # src/v1/stage0/src/v1_compiler_compile.rs # src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs # src/v1/stage0/src/v1_compiler_emit.rs # src/v1/stage0/src/v1_compiler_emit_rust.rs # src/v1/stage0/src/v1_compiler_infer.rs # src/v1/stage0/src/v1_compiler_infer_env.rs # src/v1/stage0/src/v1_compiler_infer_items.rs # src/v1/stage0/src/v1_compiler_infer_method.rs # src/v1/stage0/src/v1_compiler_infer_patterns.rs # src/v1/stage0/src/v1_compiler_infer_resolve.rs # src/v1/stage0/src/v1_compiler_infer_service.rs # src/v1/stage0/src/v1_compiler_infer_types.rs # src/v1/stage0/src/v1_compiler_parse.rs # src/v1/stage0/src/v1_compiler_trait_derive_emit.rs # src/v1/stage0/src/v1_std_core.rs # src/v1/stage0/src/v1_tests_claim_transport_roster_closure_witness_test.rs
# Conflicts: # src/v1/stage0/src/v1_compiler_emit_rust.rs # src/v1/stage0/src/v1_compiler_infer.rs # src/v1/stage0/src/v1_compiler_infer_types.rs
# Conflicts: # src/v1/stage0/src/v1_compiler_emit_rust.rs # src/v1/stage0/src/v1_compiler_infer_method.rs # src/v1/stage0/src/v1_std_core.rs
Two generated mirrors conflicted: v1_compiler_infer.rs and v1_compiler_infer_types.rs. The generated-artifact merge driver refused them by design - it leaves the ours side in the worktree with NO conflict markers and marks the path unmerged, because neither side's bytes are the projection of the MERGED authorities and picking a side drops the other's authority-derived content. So they were NOT hand-resolved. They are the output of claim_executor --required-regen over the merged .dag tree, installed from target/stage0-regen-candidate/src, and verified byte-identical to that candidate. CHECKED, because a regeneration that silently drops one side looks exactly like a correct one: this branch's subject is occurrence identity, and the regenerated mirrors carry 148 and 31 references to NodeOccurrenceIdentity/occurrence_identity respectively. No .dag file conflicted, so the authority merged cleanly and only its projection needed rebuilding. Carries the same two rustfmt reflows as #9644 (cli_run.rs, line-length only, from #9637 lengthening the roadmap authority paths): pre-existing on main, arriving here via the merge, and the generated pre-commit hook refuses without them. NOT INCLUDED, deliberately: main also carries generated-surface drift in v1_rt.rs and four drifted generated artifacts. Those are main's, not this branch's, and converging them here would hide them inside an unrelated PR. #9644 covers the artifact drift; v1_rt.rs is separate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f9c70ddb8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ItemResolveResult { | ||
| item: Node { | ||
| name: item.name, span: item.span, ident_span: item.ident_span, children: resolved_children, | ||
| occurrence_identity: OccurrenceSynthetic, name: item.name, span: item.span, ident_span: item.ident_span, children: resolved_children, |
There was a problem hiding this comment.
Preserve item identities during resolution
Every successfully parsed declaration reaches this reconstruction with a minted item.occurrence_identity, but the resolved item is unconditionally marked OccurrenceSynthetic. Consequently, compile_to_resolved produces module-item nodes that can no longer be correlated with the authored IDs retained in the graph's occurrence-transport sidecar. Carry item.occurrence_identity into this semantic rebuild instead.
Useful? React with 👍 / 👎.
| let resolved_anno = if texpr.type_annotation == none { none } else if is_type_expr_annotation(n: texpr.type_annotation.value) { Present { value: anno_resolved.resolved } } else { texpr.type_annotation } | ||
| let let_node = Node { | ||
| name: let_binding_name_at(texpr: texpr, source_indices: env.source_indices), | ||
| occurrence_identity: OccurrenceSynthetic, name: let_binding_name_at(texpr: texpr, source_indices: env.source_indices), |
There was a problem hiding this comment.
Preserve let-expression identity during resolution
When an authored let is resolved, this replacement node discards texpr.occurrence_identity and becomes synthetic. Thus, even if item-level identity is preserved, every resolved let loses its parser-minted occurrence and no longer matches its sidecar entry; use the original expression's identity for this rebuild.
Useful? React with 👍 / 👎.
| PropertyInferenceResult { | ||
| prop: Node { | ||
| name: p.name, span: p.span, ident_span: p.ident_span, | ||
| occurrence_identity: OccurrenceSynthetic, name: p.name, span: p.span, ident_span: p.ident_span, |
There was a problem hiding this comment.
Keep authored property identity during inference
For any property whose value is inferred, this reconstruction replaces the property wrapper's minted identity with OccurrenceSynthetic. Properties that take the deferred branch retain p unchanged, so identity behavior now depends on the inference judgment rather than authorship, and judged properties cannot be correlated with their parser-side occurrence entries. Preserve p.occurrence_identity here.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y
…the string literal it was authored as Bisect pinned main's runtime failure (trim expects a string, got Null on the converge actuator) to 655f82a (#9344). Mechanism: the rewritten parse_optional_from_key built the from_key property's value node with NoExprData (key carried only as a node NAME), and the new field_to_child_node passes parsed properties through instead of re-materializing them — but the interpreter's extract_from_key accepts only ExprLiteral{LitStr}, so every 'output field from "channel"' mapping silently missed, the output key fell back to the field name, and effect-result fields decoded as Null (git.Core.ConfigLocalGetInRepo: .success survived by name, .value did not). The from token IS a string literal in the grammar (ShLitStr), so the fix makes the property value carry ExprLiteral{LitStr{key}} at the one construction site in v1.compiler.parse parse_optional_from_key; the mirror is regenerated via --required-regen (surface drift resolved by installing the candidate). Smoke: the converge actuator executes end-to-end again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y
…osition (13 clusters to named submodules) (#9648) * guarantee_rung_drop: close the record #9612 left unterminated The wall_deadline_shared_fill_attribution_stall record landed without its closing brace, so every gunbc run over the dag root refused at module index (expected expression, found Eq) -- the same collided merge that duplicated the cli_run.rs definitions. With the brace, the documented converge actuator entry runs end-to-end again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Plan: hand off the per-invocation whole-tree tax finding Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Correct the pool-tax finding: linear ~20-25ms/pool-module eager graph facts, no cwd switch; fast controls were panics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split 1/n: move seven census clusters to cli_run/ submodules (pure code motion) test_migration, compile_clean, non_fold_residue, class_b_census, languages_census, external_authority, inert_carrier — 107 items, ~2.1k lines. Mechanics: each cluster becomes a cli_run/ submodule with 'use super::*' back into the parent plus the parent's use-header; the parent re-exports 'pub(crate) use <mod>::*' so every existing path keeps resolving. Private moved items widen to pub(crate), which rewraps a few signatures under rustfmt. No semantic change; build-verified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split 2/n: witness_gates, emit_host, complexity_gates, doc_graph, declared_refs, census_heads (pure code motion) 89 items, ~2.1k lines. Bin-consumed pub fns get explicit pub use re-exports (the pub(crate) glob does not cross the lib/bin crate boundary). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split: widen eight report/plan types to pub(crate) (private-interface lints; CI sets -D warnings) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Plan log: cli_run decomposition progress and the two deferred cores Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split 3/n: fallback_arm_census, p1_cohort, owned_data, live_read_decode, active_workset (pure code motion) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Remove merge markers both brace-fixes left in guarantee_rung_drop.dag Both sides of the merge fixed #9612's unclosed record identically; the auto- merge kept both hunks' markers. Smoke-verified: the converge actuator (now at dag/gunbc/repo/ after the filename reorg) compiles and executes again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split 4/n: entry_resolve — the resolver/index core (75 items, ~2.5k lines, pure code motion) The pool-tax subject now has its own reviewable home: module path index, module-graph facts, import closures, the process shared index and resolve store (thread_local statics widened to pub(crate)), typed-module cache, multi-entry index shell, resolve stage/span accounting. Bin-consumed fns get explicit pub use; two cache types widened for the private-interface lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * cli_run split 5/n: required_floor_runner — the floor fold and claim execution (49 items, ~4.8k lines, pure code motion) run_required_floor, claim evaluation/measurement, discovery corpus, diff observation, prepared-subject inventory, resource sampling, cgroup envelope, route-gap expectations, floor stream/verbosity plumbing. Same recipe: bin- consumed fns re-exported pub; two expectation/edit types widened for the private-interface lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Plan log: resolver core and floor runner moved Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Plan: standing dependency map (store/native/delete-eval-loop) and the single pre-registered execution test Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Plan log: bisect pins the trim-Null runtime regression to #9344 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y * Fix #9344's effect-output regression: the from-key property value is the string literal it was authored as Bisect pinned main's runtime failure (trim expects a string, got Null on the converge actuator) to 655f82a (#9344). Mechanism: the rewritten parse_optional_from_key built the from_key property's value node with NoExprData (key carried only as a node NAME), and the new field_to_child_node passes parsed properties through instead of re-materializing them — but the interpreter's extract_from_key accepts only ExprLiteral{LitStr}, so every 'output field from "channel"' mapping silently missed, the output key fell back to the field name, and effect-result fields decoded as Null (git.Core.ConfigLocalGetInRepo: .success survived by name, .value did not). The from token IS a string literal in the grammar (ShLitStr), so the fix makes the property value carry ExprLiteral{LitStr{key}} at the one construction site in v1.compiler.parse parse_optional_from_key; the mirror is regenerated via --required-regen (surface drift resolved by installing the candidate). Smoke: the converge actuator executes end-to-end again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017qPeVyc2VjbdN4os17UG3y --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Make
NodeOccurrenceIdentitya required field across the complete semantic v1Nodeconstruction surface. Authored parser construction mints identity transactionally; semantic rebuilds preserve it; genuinely compiler-created nodes nameOccurrenceSyntheticexplicitly; the post-parse walk validates carried identity and produces the occurrence sidecar.This draft currently contains the prerequisite required-field control and the pre-change stamp-order oracle. The carrier conversion remains in progress.
Admission authority
§4b guarantee row: parser context publication
ifcondition/branch/parent publication; recursive accepted-child lists for predicates, variants, type arguments, fields, uses, service operations, resource capabilities, parameters, statements, lambda statements, arguments, match arms/statements, field initializers, and expression lists; slice end-operand publication (#9344). The index arm was made uniform but had no observed failure. Refusing error paths publish no successful node/context pair and are outside this population. This is the bounded population actually repaired, not a claim over all parse shapes.Test plan
target/release/gunbc run --claim-run ... --function omitted_required_record_field_refuses— PASS; asserts exactly one blockingMissingFieldrow namingidentity.target/release/gunbc run --claim-run ... --function complete_required_record_literal_accepts— PASS.cargo test -p v1-compiler --test namespace_occurrence_serde occurrence_transport_round_trips_with_node_identity_and_paths -- --nocapture— PASS on the pre-change stamp-order oracle.Build receipts:
The diagnostic-census fixture truthfully declares
ReadsLiveTree; direct execution passes, while the current required floor declines live-tree witnesses. The PR does not claim required-floor enrollment for that control.