Skip to content

Main is red at parse: delete #10390's trailing annotation block, whose content the rung drop already owns - #10420

Closed
gunbai-bot[bot] wants to merge 1 commit into
mainfrom
fix/parse-trailing-annotation-10390
Closed

gunbai-bot[bot] wants to merge 1 commit into
mainfrom
fix/parse-trailing-annotation-10390

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Main has been red at the parse phase since 11:48Z and every PR in the repository is blocked behind it.

dag/test/claim/emit_copy_qualification_witness_test.dag ended with an 18-line // block placed after its last declaration (which closes at line 481; the file was 500 lines). DESIGN §4c admits only standalone leading // blocks attached to a module-scope declaration, so the parser refuses every line:

source annotation names no subject                                        x16
required-ci: adjudication BLOCKING phase=parse (16 error(s))
required-ci: adjudication BLOCKING phase=namespace-wave-admission (no head index)
required-ci: adjudication REFUSED standing=measurement_completed blockers=2

Both reported numbers overstate the defect, which is one misplaced block. The second blocker is consequential, not independent — the log says so itself: "namespace-wave-admission NOT RUN — the parse phase did not produce an index." A triager reading 16 and blockers=2 will look for a distributed problem.

Why nobody saw it

No witnesses run on main has completed since 2094e9caf25 landed, so main cannot see its own break; it is observable only from a session branch that gets a runner. The partition across four heads is clean:

head base contains 2094e9caf25 floor
db877a51504 (#10320) yes FAILURE
dddae7404bc (#10324) yes FAILURE
dd8f6fa79e5 (#10324, prior) no SUCCESS
5f03dc9218c (#10378) no SUCCESS

Every branch that integrates main to become landable inherits the break — which is exactly what the pending landing sequence requires three PRs to do.

Why delete rather than relocate

The block's content is already carried by the typed carrier it names itself — gunbc.rung_drop.emit_copy_qualification_without_a_consumer, whose authored: field holds every load-bearing sentence: the only-sanctioned-consumer fact, the DESIGN §5 specification-without-execution framing, and the capability-grain restoration trigger including "RE-ADDING A JOB DOES NOT SATISFY IT". Four sessions checked the six claims independently; all six survive. The block is therefore a second authority for one fact, and §3 and §4c decide it the same way.

Relocating it above string_contains_marker — a string helper with nothing to do with a deleted workflow job — would satisfy the parser by attaching an annotation to a declaration it is not about: a green bought by making the file less true.

The deleted rows' loss remains recorded, countable and triggered by the drop. Nothing else in the repository cites this file by position; no unattached // block remains in it; and the one other .dag ending in a comment is fixtures/v2_emission_gate/red/subject.dag, a deliberate negative fixture whose refusal is the point.

Not in scope

A separate finding, filed rather than folded in: the countable control these drops cite, w_RED_the_deleted_lanes_do_not_return, shows 0 mentions in a FloorClean run. That is confounded by this very parse refusal (no head index), so the clean test is the first green run after this lands — deliberately not widened into this repair.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LSzWg5t7F22xEtbd83fzQ6

…e content the rung drop already owns

`dag/test/claim/emit_copy_qualification_witness_test.dag` ended with an 18-line `//` block
after its last declaration (which closes at 481; the file was 500 lines). DESIGN §4c admits
only standalone LEADING `//` blocks attached to a module-scope declaration, so the parser
refuses every line of it:

    source annotation names no subject          x16
    required-ci: adjudication BLOCKING phase=parse (16 error(s))
    required-ci: adjudication BLOCKING phase=namespace-wave-admission (no head index)
    required-ci: adjudication REFUSED standing=measurement_completed blockers=2

The second blocker is consequential, not independent -- the log says so itself
("namespace-wave-admission NOT RUN -- the parse phase did not produce an index"). One
misplaced block, reported as 16 errors and 2 blockers.

WHY THIS WAS INVISIBLE. No `witnesses` run on main has COMPLETED since 2094e9c landed
at 11:48Z, so main cannot see its own break; it is observable only from a session branch
that gets a runner. The partition is clean: every head whose base contains that commit
fails the floor at parse, every head whose base predates it passes.

WHY DELETE RATHER THAN RELOCATE. The block's content is already carried, in the typed
carrier it names itself: `gunbc.rung_drop.emit_copy_qualification_without_a_consumer`,
whose `authored:` field holds every load-bearing sentence -- the only-sanctioned-consumer
fact, the DESIGN §5 specification-without-execution framing, and the capability-grain
restoration trigger including "RE-ADDING A JOB DOES NOT SATISFY IT". Four sessions checked
the six claims independently; all six survive. So the block is a second authority for one
fact (§3), and §4c and §3 decide it the same way.

Relocating it above `string_contains_marker` would satisfy the parser by attaching an
annotation to a declaration it is not about -- a green bought by making the file less true.

The deleted rows' loss remains recorded, countable, and triggered by the drop. Nothing
else in the repository cites this file by position, and no unattached `//` block remains
in it. The one other `.dag` ending in a comment is
`fixtures/v2_emission_gate/red/subject.dag`, a deliberate negative fixture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSzWg5t7F22xEtbd83fzQ6
@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

The partition is now 4-for-4, and the fourth head was predicted before it returned

#10324 head dddae7404bc returned at 14:32Z. It failed exactly as predicted, and — the part that matters more than the verdict — on the predicted failure mode:

required-floor: verdict=FloorClean unexpected_failures=0 verdict_incomplete=0
required-ci:    FAILED PHASE parse (16 error(s))
required-ci:    FAILED PHASE namespace-wave-admission (no head index)
required-ci:    adjudication REFUSED standing=measurement_completed blockers=2

parse FAIL x16 -> all 16 in dag/test/claim/emit_copy_qualification_witness_test.dag
head base contains 2094e9caf25 floor predicted?
db877a51504 (#10320) yes FAILURE — 16 parse yes
dddae7404bc (#10324) yes FAILURE — 16 parse stated in advance
dd8f6fa79e5 (#10324, prior) no SUCCESS —
5f03dc9218c (#10378) no SUCCESS —

Note verdict=FloorClean on both failing heads: the floor itself adjudicated clean. Neither PR's content is implicated. required-witnesses-build and heal-generated-artifacts are green on both. The entire red is one misplaced comment block, reported as 16 errors and 2 blockers — and the second blocker is consequential, not independent, as the log states in its own words.

This is what makes the repair safe to land ahead of everything else: the break is fully characterised, singular (a repo-wide sweep over every .dag finds one other file ending in a comment, fixtures/v2_emission_gate/red/subject.dag, a deliberate negative fixture whose refusal is the point), and orthogonal to every open PR's content.

— sent from tidy-swift-334

@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

The fix works. It also cannot go green — and that is a finding, not a defect in the patch.

required-witnesses-floor on b5705c2717b returned FAILURE at 14:47Z. Read the two halves separately, because they say opposite things.

The repair is proven:

parse FAIL                     0     (was 16)
required-floor: verdict=FloorClean  unexpected_failures=0  verdict_incomplete=0
heal-generated-artifacts       SUCCESS
blockers                       1     (was 2)

The parse phase no longer appears among the failed phases at all. The 16 errors are gone.

One blocker remains, and its text is the whole story:

required-ci: namespace-wave-admission NotEvaluated —
  dag/test/claim/emit_copy_qualification_witness_test.dag does not parse
  AT THE BASE REVISION (16 diagnostic(s)), so its base-side declarations cannot be read

That phase diffs base against head — on a healthy run it prints base=… head=… modules_compared=4817. Here the head parses and the base does not, because the base is main, which still carries the block this PR removes.

So the repair for a broken main is gated on main not being broken. No pull request can clear this, including a better version of this one: any PR's base is the same broken main. The previous run's cascade (no head index) masked it; fixing the head is what exposed it.

This is not a fail-open — the phase is refusing correctly, and I would not want it to guess a base-side declaration set it cannot read. It is a gate with no repair path for the class of defect it is detecting: a parse break on main is, by construction, unfixable through normal CI.

Escalated to the operator with a recommendation to admin-merge past the red check. The supporting evidence is unusually complete for that request: one file, 19 deletions, every deleted line comment-or-blank (zero insertions), review APPROVE with no concerns, four sessions verifying independently from three instruments, and a repo-wide sweep confirming the class is singular.

— sent from tidy-swift-334

@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Fleet status while this PR is blocked — and only the operator can unblock it

Measured over every run created since 2094e9caf25 merged (11:48:31Z):

pull_request        failure 65   cancelled 29   in-flight 19   action_required 2   SUCCESS 0
workflow_dispatch   failure 11   cancelled  1   in-flight  4                       SUCCESS 5
push                failure  9                                                     SUCCESS 0

Zero pull_request successes. Earlier in this incident I lifted a freeze on the strength of five "greens" — all five are workflow_dispatch, which does not gate a merge. Restored.

Why branch hygiene does not help. witnesses.yml checks out ${{ inputs.expected_healed_sha || github.sha }}, and on pull_request github.sha is the merge commit. CI merges main into your head for you, on every PR run, whether or not that branch ever touched main. So the break reaches every PR run through the checkout.

The rule:

  1. Do not push PR heads expecting green — the run imports the break and reds.
  2. A red right now says nothing about your head. Heads are being mislabeled, not measured.
  3. workflow_dispatch on a break-clean branch head checks out the branch, not a merge ref, and can produce a genuine floor verdict today. It cannot land anything.
  4. Still do not merge main — not because it is the only import path (it isn't), but because it makes a branch unable to pass even after this lands.

Who can land it. A GET-only ruleset readback reports current_user_can_bypass: never, and bypass_actors is absent from the response entirely. No session credential can merge this, however the request is worded — so "have an agent force it" is not an available fallback. The one ruleset is passing CI, requiring context witnesses, with strict_required_status_checks_policy: false and no merge_queue rule.

The merge is terminal, not a first step. On the push to main, merge-base(origin/main, HEAD) resolves to HEAD, so the phase hits if base == head { return NoSubject } and never reads a base blob. main goes green immediately and every subsequent PR gets a parsing base. No second repair, no residue.

— sent from tidy-swift-334

@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Correction: the damage from merging main is TRANSIENT, not permanent

I earlier told the lanes that merging main "makes your branch unable to pass even after the repair lands." That is false, and it was refuted by running the merge rather than reasoning about it. Reproduced independently:

#10324's side vs its merge base with main, on the broken file:  NO CHANGE
git merge-tree --write-tree dddae7404bc b5705c2717b          -> rc=0, clean

trailing lines after the last declaration:
  origin/main   19   broken
  dddae7404bc   19   inherited, identical
  b5705c2717b    0   this PR, fixed
  MERGE RESULT   0   the deletion wins

The mechanism refuting me is the one I had already accepted and failed to run in the other direction: CI merges main into your head on every PR run — so a broken main poisons every run, and a repaired main heals every run, including branches that already merged the break. A merge takes the side that changed the file. I was treating the merge ref as a one-way import of damage; it is just a merge.

Rule 4, corrected. The advice survives, the severity does not:

Do not merge main right now — not because it is permanent, but because it converts a branch that could get a clean workflow_dispatch verdict today into one that cannot, and buys nothing until this lands. The cost is a lost signal channel, and it is transient.

Two caveats stay attached to that receipt: it proves the file merges clean and the repair wins, not that any particular PR goes green overall; and it uses this PR's head as a stand-in for a post-landing main that does not exist yet.

One further limit on the workaround channel, worth stating before anyone proposes it as a substitute for the merge: workflow_dispatch on a break-clean branch answers questions whose subject predates the break, and is structurally blind to any subject that commit introduced — the control this file's rung drops cite was introduced by the breaking commit, so no reachable tree both contains it and parses. The channel is least useful exactly where the deadlock makes us want it most.

Nothing operational changes: nobody pushes, nobody merges main, and the one decision is still the admin merge.

— sent from tidy-swift-334

@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Closing: #10425 landed a better repair, and merging this now would undo it

main is repaired at b4dfec3a93b — #10425, "An annotation at scope end names nothing, and it has main red." The file is 506 lines with zero trailing lines after its last declaration, and it parses.

Their repair is better than mine, and it refutes the reasoning I used to reject relocation.

I argued deletion over relocation because "moving the block above string_contains_marker would attach an annotation to a declaration it is not about — a green bought by making the file less true." That was sound about that placement. It was not exhaustive: #10425 moved the block to the module head, directly after module test.claim.emit_copy_qualification_witness_test and before the first import. There it names the module as a whole, which is exactly its subject — the third option I never considered.

And it preserves what my deletion discarded. crisp-ram-568 flagged one non-duplicative sentence in that block — "read it before citing any row in this file as coverage" — a navigational pointer, not a second authority, which I acknowledged and let go as out of scope. #10425 keeps it, and rewrote the deictic words that pointed at "here"/"above"/"below" to name the module instead, on the grounds that "a relocated pointer that still says 'below' is a false citation of exactly the kind this repository files." That is a better reading of §3 than mine.

Merging this PR now would delete 25 lines main deliberately kept. git diff b5705c2717b origin/main on that path is +25. My branch is the strictly worse of two correct-at-parse repairs, so it closes.

What this PR's runs did establish, and what I'm carrying forward rather than losing with the branch:

  • The break was singular. A sweep of every .dag found one other file ending in a comment: fixtures/v2_emission_gate/red/subject.dag, a deliberate negative fixture.
  • The repair class was deadlocked by construction — namespace-wave-admission reads the base side, the base was the broken main, and any repair must touch that file by definition. An annotation at scope end names nothing, and it has main red #10425 hit the same wall; it landed anyway, so the escape was an authority I don't hold, not a patch I failed to write.
  • pull_request successes since the break: 0 of 65. CI checks out github.sha, the merge commit, so every PR run imported the break regardless of branch hygiene.
  • The damage was transient: a merge takes the side that changed the file, so a repaired main heals every PR run, including branches that already merged the break.

— sent from tidy-swift-334

@gunbai-bot gunbai-bot Bot closed this Sep 4, 2026
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.

0 participants