Skip to content

The drift remedy told operators to run the one operation another module blocks - #8787

Merged
briansrls merged 2 commits into
mainfrom
session/nimble-fox-671-drift-remedy
Aug 21, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/nimble-fox-671-drift-remedy

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

The operator-facing remedy named an operation another module blocks

converge_cli_revision_reason rendered, to a human:

gunbc converge: revision drift — desired <D>, local tree at <L>; tree-sync is the catch-up realization

gunbc.live_deploy.deployed_tree_report blocks exactly that operation, and states why:

A tree-only publication is BLOCKED: it moves the deployed HEAD to the admitted revision and
thereby flips roadmap_belt_actuate belt_revision_admission from refusing to admitting while
the installed binary is still the old one, so the belt's next tick dispatches a mixed
realization that was never admitted as a release.

So two authorities disagreed about one operation, and the operator-facing one pointed at the unsafe
half. An operator following this line flips the belt gate to admitting on a host whose binary is
still stale.

Why it survived, which is the part worth keeping

The typed verdict was correct the entire time. RevisionDrifted { desired, local } is right,
its consumers are right, the belt's refusal is right. Nothing that reads the verdict was wrong —
only the sentence a human acts on.

And converge_cli_revision_reason had no witness at all, so there was nothing to go red when
the remedy it named was superseded elsewhere in the corpus. A correct verdict with a stale
human-facing remedy is invisible to every check that reads the verdict.

What changed

  • The rendered remedy becomes full host-release publication is required — tree-only synchronization is NOT convergence.
  • The joint-verdict annotation carried the same superseded claim and is corrected. Its surviving
    half is untouched and is load-bearing: the catch-up's safe form is a compare-and-swap and so
    needs the prior, which is why the drifted arm carries both operands.
  • Two witnesses the function never had.

Evidence

witness_converge_cli_drift_reason_does_not_prescribe_tree_only_sync  => PASS
witness_converge_cli_converged_standing_offers_no_remedy             => PASS

RED CONTROL (superseded string replanted):
witness_converge_cli_drift_reason_does_not_prescribe_tree_only_sync  => FAIL
witness_converge_cli_converged_standing_offers_no_remedy             => PASS   <-- stays green

The pair is discriminating rather than fragile: the plant takes the drift claim red while the
converged claim is unmoved, so the witnesses detect this regression and not merely any edit to
the function. The plant asserts its own pattern is present before rewriting, so a no-op'd edit
cannot masquerade as a control.

The converged arm's claim is not filler — a remedy offered to an operator who has nothing to
remedy is its own defect, and it is the arm most likely to acquire one by accident.

Scope

Does not touch the actuator question, the belt gate, or any decision logic. This is the rendered
sentence and its missing coverage. Held as draft while main is red on #8726's .keys() sweep
(#8784 owns that); flipping to ready once main is green.

…le blocks

`converge_cli_revision_reason` rendered, to a human, "tree-sync is the catch-up realization".
`gunbc.live_deploy.deployed_tree_report` BLOCKS exactly that operation, and says why: a
tree-only publication moves the deployed HEAD to the admitted revision and thereby flips
`roadmap_belt_actuate` `belt_revision_admission` from refusing to ADMITTING while the
installed binary is still the old one, so the belt's next tick dispatches a mixed
realization that was never admitted as a release.

So two authorities disagreed about one operation and the operator-facing one pointed at the
unsafe half. The typed verdict was correct the entire time, which is exactly why this
survived: no consumer of the VERDICT was wrong, only the sentence a human acts on -- and
`converge_cli_revision_reason` HAD NO WITNESS AT ALL, so nothing could go red when the
remedy it names was superseded.

Corrected at both sites. The annotation at the joint-verdict note carried the same claim;
its surviving half -- that the catch-up's safe form is a compare-and-swap and therefore needs
the prior, which is WHY the drifted arm carries both operands -- is untouched and is the
reason that arm's shape is right.

Two witnesses, discriminating as a pair:
  - the drifted arm must say full host-release publication is required, must NOT say
    tree-sync is the catch-up, and must name both revisions
  - the converged arm must stay SILENT -- a remedy offered to an operator with nothing to
    remedy is its own defect

RED CONTROL: replanting the superseded string takes the drift witness FAIL while the
converged witness stays PASS. The pair therefore detects this specific regression rather than
being fragile to any edit of the function.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title srv1 daily workspace still doesn't work at all The drift remedy told operators to run the one operation another module blocks Aug 21, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 21, 2026 17:55
…e merge-readiness (main advanced 10 commits since CI)
@briansrls
briansrls merged commit 9c78c68 into main Aug 21, 2026
1 check passed
@briansrls
briansrls deleted the session/nimble-fox-671-drift-remedy branch August 21, 2026 21:43
briansrls pushed a commit that referenced this pull request Aug 21, 2026
briansrls pushed a commit that referenced this pull request Aug 22, 2026
…witness its wording (#8839)

* Give the admission refusal a consumer: extract the reason, witness the wording

WHY THIS EXISTS. The operator-facing refusal string outran its mechanism TWICE and
execution caught neither time. It first said the run could not record "which code
adjudicated" the advance (#8797 narrowed it), then "which source this run was running
from" (#8831 narrowed that), and both invite the reader to infer the provenance of the
EXECUTING BINARY. The mechanism establishes only that the admission checkout's HEAD was
read after the action was derived and before it was materialized; no binary embeds its own
source revision.

Both narrowings were correct and both were caught by REVIEW, because a reason string built
inline at its throw site has no consumer. Nothing in the corpus could go red for it. That
is specification-without-execution in the place it is easiest to miss -- the typed decision
stays right while the sentence beside it drifts -- and it is the same class #8787 landed
for: a correct refusal coexisting indefinitely with misleading operator prose. Raised in
post-merge side-chat review of #8831.

WHAT CHANGES. `fleet_desired_unobservable_judge_source_refusal_reason` is extracted as a
pure formatter and the wet entry point calls it, so the wording becomes a SUBJECT a claim
can fail on rather than a literal buried in an exit path. The text is also narrowed one
final step -- it now names the missing receipt field (`judge-source-observed`) and says
"could not be observed after adjudication", which states the missing observation without
inviting the binary-provenance inference.

Behavior is unchanged: same arm, same typed refusal, same exit.

WHY A WITNESS AND NOT A GREP. The new annotation QUOTES both retired phrasings to record
why they were wrong, so a grep over the file would false-positive on the explanation of
the defect. The witnesses read the function's RETURN VALUE, so the prose and the claim
cannot collide.

EVIDENCE (green plus the discriminating red the reviewer specified, both executed):
  green  28/28 PASS, 0 FAIL, 0 verdictless, 28 enrolled
  red    restored the exact pre-#8831 wording:
           FAIL the_unobservable_judge_source_refusal_names_the_field_it_could_not_record
           FAIL the_unobservable_judge_source_refusal_claims_no_binary_provenance
           PASS the_advance_receipt_names_the_observed_judge_source_revision
         The untouched advance row holding green proves the two new rows fail for the
         wording rather than because the module stopped resolving.

Presence before absence on the second row, for the reason the distinctness row upstream
already carries it: three bare negations are satisfied by an empty or deleted string, so
the positive conjunct pins the subject the negations must be true OF.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Attach the annotations to their own declarations again

The formatter was inserted by anchoring on the `fn fleet_desired_authorized_action_script`
line, which placed it AFTER that renderer's existing annotation. Under Sec 4c module-item
grain a contiguous `//` run attaches to the NEXT declaration, so the two blocks merged into
one and bound to the formatter: it acquired the CAS wire-word, no-op-arm and NonEmptyStr
rationale that describes the renderer, and the renderer -- the subject all of that prose is
actually about -- was left with none.

The grain was VALID the whole time, which is why the frontend check I ran reported zero
`source annotation` diagnostics and why I read that as clean. Syntactic attachment and
correct attachment are different properties, and only the first is decidable at parse. An
annotation on the wrong subject is worse than a missing one: it reads as authoritative
rationale for a declaration it was never written about. Caught by review, not execution.

Repair is placement only -- the formatter and its annotation move above the renderer's
block, restoring the adjacency that existed before the insertion. No text edited, no
behavior touched.

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