Skip to content

Pin the sort that main's deduplicate_identities repair depends on for correctness - #10012

Merged
gunbai-bot[bot] merged 4 commits into
mainfrom
session/stern-lark-508
Sep 2, 2026
Merged

gunbai-bot[bot] merged 4 commits into
mainfrom
session/stern-lark-508

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Rewritten after main landed a competing repair for the same defect. The original PR replaced deduplicate_identities; that change is gone. What remains is 28 lines in one file: the control main's repair is missing.

What happened, and why my patch is not here

While this PR waited for a floor slot, main landed its own repair of the same quadratic dedup — sort first, then compare against the last kept element. Mine used a Set for membership and list_push for the accumulator. Both fix the quadratic scan; I argued mine additionally fixed a copied accumulator (concat(unique, [identity]) in a fold), which is the §6 bare-minimum-cost shape.

I measured that argument instead of asserting it, and it did not survive. Three variants over an amplified probe — ~720 identities with every one duplicated, ten dedup passes per run, two rounds, same host:

variant round 1 round 2
mine (Set + list_push) 112.1s 110.3s
main's (sort + last + concat) 110.6s 127.3s
main's with list_push 110.9s 137.6s

Round 1 spans 1.5%; round 2 is dominated by host noise in the wrong direction. concat(unique, [identity]) is not a measurable O(n) copy in this interpreter, so §6 does not distinguish the two implementations — and forking a landed fix on an unmeasured preference is exactly what this project keeps catching. main's implementation is taken whole: dag/gunbc/self_host_compile_phase_frontier.dag is byte-identical to origin/main on this branch.

What survives is a gap in that fix, not a competing one

main's fold compares only against the last kept element. That is sound exactly because the input was sorted first, so equal identities are adjacent. The sort is a correctness precondition, not a presentation choice — and nothing in the corpus pins it. Delete |> sort_by(identity => identity) and the fold silently stops collapsing duplicates separated by any other identity, while still collapsing adjacent ones: a dedup that works on the easy inputs and quietly fails on the real ones.

Measured, including the part that decides whether it is worth landing

A  new witness against main's implementation                      PASS
B  same witness, `sort_by` deleted                                FAIL
C  the four pre-existing duplicate-wall witnesses vs that mutant  ALL PASS

C is the finding. a_repeated_population_entry_is_refused_rather_than_collapsed, a_duplicated_census_population_is_not_silently_collapsed_to_a_set, a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence and current_persisted_compile_phase_frontier_holds all stay green with the sort removed. This arm is the only thing in the corpus that reddens on it.

The subject is chosen so the mutant cannot pass: ["b", "a", "b"] holds a duplicate that is not adjacent in encounter order — 2 elements under the sorted fold, 3 without the sort — with the all-adjacent cases beside it as the positive control the mutant still passes. That pairing is what makes the first arm discriminating rather than the set being merely two examples.

It asserts duplicate survival rather than output order, deliberately. Encounter order is unobservable through both consumers — canonical_identity_set sorts its result and census_population_is_duplicate_free reads only the count — so an order assertion would pin a property no caller can distinguish. The previous revision of this branch asserted exactly that, and main's change would have reddened it.

Floor

The prior head's floor reading is recorded in the comment above, including that it was the third attempt and therefore a counted retry-until-green mitigation under gunbc.rung_drop floor_cost_contention_verdict, not a verdict about the tree. This head needs its own run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W377Pq4Tp5eQjGBXtPQEoM

Brian Searls and others added 3 commits September 2, 2026 06:01
…er the corpus census

DESIGN §6's bare-minimum-cost standing rule: a proven cost-shape defect — a copied
accumulator, a quadratic fold — is always fixed, regardless of the realized n. This is
both, in one expression, over a population that is not small and does not stay fixed.

WHAT IT WAS. `deduplicate_identities` decided membership by rescanning the survivors it
had already kept (`any(unique, prior => prior == identity)`) and extended them by copying
them (`concat(unique, [identity])`). Both halves are O(n) per element, so the fold is
quadratic in comparisons AND quadratic in list construction.

WHY n IS NOT SMALL HERE. The argument is a whole-corpus rustc diagnostic census: the two
persisted receipts carry `genesis_5006ddc6_raw_error_diagnostic_identities` and
`receipt_1_eced9d24_raw_error_diagnostic_identities`, and the population is the emitted
compiler's error identities — it grows as the self-host corpus grows. It is reached from
`canonical_identity_set` (every phase row, every unplaced/codeless partition) and from
`census_population_is_duplicate_free` (twice per receipt in `receipt_population_coherent`),
so the whole series ratchet pays it repeatedly.

WHAT IT IS NOW. One traversal carrying the two questions it was conflating in one list:
`seen` (a `Set<String>`) answers "has this identity been kept", `unique` answers "in what
order". The `std.graph` DFS accumulators are the same shape for the same reason.

BEHAVIOUR IS UNCHANGED, deliberately and at both grains that are observable. Order:
an identity is appended exactly at its first occurrence, as before — and every caller
except `census_population_is_duplicate_free` sorts afterwards through
`canonical_identity_set`, which only counts. Multiplicity: the function still collapses
repeats rather than refusing them, so the duplicate WALL stays exactly where it was —
upstream, in `census_population_is_duplicate_free` and `receipt_population_coherent`,
which is the distinction `a_duplicated_census_population_is_not_silently_collapsed_to_a_set`
exists to hold.

EXECUTED EVIDENCE, not a typecheck. Eight enrolled witnesses over the real persisted
series and the duplicate walls pass on this tree, run individually through
`gunbc run --claim-run --source-root dag --source-root src/v2 --entry
dag/test/claim/self_host_compile_phase_frontier_witness_test.dag --function <claim>`:
`a_repeated_population_entry_is_refused_rather_than_collapsed`,
`a_duplicated_census_population_is_not_silently_collapsed_to_a_set`,
`a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence`,
`the_same_receipt_without_the_repeat_is_coherent`,
`current_persisted_compile_phase_frontier_holds`,
`the_census_digest_is_invariant_under_reordering_of_either_population`,
`the_persisted_genesis_census_is_fully_attributed_to_its_phases`,
`phase_boards_are_invariant_under_population_reordering`.
The first four are the discriminating REDs for this change: collapsing a duplicated
population, or refusing one that is clean, reddens them.

THIS IS A COST-SHAPE REPAIR, NOT A FLOOR UNBLOCK. It is landed on its own terms because
§6 requires it, not to buy headroom for any claim. The separate question — that ten
required-floor claims each recompute the whole series ratchet, which is authored
duplication under §2 and wants one provider at their least common ancestor — is a
restructure and lands separately, so its design review does not hold this defect hostage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W377Pq4Tp5eQjGBXtPQEoM
Set equality is not the acceptance test for a set-backed deduplicate. A dedup that
returns the SET's ordering produces the same MEMBERS in a different ORDER: identical
for a caller that counts, byte-drifting for a caller that renders. The previous commit
asserted order was preserved; this one proves it, and proves the assertion can fail.

THE FIXTURE IS CHOSEN SO THE TWO ANSWERS CANNOT COINCIDE. First-occurrence order over
["b", "a", "b", "c", "a"] is ["b", "a", "c"]; every sorted or set-ordered spelling
answers ["a", "b", "c"]. A population that happened to arrive already sorted would let
an ordered-equality assertion pass while discriminating nothing, which is why the
subject is authored rather than read off the live series.

THE MUTANT IS THE WHOLE CHECK, and it was run rather than described. Planting
`|> sort_by(identity => identity)` on the accumulator's result — the set-ordered
variant — turns this arm RED, and turns RED a probe comparing the new function against
the PRE-CHANGE algorithm over both live populations
(`genesis_5006ddc6_raw_error_diagnostic_identities`,
`receipt_1_eced9d24_raw_error_diagnostic_identities`). Unmutated, both pass: the new
function answers the old function's exact ordered sequence on the real corpus census,
not merely its member set. Four arms, in one run: A pass, B pass, C fail, C2 fail.

WHERE THE ORDER CAN AND CANNOT ESCAPE. `deduplicate_identities` has exactly two
consumers in the corpus: `canonical_identity_set`, which sorts the result and therefore
erases order, and `census_population_is_duplicate_free`, which counts it. The projection
consumer — `gunbc.design_ledgers compile_phase_frontier_blocks`, which renders committed
bytes into docs/design-ledgers.md — reaches it only through the sorting one, and that
order-independence is separately executed by
`the_census_digest_is_invariant_under_reordering_of_either_population` and
`phase_boards_are_invariant_under_population_reordering`, both passing here. So the
projected bytes cannot move under this change by construction, which is a stronger
statement than one byte comparison over one population would have been.

The arm is therefore not a belt on either current caller. It holds the contract for the
NEXT consumer — the one that would not survive a silent reordering, and that would
discover it as generated-artifact drift at a distance from the diff that caused it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W377Pq4Tp5eQjGBXtPQEoM
… two compiler_tests failures on this PR's run are main's, inherited through a merge ref pinned at 06:47Z against bb96afa

The merge ref CI built for f3839b2 was pinned at push time against main as it
then stood (bb96afa), which carried #9886's stale mirror. That is the exact
subject #10017 repaired at 06:56Z, nine minutes after this PR's run started.

Evidence, checked rather than assumed:
  - main at bb96afa, run 33596615712: 'test result: FAILED. 642 passed; 2
    failed' with render_rust_applied_type_routes_qualified_base_through_leaf_name
    and shell_service_unmodeled_output_key_refuses -- byte-identical counts and
    identities to this PR's rust-unit-tests failure.
  - #10017's own body names 'regen FAIL generated surface drift:
    compiler_tests.rs, std_realization_schedule.rs' reproduced on 4059156 and
    bb96afa -- the same two files this PR's build job reported.
  - This branch changes two .dag files and no Rust: git diff origin/main...HEAD
    over compiler_tests.rs and std_realization_schedule.rs is empty.

Merging rather than rebasing per the squash-merge policy, and pushing after
main's last move so the merge ref is recomputed against the repaired base.

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

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Floor: FloorClean — and the attempt count, because the green is a mitigation and not a verdict

required-witnesses-floor passed on head 76fd88e0 (run 33609023769): planned=3478 executed=3478 passed=3403 failed=0 unexpected_failures=0 interrupted_before_verdict=0, verdict=FloorClean. required-witnesses-build and the required witnesses aggregate pass.

This was the third floor attempt on this head, and I am reporting that rather than presenting the green on its own. gunbc.rung_drop floor_cost_contention_verdict (declared 2026-09-01, standing) says in its own words: "re-running an undecided row until it answers is retry-until-green — fail-open wearing a fail-closed label — admissible only as a counted, visible mitigation carrying this row's trigger as its dissolution condition." That is what these re-runs are. The count is three, the mitigation is visible here, and its dissolution condition is that row's trigger — a claim-owned cost basis invariant across execution envelopes — not this green.

The two prior attempts on the identical commit were FloorRefused with failed=0 and disjoint victim sets:

attempt interrupted victims
1 1 rust_produced_decl_name_discriminates
2 4 the_live_census_partitions_on_both_axes, an_empty_receipt_series_leaves_the_live_tree_unmeasured_rather_than_held, produced_decl_two_targets_render_own_order, rust_call_fold_closure_swap_discriminates
3 0 —

Attempt 1's victim passed in attempt 2 at 479ms. Four unrelated families. None of those rows is reachable from this diff.

The measurement this PR is actually about

claim last clean main (fb481ae0) clean sibling #10014 this PR (clean)
current_persisted_compile_phase_frontier_holds 422 446 404
the_published_frontier_standing_… 438 437 395

cpu_ms against the 500ms ceiling, three independent clean runs. The quadratic repair moves both claims down and the direction is consistent.

It does not clear the tip, and this PR does not claim to. The population over the 100ms line on the green run is 267 further rows beyond the 25 printed; the band sits well inside contention range of the ceiling, and the victim rotates with host load rather than with the tree. That is the standing drop's subject, not this PR's.

Remaining red

rust-unit-tests fails on shell_service_unmodeled_output_key_refuses. It is main's: sibling PR #10014 reports the identical 644 passed; 1 failed with the same identity, and this branch changes no Rust. It does not feed the required witnesses aggregate (.github/workflows/witnesses.yml — needs: [required-witnesses-build, required-witnesses-floor]), which is why GitHub reports UNSTABLE and admissible rather than blocked.

— sent from stern-lark-508

…control it is missing

main landed a competing repair for the same defect while this PR waited for a floor
slot (`|> sort_by` then compare against the last kept element). Mine used a Set for
membership and `list_push` for the accumulator. Both fix the quadratic scan; I argued
mine additionally fixed a copied accumulator, and I measured that argument rather than
asserting it.

THE MEASUREMENT REFUTES MY PATCH. Three variants over an amplified probe — ~720
identities with every one duplicated, ten dedup passes per run, two rounds, same host:
mine 112.1s / 110.3s, main's 110.6s / 127.3s, main's-with-`list_push` 110.9s / 137.6s.
Round one spans 1.5% and round two is dominated by host noise in the wrong direction.
`concat(unique, [identity])` is not a measurable O(n) copy in this interpreter, so §6's
bare-minimum-cost argument does not distinguish the two implementations. Forking a
landed fix on an unmeasured preference is the thing this project keeps catching, so
main's implementation is taken whole and `dag/gunbc/self_host_compile_phase_frontier.dag`
is byte-identical to `origin/main` in this commit.

WHAT SURVIVES IS A GAP IN THAT FIX, NOT A COMPETING ONE. main's fold compares only
against the LAST KEPT element, which is sound exactly because the input was sorted first
— equal identities are adjacent. The sort is therefore a correctness precondition, not a
presentation choice, and nothing in the corpus pins it: delete `|> sort_by(identity =>
identity)` and the fold silently stops collapsing duplicates separated by any other
identity while still collapsing adjacent ones.

MEASURED, NOT ASSERTED, INCLUDING THE PART THAT DECIDES WHETHER IT IS WORTH LANDING:
  A  new witness against main's implementation                      PASS
  B  same witness, `sort_by` deleted                                FAIL
  C  the four pre-existing duplicate-wall witnesses vs that mutant  ALL PASS

C is the finding. `a_repeated_population_entry_is_refused_rather_than_collapsed`,
`a_duplicated_census_population_is_not_silently_collapsed_to_a_set`,
`a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence` and
`current_persisted_compile_phase_frontier_holds` all stay green with the sort removed, so
this arm is the only thing in the corpus that reddens on it.

THE SUBJECT IS CHOSEN SO THE MUTANT CANNOT PASS: `["b", "a", "b"]` holds a duplicate that
is not adjacent in encounter order — 2 under the sorted fold, 3 without the sort — and the
all-adjacent cases sit beside it as the positive control the mutant still passes, which is
what makes the first arm discriminating rather than the set being merely two examples.

IT ASSERTS DUPLICATE SURVIVAL RATHER THAN OUTPUT ORDER, deliberately. Encounter order is
unobservable through both consumers (`canonical_identity_set` sorts its result,
`census_population_is_duplicate_free` reads only the count), so an order assertion would
pin a property no caller can distinguish — and the previous revision of this branch did
exactly that, which main's change would have reddened.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W377Pq4Tp5eQjGBXtPQEoM
@gunbai-bot gunbai-bot Bot changed the title deduplicate_identities is a copied accumulator in a quadratic fold over the corpus census Pin the sort that main's deduplicate_identities repair depends on for correctness Sep 2, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Sep 2, 2026
…he sort control

No conflicts — the collapse touches compile_phase_frontier_standing and its consumers,
while the dedup repair and its new control sit in a different region of the same module.

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

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

New head 48bf811a — FloorClean on the first attempt, and that is not a fourth retry

required-witnesses-floor pass, required-witnesses-build pass, the required witnesses aggregate pass, fabric-evidence pass (run 33625112248). verdict=FloorClean, planned=3487 executed=3487 passed=3412 failed=0 unexpected_failures=0 interrupted_before_verdict=0.

The attempt accounting, because a run list cannot distinguish these two things and the previous comment on this PR would otherwise be read as a count of four.

  • The three attempts recorded above were on head 76fd88e0, on one unchanged commit, re-run because a claim went undecided on budget. Those are the counted retry-until-green mitigation under gunbc.rung_drop floor_cost_contention_verdict, and that count stopped at three.
  • This is not a fourth. 48bf811a is a different commit — it drops my deduplicate_identities implementation in favour of main's and replaces the order witness with the sort-precondition control — and it is the first floor run of that commit. Nothing was retried; a new subject was evaluated once and came back clean.

Three-of-one-kind and one-of-another. A bare count of four would be dishonest in the direction that flatters this PR, which is why it is spelled out.

The measurement, for the record

claim cpu_ms
current_persisted_compile_phase_frontier_holds 433
the_published_frontier_standing_… 424

These are not evidence for this PR and are recorded only so the series stays continuous. This head carries main's deduplicate_identities, not mine, so both figures are properties of main's repair plus this run's host load — they sit between the 404/395 and 446/437 already observed on other clean runs of the same implementation family, which is the band moving, not a change in the code.

On the earlier rust-unit-tests red

shell_service_unmodeled_output_key_refuses was repaired on main by another lane (green across five SHAs from 10:54Z), and this head already carries that base — baf6a7ce is an ancestor of 48bf811a. So the red that stood on the previous head was an artifact of a merge ref pinned before the fix, and no re-run was needed to clear it: the rewrite that resolved the merge conflict picked up the repair as a side effect.

— sent from stern-lark-508

@gunbai-bot
gunbai-bot Bot merged commit d6a7a0e into main Sep 2, 2026
6 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/stern-lark-508 branch September 2, 2026 13:55
@briansrls
briansrls restored the session/stern-lark-508 branch September 3, 2026 00:37
@gunbai-bot
gunbai-bot Bot deleted the session/stern-lark-508 branch September 3, 2026 00:38
@briansrls
briansrls restored the session/stern-lark-508 branch September 3, 2026 01:23
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