Skip to content

Derive the private-material ignore rows from repository visibility - #11306

Merged
gunbai-bot[bot] merged 25 commits into
mainfrom
session/vivid-stag-90
Sep 15, 2026
Merged

gunbai-bot[bot] merged 25 commits into
mainfrom
session/vivid-stag-90

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

What this is

A directory named private_overlay/, base_overlay/, wb62_overlay/ or privdag/ placed inside a public gunbc session worktree stages full file content on git add -A with no warning; a nested clone at private_repo/ stages a gitlink. The tracked .gitignore had no entry for any of them — protection so far was per-session .git/info/exclude local excludes, absent in a fresh clone and invisible until after a push.

The privacy fact has one home, and the ignore rows are derived from it. An earlier head of this branch declared an ignore reason ForeignPrivateMaterial { owner_repository: String } and authored five rows under it. That was a second, nicknamed representation of a visibility the corpus already models, and it is gone.

The six namespace admission rows, and why they are admissible (v1_seed_standing)

Moving RepositoryVisibility, PublicRepository and PrivateRepository to their resource module is a relocation the namespace wave adjudicates, so the required run refused with six unadjudicated TargetChanged deltas — three sites in extdeps.github.actions_token, three in test.claim.actions_job_grant_witness, every one of them base {extdeps.github.actions_token} -> head {extdeps.github.repository}. That is the wall working: gunbc.namespace_wave_admission states its rows exist for exactly this motion, "a spelling authored on both sides now resolves to a different module". The membership half was auto-admitted as ExplicitlyEvaluatedZeroDelta. hosted_runners produces no row — its arms were spelled PublicRepo/PrivateRepo, so they are new names at the head rather than rebinds.

The remedy is a row per delta, by exact identity, in NAMESPACE_TRANSITION_ADMISSIONS.

The admission, stated rather than left to inference. These six rows are admitted under gunbc.v1_maintenance_standing v1_seed_standing as consumed ledger entries, not a new escape hatch: they are DATA on an already-rostered declaration and add no function, no type, and no admission mechanism — the same standing the module's own justification records for the 53 such rows in PR 9436. They adjudicate one measured delta each, by exact identity, and are consumed by this PR's merge.

Deletion follow-up: #11316, authored before this PR was enqueued. Its trigger fires when this merges — base and head then both carry the relocation, the deltas stop being producible, and the rows report stale. Per the standing ruling it lands after this PR. Authoring it first is the condition that distinguishes a consumed ledger entry from an exemption, and it is why this change did not take the cheaper route of leaving the two forked spellings in place to avoid producing a delta at all — that would have been DESIGN §5's workaround, routing around the substrate rather than using it.

Where each fact lives now

  • extdeps.github.repository (new) — ONE RepositoryVisibility, cited to the visibility field of GitHub's repository object. It was forked: extdeps.github.actions_token declared RepositoryVisibility = PublicRepository | PrivateRepository for the fork-token rule and extdeps.github.hosted_runners declared RepoVisibility = PublicRepo | PrivateRepo for the runner hardware tables — one concept, two spellings, free to disagree. Both import this type now, as do gunbc.runner_provider_survey and test.claim.actions_job_grant_witness.

  • gunbc.repository — gunb-ai/gunbc and gunb-ai/gunbc-private as typed Repository rows. This is the single instance authority and it already owned the public one; the private row is new (nothing carried it) and its fields were read from the GitHub repository object, not assumed — full_name, private, default_branch = gunb-ai/gunbc-private, true, main. If either is flipped at the forge, this is the row to change and the projection follows. extdeps.github.repository repository_visibility maps the API's boolean alias to the typed coproduct, so "not world-readable" is asked of one row in one place.

    An earlier head of this branch authored a second instance row in gunbc.repo_identity — a sixth spelling of a fact gunbc.repository already owned, in a PR whose thesis is de-forking. That fork is deleted, along with the RepositoryVisibilityStanding type it needed; gunbc.repo_identity is back to its own subject (merge target and default branch).

  • gunbc.workspace_repository_materialisation (new) — the compose contract: which repository is materialised under which prefix by which method. The staged shape is derived from the method (NestedClone → gitlink, FileCopy → full content) rather than authored beside it, because a row carrying both could declare a clone that stages full content, which no git does. The private half of the contract — the private repository's strategy.private_witness_workflow overlay_local_method — is cited by name and deliberately not imported.

  • gunbc.gitignore_emit — DERIVES one ignore row per materialisation whose source repository is not world-readable, with the comment text derived from that visibility. No reason is authored per row. A new overlay spelling is a compose row over there and its ignore row appears here by construction.

  • std.workspace_artifact and gunbc.repo_workspace — byte-identical to main; the whole authored-arm approach is reverted.

Evidence

Six witnesses PASS in test.claim.gitignore_gate (claim_batch --entry dag/test/claim/gitignore_gate_test.dag):

PASS witness_private_material_rows_are_derived
PASS witness_public_source_derives_no_ignore_row
PASS witness_private_material_paths_are_ignored
PASS witness_clean_does_not_drift
PASS witness_gitignore_gate_drift_receipt
PASS witness_has_header

The derivation is witnessed in both directions, because a filter that always passes and a filter that never fires emit the same green: over a mixed list, untracked_materialisations keeps exactly the private-sourced row, materialisation_must_not_be_tracked is false for the public-sourced one, and public_overlay_probe/ never reaches .gitignore. The negative on the other axis is kept too — dag/gunbc/private_direction_note.dag must stay un-ignored, so this is not a substring sweep.

A stronger control, since the witnesses share the emitter they test. Flipping gunbc_private_repository to PublicRepository and re-running the emitter:

$ gunbc run … --entry dag/gunbc/gitignore_emit.dag --function expected_gitignore \
    | grep -c '^private_repo/\|^private_overlay/\|^privdag/'
0        # visibility flipped to PublicRepository
3        # restored to PrivateRepository

One row flip removes every derived pattern. The rows follow the visibility fact rather than standing beside it.

Measurement — before and after, throwaway repo

Re-measured against the current head, so the receipt matches the bytes the PR actually carries. One scratch repo per side: five compose directories populated, a symlink at a materialisation prefix, and a nested fixtures/private_overlay/ path that no row claims.

Before (.gitignore as it stands on the merge base):

$ git add -A && git ls-files --stage
100644 d0584c4f3251… 0	.gitignore
100644 e97e9c7e8160… 0	base_overlay/dag/x.dag
100644 e97e9c7e8160… 0	private_overlay/dag/strategy/x.dag
100644 e97e9c7e8160… 0	private_repo/dag/x.dag
120000 0a7c3223a461… 0	private_repo_link
100644 e97e9c7e8160… 0	privdag/gunbc/x.dag
100644 e97e9c7e8160… 0	wb62_overlay/dag/x.dag

Every prefix stages full file content, and the symlink stages as 120000 with the target path as its blob.

After (this branch's derived .gitignore, blob 1d8aee59bc76, which is the committed file):

$ git add -A && git ls-files --stage
100644 1d8aee59bc76… 0	.gitignore
100644 57e6630bd00f… 0	fixtures/private_overlay/x.dag

Three properties in one run: the five directories are ignored; the symlink at private_repo is ignored (it is absent from the staging list, which the trailing-slash form did not achieve); and fixtures/private_overlay/ — nested, same-named, claimed by no row — stays trackable, which is the public material the anchoring protects.

What rung this is, and what it is not (DESIGN §4b)

Rung 2, mechanically preventable, at best. The derivation does not change that — it removes a second representation of the privacy fact, which is a §3 defect, not a §4b rung.

  • git add -f bypasses a tracked ignore entirely.
  • An ignore reaches nothing already committed; this row has previously watched auto-push publish exactly that shape with a clean git status.
  • The guard is path-shaped while the hazard is content-shaped, and the prefix is a parameter of the producing recipe — so the rostered prefixes are the ones observed, not the set that can occur. The derivation makes adding a spelling one row; it does not make an untyped spelling safe.
  • It is real only while it stays enrolled: deleting a materialisation row, or a visibility standing that stops being true at the forge, silently reopens the vector.

The row's next-rung trigger is unchanged and undischarged: the private-witness step must materialise its overlay outside the public checkout. An ignore naming prefixes inside the worktree is by construction not that capability, and the receipt says so rather than narrowing the trigger to what it just built.

Not in scope, stated rather than left silent

The same upstream fact is spelled two more times: extdeps.github.github Repository.private: Bool and extdeps.github.code_search CodeSearchRepository.private: Bool. Those are the API's boolean alias for visibility, their consumer set is two orders larger than the two coproducts unified here (dozens of witnesses construct private: false), and folding them in is its own change. It is recorded in the new module's annotation as a named follow-up.

GitHub's visibility also admits internal for enterprise accounts. It is not modeled: no row in this corpus observes one, and an arm nothing constructs would be a state no evidence supports. The annotation names what closing it would take.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F

gunbc-ci-auto-heal and others added 2 commits September 13, 2026 19:43
A directory named private_overlay/, base_overlay/, wb62_overlay/ or privdag/
placed in a PUBLIC gunbc session worktree stages full file content on
`git add -A` with no warning; a nested clone at private_repo/ stages a gitlink.
The tracked .gitignore carried no entry for any of them, so the protection that
existed was a per-session .git/info/exclude — absent in a fresh clone and
invisible until after a push.

std.workspace_artifact gains an IgnoreReason arm ForeignPrivateMaterial, which
is not a stronger MayContainSecrets: that arm is about bytes this repository's
own tools produce that happen to carry a credential, and these are bytes that
belong to a DIFFERENT repository with a different visibility, so tracking them
is a disclosure rather than a hygiene defect. gunbc.repo_workspace declares the
five observed spellings under it and .gitignore is regenerated through
gunbc.gitignore_emit; the stage0 mirror is installed from --required-regen's own
candidate.

The recurring_failure_mode receipt states what this is and is not: rung-2
mitigation, path-shaped against a content-shaped hazard, bypassed by
`git add -f`, out of reach of already-committed content, and real only while the
rows stay enrolled. The row's next-rung trigger — private material materialised
OUTSIDE the public checkout — is unchanged and undischarged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
Re-scoped on operator direction: the privacy fact must have one home and the
ignore rows must be derived from it, not authored beside it. The previous head
declared a ForeignPrivateMaterial ignore reason carrying a stringly owner on
every row — a second, nicknamed representation of a visibility the corpus
already models. That arm is gone.

The fact now lives once. extdeps.github.repository carries a single
RepositoryVisibility, which was forked into actions_token.RepositoryVisibility
and hosted_runners.RepoVisibility; both import it now, as do
runner_provider_survey and the actions-job-grant witness. gunbc.repo_identity
carries the visibility standing of gunb-ai/gunbc (public) and
gunb-ai/gunbc-private (private), which is the whole fact "not world-readable".

Where that material lands is a fact of the compose realization, not an ignore
row: gunbc.workspace_repository_materialisation declares repository x prefix x
method, and derives the staged shape from the method rather than authoring it
beside it, so no row can declare a clone that stages full content. The private
half of the contract — strategy.private_witness_workflow overlay_local_method —
is cited by name and not imported.

gunbc.gitignore_emit then derives one ignore row per materialisation whose
source repository is not world-readable, with the comment text derived from that
visibility. A new overlay spelling is a compose row and the ignore follows by
construction; flipping a repository to public at the forge removes its rows from
the projection with no ignore list edited.

Witnessed in both directions: the five private prefixes appear, and a
materialisation of the PUBLIC repository derives no row at all. Flipping
gunbc_private_repository to PublicRepository and re-running the emitter drops
all five patterns, so the rows follow the visibility fact rather than standing
beside it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot gunbai-bot Bot changed the title Declare private-repository material as an ignore reason, not a hand edit Derive the private-material ignore rows from repository visibility Sep 13, 2026
@gunbai-bot

gunbai-bot Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

The APPROVE from codex/gpt-6-astra (review 65640) was against the previous head e31bccb6e3b, which declared an IgnoreReason arm ForeignPrivateMaterial { owner_repository: String } and authored five rows under it. That design has been replaced at operator direction, so the approval reviewed a diff that no longer exists — flagging it rather than carrying it forward.

Current head 1b888404952: the privacy fact lives once (extdeps.github.repository RepositoryVisibility, previously forked between actions_token and hosted_runners), the repositories' standings live in gunbc.repo_identity, the compose contract lives in gunbc.workspace_repository_materialisation, and gunbc.gitignore_emit derives the rows from the join. std.workspace_artifact and gunbc.repo_workspace are byte-identical to main again. Full rationale and evidence are in the rewritten PR body.

— sent from vivid-stag-90

@gunbai-bot

gunbai-bot Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Floor lane status, with one correction to my own earlier read.

The first floor red carried two INTERRUPTED-BEFORE-VERDICT rows (v2.test.parse witnesses at 504-505ms against a 500ms CPU budget). I re-ran the identical head to separate my diff from runner speed: the second run reports interrupted_before_verdict=0 and verdict=FloorClean. Those interrupts were host noise, not this change.

The actual blocker was present in both runs and is not a witness failure at all. Measurement is clean — verdict=FloorClean, passed=3729, claims_failed=0, unexpected_failures=0. The ADJUDICATE step refuses:

required-ci: adjudication BLOCKING phase=namespace-wave-admission identity=<phase>
  cause=namespace-wave-admission (6 unadjudicated delta(s), 0 stale, 0 consumed)

All six are TargetChanged bindings, and they are exactly what this PR sets out to do — three spellings repointed from the old fork to the new authority:

module declaration spelling
extdeps.github.actions_token ActionsRepositoryPolicyObservation RepositoryVisibility
extdeps.github.actions_token fork_write_tokens_reachable PrivateRepository, PublicRepository
test.claim.actions_job_grant_witness fork_policy_allows, fork_policy_denies PrivateRepository
test.claim.actions_job_grant_witness public_fork_policy_allows PublicRepository

base {extdeps.github.actions_token} → head {extdeps.github.repository} in every case. The membership half of the same motion was auto-admitted as ExplicitlyEvaluatedZeroDelta; this is the wall working, not misfiring — gunbc.namespace_wave_admission states its rows exist for precisely this motion, "a spelling authored on both sides now resolves to a different module".

The remedy is a row per delta in NAMESPACE_TRANSITION_ADMISSIONS, a const roster that today stands empty in src/v1/stage0/src/namespace_wave_admission.rs. That is hand Rust under src/v1, which my brief forbids, so I have escalated rather than authoring it on my own judgement. Holding here.

— sent from vivid-stag-90

The namespace wave refused gunbc#11306 with six unadjudicated TargetChanged
deltas: the spellings RepositoryVisibility, PublicRepository and
PrivateRepository now resolve to extdeps.github.repository instead of
extdeps.github.actions_token, in actions_token (three sites) and the
actions-job-grant witness (three). That is the wall working — the relocation is
exactly what this branch performs — and its designed remedy is a row per delta,
by exact identity, in NAMESPACE_TRANSITION_ADMISSIONS.

Admitted under gunbc.v1_maintenance_standing v1_seed_standing as a CONSUMED
LEDGER ENTRY, not an escape hatch: the rows are data on an already-rostered
declaration and add no function, type or admission mechanism, which is the same
standing PR 9436 recorded for 53 such rows. hosted_runners produces no row — its
arms were spelled PublicRepo / PrivateRepo and are new names at the head rather
than rebinds.

DISSOLVE-ON is gunbc#11306 merging, and the deletion PR is authored and linked
before this is enqueued, so the trigger has a waiting actuator rather than a
sentence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
# Conflicts:
#	src/v1/stage0/src/namespace_wave_admission.rs
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

On the note about Repository.private: Bool / CodeSearchRepository.private: Bool having no named lane — that is a decision rather than an omission, and worth stating so it does not read as the latter.

It was escalated and ruled on: the two boolean fields are a recorded §3 follow-up and are explicitly not to be chased in this PR. The reason is scope, not doubt about the finding — those two are the API's boolean alias for the same visibility fact, and their consumer set is two orders larger than the two coproducts unified here (dozens of witnesses construct private: false), so folding them in would swamp a change whose subject is the ignore derivation. The divergence is stated in extdeps.github.repository rather than left silent, which is the §3b middle value the review names.

A lane for it is the owning session's call, not mine to open from here; the annotation is the durable record until one exists.

Same for the other deliberate gap: GitHub's visibility admits internal, and it stays unmodelled until a row observes one — a downstream coverage obligation, never an authored Unobserved arm.

Two notes on the current head d7cf3d382e7, which is a merge of main, not a rebase:

— sent from vivid-stag-90

…is touch by the wall

The #11182 inventory-evidence relocation reached base, so the required floor
reports its seven admission rows as CONSUMED — 0 unadjudicated, 0 stale, seven
already satisfied at the base. The wall charges a consumed row's deletion to the
roster's NEXT TOUCH, and this branch is that touch by virtue of adding its own
six rows to the same array, so the debt is this PR's to pay rather than a
refusal to route around.

Deleting them removes nothing that could still fire: an admission row admits a
delta between base and head, and with the transition present at the base there
is no delta left for these to admit. Their header paragraph goes with them
rather than being left describing rows that no longer exist — the stale-citation
shape the paragraph above it already names — and that paragraph's own closing
sentence, which said the #11182 set was what remained below, is corrected for
the same reason.

#11274 is not emptied by this: it keeps its recurring_failure_mode row.
Identical deletions on both sides merge cleanly.

Verified by identity rather than by count: the four #11182 spellings
(AllLedgersAdmitted, InventoryLotEvidence, LedgerEvidenceRefused,
admit_ledger_evidence) are gone, and this PR's six rows stand unchanged at
RepositoryVisibility 1, PublicRepository 2, PrivateRepository 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Head 1ece3c439f2: retired the seven consumed #11182 relocation admissions, charged to this PR by the wall.

The previous floor run reported 0 unadjudicated, 0 stale, 7 consumed admission(s) due for correction or deletion — this PR's own six rows adjudicate cleanly; the refusal was that #11182's relocation had reached base, making its seven rows consumed, and the wall charges a consumed row's deletion to the roster's next touch, which this branch is by virtue of adding rows to the same array. verdict=FloorClean, claims_failed=0, unexpected_failures=0 throughout — nothing was failing.

Deleting them removes nothing that could still fire: with the transition present at the base there is no delta left for them to admit. Their header paragraph went with them rather than being left describing rows that no longer exist, and the preceding paragraph's closing sentence — which claimed the #11182 set was what remained below — is corrected for the same stale-citation reason that paragraph itself names.

#11274 is not emptied by this: it keeps its recurring_failure_mode row. Identical deletions on both sides merge cleanly in git, so there is no collision between the lanes.

Verified by identity, not by count: the four #11182 spellings (AllLedgersAdmitted, InventoryLotEvidence, LedgerEvidenceRefused, admit_ledger_evidence) are gone; this PR's six stand unchanged at RepositoryVisibility 1, PublicRepository 2, PrivateRepository 3. Roster goes 13 rows to 6.

— sent from vivid-stag-90

gunbc-ci-auto-heal and others added 4 commits September 14, 2026 03:29
REFUSAL FOLDED IN: gunbc.gitignore_emit emitted the materialisation prefixes
unanchored, so `private_overlay/` also ignored `fixtures/private_overlay/x.dag`
— material outside the modeled private prefix, which may be perfectly public.
Git reads a pattern with no leading slash as matching at any depth, while a
materialisation row declares a prefix AT THE WORKSPACE ROOT, so the unanchored
form asserted something the model does not.

The pattern is now derived through materialisation_ignore_pattern as
concat("/", prefix) — the same anchoring the generated-artifact arm in this file
already applies, and derived from the row rather than hand-spelled.

A SECOND DEFECT SAT BEHIND THE FIRST and would have survived an emitter-only
fix: pattern_matches discarded the leading slash on every directory pattern, so
path_is_ignored answered the UNANCHORED question for anchored patterns. The
predicate would have called the nested fixture path ignored while git, reading
the same file, would not — two answers to one question, and a witness would have
read the wrong one. anchored_dir_matches closes it; path_is_ignored has no
consumer outside this gate.

The witness pair is the discriminator, and it was verified to go red without the
fix rather than assumed to: a root-level materialisation path is ignored, and
fixtures/private_overlay/example.dag, dag/test/fixture/privdag/sample.dag and
vendor/private_repo/readme.md are NOT.

The receipt gains the measured host facts. The only thing covering the overlay
prefix before this change was the common git dir's info/exclude — uncommitted,
unreviewed, absent in a fresh clone, so check-ignore returned a reassuring answer
for the wrong reason; and that same file is itself unanchored, so it is
simultaneously too narrow to travel and too broad where it applies. Three
staging behaviours are now measured rather than two — clone/gitlink/warns,
copy/100644/silent, symlink/120000/target-path/silent — and the third needs no
method arm, because the derivation reads visibility and prefix only, so one
prefix row covers every staging behaviour at that prefix. private_overlay_m/
gets no row: it was never observed being produced, appearing only in that
exclude. And the ignore row is one wall of several: `git worktree prune` does
not delete files, so residue survives outside every worktree git knows about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
The floor refused the witnesses lane with CLAIM-SCOPE REFUSAL
cause=AmbiguousBareNameRead scope=test.claim.gitignore_gate, two sites: `String`
and `Unit` are read bare by extdeps.python while two transitively-reached modules
declare each of them.

The ambiguity is latent in extdeps.python and this branch surfaced it by
widening that scope's closure — an ambiguous bare read refuses only once BOTH
declaring modules are reachable, so the defect was there and unreachable rather
than introduced here.

Verified at the declaration sites rather than taken from the diagnostic's
wording: `String` is declared by std.string_type, so the existing
`import std.types { String }` named a module that does not declare it and bound
nothing, which is the case the refusal text calls out explicitly; and `Unit` is
declared by std.types and used bare at the exit arm with no import naming it at
all. The import now names the declaring authority for each.

Note on evidence: the gitignore_gate witnesses pass locally both before and
after this change, so that green does not cover this refusal — claim_batch does
not perform the floor's claim-scope check. The required lane is the verifier.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
#11274 landed on main and retired the seven consumed #11182 relocation
admissions — the same rows this branch retired when the wall charged them to its
own touch. The identical deletions reconcile exactly as predicted: main's array
is empty, this branch's carries its own six #11306 rows, and the merge keeps
those six with the seven gone from both sides.

One difference is resolved in this branch's favour rather than split. #11274
deleted the seven rows but left the paragraph above them standing, still
asserting that "THE #11182 RELOCATION ROWS SURVIVE THIS DISSOLUTION" and
describing seven rows that no longer exist. That is the stale-citation shape the
preceding paragraph in the same file names explicitly — prose naming rows
neither of which exists reads as coverage — so the paragraph stays deleted here,
and the earlier paragraph's closing sentence continues to name what actually
remains below.

Verified by identity: six rows, RepositoryVisibility 1, PublicRepository 2,
PrivateRepository 3; no #11182 spelling and no #11182 prose survives.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
…ink is covered

REFUSAL FOLDED IN, and the refused claim was mine. The annotation added with the
anchoring repair said one prefix row covers every staging behaviour at that
prefix. That is false. A gitignore pattern ending in a slash matches DIRECTORIES
ONLY, so /private_repo/ sails straight past a symlink named private_repo —
measured in a scratch repository, it stages as mode 120000.

THE REASONING THAT PRODUCED IT IS RECORDED RATHER THAN QUIETLY REPLACED, in the
module annotation and in the RFM receipt, because it is the seductive kind: the
derivation IS method-agnostic — it reads visibility and prefix and nothing else —
but coverage is decided by the emitted PATTERN, not by the derivation. A true
statement about one layer was carried into a claim about another, and the gap was
invisible because both sentences describe the same row.

THE FIX IS THE PATTERN FORM, not a new method arm. The materialisation row now
carries a bare PATH PREFIX (private_repo, not private_repo/) and the emitter owns
the gitignore punctuation, so neither the depth question nor the inode-kind
question is answerable from the model's side. The emitted pattern is anchored and
unslashed, which matches a file, a directory and a symlink at that path — all
three measured in a scratch repo, with a nested same-named path still spared, so
the public-material property the anchoring repair bought is unchanged.

EVIDENCE, and one honest limit. Nine gate witnesses pass. The red control is
line-exact: witness_private_material_rows_are_derived asserts each whole line
(newline-delimited), so restoring the trailing slash makes it FAIL — verified.
THE LIMIT: witness_materialisation_patterns_are_root_anchored still PASSES under
the broken pattern, because path_is_ignored has no inode-type input and cannot
distinguish a symlink from a directory at all. So the byte-level assertion is the
wall for this class, and the scratch-repo measurement is what grounds it; the
predicate is not evidence here and is not cited as such.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Migration recipe from #11345 (directory-is-membership cut of NAMESPACE_TRANSITION_ADMISSIONS).

This PR still authors const rows. After #11345 lands (or if you rebase onto it):

  1. One file per row at dag/gunbc/namespace/transition_admission/<stem>.dag. Stem is the relocation identity in stem form (module/declaration/spelling), not the owner PR number.
  2. Shape: TransitionAdmission { label, subject, disposition } with enclosing / expected_candidates as decl_ref(...).
  3. Drop the Rust hunk on the deleted const. Do not reintroduce a list.

Consumed-row deletion after merge is deleting that file (#11316 stays the follow-up; it becomes a file delete).

gunbai-bot Bot pushed a commit that referenced this pull request Sep 14, 2026
The const's prose about what remains used to rot beside the array. Empty-is-not-permissive and the #11306/#11316 inheritance live on gunbc.namespace.transition_admission; this cut still inherits six files or zero, never a pre-migration onto an unlanded PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
REQUEST_CHANGES folded in (review 65999). The emitted header still described the
pre-derivation world: it attributed the file to gunbc.repo_workspace alone and
claimed every pattern carries "a typed ignore reason", while this branch had
added a third arm whose reason text is derived from a repository's VISIBILITY and
not from std.workspace_artifact IgnoreReason at all. A reader trusting the header
was told the file had a model it no longer has.

That is the same defect this branch already repaired twice in the admission
roster's comments — prose that reads as coverage for a model that is no longer
true — and it is worse in a generated artifact, because nothing else in the file
disagrees with the header and it goes stale silently.

The header now names each arm with its real home: workspace footprints from
gunbc.repo_workspace carrying a typed IgnoreReason; non-world-readable material
from gunbc.workspace_repository_materialisation joined with the visibility
standings in gunbc.repo_identity, whose pattern is the row's root-anchored prefix
and whose reason is derived rather than authored per row; and generated artifacts
from gunbc.generated_artifact commit policy. Regenerated through the drift-gated
path.

The witness is strengthened to match rather than left asserting one substring:
witness_has_header now requires every producer to be named, so adding a fourth
arm without announcing it turns the gate red instead of passing quietly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 67abf669a9d (review 65999). The finding was right and it is the same defect this branch already repaired twice in the admission roster's own comments — prose that reads as coverage for a model that is no longer true — which is worse in a generated artifact, because nothing else in the file disagrees with the header and it goes stale silently.

The header now names each arm with its real home rather than attributing the file to gunbc.repo_workspace alone:

# gunbc .gitignore — generated via gunbc.gitignore_emit from gunbc.repo_workspace,
#   gunbc.workspace_repository_materialisation and gunbc.generated_artifact — do not hand-edit.
#
# THREE ARMS, each with its own producer and its own reason for being untracked.
# 1. Workspace footprints, from gunbc.repo_workspace: ... a typed std.workspace_artifact IgnoreReason.
# 2. Material from a repository that is not world-readable, from
#    gunbc.workspace_repository_materialisation joined with each source repository's visibility in
#    gunbc.repo_identity: the pattern is the row's root-anchored prefix and the reason text is
#    DERIVED from that visibility, never authored per row.
# 3. Generated artifacts, derived from gunbc.generated_artifact commit policy.

Regenerated through the drift-gated path, not hand-edited.

The witness is strengthened rather than merely updated. It previously asserted one substring, which is exactly how the old header survived the arm being added. witness_has_header now requires every producer to be named by name, so adding a fourth arm without announcing it turns the gate red instead of passing quietly. All nine gate witnesses pass.

— sent from vivid-stag-90

…r it

REQUEST_CHANGES folded in (review 66024). The clause asserting that
expected_gitignore() does not contain "public_overlay_probe/" was permanently
green by construction, and the review is right that it would have been cited as
coverage.

THE PRESCRIBED FIX WOULD HAVE LEFT A SUBTLER DECORATION STANDING, which is why
the clause is deleted instead of edited. The review names one reason — this
branch made the emitter produce bare prefixes, so a leak would read
/public_overlay_probe and a search for the slash-bearing spelling can never fail.
Dropping the slash repairs that and not the second reason: the probe rows are
TEST-LOCAL data and are never members of workspace_materialisations(), which is
the roster expected_gitignore() folds, so no spelling of the probe can appear in
the projection under any behaviour of the code. The clause was unfalsifiable
about the emitter, not merely misspelled.

What remains is discriminating, and that is verified rather than asserted: with
materialisation_must_not_be_tracked forced to admit everything — the exact defect
the witness exists to catch — witness_public_source_derives_no_ignore_row FAILS.
Restored, all nine gate witnesses pass.

The reason for the deletion is recorded beside the witness, so the next author
does not helpfully add the clause back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 71b980819f0 (review 66024). The finding is correct — that clause was permanently green by construction — but the prescribed fix would have left a subtler decoration standing, so the clause is deleted rather than edited.

The review names one reason: this branch made the emitter produce bare prefixes, so a leak would read /public_overlay_probe and a search for the slash-bearing spelling can never fail. Dropping the slash repairs that and not the second reason: public_sourced_materialisation and private_sourced_materialisation are test-local data and are never members of workspace_materialisations(), which is the roster expected_gitignore() folds. So no spelling of the probe — slashed, bare, or otherwise — can appear in the projection under any behaviour of the code. The clause was unfalsifiable about the emitter, not merely misspelled. Asserting the whole emitted line, the other suggested form, would have been green by construction for the same reason.

What remains is discriminating, and I verified that rather than assuming it: forcing materialisation_must_not_be_tracked to admit everything — the exact defect the witness exists to catch — makes witness_public_source_derives_no_ignore_row FAIL. Restored, all nine gate witnesses pass. The three surviving conjuncts do the work over a list the witness controls, which is the only place a public-sourced row can be constructed at all.

The reason for the deletion is recorded beside the witness, so the clause does not get helpfully added back later.

— sent from vivid-stag-90

gunbc-ci-auto-heal and others added 3 commits September 14, 2026 07:54
#11347 landed an admission row for the gunbc#11193 artifact_store_fs anchor leaf
into the same const this branch appends to — the third append-vs-append collision
on this array in one day. Both row sets survive: main's one row and this branch's
six, seven total, verified by identity rather than count.

Main's three bare-read repairs (ipmi, cron, artifact_store_fs) are disjoint from
this branch's extdeps.python repair, so those do not interact.

The stale #11182 paragraph stays deleted. It returned on main's side because
#11274 removed its seven rows and left the prose asserting they survive; this
branch removed it once already and the same reasoning applies unchanged — prose
describing rows that no longer exist reads as coverage, which the paragraph above
it names as the defect to avoid.

The standing sentence naming what remains below is corrected again, to name both
sets. That sentence has now gone stale twice in one day from merges that changed
the population under it, and it now says so: a census kept beside an array rots
every time the array moves, which is the standing argument for the
directory-is-membership cut in #11345.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
…h by the wall

#11347 landed, so the artifact_store_fs anchor relocation is at base and its one
admission row reports CONSUMED — 0 unadjudicated, 0 stale, 1 consumed due for
deletion. The wall charges a consumed row's deletion to the roster's NEXT TOUCH,
and this branch is that touch again by virtue of carrying its own six rows.

APPLIED UNDER THE STANDING RULING RATHER THAN RE-ASKED. The identical question
was decided today for the seven #11182 rows: the wall is designed to charge the
next touch, identical deletions on both sides merge cleanly in git, and waiting
costs hours of serialized CI and review on another lane's PR plus a re-run here,
against one push. #11356 owns the same retirement and is not emptied by this — it
keeps whatever else it carries, exactly as #11274 kept its failure-mode row.

Deleting it removes nothing that could still fire: with the transition present at
the base there is no delta left for it to admit. Its doc paragraph goes with it
rather than being left describing a row that no longer exists.

Verified by identity: the extdeps_external_authority_anchor spelling is gone and
no #11193 reference survives anywhere in the file; this branch's six stand
unchanged at RepositoryVisibility 1, PublicRepository 2, PrivateRepository 3.

The standing sentence above the array is corrected for the THIRD time in one day,
and now says so. This one retired a row this branch never authored, which is the
sharpest form of the argument for the directory-is-membership cut in #11345: a
census kept beside an array that every lane appends to rots continuously.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
REQUEST_CHANGES folded in (review 66093), and the finding is correct and sharp:
this branch minted gunbc_public_repository in gunbc.repo_identity carrying owner
"gunb-ai", name "gunbc" and world-readability — a SIXTH spelling of an instance
fact gunbc.repository gunbc_repository already owns, in a change whose whole
thesis is de-forking. gunbc.repository's own note anticipates the move verbatim:
the answer to five nicknames is not a sixth carrying a promise to consolidate
later, it is one authority the others CONSUME. I did not grep the gunbc layer for
an existing repository instance before authoring one, which is the whole defect.

WHAT LANDS INSTEAD. RepositoryVisibilityStanding is DELETED along with its two
helpers; nothing carries owner/name/visibility a second time. extdeps.github
.repository gains repository_visibility, a function over the EXISTING Repository
that maps the API's boolean alias to the typed coproduct, plus
repository_is_world_readable over it. That is the bridge between the upstream's
two spellings, it exists once, and it is where the consolidation this module
already named as a follow-up actually begins rather than being promised.

gunbc.repository gains gunbc_private_repository beside the row it already owns,
because no typed row for the private repository existed anywhere — that fact is
new, not a fork. Every field is OBSERVED from the GitHub repository object read
2026-09-14, not assumed: full_name, private and default_branch came back
gunb-ai/gunbc-private, true and main. default_branch is not inferred from the
public repository's; a sibling is free to differ and a guessed field is the kind
of quietly-wrong fact that survives until something acts on it.

gunbc.repo_identity is back to its own subject — default branch and remote — and
the materialisation rows source Repository directly, with the slug read off
full_name rather than recomputed.

Evidence: nine gate witnesses pass, and the derivation still tracks its authority
rather than a copy of it — flipping gunbc_private_repository to private: false
drops all five derived patterns from the projection (3 to 0 on the three original
prefixes), restored when reverted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 7eed991a201 (review 66093). The finding is correct and it is the sharpest one this PR has had: I minted gunbc_public_repository carrying owner/name/world-readability while gunbc.repository gunbc_repository already owned exactly that instance — a sixth spelling, in a change whose whole thesis is de-forking. I did not grep the gunbc layer for an existing repository instance before authoring one, which is the entire defect; that module's own note anticipates the move verbatim.

What lands instead of a repaired fork:

  • RepositoryVisibilityStanding and its two helpers are deleted. Nothing carries owner/name/visibility a second time.
  • extdeps.github.repository gains repository_visibility, a function over the existing Repository mapping the API's boolean alias to the typed coproduct, plus repository_is_world_readable. That is the bridge between the upstream's two spellings, it exists once, and it is where the consolidation this module already named as a follow-up actually begins rather than being promised again.
  • gunbc.repository gains gunbc_private_repository beside the row it already owns. No typed row for the private repository existed anywhere — that fact is new, not a fork.
  • gunbc.repo_identity is back to its own subject (default branch and remote), and materialisation rows source Repository directly with the slug read off full_name rather than recomputed.

On the instance fields: observed, not assumed. Every field of the new row came from the GitHub repository object read 2026-09-14 — full_name, private and default_branch returned gunb-ai/gunbc-private, true, main. I did not infer default_branch from the public repository's; a sibling repository is free to differ, and a guessed field is the kind of quietly-wrong fact that survives until something acts on it.

Evidence: nine gate witnesses pass, and the derivation still tracks its authority rather than a copy — flipping gunbc_private_repository to private: false drops every derived pattern from the projection (3 → 0 on the three original prefixes), restored when reverted.

One correction to something I said earlier on this PR: I described the private: Bool consolidation as "two orders larger". That was a count of constructions of the type across witnesses, not of reads of the field — the review's git grep '\.private\b' count of the latter is the one that matters for the instance, and it is small. The type-level divergence stays a stated follow-up; the instance-level fork is gone.

— sent from vivid-stag-90

REQUEST_CHANGES folded in (review 66104). When the forked instance row was
deleted from gunbc.repo_identity, the receipt in this row still said that module
carries the visibility standing of both repositories. That became false in the
same commit that fixed the fork, and it is the same stale-citation shape this
branch has now corrected four times elsewhere — prose naming an authority that no
longer holds the fact, which reads as coverage.

The receipt now names gunbc.repository and its two typed Repository rows, says
the private row's fields were read from the GitHub repository object rather than
assumed, and names extdeps.github.repository repository_visibility as the mapping
from the API's boolean alias to the typed coproduct. The PR body carried the same
claim and is corrected with it.

The one surviving mention of gunbc.repo_identity, in extdeps.github.repository's
annotation, is deliberate and stays: it is past tense, recording what an earlier
draft did and why it was wrong, which is history rather than a citation.

No projection is owed: docs/design-failure-modes.md is gitignored and untracked,
so the failure-mode ledger has no committed artifact to regenerate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@gunbai-bot

gunbai-bot Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 0d60267565f (review 66104). Correct, and it is worth being blunt about the shape: the commit that deleted the fork left my own receipt citing the authority it had just emptied. That is the fifth stale-citation of this run and the first one I introduced while fixing a different instance of the same class — the repair moved the fact and I did not re-read what pointed at it.

The receipt now names gunbc.repository and its two typed Repository rows, records that the private row's fields were read from the GitHub repository object rather than assumed, and names extdeps.github.repository repository_visibility as the mapping from the API's boolean alias to the typed coproduct. The PR body carried the identical claim and is corrected with it.

One mention of gunbc.repo_identity survives on purpose, in extdeps.github.repository's annotation: it is past tense, recording that an earlier draft authored a row there and why that was a sixth spelling. That is history, not a citation — deleting it would remove the reason the current shape exists.

No projection is owed. docs/design-failure-modes.md is gitignored and untracked, so the failure-mode ledger has no committed artifact to regenerate; I checked rather than assuming the earlier receipt edits had been silently drifting.

— sent from vivid-stag-90

gunbc-ci-auto-heal and others added 2 commits September 14, 2026 10:10
#11356 landed and retired the gunbc#11193 anchor admission row — the row this
branch had already retired when the wall charged it to this touch. The identical
deletions reconcile exactly as the standing ruling predicts: the row is gone from
both sides and this branch's own six remain.

Both sides also independently removed the stale #11182 prose, which is the fourth
time that paragraph has been repaired today by two different lanes reaching the
same conclusion from the same rule.

One sentence of main's is kept rather than dropped with its body: main's revision
says empty is the roster's resting state, which is true in general and false in
the instant after this merge, since six rows are present. It is folded in as a
sentence that stays true either way — the six are consumed by their own merge and
#11316 is already authored to delete them, so a populated roster is a transition
and never a steady state.

Verified by identity: six rows, RepositoryVisibility 1, PublicRepository 2,
PrivateRepository 3; no #11193 row and no #11182 prose survives.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
Sixth re-integration, fifth append-vs-append on this one const. Main accumulated
three commits in the file — #11356 emptying the roster, #11256, and #11214
landing fifteen rows for the operator-supplied-token relocation — producing seven
conflict regions. Both row sets survive: fifteen plus six, verified by spelling
rather than by count.

Main's own "THE ROSTER IS EMPTY AGAIN, which is its resting state" paragraph is
dropped, and not on this branch's preference: it became false ON MAIN when
#11214 landed fifteen rows above it and nothing updated the prose. Keeping it
would have carried a claim contradicted by the array directly beneath it, which
is the stale-citation shape this file names as the defect to avoid and which this
branch has now repaired five times.

The sentence naming what remains below already records that it has gone stale
repeatedly; this merge is another instance and does not change its argument.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
… wall

#11214 landed, so the operator-supplied-token relocation is at base and its
fifteen admission rows report CONSUMED — 0 unadjudicated, 0 stale, 15 consumed
due for deletion, with this branch's own six adjudicating cleanly. The wall
charges a consumed row's deletion to the roster's next touch and this branch is
that touch again.

Applied under the standing ruling rather than re-asked; this is the third time it
has fired on this branch and the second time for rows another lane authored.
#11259 is the authored deletion draft for these fifteen and is not emptied by
this — it keeps whatever else it carries, as #11274 and #11356 did.

Their paragraph goes with them rather than being left describing rows that no
longer exist.

Verified by identity: no #11214 reference survives anywhere in the file; this
branch's six stand unchanged at RepositoryVisibility 1, PublicRepository 2,
PrivateRepository 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@briansrls
briansrls added this pull request to the merge queue Sep 14, 2026
briansrls pushed a commit that referenced this pull request Sep 14, 2026
…11345)

* Cut the namespace transition-admission roster to directory membership.

Delete the hand-Rust const so permission is one .dag file per relocation; appends and consumed deletions no longer collide on a shared array.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Type expected_candidates as DeclarationRef, not a string list.

The wall still joins declaring-module identity; the authored row now names those identities with the same declaration-reference type as enclosing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Supersede the const-ness-as-safety claim in the roster carrier.

Permission stays authored and reviewable; the vehicle is directory membership, not a const. Missing directory is the empty roster and admits fewer rows, never more.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Home the empty-roster standing record on the membership module.

The const's prose about what remains used to rot beside the array. Empty-is-not-permissive and the #11306/#11316 inheritance live on gunbc.namespace.transition_admission; this cut still inherits six files or zero, never a pre-migration onto an unlanded PR.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop the leftover const census and refuse a phantom candidate leaf.

The #11182 permission paragraph had attached to WaveAdmissionPopulation after
the const died. Candidate DeclarationRef.decl_name must equal Binding.spelling.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Enumerate the directory-row parse helpers on the seed census.

The bijection sentence on that row was false after the const was replaced; name the helpers the loader actually added.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Do not re-home the consumed gunbc#11193 admission as a directory row.

Co-authored-by: Cursor <cursoragent@cursor.com>

#11356 owns that deletion (also carried on #11214). Copying it onto the new carrier would duplicate their receipt and keep a consumed row on a roster touch.

* Own the used_row fixture strings; Binding is no longer &'static.

Co-authored-by: Cursor <cursoragent@cursor.com>

#11250's merge-queue tests used const-roster literals; the directory cut stores owned String.

* Stop claiming the admission roster is a .rs file.

Row files are .dag and in sweep; roster_touched still reads the unfiltered diff because prefix match is not in_sweep_scope.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 14, 2026
gunbc-ci-auto-heal and others added 2 commits September 15, 2026 00:05
Seventh re-integration, sixth append-vs-append on this const. #11138 landed
thirty-seven string_eq collapse rows carrying a label CONSTANT rather than a
literal, which is why a label grep for this branch's spelling found none of them
— the shape of a row changed, not just the population. Both sets survive:
thirty-seven plus six, the label const kept, verified by label rather than count.

Main's "THE ROSTER IS EMPTY AGAIN, which is its resting state" paragraph is
dropped for the second time, on the same ground as the first and not as a
preference: it is false ON MAIN, where thirty-seven rows sit directly beneath it.
It returned because the lanes that emptied and refilled the array did not touch
the prose above it — which is the whole failure this paragraph keeps
demonstrating about itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
#11138 landed, so the string_eq collapse is at base and its thirty-seven rows
report CONSUMED — 0 unadjudicated, 0 stale, 37 consumed due for deletion, with
this branch's six adjudicating cleanly throughout. The wall charges a consumed
row's deletion to the roster's next touch; this branch is that touch for the
fourth time, and the third time for rows another lane authored.

STRING_EQ_COLLAPSE_LABEL goes with them. A label constant is text shared by the
rows that cite it — no function, type or host capability — and this file's own
history records the rule: it dissolves with the last row carrying it. Leaving it
would be a declaration nothing consumes.

Their paragraph goes too, rather than being left describing rows that no longer
exist.

Verified by identity: no STRING_EQ_COLLAPSE_LABEL reference survives anywhere in
the file; this branch's six stand unchanged at RepositoryVisibility 1,
PublicRepository 2, PrivateRepository 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSpQ3EJ1Nn8V16yEDqbG4F
@briansrls
briansrls added this pull request to the merge queue Sep 15, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 15, 2026
gunbc-ci-auto-heal and others added 5 commits September 15, 2026 06:44
… prose

Eighth re-integration, seventh append-vs-append on this const. #11373 landed
thirty-two PCI identity rows; #11138's thirty-seven were retired on main by that
same touch. Both live sets survive: thirty-two plus this branch's six.

I REVERSED A JUDGEMENT I HAD MADE TWICE. On the previous two merges I deleted
main's "THE ROSTER IS EMPTY AGAIN" paragraph as false — thirty-seven rows sat
beneath it. Reading main's block properly this time, that paragraph is not
orphaned prose: main carries a corrected successor ("THE ROSTER RETURNED TO EMPTY
ON MAIN ... AND THIS BRANCH REFILLS IT"), and the #11138 paragraph that looks
stale is followed by its own trigger record saying the thirty-seven went when
#11138 merged and were deleted by #11373. The block is a curated history whose
authors state why entries are kept — "the only place in this file that NAMES the
retired row" — and one of them is explicit that an unexamined deletion must not
be passed to whoever next touches the file.

So main's prose is taken INTACT here and nothing of it is removed. My earlier
deletions were defensible on the text I had read, and repeating them now would be
me re-removing, for a third time, text another lane deliberately maintains. The
one paragraph this branch adds is its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#11373 landed, so the PCI identity repair is at base and its thirty-two rows
report CONSUMED — 0 unadjudicated, 0 stale, 32 consumed due for deletion, this
branch's six adjudicating cleanly throughout. Fifth time the wall has charged
this touch, fourth for rows another lane authored.

#11373's own paragraph says a separate cleanup PR must remove these and that the
admission does not waive it. That remains true and this does not replace it: the
wall charges the roster's next touch, this branch is it, and the standing ruling
is to pay rather than serialize behind another lane's PR. That lane keeps
whatever else its cleanup carries.

WHAT IS DELETED AND WHAT IS NOT, now that the distinction has bitten once. The
paragraph BOUND to these rows goes with them — it describes thirty-two rows that
no longer exist. Main's HISTORICAL entries stay untouched: the empty-roster
paragraph, its corrected successor, the #11138 record, and the sentence noting
those rows were deleted on #11373's touch. That last one still cites #11373 and
is correct history, not a dangling reference to what this commit removed. I
deleted main's prose twice before on a reading that turned out to be wrong; the
rule I am applying now is narrower and is the file's own: a paragraph dies with
the rows it describes, and nothing else does.

Verified: no #11373 ROW survives; main's three historical paragraphs survive;
this branch's six stand at RepositoryVisibility 1, PublicRepository 2,
PrivateRepository 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ninth re-integration, eighth append-vs-append on this const, and the third
distinct row shape this branch has had to recognise: #10729 landed thirty-five
rows under TWO label constants (SCM_MERGE_BASE_COHOME_LABEL,
SCM_SOURCE_RECOVERY_REHOME_LABEL), after literals and after a single constant.

Both live sets survive: thirty-five plus this branch's six, both label constants
kept, verified by label form rather than by a pattern guessed from the previous
shape.

Main's prose is taken intact again. Nothing of main's is removed.

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

#10729 landed, so the SCM re-home cohort is at base and its thirty-five rows
report CONSUMED — 0 unadjudicated, 0 stale, 35 consumed due for deletion, this
branch's six adjudicating cleanly throughout. Sixth time the wall has charged
this touch, fifth for rows another lane authored.

Both SCM_SOURCE_RECOVERY_REHOME_LABEL and SCM_MERGE_BASE_COHOME_LABEL go with
them, by the rule this file states and this branch applied once already: a label
constant is text shared by the rows citing it and dissolves with the last one.

THE PROSE SPLIT IS THE CAREFUL PART. The paragraphs BOUND to this cohort go with
it — the one introducing the SCM re-home rows and the one recording that five of
them had already gone on their own trigger, both of which describe rows that no
longer exist here. The paragraph ABOVE them stays: it records that #11373's
thirty-two rows dissolved on their own trigger, which is history about a
different cohort and remains true. That distinction is the one this branch got
wrong twice by deleting main's history along with stale text, and the rule it now
applies is the file's own: a paragraph dies with the rows it describes, and
nothing else does.

Verified: no SCM label constant or row survives; the #11373 dissolution record
survives; this branch's six stand at RepositoryVisibility 1, PublicRepository 2,
PrivateRepository 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…slash), matching the emitted bytes

The gate refused 0c7c280 because the receipt still described the committed
anchored row as /private_overlay/ while the head deliberately emits it without
the slash (trailing-slash patterns are directory-only and miss a symlink).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qc3VJ9KnBA7aXp2ZQjCwTq
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 15, 2026
Merged via the queue into main with commit 9f5e498 Sep 15, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/vivid-stag-90 branch September 15, 2026 17:09
gunbai-bot Bot pushed a commit that referenced this pull request Sep 15, 2026
Their DISSOLVE-ON fired: #11306 merged as 9f5e498, so the repository-
visibility relocation is present at the base of every pull_request build, the six
TargetChanged deltas are no longer producible, and the rows report CONSUMED —
refusing every unrelated PR until they go. Their paragraph goes with them rather
than being left describing rows that no longer exist.

REBUILT FROM MAIN RATHER THAN MERGED FORWARD. This branch was authored before
#11306 landed and had drifted 114 commits behind; merging main into it conflicted
on the branch's own stale copies of that PR's files, and its diff against main
had become a 715-file, 81k-line revert. A draft in that state is dangerous rather
than merely stale, so the branch is reset to main and carries exactly one change:
the roster returns to empty, which is its resting state.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@briansrls
briansrls restored the session/vivid-stag-90 branch September 15, 2026 17:13
gunbai-bot Bot pushed a commit that referenced this pull request Sep 15, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Sep 15, 2026
Keep the #11306 visibility rows beside the C2 deployment_spec_srv1 rebinds.

Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot pushed a commit that referenced this pull request Sep 15, 2026
Resolve roadmap_authority.dag onto the PR's active(...) form (keeping main's
updated fn and new nodes, authored sizing dropped), union the stage0
namespace transition admissions (#11306 rows + #10994 rows), and regenerate
docs/design-rung-drops.md from gunbc.rung_drop.

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.

0 participants