Repository navigation
The GitHub ruleset stops being a web setting and becomes a converged .dag authority - #9404
Conversation
….dag authority DESIGN's Building & checks bullet states, as the fact the whole two-lane split turns on, that this repository's `passing CI` ruleset is active, carries no bypass actors, and names exactly ONE required status check -- `witnesses`. Until now that sentence was the only place the fact lived on our side of the boundary. Nothing declared it, nothing read it back, and nothing in the tree went red if it changed: specification without execution, at the outermost boundary the project has. `extdeps.github.rulesets` models the upstream interface -- rulesets, enforcement, targets, rule types, bypass standing, and the whole-ruleset PUT -- and nothing about what this repository wants. `gunbc.repo_ruleset` owns the policy and follows `gunbc.repo_local_git_config`'s binding pattern exactly: desired -> observe -> reconcile -> apply -> READ BACK -> verify, with convergence claimed only from the post-apply read and never from the apply's own 200. The §3 win is that the required context's name is IMPORTED from `gunbc.witness_floor_workflow` `witness_floor_workflow_job_id` -- the row the emitted workflow names its aggregation job with -- so renaming the job can no longer leave the ruleset naming a context nothing publishes, which is the failure that shows up as a check stuck pending rather than red. Every observation and verdict is typed rather than a Bool: three ways a read can fail (status refusal / transport refusal / undecodable body, never collapsed into an empty ruleset), three states for the status-check rule (absent / exactly these / more than one, so "no rule" and "no contexts" cannot render alike), and fourteen named divergences. Ownership is Owned rather than Ensured -- the opposite of repo_local_git_config's choice -- because "witnesses is the ONE required context" is a claim about the roster, so an extra context must plan a removal rather than be refused. EXECUTED, not typechecked. `verify` runs green against the live ruleset, and RED with a planted extra desired context (`required context missing: a-context-nothing-publishes`, exit 1). All ten witness bodies execute true, including a positive control that a desired-shaped observation diverges in nothing. `converge` was NOT executed: it writes to GitHub and the live ruleset already converges, so there was nothing to apply. NOT CLAIMED: neither entry point is enrolled in CI. `verify` is a route somebody runs, so the class climbs from unobservable to *mitigatable* -- drift is detectable, not detected. Enrolling it as a required phase is a separate change under its own operator agreement, and is named as this row's next-rung trigger. The DESIGN bullet and two notes in `gunbc.witness_floor_workflow` said the ruleset is not a `.dag` fact. It is one now, so those are corrected in place rather than left as knowingly-false recitals -- while keeping what did not change: a converged authority actuates and detects, it does not gate, so the aggregation job's window argument stands untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review 56496, and it is right. `bypass_divergences` matched `BypassNever`
and collapsed everything else into one `_` arm emitting a single static
sentence -- total over the type and blind one level down, the exact
pattern the rest of this module is written to avoid.
Three facts sat under that wildcard with three different remedies.
`pull_requests_only` and `always` are real, DIFFERENT bypass grants, and
which one it is decides which role to revoke. `UnrecognizedBypassStanding`
is not a permissive ruleset at all -- it means GitHub's vocabulary moved
and this module's reading is no longer established, whose remedy is to
extend the parser. Its `raw` payload was discarded, which is the only
thing that says what to extend the parser WITH.
So: `RulesetBypassStandingUnrecognized { raw }` is its own divergence, the
two grants are named arms carrying the observed label the way the
neighbouring `RulesetEnforcementDrift` / `RulesetTargetDrift` arms already
did, and `ruleset_bypass_standing_wire_label` lands beside the other
wire-label projections in extdeps rather than being spelled here.
MUTATION RECEIPT, because the existing witness did not catch this and it
is worth recording why. `w_RED_a_reader_that_may_bypass_is_a_divergence`
COUNTED divergences, and a wildcard defeats counting -- it stayed true
under both shapes. The new
`w_RED_the_three_non_never_bypass_standings_render_differently`
DISCRIMINATES: executed against the pre-fix collapsed form it returns
false, against the split form true. All 11 witness bodies execute true on
the fixed tree; live `verify` still exits 0 against the real ruleset.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Fixed in the pushed commit — review 56496 was right on every point.
One thing worth flagging beyond the fix: the existing witness did not catch this, and the reason is instructive. All 11 witness bodies execute true on the fixed tree; live |
…t to land #9404 merged at 13:15:42Z. The three files it added -- gunbc.repo_ruleset, extdeps.github.rulesets and the witness module -- are on main and are BYTE-IDENTICAL to this branch's copies. Because the merge was a squash, the branch kept its own two commits, which is the only reason GitHub renders a diff for #9449 at all. The real content delta ran the other way: main was 25 commits ahead, so was 125 files and 17,238 deletions -- src/v2/std/effect_reach.dag, src/v2/workflow/required_floor.dag, src/v2/std/text.dag and others. Merging that PR would have DELETED 25 commits of landed work from main. The conflict was the symptom; a rebase would have preserved the hazard rather than removing it. So this merge resolves every path to main. That is not picking a side over authority-derived bytes: main's content is a strict superset of this branch's here, since this branch's own contribution is already in it unchanged. The check is exact rather than argued -- the resulting tree is identical to origin/main, whole-tree, so #9449's diff is now empty and it can neither revert anything nor land anything. DESIGN.md reached the generated-artifact merge driver, which correctly REFUSED rather than answering true. Its regeneration recipe is the right remedy when both sides carry distinct authority-derived content; it does not apply when one side is a subset of the other and the result is proven equal to main byte-for-byte. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rect regeneration (#9456) * Prose authored into the generated artifact is deleted by the next correct regeneration DESIGN.md carried 1,295 bytes that no .dag authority produces. They were authored straight into the generated file by #9418 (the bound-shaped-closure failure mode, and two fragments of the emit-stage census receipt) and #9404 (the repo_ruleset boundary clause), so every correct regeneration deletes them. tidy-wolf-288's #9427 regenerated DESIGN.md during a conflict resolution and lost them; that run was correct and the loss was pre-existing on main. This is the third orphaned-prose incident in this session, which is what makes it a class rather than three accidents: the generated artifact is writable, so prose lands there instead of in the authority and survives only until someone regenerates. Rehomed each passage into the authority that owns it -- the failure-mode entry into gunbc.recurring_failure_mode as an ordinary roster row between positional_citation and authority_substitution, the two bullets into gunbc.design_document -- then regenerated. DESIGN.md now reproduces all three passages from source, and lines 147 and 151 come back byte-identical to what main had committed. Regenerating also exposed drift in the other direction, which is the more useful finding: the authorities already carried content main's generated files did not. gunbc.recurring_failure_mode's diagnostic_name_mechanism_silent entry (3,445 chars) had never reached DESIGN.md, three docs/plans files were stale against their authorities, and two were never committed at all. Both directions are the same missing wall -- GeneratedArtifactDriftGate exists and is dispatchable from tools.ci_gates, but has no production caller, so nothing compares the generated tree to what the authorities produce. Measured: zero tokens lost from DESIGN.md, zero deletions in the line-140 diff against main. The three token differences in two plan docs are authority rewrites main had not regenerated, not drops. This does not re-enroll the drift gate; that is a separate change under its own operator agreement, and until it lands the class stays at review diligence -- a fourth incident is writable today exactly as the first three were. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Do not commit a generated plan that renders another module's body review 56662 on #9456 found docs/plans/import-namespace-program.md carrying almost entirely the v2-corpus-self-host plan despite its own title and its own authority at gunbc.plans.import_namespace_program. Verified, and the finding is correct. The cause is not this change. Both plan modules declare the same ten bare module-scope names -- status_block and section_1 through section_9 -- and the resolver collapses same-named module-scope fns into one global slot, so import_namespace_program_body() calls section_N and reaches v2_corpus_self_host's definitions. Measured at identity grain: the import_namespace authority's own section_3 text ("3. The landing order, and why grammar is last") appears zero times in its rendered output, while v2_corpus_self_host's section_3 appears in both files. That is the defect #9393 repairs, and it is open. Until it lands, regenerating this path cannot produce a correct artifact, so the file is removed from this change rather than landed corrupt -- the same call as review 56457 on #9392, where sweeping unread projections into an unrelated repair was the error. docs/plans/v2-corpus-self-host.md is KEPT, and the distinction is measured rather than assumed: its rendered body contains its own authority's section_3, so it is the module the collapsed slot resolves to and its output is correct. Dropping it too would remove a correct artifact to look consistent. This leaves the tree not fully derived on one path, which is a real and stated gap: after #9393 lands, regenerating produces the correct import-namespace-program.md and it should be committed then. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Re-drop the corrupt generated plan the merge regeneration re-added review 56834 is correct and this is my defect. Commit dd04d3d deleted docs/plans/import-namespace-program.md because it renders gunbc.plans.v2_corpus_self_host's body under its own title. The merge in 4ad6197 regenerated every artifact via main_wet, which writes all 72 committed artifacts unconditionally, so the file came back and the merge silently reverted a deliberate deletion. Re-verified at identity grain rather than assumed: the file carries v2_corpus_self_host's section_3 text and ZERO occurrences of import_namespace_program's own section_3. Same corruption, same cause -- the bare-name collision #9393 repairs, where both plan modules declare status_block and section_1..section_9 and the collapsed global slot sends import_namespace_program_body() to the other module's definitions. WHAT I GOT WRONG, because the mechanism will repeat for anyone else: I treated regeneration as safe because it is derived, and a derived operation cannot know that one of its outputs is deliberately not committed. main_wet has no notion of an artifact under repair. So the deletion is not durable across a regeneration and must be re-applied after every one until #9393 lands. That is a property of this interim state, not of the gate. docs/plans/v2-corpus-self-host.md stays: it is the module the collapsed slot resolves to, its rendered body contains its own authority's section_3, and dropping a correct artifact to look symmetrical would remove real content. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Regenerate the projection that #9393 made materializable `docs/plans/import-namespace-program.md` was emitted carrying `v2-corpus-self-host`'s entire body — the bare-name collision #9393 repaired. Reviews 56662 and 56834 required it be deleted rather than committed corrupt, which left the drift gate legitimately refusing on this branch for an absent expected artifact. With #9393 on main the projection materializes through the repaired route, so the file is regenerated and committed. It is the only artifact whose bytes changed: the other 71 regenerate byte-identical. Evidence it took the repaired route, not merely that the file exists: size 15996 -> 10852 bytes (15996 was v2-corpus-self-host's 15974, which is what the collision was) headings "Plan — the import/namespace program" + its own 7 sections; zero overlap with v2-corpus-self-host's first 400B distinct digest from v2-corpus-self-host Acceptance, all executed against the composed tree: regeneration is idempotent 0 of 76 artifacts differ across two passes read-only gate 0 findings, 76 artifacts read discriminating RED perturbing DESIGN.md makes the gate refuse, so the green is not vacuous; restored byte-identical afterwards Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop two plan markdowns their carriers forbid (review 57000) `gunbc.plans.import_namespace_program` and `gunbc.plans.v2_corpus_self_host` both declare `projection: PlanIsAuthorityOnly`. Neither markdown exists on main. This PR was adding both. Deleted, not regenerated — the .dag carriers already own the prose. WHY IT HAPPENED, since the timing is the whole of it and it was not a regenerator defect: 22:23:43Z I regenerate. The carrier then said EMIT, and main_wet correctly wrote docs/plans/import-namespace-program.md. 22:46:26Z #9415 lands PlanIsAuthorityOnly for both carriers, in the same change that enrols the generated-artifact phase. later I merge main. The post-merge regeneration correctly writes NEITHER file — main_wet honours the ruling. But `git add -A` preserved the leftovers from the pre-ruling pass. So the work was right when done and the base moved under it. The regenerator is not at fault and needs no change. The review's deeper point is the one worth recording. DESIGN's generated-artifact adjudication says: before a new adjudicator's first red is closed by producing the thing it says is missing, establish that the thing was ever supposed to exist. The gate's red here was ABSENT, not DRIFTED, and I closed it by producing the file — the exact move that paragraph forbids. I merged that sentence into DESIGN.md myself while resolving the CI-row conflict and did not apply it to my own diff. Verified after deletion: drift gate exit 0, 0 refusals main neither path present, so the diff no longer adds them Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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>
DESIGN's Building & checks bullet states, as the fact the whole two-lane
split turns on, that this repository's
passing CIruleset is active,carries no bypass actors, and names exactly ONE required status check --
witnesses. Until now that sentence was the only place the fact lived onour side of the boundary. Nothing declared it, nothing read it back, and
nothing in the tree went red if it changed: specification without
execution, at the outermost boundary the project has.
extdeps.github.rulesetsmodels the upstream interface -- rulesets,enforcement, targets, rule types, bypass standing, and the whole-ruleset
PUT -- and nothing about what this repository wants.
gunbc.repo_rulesetowns the policy and follows
gunbc.repo_local_git_config's bindingpattern exactly: desired -> observe -> reconcile -> apply -> READ BACK ->
verify, with convergence claimed only from the post-apply read and never
from the apply's own 200.
The §3 win is that the required context's name is IMPORTED from
gunbc.witness_floor_workflowwitness_floor_workflow_job_id-- the rowthe emitted workflow names its aggregation job with -- so renaming the job
can no longer leave the ruleset naming a context nothing publishes, which
is the failure that shows up as a check stuck pending rather than red.
Every observation and verdict is typed rather than a Bool: three ways a
read can fail (status refusal / transport refusal / undecodable body,
never collapsed into an empty ruleset), three states for the status-check
rule (absent / exactly these / more than one, so "no rule" and "no
contexts" cannot render alike), and fourteen named divergences.
Ownership is Owned rather than Ensured -- the opposite of
repo_local_git_config's choice -- because "witnesses is the ONE required
context" is a claim about the roster, so an extra context must plan a
removal rather than be refused.
EXECUTED, not typechecked.
verifyruns green against the live ruleset,and RED with a planted extra desired context (
required context missing: a-context-nothing-publishes, exit 1). All ten witness bodies executetrue, including a positive control that a desired-shaped observation
diverges in nothing.
convergewas NOT executed: it writes to GitHub andthe live ruleset already converges, so there was nothing to apply.
NOT CLAIMED: neither entry point is enrolled in CI.
verifyis a routesomebody runs, so the class climbs from unobservable to mitigatable --
drift is detectable, not detected. Enrolling it as a required phase is a
separate change under its own operator agreement, and is named as this
row's next-rung trigger.
The DESIGN bullet and two notes in
gunbc.witness_floor_workflowsaidthe ruleset is not a
.dagfact. It is one now, so those are corrected inplace rather than left as knowingly-false recitals -- while keeping what
did not change: a converged authority actuates and detects, it does not
gate, so the aggregation job's window argument stands untouched.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com