Skip to content

The fresh-host bootstrap gains its invoker: an absent tree is an ordinary Create - #10760

Merged
briansrls merged 1 commit into
mainfrom
fresh-host-invoke
Sep 7, 2026
Merged

briansrls merged 1 commit into
mainfrom
fresh-host-invoke

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

The capability had no invoker

#10722 built the Git-native bootstrap and proved it wet. #10724 made the publication member invoke that oneshot and nothing else. But the tree member still refused absence with RepositoryBootstrapUnavailable — a decision made before the transition could run — so a fresh host stayed undeployable.

That sequencing was deliberate: a fresh host must not depend on a capability introduced in the same change. This is the commit it was deferred to.

The absent arm needs no member special case

decide_member collapses to Create { member, to: desired } for every member. The tree is no longer singled out.

The refusal cause is deleted, not left unreachable

RepositoryBootstrapUnavailable read: "the repository root is absent and no bootstrap transition exists". That was true when written and is now false. A refusal cause whose message denies a capability shipping in the same tree is worse than dead code — the next author reads it as a standing limitation.

The wall did not disappear; it moved to where it can be checked

A fresh host is no longer refused at planning time on a stale claim. It is refused at execution time by the transition, on observation:

  • a non-empty root refuses with the original pre-state cause
  • checkout -b refuses an existing branch
  • an empty expected-old refuses an existing ref
  • the readback refuses a repository that is not at the candidate

Construction over declaration.

The stall climbs one rung, not two

deployed_repository_empty_root_bootstrap_stall: OutsideTheLadder → Mitigatable.

No longer outside the ladder — the operation has a route and it executes. Not MechanicallyPreventable, and the distinction is the enrolment of the evidence, not the quality of the wall: the wet witnesses perform host effects, so the hermetic floor refuses them at its boundary and counts them executed while they assert nothing. Reporting MechanicallyPreventable would cite a wall that does not run (§4b(1)). The next-rung trigger is now exactly that — enrol those two rows in a lane that executes them.

Evidence, split into two discriminating halves

witness claim
an_absent_repository_plans_the_tree_publication absence is a Create whose plan publishes
the_publication_member_emits_convergence_and_no_rsync the publishing plan's tree fragment carries the convergence invocation and its readback, and no rsync

The second is #10724's outstanding acceptance item: that the actuator reaches the transition, which is a different claim from the transition working.

A single end-to-end witness over a full-install plan would have passed for reasons neither half pins down — a wholesale install emits the same line whatever the observation was. The first arm reds if absence still refuses; the second reds if a bootstrap plans no publication, which is the fresh host that installs nothing and reports success.

The unit-name residue is recorded, not asserted away

The first draft of that witness also asserted gunbc-tree-sync.service is absent from the fragment. It is not — the convergence unit is still written to the tree-sync path, the §3 nickname #10724 declared as residue rather than repaired. Asserting its absence would assert a member-lifecycle migration that has not happened.

Verified on srv1

Apply closure resolves with zero diagnostics; member_identity 11/11; emit_test 59/59 plus the corrected actuator claim.

🤖 Generated with Claude Code

https://claude.ai/code/session_019iXPtAqzPaNBZbaaM5rxrY

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

…nary Create

#10722 built the Git-native bootstrap and proved it wet; #10724 made the publication member invoke
that oneshot and nothing else. But the tree member still refused absence with
RepositoryBootstrapUnavailable, so the decision was made BEFORE the transition could run and a fresh
host stayed undeployable. The capability had no invoker. That sequencing was deliberate -- a fresh
host must not depend on a capability introduced in the same change -- and this is the commit it was
deferred to.

THE ABSENT ARM NEEDS NO MEMBER SPECIAL CASE AT ALL now. decide_member collapses to
`Create { member, to: desired }` for every member; the tree is no longer singled out.

REPOSITORYBOOTSTRAPUNAVAILABLE IS DELETED, NOT LEFT UNREACHABLE, and the reason is what its text
said. It read: "the repository root is absent and no bootstrap transition exists". That sentence was
true when written and is now false. A refusal cause whose message denies a capability shipping in the
same tree is worse than dead code -- the next author reads it as a standing limitation.

THE WALL DID NOT DISAPPEAR, IT MOVED TO WHERE IT CAN BE CHECKED. A fresh host is no longer refused at
PLANNING time on a stale claim; it is refused at EXECUTION time by the transition, on observation: a
non-empty root refuses with the original pre-state cause, `checkout -b` refuses an existing branch, an
empty expected-old refuses an existing ref, and the readback refuses a repository that is not at the
candidate. Construction over declaration.

THE STALL CLIMBS ONE RUNG, NOT TWO. gunbc.guarantee_stall.deployed_repository_empty_root_bootstrap_stall
goes OutsideTheLadder -> Mitigatable. It is no longer outside the ladder: the operation has a route
and it executes. It is NOT MechanicallyPreventable, and the distinction is the enrolment of the
evidence rather than the quality of the wall -- the wet witnesses perform host effects, so the
hermetic floor refuses them at its boundary and counts them executed while they assert nothing.
Reporting MechanicallyPreventable would cite a wall that does not run (DESIGN 4b(1)). The next-rung
trigger is now exactly that: enrol those two rows in a lane that executes them.

EVIDENCE, and it is split into two discriminating halves rather than one end-to-end assertion:
  member_identity_witness an_absent_repository_plans_the_tree_publication
    -- absence is a Create whose plan publishes; a plan that still refused fails the first arm, and
       one that derived nothing for the tree fails the second, because a bootstrap planning no
       publication is the fresh host that installs nothing and reports success.
  emit_test the_publication_member_emits_convergence_and_no_rsync
    -- the publishing plan's tree fragment carries the convergence invocation and its readback, and
       no rsync. This is #10724's outstanding acceptance item: that the ACTUATOR reaches the
       transition, which is a different claim from the transition working.
A single end-to-end witness over a full-install plan would have passed for reasons neither half pins
down, because a wholesale install emits the same line whatever the observation was.

THE UNIT-NAME RESIDUE IS RECORDED, NOT ASSERTED AWAY. The first draft of that witness also asserted
`gunbc-tree-sync.service` is absent from the fragment. It is not: the convergence unit is still
WRITTEN TO the tree-sync path, the section 3 nickname #10724 declared as residue rather than repaired.
Asserting its absence would assert a member-lifecycle migration that has not happened.

Verified on srv1: apply closure resolves with zero diagnostics, member_identity 11/11, emit_test
59/59 plus the corrected actuator claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019iXPtAqzPaNBZbaaM5rxrY
@briansrls
briansrls merged commit 69f7fe8 into main Sep 7, 2026
4 checks passed
@briansrls
briansrls deleted the fresh-host-invoke branch September 7, 2026 19:24
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