Closes#1389. Pipeline-level fix, not a per-package symptom patch.
Root cause: the next publish step bumps each package's own version but left @mosaicstack/* dependency ranges as caret ranges (^0.0.3-next.NNNN). A caret range leaves the resolver free to pick any later build in the same major.minor.patch tuple — on a host with a stale cache, an installer-side scaffold pinned at stable, or a registry proxy hiccup, that freedom is how a gateway@next install ends up executing stable-era dependency code (web1 evidence: old tier validator rejecting 'standalone', missing drizzle migrations, stable versions in the tree despite matching -next builds existing on the registry — every published @next manifest carries next-pinned ranges, measured across all 0.0.7-next.* builds, so the leak is resolver-path freedom, not manifest content).
Fix (publish.yml, publish-next-npm): after the existing version-bump pass, a second pass rewrites every published manifest's @mosaicstack/* entries (dependencies, devDependencies, peerDependencies, optionalDependencies) to the EXACT same-pipeline build recorded in pass 1. Exact pins make the stable-fallback class unrepresentable regardless of the resolver's path. A @mosaicstack dep outside the publish set fails the publish loudly (cannot pin).
New post-publish guard (same step, after the existing @mosaicstack/mosaic@next version check): npm-views every freshly published manifest and fails the pipeline when any @mosaicstack/* entry is not an exact -next. pin — stable-range leaks AND cross-pipeline pins both fail CI instead of shipping.
Evidence (hermetic; scripts extracted from the committed YAML, mock npm registry): bump+pin pass rewrites a 3-package sandbox monorepo to exact next.9999 pins across nested deps; guard green on exact pins; red on a ^0.0.3 stable range ('stable-leak class'); red on a 0.0.4-next.8888 cross-pipeline pin. Shell blocks bash -n clean; YAML validated. Registry/publish infra untouched beyond the repo's own pipeline definition — no external access needed.
Closes #1389. Pipeline-level fix, not a per-package symptom patch.
Root cause: the next publish step bumps each package's own version but left @mosaicstack/* dependency ranges as caret ranges (^0.0.3-next.NNNN). A caret range leaves the resolver free to pick any later build in the same major.minor.patch tuple — on a host with a stale cache, an installer-side scaffold pinned at stable, or a registry proxy hiccup, that freedom is how a gateway@next install ends up executing stable-era dependency code (web1 evidence: old tier validator rejecting 'standalone', missing drizzle migrations, stable versions in the tree despite matching -next builds existing on the registry — every published @next manifest carries next-pinned ranges, measured across all 0.0.7-next.* builds, so the leak is resolver-path freedom, not manifest content).
Fix (publish.yml, publish-next-npm): after the existing version-bump pass, a second pass rewrites every published manifest's @mosaicstack/* entries (dependencies, devDependencies, peerDependencies, optionalDependencies) to the EXACT same-pipeline build recorded in pass 1. Exact pins make the stable-fallback class unrepresentable regardless of the resolver's path. A @mosaicstack dep outside the publish set fails the publish loudly (cannot pin).
New post-publish guard (same step, after the existing @mosaicstack/mosaic@next version check): npm-views every freshly published manifest and fails the pipeline when any @mosaicstack/* entry is not an exact -next.<this-pipeline> pin — stable-range leaks AND cross-pipeline pins both fail CI instead of shipping.
Evidence (hermetic; scripts extracted from the committed YAML, mock npm registry): bump+pin pass rewrites a 3-package sandbox monorepo to exact next.9999 pins across nested deps; guard green on exact pins; red on a ^0.0.3 stable range ('stable-leak class'); red on a 0.0.4-next.8888 cross-pipeline pin. Shell blocks bash -n clean; YAML validated. Registry/publish infra untouched beyond the repo's own pipeline definition — no external access needed.
The next publish step bumped each package's own version but left
@mosaicstack/* dependency ranges as published caret ranges
(^0.0.3-next.2636). A caret range leaves the resolver free to pick any
later build in the tuple — and on a host with a stale cache, an
installer-side scaffold pinned at stable, or a registry proxy hiccup,
that freedom is how a gateway@next install ends up executing stable-era
dependency code (web1 evidence in #1389: old tier validator, missing
migrations, stable versions in the dependency tree despite matching
-next builds existing).
Pipeline fix (not a per-package symptom patch): pass 2 of the publish
script rewrites every published manifest's @mosaicstack/* entries
(dependencies, devDependencies, peerDependencies, optionalDependencies)
to the EXACT same-pipeline build recorded in pass 1 — exact pins make
the stable-fallback class unrepresentable regardless of resolver path.
A dep outside the publish set fails the publish loudly (cannot pin).
New post-publish guard (same step, after the existing version check):
npm-views every freshly published manifest and fails the pipeline when
any @mosaicstack/* entry is not an exact -next.<pipeline> pin —
stable-range leaks and cross-pipeline pins both red.
Hermetic evidence (scripts extracted from the YAML, mock registry):
bump+pin rewrites a 3-package sandbox to exact next.9999 pins;
guard green on exact pins; red on ^0.0.3 stable range; red on
0.0.4-next.8888 cross-pipeline pin. No registry access needed to
re-verify (mock-npm pattern).
PASS at 8080661557. Independent review (rev-code-01): pin transform verified against every shape (caret/tilde/workspace/star in all four dep fields -> exact same-pipeline; non-mosaic deps, private and non-mosaic manifests untouched; throw-path fail-closed, live tree zero unpin-able edges across 24 publishable / 42 dep edges). Guard run from the committed YAML against a mock registry: RED on stable-range, RED on cross-pipeline pin, RED on npm-view failure, GREEN only on all-exact — no false-green path found. Registry exoneration confirmed live: gateway@next (2639) carries 13/13 caret next-pinned deps, zero stable ranges. Scope: publish.yml only +114/-7, no secrets, pipeline 2642 8/8; 2640 test-step flake dismissal judged sound (outside diff blast radius, rerun green). Full record: fleet/agents/rev-code-01/work/T63FIX1389R-REVIEW.md on brain main (9f356efd).
PASS at 8080661557c70a3da379d398e9d3f371b82664e9. Independent review (rev-code-01): pin transform verified against every shape (caret/tilde/workspace/star in all four dep fields -> exact same-pipeline; non-mosaic deps, private and non-mosaic manifests untouched; throw-path fail-closed, live tree zero unpin-able edges across 24 publishable / 42 dep edges). Guard run from the committed YAML against a mock registry: RED on stable-range, RED on cross-pipeline pin, RED on npm-view failure, GREEN only on all-exact — no false-green path found. Registry exoneration confirmed live: gateway@next (2639) carries 13/13 caret next-pinned deps, zero stable ranges. Scope: publish.yml only +114/-7, no secrets, pipeline 2642 8/8; 2640 test-step flake dismissal judged sound (outside diff blast radius, rerun green). Full record: fleet/agents/rev-code-01/work/T63FIX1389R-REVIEW.md on brain main (9f356efd).
orch-01
merged commit d790572e2e into next2026-08-24 23:05:38 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #1389. Pipeline-level fix, not a per-package symptom patch.
Root cause: the next publish step bumps each package's own version but left @mosaicstack/* dependency ranges as caret ranges (^0.0.3-next.NNNN). A caret range leaves the resolver free to pick any later build in the same major.minor.patch tuple — on a host with a stale cache, an installer-side scaffold pinned at stable, or a registry proxy hiccup, that freedom is how a gateway@next install ends up executing stable-era dependency code (web1 evidence: old tier validator rejecting 'standalone', missing drizzle migrations, stable versions in the tree despite matching -next builds existing on the registry — every published @next manifest carries next-pinned ranges, measured across all 0.0.7-next.* builds, so the leak is resolver-path freedom, not manifest content).
Fix (publish.yml, publish-next-npm): after the existing version-bump pass, a second pass rewrites every published manifest's @mosaicstack/* entries (dependencies, devDependencies, peerDependencies, optionalDependencies) to the EXACT same-pipeline build recorded in pass 1. Exact pins make the stable-fallback class unrepresentable regardless of the resolver's path. A @mosaicstack dep outside the publish set fails the publish loudly (cannot pin).
New post-publish guard (same step, after the existing @mosaicstack/mosaic@next version check): npm-views every freshly published manifest and fails the pipeline when any @mosaicstack/* entry is not an exact -next. pin — stable-range leaks AND cross-pipeline pins both fail CI instead of shipping.
Evidence (hermetic; scripts extracted from the committed YAML, mock npm registry): bump+pin pass rewrites a 3-package sandbox monorepo to exact next.9999 pins across nested deps; guard green on exact pins; red on a ^0.0.3 stable range ('stable-leak class'); red on a 0.0.4-next.8888 cross-pipeline pin. Shell blocks bash -n clean; YAML validated. Registry/publish infra untouched beyond the repo's own pipeline definition — no external access needed.
PASS at
8080661557. Independent review (rev-code-01): pin transform verified against every shape (caret/tilde/workspace/star in all four dep fields -> exact same-pipeline; non-mosaic deps, private and non-mosaic manifests untouched; throw-path fail-closed, live tree zero unpin-able edges across 24 publishable / 42 dep edges). Guard run from the committed YAML against a mock registry: RED on stable-range, RED on cross-pipeline pin, RED on npm-view failure, GREEN only on all-exact — no false-green path found. Registry exoneration confirmed live: gateway@next (2639) carries 13/13 caret next-pinned deps, zero stable ranges. Scope: publish.yml only +114/-7, no secrets, pipeline 2642 8/8; 2640 test-step flake dismissal judged sound (outside diff blast radius, rerun green). Full record: fleet/agents/rev-code-01/work/T63FIX1389R-REVIEW.md on brain main (9f356efd).