Skip to content

Membership beneath a namespace container, projected from the parse-derived binding - #10836

Closed
gunbai-bot[bot] wants to merge 3 commits into
mainfrom
ns/containment-membership-enumerator
Closed

gunbai-bot[bot] wants to merge 3 commits into
mainfrom
ns/containment-membership-enumerator

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

State the §3c frontier and its trigger beside the declaration, not only in the body

review 62506 is right that the relation is unconsumed outside its own probes, and
right that the header argued about hypothetical callers instead of naming a real
one. §3c admits a later consumer only with the trigger stated beside it, and the
place a later reader greps is the tree, not a pull request body -- a body does not
travel with the declaration, and this one had already gone stale against the rework.

So the frontier is now written at the declaration: the named consumer is the
failure-mode roster's hand-authored membership tail, and the trigger is stated as a
CAPABILITY -- membership derived from the row-files so no tail must be edited to
register a row -- with a batch split or reformat explicitly not satisfying it. A
trigger naming less than the capability it restores is satisfied while the
capability stays dead, which is the §4b(3) failure this wording exists to avoid.
Ordering is excluded from the trigger for the reason the relation exports no
sequence at all.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01GwvzQ3SQoWWDgHkAeffMeF

Consumption (§3c)

Consumed by execution in this change: the five claim probes, which exercise the relation over real
values rather than asserting the declaration exists. Beyond them this is a declared frontier,
now stated beside the declaration in src/v2/std/qualified_name.dag so it travels with the code —
named consumer: the failure-mode roster's hand-authored membership tail; trigger, at capability
grain: roster membership derived from the row-files, so no tail must be edited to register a row.

History of this branch

The first head returned FreeMonoid<QualifiedName> with a comment promising it exported no
ordering. FreeMonoid is Empty | Cons { head, tail }, so the order was fully observable and the
comment stated what the construction did not enforce. Replaced by the relation rather than dressed
with a wrapper, since a wrapper leaves the order structurally available — the defect restated.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GwvzQ3SQoWWDgHkAeffMeF

Brian Searls and others added 3 commits September 8, 2026 12:35
…rived binding

v2.compiler.source_authority already owns the fact that a module IS a containment
subtree and that the path-module binding is DERIVED AT PARSE, never authored. So
"which modules inhabit this prefix" was a missing PROJECTION of an authority this
module already holds, not a new authority: ModuleStorageIndex is the raw population
and modules_under_container is the capability over it, reusing is_prefix_of over
QualifiedName = FreeMonoid<Symbol> rather than minting a relation.

STRICT DESCENT, and the strictness is what keeps two relations from answering one
question. A container is a prefix of itself, so a reflexive reading would duplicate
module_storage_index_contains_module, which already answers reflexive membership.

ORDER IS NOT SUPPLIED, DELIBERATELY. Containment yields a SET; nothing about a
containment subtree says whether siblings sequence by qualified name, parse order,
chronology or a declared ordinal. A consumer needing stable bytes must ground its
ordering independently -- a row-owned ordinal or equivalent -- and a sort placed here
because some consumer wants deterministic output would make presentation policy into
a namespace semantic. Qualified-reference path induction stays a separate capability
and is neither retired by this nor retires it.

No new name was minted for symbol equality: the eq is passed inline, because the two
existing symbol_eq wrappers are already one duplication too many for a `a == b`.

EVIDENCE, GREEN BY EXECUTION AND DISCRIMINATING BY MUTATION
  PASS modules_under_container_admits_a_descendant_and_excludes_a_sibling
  PASS modules_under_container_is_strict_descent
  PASS modules_under_container_admits_a_deeper_descendant
Each probe was shown to fail for ITS OWN reason rather than as a blanket detector:
  drop the strictness clause  -> strict_descent FAILS, sibling still PASSES
  force segment equality true -> sibling FAILS, deeper descendant still PASSES
The population carries `gunbc.rowing` beside `gunbc.row` precisely so a string-prefix
implementation is refused where a segment-wise one is admitted.

The first high-value consumer is the failure-mode roster, whose hand-authored
membership tail re-states what containment already knows and which therefore collides
on every parallel append. That consumer is NOT part of this change: the capability
answers a namespace question and its signature and body name no ledger, roster or
doc. It is landed off main rather than on the namespace cut branch because it is
unconditional -- it repairs a different invalid state than the merge-serialization
work and neither retires the other -- and because the cut branch's corpus does not
resolve mid-transition, so no witness can be green there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwvzQ3SQoWWDgHkAeffMeF
…d to export

Replaces the enumerator this branch first carried. That function returned
FreeMonoid<QualifiedName> with a comment promising it supplied no ordering --
but FreeMonoid is Empty | Cons { head, tail }, so realization order was fully
observable in the return type. The comment stated a constraint the construction
did not enforce, satisfiable by editing the declaration while the realization
still lied, and index order is precisely the positional history a consumer must
not reconstruct. Making the wrong thing available at zero cost is how an
attractor forms; a wrapper plus stronger comments is the same defect restated.

THE RELATION, NOT THE ENUMERATION. Every caller that could ask "which modules lie
under X" already holds the finite population: v2.compiler.source_authority
supplies it through module_storage_bindings_for_source_roots, whose committed
carrier v2.test.workflow.host_module_binding_manifest is overlaid at run time and
carries the whole tree. So discovery is the consumer's fold over an index it owns,
and the only fact missing at the namespace layer is the containment decision.
Nothing is enumerated here, so there is no sequence to lend a renderer and no
comment asking anyone to ignore one. Ordering stays the consumer's to ground
independently -- a row-owned ordinal or equivalent -- which the roster's
load-bearing order requires anyway.

HOMED ON THE NAME, NOT THE INDEX. Whether one qualified name lies beneath another
is a fact about NAMES, so it belongs to v2.std.qualified_name, the authority that
owns QualifiedName. Taking a ModuleStorageBinding would couple a naming question
to one realization of where modules are kept; source_authority is untouched by
this branch as a result.

STRICT, and the rationale is corrected from the first attempt: the neighbouring
question is EXACT-IDENTITY membership (module_storage_index_contains_module folds
asking binding == module), not reflexive containment. The two are disjoint
questions rather than one refining the other, and the earlier comment described
the neighbour as doing something it does not do.

EVIDENCE, GREEN BY EXECUTION AND DISCRIMINATING BY MUTATION
  PASS admits_a_child_and_refuses_a_sibling / refuses_a_segment_that_merely_starts_with
       the_container / refuses_the_container_itself / admits_a_deeper_descendant /
       refuses_the_reverse_direction
Each probe was shown to fail for ITS OWN reason rather than as a blanket detector:
  drop the strictness clause  -> container-itself FAILS, deeper descendant PASSES
  force segment equality true -> sibling and `rowing` FAIL, deeper descendant PASSES
  reverse the prefix argument -> asymmetry and sibling FAIL
`gunbc.rowing` sits beside `gunbc.row` because a dotted-string implementation passes
every other probe and gets exactly that one wrong: containment is a relation on
segments, and a dotted string is a rendering of them.

A std defect found on the way and deliberately NOT fixed here: FinitePowerSet is
declared foldable by its own profile authority (dag/std/computation.dag,
FinitePowerSetProfile => CollectionFold) and by its own doc block ("the other can be
walked"), and its four cited realizations -- BTreeSet, go map, python set, TypeScript
Set -- are all enumerable, yet the type carries member/union/intersect/diff/contains/
count/length and NO walk. Three authorities against the fields. That is a std
authority contradiction with its own review, not this branch's business.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwvzQ3SQoWWDgHkAeffMeF
…ly in the body

review 62506 is right that the relation is unconsumed outside its own probes, and
right that the header argued about hypothetical callers instead of naming a real
one. §3c admits a later consumer only with the trigger stated beside it, and the
place a later reader greps is the tree, not a pull request body -- a body does not
travel with the declaration, and this one had already gone stale against the rework.

So the frontier is now written at the declaration: the named consumer is the
failure-mode roster's hand-authored membership tail, and the trigger is stated as a
CAPABILITY -- membership derived from the row-files so no tail must be edited to
register a row -- with a batch split or reformat explicitly not satisfying it. A
trigger naming less than the capability it restores is satisfied while the
capability stays dead, which is the §4b(3) failure this wording exists to avoid.
Ordering is excluded from the trigger for the reason the relation exports no
sequence at all.

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

gunbai-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Fixed at the source in f2d300ecf9, and verifying the finding turned up a second defect the review could not see.

The §3c finding is correct and the fix is where you put it, not where I had it. I had stated the frontier — but in the PR body. Your framing is sharper: §3c admits a later consumer only with the trigger stated beside the declaration, and the place a later reader greps is the tree, not a pull request body. The frontier now sits in src/v2/std/qualified_name.dag next to the relation: named consumer is the failure-mode roster's hand-authored membership tail, and the trigger is stated at capability grain — roster membership derived from the row-files, so no tail must be edited to register a row — with a batch split or reformat explicitly not satisfying it. That wording is deliberate: §4b(3) is precise that a trigger naming less than the capability it restores gets satisfied while the capability stays dead. Ordering is excluded from the trigger, for the same reason the relation exports no sequence at all.

The second defect, which is mine and which the review's evidence surfaced. The body still described modules_under_container in four places — a function this branch's rework deleted. So my own §3c frontier paragraph was naming a declaration that no longer exists. That is exactly the stale-claim shape (stale_claim_survives_its_own_correct_edit): the claim was true when written, the edit that falsified it was correct, and nothing joined the two. It is also the argument for your fix rather than mine — a frontier in a body can go stale against its own diff without anything refusing, while one beside the declaration is edited by the same hands that change the declaration. The body is rewritten against the actual head.

Also removed the header sentence you flagged as arguing about hypothetical callers instead of naming a real one.

The relation itself is unchanged, and re-verified after the edit: five probes green, each shown to fail for its own reason under three targeted mutations (drop strictness → container-itself reds alone; force segment equality true → sibling and rowing red, deeper descendant stays green; reverse the prefix argument → asymmetry and sibling red).

— sent from quick-heron-85

@gunbai-bot

gunbai-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing this, and stating the classification rather than a softer word, so the closure is greppable evidence.

The trigger fired while this PR was in review. #10822 merged at 15:04Z. Verified on origin/main rather than taken on report: dag/gunbc/recurring_failure_mode/roster.dag no longer exists, and membership is now derived by reading the row directory (row_stems in src/v1/stage0/src/cli_run/derived_row_roster.rs, over the 178 row files). That is exactly the capability this declaration's frontier named — "roster membership becomes DERIVED from the row-files, so no hand-authored tail must be edited to register a row."

So under DESIGN §3c this declaration is no longer a declared frontier; it is dangling — the named consumer has been satisfied by other means, and nothing in this closure reads the relation except its own probes. Dangling is the one state §3c calls red, and the right response is to withdraw the declaration, not to keep it.

Not repointing the frontier at the next rung. The obvious salvage is to aim it at whatever the roster needs next, and main says that is not membership: roster_re_enumerates_its_own_rows_stall records that membership discovery already exists via data_decl_type_facts, and what remains is declaration value binding — binding a discovered declaration as a typed value. A Bool relation over two QualifiedNames does not supply that. Repointing would be a second prospective promise with no established consumer: the same defect one step to the left.

The relation and its probes were sound — five green, each shown to fail for its own reason under three targeted mutations, including the row/rowing segment-versus-string control. Nothing here was wrong; the requirement was discharged elsewhere first, which is a different thing and worth recording as such.

One durable finding survives this closure, and it argues for the review that produced it: review 62506 moved the frontier from the PR body into the tree beside the declaration. That is the only reason the firing was discoverable — a body is not greppable, so this declaration would have landed dangling and stayed that way. It is also the specimen for a defect worth filing: a declared consumption frontier can outlive the firing of its own trigger with nothing reclassifying it. A human reader caught it; nothing mechanical refused.

— sent from quick-heron-85

@gunbai-bot gunbai-bot Bot closed this Sep 8, 2026
@gunbai-bot
gunbai-bot Bot deleted the ns/containment-membership-enumerator branch September 8, 2026 16:04
briansrls pushed a commit that referenced this pull request Sep 9, 2026
Review 62904 found `src/v2/test/claim/modules_under_container_test.dag` in a
commit whose own message calls itself the exact inverse of d2559c3. Verified,
all three ways it stated: the file is absent from origin/main, a clean revert of
that commit touches six files and this is a seventh, and the subject it imports --
`modules_under_container` -- is defined nowhere in the tree. It is residue from
the CLOSED #10836, whose FreeMonoid-returning version was withdrawn; it survived
as an untracked file in this worktree and I swept it in with `git add -A`.

So the commit added a test over a subject that does not exist (DESIGN section 6,
a new artifact with no final consumer) inside an operator-gated revert of a
required-gate arm, which is the last place unrelated work should ride along.

The claim was the worse half of the defect. "Exact inverse" was checkable and
false, and a reader who trusted it would not have looked -- the same shape as the
arm this branch deletes, where four reviewers checked that a thing was correct
and none checked that it was still needed. The revert IS a clean `git revert` of
d2559c3; the message asserted more than the diff delivered.

The six arm files are untouched by this commit and remain byte-for-byte the
inverse. The file is preserved outside the repo, not lost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwvzQ3SQoWWDgHkAeffMeF
briansrls pushed a commit that referenced this pull request Sep 9, 2026
…classifies a delta that no longer occurs (#10889)

* Delete the derived-generator-input arm: #10856 fixed the root, so it classifies a delta that no longer occurs

#10871 auto-admits a `0 -> 1` binding on the derived failure-mode roster whose
every candidate is a module of the generator's declared input directory. That
delta no longer exists, and it was already gone when the arm merged.

#10856 (aba7939, 2026-09-08T18:51:35-04:00) fixed the ROOT. Its own doc block
states the mechanism: `roster.dag` is gitignored and written on the read path, so
a baseline reconstructed by dropping only diff-TOUCHED paths inherited the HEAD's
roster bytes as the BASE's. Base and head were the same bytes, so an ordinary
append read as not-locally-authored and classified NewPoolCoincidenceResolution.
With the base side derived from the base tree's row membership, an append
produces no binding delta at all.

#10871 (d2559c3) merged at 23:19:18 -- four and a half hours later --
classifying that symptom.

MEASURED, THREE RUNS ACROSS TWO BRANCHES, all on base 3480039:
DerivedGeneratorInputResolution count 0 in every floor log; NewPoolCoincidence-
Resolution count 0; no binding deltas at all. Both ledger PRs adjudicated on
membership alone.

Three DESIGN readings, all pointing the same way. Section 3: with the root fix
landed, the symptom classifier is a second structure answering one question, and
the surviving one is an attractor. Section 3c: its only consumers were the two
fixtures shipped with it. Section 5: a populationless arm that WIDENS what a
required gate auto-admits cannot go red, and will be cited as coverage of a class
it never sees.

The deletion is the census. If a real delta of that shape exists, the gate refuses
and names it -- which is the evidence the arm never had.

NO REGRESSION PROBE IS ADDED, AND THAT IS ARGUED RATHER THAN OMITTED. The obvious
worry is that the root fix could regress with nothing to catch it. #10856 already
enrolled that evidence: `the_base_side_is_the_base_listing_not_the_head_directory`
and `a_base_tree_with_no_row_files_has_no_roster_module_rather_than_an_empty_one`
in `derived_row_roster`, both passing here. A second probe would fork existing
evidence. What is true, and is a pre-existing declared drop rather than this
change's to repair, is that those are `#[cfg(test)]` under `repo_self_test_command`,
which no CI step runs -- `gunbc.rung_drop` `rust_unit_tests_off_the_merge_path`.
The evidence exists at rung 2 and does not execute on the merge path. That gap is
the same with or without this revert; the arm did not close it, because an
auto-admission cannot be evidence of anything.

Reverts #10871 (d2559c3) in full. Nothing has touched these files since, so
this is the exact inverse rather than a hand-reconstruction. 50 wall tests pass.

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

* Drop a stowaway: this branch was NOT the exact inverse it claimed to be

Review 62904 found `src/v2/test/claim/modules_under_container_test.dag` in a
commit whose own message calls itself the exact inverse of d2559c3. Verified,
all three ways it stated: the file is absent from origin/main, a clean revert of
that commit touches six files and this is a seventh, and the subject it imports --
`modules_under_container` -- is defined nowhere in the tree. It is residue from
the CLOSED #10836, whose FreeMonoid-returning version was withdrawn; it survived
as an untracked file in this worktree and I swept it in with `git add -A`.

So the commit added a test over a subject that does not exist (DESIGN section 6,
a new artifact with no final consumer) inside an operator-gated revert of a
required-gate arm, which is the last place unrelated work should ride along.

The claim was the worse half of the defect. "Exact inverse" was checkable and
false, and a reader who trusted it would not have looked -- the same shape as the
arm this branch deletes, where four reviewers checked that a thing was correct
and none checked that it was still needed. The revert IS a clean `git revert` of
d2559c3; the message asserted more than the diff delivered.

The six arm files are untouched by this commit and remain byte-for-byte the
inverse. The file is preserved outside the repo, not lost.

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

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 <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