Skip to content

fix(sync): keep a real per-tuple floor when canonical gains a clause - #4

Merged
PerryLink merged 1 commit into
masterfrom
fix/peer-range-floor-merge
Sep 20, 2026
Merged

PerryLink merged 1 commit into
masterfrom
fix/peer-range-floor-merge

Conversation

@PerryLink

Copy link
Copy Markdown
Owner

targetRange() returned the canonical range as soon as the clause counts differed:

if (!cur || !can || cur.length !== can.length) return canonical

That was harmless only while canonical never changed length — and #2 added the 0.1.6-0 clause, which is exactly a length change. From that commit on, the sync tool silently downgrades any repository whose declared range has a different clause count while carrying a genuinely higher floor:

repo declares canonical old result wanted
>=0.1.2-rc.1 <0.2.0 || >=0.1.5-rc.1 <0.2.0 3 clauses >=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 — the 0.1.5-rc.1 floor is lost keep 0.1.5-rc.1
>=0.1.5-rc.1 <0.2.0 3 clauses canonical — floor lost keep 0.1.5-rc.1

This matters more than a normal edge case because --write is the tool the whole ecosystem is re-pinned with: running it would quietly walk real per-package floors backwards.

Fix. When the counts match, keep the pairwise merge as before. When they differ, pair clauses by [major, minor, patch] tuple instead, so a higher floor in a shared tuple survives while the new clause is added; a current clause whose tuple canonical does not carry is preserved only when its floor is above every canonical floor (a real requirement), and anything below is still raised to canonical (drift-low).

Tests. test/sync-peer-range.test.mjs gains the two-clause and single-clause merge cases, and the end-to-end fixture now exercises the merge (it previously used a floor raised above canonical so the old bypass never ran). test/check-peer-range-latest.test.mjs's CANONICAL constant is updated to the three-clause shape and the "future tuple" assertion moves to 0.1.7-rc.1, so the tripwire test still tests what it says.

Data note. data/peer-range.json now records why the third clause uses a -0 floor (it admits every 0.1.6 prerelease, including 0.1.6-alpha.2) rather than the bare >=0.1.6 form the tripwire warns about.

Not in this PR — the compat.yml re-anchor. The workflow change (weekly 0 4 * * 1 + pull_request instead of monthly; pin @deepseek-ai/dsh@0.1.6-alpha.2, dsh-base/dsh-headless@0.1.6-alpha.2; minimumReleaseAge: 0 in the scratch profile; keeping #1's 25-minute cap) cannot be pushed with the token this branch was prepared with — GitHub rejects any push touching .github/workflows/* without the workflow scope. The ready-to-apply patch is kept outside the repository and will be applied separately.

Gate on this branch: pnpm run build ✓ · pnpm run typecheck ✓ · pnpm test 66 passed / 9 files ✓ · verify-self-contained ✓ · verify-artifacts ✓.

targetRange() returned canonical as soon as the clause counts differed, which was safe only while canonical never changed length. Adding the 0.1.6-0 clause changed exactly that: a repo declaring '>=0.1.2-rc.1 <0.2.0 || >=0.1.5-rc.1 <0.2.0' (a genuinely higher 0.1.5 floor) was silently rewritten down to canonical's >=0.1.5-alpha.1, and a single-clause '>=0.1.5-rc.1 <0.2.0' lost its floor the same way. Clauses now pair by [major, minor, patch] tuple when the counts differ, so the higher floor survives while the new clause is added. Tests cover both shapes and the end-to-end fixture exercises the merge instead of the raised-floor bypass. data/peer-range.json documents why the third clause uses a -0 floor.
@PerryLink
PerryLink merged commit 46a9827 into master Sep 20, 2026
10 checks passed
@PerryLink
PerryLink deleted the fix/peer-range-floor-merge branch September 20, 2026 14:04
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