Skip to content

fix: Julia 1.12 CI floor ([sources] needs Pkg 1.11+); idempotent canonicalize_presentation#76

Merged
hyperpolymath merged 3 commits into
mainfrom
fix/canonicalize-idempotent
Jul 21, 2026
Merged

fix: Julia 1.12 CI floor ([sources] needs Pkg 1.11+); idempotent canonicalize_presentation#76
hyperpolymath merged 3 commits into
mainfrom
fix/canonicalize-idempotent

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Two follow-ups to #72 (squash-merged as 28505a5 with its first CI run still red):

1. CI: the new Julia job needs Julia ≥ 1.11

The krl-tests job added in #72 installed Julia 1.10, but server/Project.toml resolves its unregistered sibling deps (KnotTheory.jl / Skein.jl / AcceleratorGate.jl) through a [sources] table — a Pkg 1.11+ feature that 1.10 silently ignores. Pkg.instantiate therefore fell back to a registry lookup and died with expected package KnotTheory [215268c9] to be registered (observed on #72's CI run). Local verification had run on 1.12.6, which is why it passed there. CI now pins the 1.12 juliaup channel, with a comment explaining the floor.

2. canonicalize_presentation was not idempotent

The single BFS-relabelling pass can change the very ordering it derived labels from, so blob(canonicalize(p)) ≠ blob(canonicalize(canonicalize(p)))measured at 95/200 seeded BR-5 trials once the upstream KnotTheory.jl PD-integrity bugs (hyperpolymath/KnotTheory.jl#43) were fixed and the harness could see real diagrams. A fingerprint that changes when you canonicalise twice cannot serve as a semantic identity.

Fix: iterate the pass, detect the inevitable cycle of serialised states, and return the lexicographically minimal state on the cycle — a fixed point reached from every presentation in its orbit. Where the old pass was already stable (the entire shipped test corpus), output is unchanged, so stored fingerprints remain valid.

Verification

BR-5 fuzz, 200 trials, against KnotTheory.jl with the #43 fixes applied:

Suite Result
presentation well-formedness 6752/6752 pass
descriptor determinism 800/800 pass
crossing-order invariance 600 pass + 1 expected Broken (11/200 quandle_key residual → upstream KnotTheory.jl#42)
canonical-blob round-trip (incl. idempotency) 600/600 pass — was 95/200 failing before the fix

Merge order

This PR is independent of KnotTheory.jl#43 (it validates against both old and fixed KnotTheory — the idempotency fix only touches quandledb's own layer). Once #43 merges upstream, the @test_broken R2 marker in test_quandle_axioms.jl flips to "unexpected pass" by design; a marker-removal PR follows then.

🤖 Generated with Claude Code

hyperpolymath and others added 2 commits July 21, 2026 14:03
The krl-tests job installed Julia 1.10, but server/Project.toml resolves
its unregistered siblings (KnotTheory/Skein/AcceleratorGate) through a
[sources] table — a Pkg 1.11+ feature that 1.10 silently ignores, so
Pkg.instantiate fell back to a registry lookup and failed with
'expected package KnotTheory [215268c9] to be registered' (observed on
this PR's first CI run). Local verification ran on 1.12.6; pin CI to the
1.12 channel to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cle minimum

The old single relabelling pass was not idempotent: BFS relabelling from
the canonical-pass ordering can itself change the ordering, so
blob(canonicalize(p)) != blob(canonicalize(canonicalize(p))) — measured
at 95/200 seeded BR-5 trials once the upstream KnotTheory.jl PD-integrity
bugs (braid strand-swap, r2_simplify re-splice) were fixed and the
harness could see it.

Fix: iterate the pass, detecting the inevitable cycle of serialised
states, and return the lexicographically minimal state on the cycle.
That choice is a fixed point (canonicalising it lands back on it) and is
reached from every presentation in the same orbit. Where the old pass
was already stable — every presentation in the shipped test corpus —
the result is unchanged, so stored fingerprints remain valid.

Also factors _presentation_serial out of canonical_presentation_blob so
the cycle detector and the blob share one serialisation.

Validated: BR-5 fuzz, 200 trials against fixed KnotTheory.jl — 8752
assertions pass, 0 hard failures, 1 expected Broken (11/200 quandle_key
residual, upstream KnotTheory.jl#42).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## Summary

Removes the `@test_broken` marker on the R2-invariance 5-colouring
assertion in `server/test_quandle_axioms.jl`, restoring the plain hard
`@test`.

The marker tracked an upstream defect: `r2_simplify` in KnotTheory.jl
removed a bigon without re-splicing the severed arcs, so the trefoil's
extracted presentation gained 2 phantom generators and its 5-colouring
count came out 25 instead of 5. That is fixed in
**hyperpolymath/KnotTheory.jl#43** (union-find arc re-splice + the braid
strand-swap fix underneath it).

## Merge order — do not merge early

1. quandledb #76 (CI Julia 1.12 floor + idempotent canonicalisation)
2. **KnotTheory.jl#43** ← this PR's CI checks out that repo's *default
branch*, so until #43 merges the restored hard assertion fails here (red
is expected and correct)
3. this PR

The `@test_broken` mechanism makes step 3 mandatory rather than
optional: once #43 merges, the marker reports "unexpected pass" — a hard
error — in #76's follow-up CI runs, and this PR is the remedy.

## Verification

With the #43 fix applied locally (Julia 1.12.6, 200-trial BR-5 corpus):
the axioms suite passes fully with the hard assertion restored; the only
remaining Broken mark in the repo is the BR-5 `quandle_key`
order-sensitivity counter (11/200 residual, upstream KnotTheory.jl#42 —
polynomial unit normalisation, deliberately kept).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit 0c2d9ba into main Jul 21, 2026
8 of 18 checks passed
@hyperpolymath
hyperpolymath deleted the fix/canonicalize-idempotent branch July 21, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant