Repository navigation
Bind the two import-less plan sketches from their definers, not from pool coincidence - #7872
Merged
Merged
Conversation
This was referenced Aug 5, 2026
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Aug 5, 2026
…this PR's compile-clean) Not this PR's defect. dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag are the only two of ~46 table-using modules under dag/gunbc/plans/ carrying no imports at all, so their cross-module names bind by pool coincidence (DESIGN #6985 Class B). This PR touches claim_executor.rs, and a non-selectable .rs path forces compile-clean to the whole-tree baseline, which compiles them; main pushes take the scoped path and never do. Same change as #7872 (authored off main). Carried here so this PR can go green without waiting for that to merge; when it does, the identical lines merge clean. Verified by execution: both modules compile with 0 blocking errors. Two imports are required, not one — adding md_helpers alone flips each module from ambient bare resolution to import-scoped visibility, which then refuses Plan/HasTrigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 5, 2026
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Aug 5, 2026
Resolve branch_merge_admission_model import conflict: keep both std.markdown (TableBlock, AlignNone) and md_helpers from our CI fix alongside main's md_helpers addition from #7872. Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Aug 5, 2026
Main already restored md_helpers imports in #7872; keep file byte-identical to main so this PR carries only the wet-batch observation work. Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Aug 5, 2026
…required_output Two fixes. 1. The merge with main text-merged .github/workflows/ci.yml, which is a GENERATED artifact. The textual result silently dropped main's changes: #7872's `[ ! -f X ]` -> `! [ -f X ]` POSIX transposition, and the new generated-file entries main added to the heal exclusion list (std_source_annotation.rs, v1_compiler_annotation_bind.rs, the four annotation witness tests). Regenerated with main_wet on dag/tools/generated_artifact_gate.dag so the committed bytes derive from the merged .dag sources instead of a line-wise reconciliation of two generated outputs. This is what the CI heal job was reporting. It found ci.yml drift, saw a workflow path, classified HealAuthorCommitRequired, refused to push, and failed loudly — which is precisely the behavior this PR models. The remedy is the one it names: the author commits the regeneration. The failing step was the heal push; build and regen both passed. 2. review 49025 (cursor): ci_heal_author_commit_required_output is used at ci_workflow.dag:608 and defined in ci_spec.dag:589 but was absent from the gunbc.ci_spec import list. Confirmed. The review predicted it "should fail module resolution / compile-clean" — measured, it does not: the entry resolves 409 sources today, because gunbc.ci_spec is already partially imported and so is in the pool. So the symptom is not a live break; the defect is that the reference resolves by pool-membership coincidence, the same Class B fragility repaired in the two plan sketches earlier in this branch. Imported explicitly rather than left to coincidence. Witnesses on the merged tree with a binary rebuilt from it (main changed the Rust seed, so the prior binary was stale evidence): actions_job_grant 18/0, github_app_registry 33/0, ci_heal_job 21/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls
added a commit
that referenced
this pull request
Aug 5, 2026
…ived from the existing witness row-cost receipt, with promotion-to-refusal as its declared trigger (#7862) * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * Bind the two import-less plan sketches from their definers (unblocks this PR's compile-clean) Not this PR's defect. dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag are the only two of ~46 table-using modules under dag/gunbc/plans/ carrying no imports at all, so their cross-module names bind by pool coincidence (DESIGN #6985 Class B). This PR touches claim_executor.rs, and a non-selectable .rs path forces compile-clean to the whole-tree baseline, which compiles them; main pushes take the scoped path and never do. Same change as #7872 (authored off main). Carried here so this PR can go green without waiting for that to merge; when it does, the identical lines merge clean. Verified by execution: both modules compile with 0 blocking errors. Two imports are required, not one — adding md_helpers alone flips each module from ambient bare resolution to import-scoped visibility, which then refuses Plan/HasTrigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Migrate the migration-disclosure receipt to WitnessRowCost's named fields #7845 replaced WitnessRowCost's tuple shape with named fields and inserted eval_cpu_nanos in the middle, so every positional index in this branch's new code shifted: .0/.1/.2/.5 are entry/function/eval_wall_nanos/outcome. Merging main migrated the pre-existing call sites; these six were the residue this branch adds. The skip test now calls row_measurement_is_absent(&row.outcome) rather than comparing the outcome string inline. Same behavior — that helper tests exactly selection-skipped — but it is the existing authority for the question, and the inline compare was a second copy of it (DESIGN section 3). TimedOut rows still fall through to be measured, which is deliberate: they are the population this disclosure exists to surface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.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>
briansrls
pushed a commit
that referenced
this pull request
Aug 6, 2026
…-PR — it is absent from three job logs and its observability receipt emits zero rows (#7857) * WIP: CI floor: prove whether the 64-row bin-witness wet batch executes per-PR * WIP: CI floor: prove whether the 64-row bin-witness wet batch executes per-PR * Fix cargo fmt in claim_executor wet receipt trace. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: CI floor: prove whether the 64-row bin-witness wet batch executes per-PR * Regenerate ci.yml and falsifier.yml after rebase onto main. Rebase merged #7856 path_intent cgroup ascent with wet receipt post-step; main_wet restores committed workflow bytes for heal author-commit gate. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: CI floor: prove whether the 64-row bin-witness wet batch executes per-PR * Restore md_helpers import on branch_merge_admission_model plan. Class B pool-coincidence: stripped file resolved only when an unrelated closure dragged md_helpers into the pool. Whole-tree compile-clean after workflow yml commit exposed the latent main defect; restore imports per sibling plan modules until closure-independent binding lands. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop noop branch_merge_admission_model diff after rebase. Main already restored md_helpers imports in #7872; keep file byte-identical to main so this PR carries only the wet-batch observation work. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: CI floor: prove whether the 64-row bin-witness wet batch executes per-PR * Derive discovery corpus log labels from schedule profile, not roster size. Thread spawns_host_compiler from RunnableDiscoveryBatch through BatchUnit into run_discovery_batch_node so bin-witness vs execution lanes stay correctly labeled even if the execution roster grows past the old count heuristic threshold. 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: Cursor <cursoragent@cursor.com>
briansrls
pushed a commit
that referenced
this pull request
Aug 6, 2026
…pt-index long-lane row (#7880) * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * Bind the two import-less plan sketches from their definers (unblocks this PR's compile-clean) Not this PR's defect. dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag are the only two of ~46 table-using modules under dag/gunbc/plans/ carrying no imports at all, so their cross-module names bind by pool coincidence (DESIGN #6985 Class B). This PR touches claim_executor.rs, and a non-selectable .rs path forces compile-clean to the whole-tree baseline, which compiles them; main pushes take the scoped path and never do. Same change as #7872 (authored off main). Carried here so this PR can go green without waiting for that to merge; when it does, the identical lines merge clean. Verified by execution: both modules compile with 0 blocking errors. Two imports are required, not one — adding md_helpers alone flips each module from ambient bare resolution to import-scoped visibility, which then refuses Plan/HasTrigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Follow-up to #7872: the std.markdown symbols were still binding by coincidence review 48984, on the merged #7872, is correct and my completeness claim there was not. Both plan sketches still referenced MarkdownBlock, TableBlock and AlignNone with no std.markdown import, so those three kept binding by pool coincidence — the same #6985 Class B pathology #7872 exists to close, left in place by the change closing it. THE BAD INFERENCE, named because it is the trap and not a slip: I read "0 blocking error(s)" as "every name binds from a declared import". It does not. Bare resolution still answers for whatever the closure happens to contain, so a clean compile is precisely the evidence that CANNOT separate a declared binding from a coincidental one — the compiler is green either way. Only reading the file against its own import list decides it, which is what the reviewer did and I had not. Verifying the fix by the same instrument that was blind to the defect is a DESIGN §5 specification-without-execution failure wearing an execution costume. Symbol set verified against std.markdown's 34 exports this time rather than inferred from a clean compile: these two modules use MarkdownBlock, TableBlock and AlignNone and nothing else from it. Byte-identical to the most common sibling form, carried by 18 plan modules including the three #7872 cited as precedent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Migrate the migration-disclosure receipt to WitnessRowCost's named fields #7845 replaced WitnessRowCost's tuple shape with named fields and inserted eval_cpu_nanos in the middle, so every positional index in this branch's new code shifted: .0/.1/.2/.5 are entry/function/eval_wall_nanos/outcome. Merging main migrated the pre-existing call sites; these six were the residue this branch adds. The skip test now calls row_measurement_is_absent(&row.outcome) rather than comparing the outcome string inline. Same behavior — that helper tests exactly selection-skipped — but it is the existing authority for the question, and the inline compare was a second copy of it (DESIGN section 3). TimedOut rows still fall through to be measured, which is deliberate: they are the population this disclosure exists to surface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Dissolve the concept-index long-lane row by fixing the witness's cost The witness's cost is its POOL, and the pool was 638 files. concept_index_enumeration_pool_roots was "src/v2/test/claim", and concept_decl_facts parses every .dag under the root on every call, so each parse-only witness parsed 638 files / ~3.0 MB and grew with every unrelated module added anywhere beneath it. That is precisely what the SubstrateLongLaneRow recorded ("corpus-breadth cost grows with unrelated modules in the pool") and what pushed witness_coproduct_arms_parse_only to 6065ms thread-CPU against the 5000ms fast-lane budget, rehoming it to test/claim/long/ under #7756. Breadth was never the subject. Every assertion names ONE concept by qualified name and checks its extracted fields, so the requirement is a pool CONTAINING those concepts, and the smallest pool that crosses the boundary is a directory of its own (operator ruling 2026-08-04: a witness's size is DERIVED from what it proves, never chosen for verisimilitude). src/v2/test/fixture/concept_index_pool is that pool. MEASURED, same host, same binary, toggling only the .dag source: witness_coproduct_arms_parse_only 3952ms -> 2ms whole 11-witness family, slowest 51ms (was ~4000ms for parse-only rows) All 11 pass, including the returned witness. The pool is proven non-vacuous rather than merely quiet: witness_parse_only_extract_nonempty_in_scoped_pool asserts the pool is non-empty AND contains the target, and witness_parse_only_extract_reflects_perturbed_field_type reads RecordPerturb's beta: Int out of the fixture — so the stale-field RED control cannot be passing because the pool is empty. WHY THE TYPES DID NOT ALL MOVE. The two witness families consume different inputs: concept_decl_facts_live reads the loaded module REGISTRY, concept_decl_facts reads FILES under a root. The live-registry witnesses keep local declarations (a locally-declared record IS their subject); the parse-only witnesses read the fixture pool. That is two inputs to two mechanisms, not one concept forked. A CHANGE THAT DID NOT EARN ITS PLACE ON THIS WITNESS, kept and labeled rather than quietly credited: enumerate_concepts_from_decls folded with list_snoc_item, which is list_append(xs, [item]) and therefore O(n^2) over the decl count. It is replaced with list_map (fold_list_right + Cons, O(n), order-preserving, identical output). Measured effect on this witness: 3952ms -> 3795ms, ~4%, inside noise — because the dominant cost was the host-side pool parse, not the fold. It stays because it is a proven cost-shape defect on a function enumerate_concepts() also calls corpus-wide (DESIGN section 6: fixed regardless of the realized n), NOT because it fixed anything here. My first hypothesis was that this fold WAS the cost; measurement refuted it, and the pool root was the answer. Dissolves: the SubstrateLongLaneRow, the long/ file, and coproduct_arms_parse_only_long_lane_note, all deleted together per the row's own trigger ("eval lands under gunbc_ci_fast_lane_witness_eval_budget on a measured cold run and re-enrolls per-PR discovery"). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: shell -> dag (and TS -> dag) * Drop the stale concept-index parse-only basis row invalidated by this branch witness_coproduct_arms_parse_only carried a dated basis of 3850ms from run 30550328673, measured when concept_decl_facts parsed all 638 files under src/v2/test/claim. Narrowing the pool to the witness family's own directory takes the same witness to ~1.5ms, so that basis is a measurement of a different implementation and no longer a reference for this one. Leaving it is not neutral: the drift comparator is a 2x ratio, so a 3850ms basis pins this row WithinBasis below 7700ms forever and the drift gate goes vacuous for it exactly where a future regression would show up. That is the failure committed_witness_row_cost_basis_loads_and_excludes_the_censored_row already guards against for the 900794ms censored row, in the same file. Dropped rather than re-signed: witness_row_cost_basis_host_class_note requires basis rows to be signed from a cited arm64 srv-fleet run, never a local measurement, and this container is x86. BasisAbsent is the honest third state (typed and counted, per witness_row_cost_spine_note) until the next fleet cadence re-signs it. Drift is falsifier-cadence counted and not merge-refusing, so this changes no gate verdict. 1190 rows remain, over the >=1000 floor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.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>
briansrls
pushed a commit
that referenced
this pull request
Aug 6, 2026
#7766) * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Enroll dag/extdeps/github/app.dag in scope_carrier_paths The new extdeps module declares extdeps_model_scope: ExternalModelScope but was not enrolled in any of the three landing states the scope frontier admits, so tools.extdeps_scope_placement_gate refused it in batch 1: extdeps scope placement gate: THIS CHANGE adds dag/extdeps file(s) enrolled in neither scope_carrier_paths nor scope_machinery_exempt_paths It is a scope carrier, not citation/mock machinery, so it joins scope_carrier_paths. The frozen legacy manifest is not a landing state for a newly added file. The FLOOR-FINALIZATION-REFUSED resolve-count mismatch reported alongside it is fallout from batch 1 stopping the line before batch 2 ran, not a separate defect. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Ground installation_id on the typed GitHubAppInstallationId carrier review 48056 (claude/claude-opus-4-7): GitHubAppInstallationId existed in extdeps.github.app while gunbai_ci_declared_installation_id and GithubAppRunnerConfig.installation_id stayed NonEmptyStr — a typed carrier declared and then not used, which is the same anemic-leaf class this PR exists to close. installation_id is stored, never rendered into the installer argv, so the change is field type + data row only; no emission bytes move. Witness srv4_runner_app_from_secret_manager now pins .installation_id.value. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Recut: authorize the heal push against the credential that performs it The previous cut derived .github/workflows/** push eligibility from an authored gunbai[bot] permission list while the live heal pushes with the Actions job's GITHUB_TOKEN (ci.yml, actions/checkout persisted credential). Different credentials, so the fold could have reported AutoPushEligible for a push GitHub rejects. Verified against GitHub's docs: the workflow permissions vocabulary has no `workflows` key at all, so GITHUB_TOKEN is structurally incapable here — a different state from an ungranted App permission, and conflating them is what let an unobtainable capability be modelled as a pending one. Three separated authorities: - extdeps.github.effect — typed GitHubEffect and the provider projection to required permissions. Replaces the hand-authored purpose + permission lists (the runner row claimed repository administration:write for what is actually organization_self_hosted_runners:write; prose and list disagreed and nothing could tell). The .github/workflows/** rule lives here, once. - extdeps.github.actions_token — GITHUB_TOKEN's closed scope vocabulary as a coproduct with no workflows arm, so the absent scope is unwritable. - gunbc.auth.github_credential — which credential is selected for an effect, and its capability: CredentialKindCannotSatisfy vs CredentialGrantNotObserved. Eligibility is now a relation, not an artifact property: gunbc.heal_push_plan plan_heal_push(artifacts, credential, control_plane). gunbc.generated_artifact owns what each artifact is and where it lives; the plan owns whether a given writer may advance the branch with it. Deleted as authored external state: gunbai_bot_installation_granted_permissions, gunbai_bot_ungranted_permissions, heal_app_can_push_workflow_paths, the static AppUnobserved rows, GitHubAppConsumer/GitHubAppEnrollment, permission_max_access (fabricated AppAccessRead for an absent name), and the five explanatory notes. Replaced by GitHubAppControlPlaneState: SignerCustodyMissing → AppRegistrationUnobserved → AppRegistrationPermissionMissing (carries the exact delta and settings locator) → InstallationPermissionApprovalPending → InstallationGrantObserved. No .dag edit follows an approval; the readback moves the state. gunbai[bot] is a declared migration target, not a selection. Its signer custody is SignerCustodyAbsent (the modeled PEM belongs to gunbai-ci, a different app), so every fold consuming it refuses through the credential path. Also reuses existing identity authorities rather than re-coining: the minted CommitSha collided with std.types and broke extdeps.git.git resolution; the repository target is extdeps.github.github Repository via gunbc_repository. Behaviour unchanged: ci.yml regenerates byte-identical. Witnesses green by execution (25 across three modules), including: - witness_app_grant_cannot_rescue_actions_job_credential — the direct falsifier for the previous cut: full app grant, Actions credential, workflow push still refuses - witness_actions_token_refusal_is_kind_not_grant — refusal is kind, not grant - witness_registration_gap_precedes_installation_approval — the two GitHub transitions are distinct states - witness_signer_custody_missing_precedes_every_readback - witness_unobserved_readback_never_authorizes - witness_heal_plan_* — plan partitions under a varied credential The metadata:read baseline moved to the App credential layer because the discriminating witness caught it: attached to the effect it refused every ordinary GITHUB_TOKEN push, since Actions has no metadata scope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Repoint the last heal-policy consumer; witness the dispatch/push asymmetry CI floor caught a consumer the recut missed: ci_heal_job_witness_test still imported auto_push_eligible_committed_artifact_paths and author_commit_required_committed_artifact_paths from gunbc.generated_artifact after they moved to gunbc.heal_push_plan. The compile-clean gate reded, and the "floor resolve count 1 differs from declared 2" refusal was its knock-on (the run aborted before the second resolve). Swept every moved and deleted symbol corpus-wide rather than waiting for the next run to find the next one. live_heal_dispatch_credential was declared with no consumer — an inert row. witness_dispatch_and_push_credentials_differ_in_outcome now makes it live and proves the asymmetry that motivates the whole split: the SAME Actions job credential authorizes the exact-head dispatch (actions:write is in GitHub's permissions vocabulary) and cannot authorize the workflow-path push (workflows is not). One credential, two effects, two different outcomes — which is only expressible because capability is now a function of the effect. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Remediation ownership, open permission observation, producer-gated operator packets, fail-closed repair bundle * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Fix closure-dependent resolution in two plan sketches (unblocks compile-clean) dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag carried NO import block and reached row/cell/p/h2/quote (gunbc.plans.md_helpers), Plan/HasTrigger (gunbc.plan), and gate_roster_content_hash/receipt_is_admissible (gunbc.merge_admission) as bare cross-module references. Those resolved only by pool-membership coincidence: some unrelated module elsewhere in the assembled closure had already dragged the definer into the pool. That is the Class B failure DESIGN records under the #6985 witness-discovery cascade thread. Neither file is in this PR's subject. The failure surfaced here because an all-.dag diff moves the compile-clean gate off the whole-tree baseline onto a scoped shard closure, and in that closure nothing dragged md_helpers in: CI run 31036782524 reported "function 'cell' not found in scope" 60+ times against a file this branch never touched, while the same gate passed on main's whole-tree run. Adding the explicit imports makes each module carry its own dependencies into any closure that contains it. Verified by execution: before the fix the entry resolved 22 sources by coincidence; with md_helpers imported the closure narrowed to 8 and exposed the further unresolved Plan/HasTrigger refs, which are now imported too. Both entries compile. This repairs the two files CI flagged. It does not close the corpus-wide class, which DESIGN still tracks as blocking further dag/** import-stripping. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Split SignerReadbackFailed's fused prose detail into typed causes review 48972 flagged SignerReadbackFailed { detail: NonEmptyStr } as an in-band-string discriminator. Verified: signer_seals_app was a conjunction of two structurally distinct failures, and the single construction site described them with a prose "app id or registered fingerprint disagrees" — an in-band `or`, which is the state-space conflation DESIGN lists as a recurring failure mode. The two causes have different remedies (wrong key material vs. a key GitHub has not registered), so a consumer that wants to route them apart could not. SignerSealFailure = SignerNamesDifferentApp { observed, declared } | SignerFingerprintNotRegistered { derived, registered } signer_seal_failure derives the cause and carries the disagreeing values; signer_seals_app stays as the Bool projection over it, so existing callers are unchanged. Discriminating evidence, since the pre-existing witnesses matched on `custody: _` and so could not see a cause at all: witness_seal_failure_names_which_of_the_two_causes_fired asserts the cross-app fixture yields SignerNamesDifferentApp with differing ids and the unregistered-key fixture yields SignerFingerprintNotRegistered with differing fingerprints. RED control: re-fusing the app-id arm onto the fingerprint cause reds the new witness while the older Bool-level witness stays green — that gap is exactly what this split closes. 33 witnesses green, 0 failing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Regenerate ci.yml after the main merge; import ci_heal_author_commit_required_output Two fixes. 1. The merge with main text-merged .github/workflows/ci.yml, which is a GENERATED artifact. The textual result silently dropped main's changes: #7872's `[ ! -f X ]` -> `! [ -f X ]` POSIX transposition, and the new generated-file entries main added to the heal exclusion list (std_source_annotation.rs, v1_compiler_annotation_bind.rs, the four annotation witness tests). Regenerated with main_wet on dag/tools/generated_artifact_gate.dag so the committed bytes derive from the merged .dag sources instead of a line-wise reconciliation of two generated outputs. This is what the CI heal job was reporting. It found ci.yml drift, saw a workflow path, classified HealAuthorCommitRequired, refused to push, and failed loudly — which is precisely the behavior this PR models. The remedy is the one it names: the author commits the regeneration. The failing step was the heal push; build and regen both passed. 2. review 49025 (cursor): ci_heal_author_commit_required_output is used at ci_workflow.dag:608 and defined in ci_spec.dag:589 but was absent from the gunbc.ci_spec import list. Confirmed. The review predicted it "should fail module resolution / compile-clean" — measured, it does not: the entry resolves 409 sources today, because gunbc.ci_spec is already partially imported and so is in the pool. So the symptom is not a live break; the defect is that the reference resolves by pool-membership coincidence, the same Class B fragility repaired in the two plan sketches earlier in this branch. Imported explicitly rather than left to coincidence. Witnesses on the merged tree with a binary rebuilt from it (main changed the Rust seed, so the prior binary was stale evidence): actions_job_grant 18/0, github_app_registry 33/0, ci_heal_job 21/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Refuse unmodeled installation permissions instead of narrowing past them review 49069 found an empty-observation narrow in extdeps.github.app authored_subset_of. Confirmed, and it is the DESIGN-named failure mode exactly: an observed installation permission whose wire name is outside the closed GitHubPermissionAxis set hit `Absent => acc` and was dropped, so PermissionNarrowingOmitted verified against a REDUCED set. "I cannot model this permission" was rendered as "this permission is not in the set" — bottom-as-answer conflated with bottom-as-ignorance, on the surface that checks whether a token request stays within its installation's grant. When GitHub adds an axis, the check would have gone green on less than it was asked to verify. Fixed by refusing rather than widening the silence: AuthoredPermissionProjection = AuthoredPermissions { permissions } | UnknownPermissionWireName { wire_name } PermissionNarrowingVerdict = NarrowingWithinInstallation | NarrowingExceedsInstallation | NarrowingUnverifiable { unknown_wire_name } authored_subset_of refuses on the first unmodeled wire name and carries it; permission_narrowing_verdict distinguishes exceeds-grant from cannot-verify, which are different states with different remedies; and permission_narrowing_is_within is a Bool projection that is true ONLY for NarrowingWithinInstallation, so an unknown axis is fail-closed at every existing call site rather than silently admitted. Discriminating evidence: witness_unmodeled_installation_permission_refuses_rather_than_narrowing plants "future_provider_permission" in an installation and asserts the verdict is NarrowingUnverifiable naming that wire name, that the Bool projection is false, and that the same installation without it still verifies Within. RED control: restoring the silent drop reds the new witness while witness_narrowing_may_only_narrow stays GREEN — the pre-existing witness structurally could not observe this class, which is why it survived until now. github_app_registry_witness_test: 34/34, 0 failing, on a binary rebuilt from the merged tree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Give the heal control plane its real required-permission roster review 49090 observed live_heal_control_plane passing required: [] and called it a silent noop worth revisiting when readback lands. Traced, and the severity is narrower than a fail-open but real. NOT an authorization hole: managed_credential_capability re-checks installation_holds against the ACTUAL required permission on the InstallationGrantObserved arm, so no token could be authorized for something the installation does not hold. The control plane's roster only decides the STATE. What the empty roster does corrupt is that state. registration_missing_permissions and installation_missing_permissions both filter over the roster, so an empty one makes gap detection vacuous: once readback lands, the plane reports InstallationGrantObserved no matter what the installation holds, and the operator packet — whose entire job is to name which permissions to approve — asks for nothing. Dormant today only because the custody arm short-circuits before required is read. It activates exactly when readback lands, which is the next slice, so it is fixed now rather than left as a trap for the change that turns it on. Roster set to [contents_write, workflows_write], consuming the declared rows in extdeps.github.effect rather than re-minting them, and imported explicitly rather than resolving by pool coincidence (the Class B class this branch has already hit twice). Behavior-neutral at this head, by execution: actions_job_grant 18/18, github_app_registry 34/34, ci_heal_job 21/21, heal_author_commit 7/7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Retain the located payload on binding refusals; pin token distinctness review 49121, two findings, different answers. FINDING 1 — locator erasure. Confirmed. Every non-Resolved arm of plan_heal_push_from_binding destructured with `_`, discarding checkout_step (a DeclarationRef — the LOCATED half of a located refusal) along with input and observed_kind, then collapsed to a bare HealPushRefusalCause. DESIGN §5 requires refusals be typed AND located; the type survived, the location did not. That is a narrowing of the diagnostic, and the modeled payload was already sitting right there in PushBindingResolution. HealPushBindingSite { checkout_step, input?, observed_kind? } now hangs off HealPushFailure and the payloads are threaded through instead of dropped. Discriminating evidence: witness_binding_refusal_retains_its_locator asserts the refusal carries the checkout step it came from and that the input slot is honestly Absent for the arms that have no input. RED control: re-erasing the site reds it while witness_machine_fault_never_becomes_ author_work stays GREEN — the pre-existing coverage structurally could not observe locator fidelity. FINDING 2 — the variant/string token map. The parallel-representation reading is fair, but the stated cost does not hold on inspection. The claim is that every new cause needs two edits kept in sync by diligence; it does not, because the match is exhaustive, so a new variant is a COMPILE ERROR. Forgetting the edit is already unwritable by construction. The real residual is a duplicated or empty token, which exhaustiveness cannot catch — closed here by witness_refusal_cause_tokens_are_pairwise_distinct. Dissolving the map outright needs value-level variant-name reflection, which this language does not have: the variant_name fields in std.induction and std.node are Node-tree data, not a primitive applicable to a value. Per §4b that makes this a class whose ceiling is set by a missing language capability, and the honest move is to name the capability as its trigger rather than hand-roll a second mechanism beside the first. No change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Regenerate ci.yml after the merge: restore the entry the text-merge dropped The generated-artifact merge driver resolved .github/workflows/ci.yml to my side without conflicting, silently dropping main's new exclusion entry v1_tests_claim_v1_complexity_eviction_hazard_test.rs from AUTHORED_CONFLICTS. Regenerated via main_wet against a freshly rebuilt seed (main changed cli_run.rs and compiler_tests.rs, and a stale seed self-verifies at divergence zero, so the old binary's output would not have been evidence). Sole diff is that one restored entry. The heal upload block emits the intended union: if-no-files-found: error, include-hidden-files: true derived from the roster, gated on heal_author_commit_required == '1'. * WIP: gunbc-ci-auto-heal needs to be able to run self hosted workflows on gith * Separate configurable permission keys from intrinsic job-token grants Operator correction 2026-08-06. effective_actions_grant mapped every axis with no configurable workflow `permissions:` key to ActionsGrantScopeUnavailable, which declared a grant observed on the live token structurally impossible. The exact-head Actions job reports: Contents: read Metadata: read PullRequests: read Metadata has no configurable key yet is granted. Those are two different facts and now have two carriers: axis_actions_permissions_key answers DECLARABILITY, axis_intrinsic_token_grant answers what the token carries when nothing is declared. MetadataAxis + read -> ActionsGrantResolved(read) MetadataAxis + write -> CredentialScopeNotGranted (permission_access_at_least) WorkflowsAxis -> ActionsGrantScopeUnavailable RepositoryProjectsAxis-> ActionsGrantScopeUnavailable IntrinsicTokenGrant is Absent|Read with no write variant, so an intrinsic write is unrepresentable rather than validated: no answer had to be invented for the read-or-write states no axis occupies, and observing a write-carrying intrinsic axis later is a compile error at every consumer, not a silent widening. Renamed actions_token_can_carry -> actions_token_may_declare_permission. Behavior identical, but after this correction a predicate named "can carry" returning false for Metadata while effective_actions_grant resolves it to read would restate the same conflation one layer up. HEAL BEHAVIOR UNCHANGED, verified by execution: live_heal_push_refusal_cause_token still returns ActionsJobCredentialScopeUnavailable. Metadata is not in the heal's required set, so it cannot be affected. main_wet regen produces no drift in any emitted artifact — the committed fixed point holds. Controls: corrected the stale is_scope_unavailable(MetadataAxis) assertion, and added witness_undeclarable_axis_may_still_be_granted (both polarities, so re-fusing the two facts in either direction reds) plus witness_intrinsic_read_grant_refuses_a_write_request (the capability layer). actions_job_grant 20/20, github_app_registry 34/34. Also from review 49204, one control not a restructure: pinned that no refusal cause token collides with refusal_causes_token's empty-population marker, which that fold reuses as its own "nothing accumulated yet" state. Was safe by coincidence; now safe by execution. --------- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dag/gunbc/plans/branch_merge_admission_model.dagandmerge_admission_gate_shape_proposal.dagare the only two of ~46 table-using modules underdag/gunbc/plans/that carry no imports at all. They have had none since #6927/#7254, so every cross-module name in them binds by pool-membership coincidence:resolve_infinds the definer exactly when something unrelated in the currently-assembled closure has already dragged it in. That is the Class B pathology DESIGN's #6985 thread names, and its stated remedy is import-from-definer.How it surfaced
It stopped being latent on #7862, whose compile-clean refused 127 names in exactly these two files — 96
celland 31row, an exact match to their 96 and 31 usages, so every occurrence failed whileh2/h3/p/li/ul/quotefrom the same module resolved fine. Those two aremd_helpers' only helpers whose signatures mentionstd.markdown's table types.Why this lands separately from the PR that surfaced it
#7862 touches
claim_executor.rs, and a non-selectable.rspath forces compile-clean to the whole-tree baseline:Main pushes get the scoped path instead —
main@4f9112965ran396 affected entries (floor fast path)and passed without compiling these modules at all. Main's last whole-tree compile was1d17ae068, which predates #7824.So a whole-tree-only regression can merge to main and stay invisible until an unrelated PR happens to touch a
.rsfile. That exposure belongs to the gate, not to the PR that trips it, and this repair unblocks every.rs-touching PR rather than one. The scoped/whole-tree asymmetry is worth a separate look; it is the coverage-by-illusion tier DESIGN §6 describes.What is proven, and what is not
Proven by execution — both modules compile with
0 blocking error(s)after this change, and the import lists are exactly complete. Addingmd_helpersalone flips each module from ambient bare resolution to import-scoped visibility, which then refusesPlanandHasTrigger;gunbc.planis therefore imported too, after which nothing is left unresolved. That mode flip is why the fix is two imports and not one.Not proven — I could not reproduce the original refusal locally. Under an
--entryclosure both modules compile clean on main and on #7862's tree, so the refusal is closure-dependent and needs CI's whole-treewitness_layer_rootsclosure to appear. This change is therefore justified by mechanism, not by a local red-to-green: explicit imports make binding independent of pool composition, which is precisely the property whose absence produced the refusal.Attribution between #7824 and #7862 is not established here, and no claim about it is made. Three hypotheses were formed and refuted by execution rather than acted on: a colliding
rowbinder from #7862 (refuted — 158 files on main already use(row:, 44 userow =>);md_helpersabsent from the pool (refuted — itsMarkdownBlock-returning siblings resolve in the same files); and pre-existing breakage on main (refuted, then re-opened once main's clean whole-tree run turned out to predate #7824).Import sets match the sibling convention used verbatim by
ci_merge_freshness,ci_oom_reclassificationandemission_ingestion_inverse.