Skip to content

The GitHub ruleset stops being a web setting and becomes a converged .dag authority - #9404

Merged
briansrls merged 2 commits into
mainfrom
session/wise-swift-875
Aug 27, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/wise-swift-875

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

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

gunbc-ci-auto-heal and others added 2 commits August 27, 2026 04:29
….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>
@gunbai-bot

gunbai-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in the pushed commit — review 56496 was right on every point.

bypass_divergences now has four named arms, no wildcard: BypassNever → no divergence; BypassPullRequestsOnly and BypassAlways each emit RulesetBypassGranted carrying the observed label (via a new ruleset_bypass_standing_wire_label in extdeps, beside the other wire-label projections, rather than spelled in the policy module); and UnrecognizedBypassStanding { raw } gets its own divergence variant RulesetBypassStandingUnrecognized { raw }, so "the read is no longer established" is never reported as "a bypass role was granted" — different rung, different remedy, and the raw is what says what to extend the parser with.

One thing worth flagging beyond the fix: the existing witness did not catch this, and the reason is instructive. w_RED_a_reader_that_may_bypass_is_a_divergence counted divergences, and counting is exactly what a wildcard defeats — it returned true under both shapes. The new w_RED_the_three_non_never_bypass_standings_render_differently discriminates instead, and I ran it against both: false against the pre-fix collapsed form, true against the split. So the finding is now covered by an assertion that actually flips, not just by the repair.

All 11 witness bodies execute true on the fixed tree; live verify still exits 0 against the real ruleset.

@briansrls
briansrls merged commit efc0925 into main Aug 27, 2026
3 checks passed
@briansrls
briansrls deleted the session/wise-swift-875 branch August 27, 2026 13:15
@briansrls
briansrls restored the session/wise-swift-875 branch August 27, 2026 13:24
gunbai-bot Bot pushed a commit that referenced this pull request Aug 27, 2026
…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>
briansrls pushed a commit that referenced this pull request Aug 27, 2026
…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>
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