Skip to content

Two spellings of one version constraint are one source (#647 E4.2 follow-up) - #651

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/feature-deps-source-comparison
Sep 16, 2026
Merged

Sunrisepeak merged 1 commit into
mainfrom
fix/feature-deps-source-comparison

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Self-review of #650, before 2026.9.16.1 is released, found that the gate #647 E4.2 added refuses a manifest the previous release builds. The release dispatch was cancelled for this; 2026.9.16.1 ships from this branch instead.

The reading

[dependencies]
fmtlib.fmt = ">=11.0.0"
[feature-deps.extra]
fmtlib.fmt = { version = ">= 11.0.0", reexport = true }
engine result
2026.9.15.2 (released) builds, no error and no warning
2026.9.16.1 (f4529b2a) error: ... restates the dependency 'fmtlib.fmt' with version = ">= 11.0.0", while the declaration in effect on this row names version = ">=11.0.0".

One space turns a build that worked yesterday into a refusal.

The change

A [feature-deps] restatement must name its dependency's source, and one naming another source is refused rather than silently dropped. The comparison was made on the bytes. A path was normalised first, so a path dependency was already judged on what it means; a version constraint was not. The judgement is now made on what the declarations mean -- the constraint is compared with its whitespace removed -- while the message still shows each declaration as it was written, so a genuine disagreement reads as the manifest spells it.

The same review asked why the first custom-index sync does not go through decide_for_miss/apply. It should not: that pair's debounce and one-sync-per-process guard are about the index that resolves a dependency, while this sync creates a local copy of a different set of repositories that nothing else will create, so taking the guard would let an earlier refresh of the builtin index suppress a clone the build cannot proceed without. Only the opt-outs are shared. The comment now states which half is taken and why the other is not.

Verification

  • e2e 711 gains a leg: a restatement differing only in whitespace is not refused, and one naming >=9.9.8 against >=9.9.9 still is. On f4529b2a the first half fails with the refusal quoted above.
  • Unit tests: 121 passed, 0 failed.
  • e2e 187, 710, 711, 712, 713, 714 pass locally.

…low-up)

Self-review of #650 before releasing 2026.9.16.1 found that the gate E4.2 added
refuses a manifest the previous release builds.

`[feature-deps.<f>]` must restate its dependency's source, and a restatement
naming another source is refused rather than silently dropped. The comparison
was made on the bytes of the declaration. A path is normalised first, so a path
dependency is judged on what it means; a version constraint was not, so two
spellings of one constraint were read as two sources.

Measured, with the fixture in the leg below:

  [dependencies]
  fmtlib.fmt = ">=11.0.0"
  [feature-deps.extra]
  fmtlib.fmt = { version = ">= 11.0.0", reexport = true }

  2026.9.15.2 (released):  builds, no error and no warning
  2026.9.16.1 (f4529b2):  error: ... restates the dependency 'fmtlib.fmt' with
                           version = ">= 11.0.0", while the declaration in
                           effect on this row names version = ">=11.0.0".

One space turns a build that worked yesterday into a refusal. The judgement is
now made on what the declarations mean: the constraint is compared with its
whitespace removed, while the message still shows each declaration as it was
written, so a genuine disagreement reads as the manifest spells it. A gate
refuses a restatement that names another source, and nothing else.

The same review asked why the first custom-index sync does not go through
`decide_for_miss`/`apply` when the record says the refresh sites do. It should
not: that pair's debounce and one-sync-per-process guard are about the index
that resolves a dependency, while this sync creates a local copy of a different
set of repositories that nothing else will create, so taking the guard would let
an earlier refresh of the builtin index suppress a clone the build cannot
proceed without. Only the opt-outs are shared. The comment said "the policy's
answer is taken" and now states which half is taken, and why the other is not.

Criterion: e2e 711 gains a leg. A restatement differing from the declaration
only in whitespace is not refused, and one naming `>=9.9.8` against `>=9.9.9`
still is. On f4529b2 the first half fails with the refusal quoted above.

Readings: unit 121 passed, 0 failed; e2e 187, 710 to 714 pass.
@Sunrisepeak
Sunrisepeak merged commit 2f925d4 into main Sep 16, 2026
40 checks passed
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.

2 participants