Repository navigation
feat(versioning): read the SemVer notation 3.<minor>.<run> as one lineage (readers first) - #6208
Conversation
…eage with 3.0.0-ci.<run> Readers-first half of policy `platform-semver-versioning` (Doc/Architecture/PlatformVersioning). Mints nothing new: the minter flip is a separate, later change. - PlatformReleaseOrder: from line 3.1 (SemVerEraStart) a plain <major>.<minor>.<run> with a non-zero patch carries its run number in the patch, so both notations interleave by publication order; zero-patch floors/releases (3.1.0, 4.0.0) keep their numeric-core reading. - VersionSelect: Stable never admits a run-numbered tag (a new-notation build has no label); the advisory names the pattern 3.*. - platform-version.py: the one shell-facing reader (ordinal, max-ordinal, line-pointers); main-cd's never-backwards checks, baseline and line pointers use it (3-latest 3.1-latest). - resolve-platform.py / arm-promoted-set.py / node-repo-gate.yml: parse, compose and accept both notations. - Tests incl. negative controls: the interleave cases fail with the reader reverted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Test Results 22 files ± 0 22 suites ±0 49m 29s ⏱️ +18s Results for commit a15a448. ± Comparison against base commit c375173. This pull request removes 40 and adds 45 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
…e.yml and the minor bump Doc/Architecture/PlatformVersioning §6: the open decisions become decisions taken (maintainer can override). Stable keeps following deliberately cut releases; release.yml keeps promoting and renames nothing (no -latest move in the new notation); the minor moves only through a merged pull request that edits PlatformVersion. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Several remaining legacy parsers can misorder notifications, reject valid gate inputs, or rewrite the preserved 3.1 slip.
Review effort: Balanced
Findings: 3
Open (4)
What changed in this PR
Adds readers-first support for the 3.<minor>.<run> platform-version scheme while preserving the legacy lineage.
Changes:
- Extends C#, Python, and CI readers for both version formats.
- Prevents Stable deployments from selecting continuous builds.
- Documents the versioning policy and migration sequence.
| File | Description |
|---|---|
test/MeshWeaver.Graph.Test/PlatformReleaseOrderTest.cs |
Tests cross-format ordering and floors. |
test/Memex.Portal.Shared.Test/VersionSelectTest.cs |
Tests selection across the cut-over. |
src/MeshWeaver.Plugin.Packaging/PlatformReleaseOrder.cs |
Reads patch-based build ordinals. |
src/MeshWeaver.Documentation/Data/Architecture/PolicyNotProse.md |
Registers the versioning policy. |
src/MeshWeaver.Documentation/Data/Architecture/PlatformVersioning.md |
Documents the scheme and migration. |
src/MeshWeaver.Documentation/Data/Architecture.md |
Links the new documentation. |
memex/Memex.Portal.Shared/SelfUpdate/VersionSelect.cs |
Excludes continuous builds from Stable. |
.github/workflows/node-repo-gate.yml |
Accepts new set names. |
.github/workflows/main-cd.yml |
Uses shared version readers in CD. |
.github/workflows/dotnet-test.yml |
Runs the new reader self-test. |
.github/scripts/test-gate-lane-forwards-the-callers-set.py |
Tests gate input validation. |
.github/scripts/resolve-platform.py |
Resolves both set-name formats. |
.github/scripts/platform-version.py |
Adds the shell-facing version reader. |
.github/scripts/arm-promoted-set.py |
Supports new-format arming and patterns. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| elif [[ "$PINNED_SET" =~ ^([0-9]+)\.([0-9]+)\.[1-9][0-9]*$ ]] \ | ||
| && { [ "${BASH_REMATCH[1]}" -gt 3 ] || { [ "${BASH_REMATCH[1]}" -eq 3 ] && [ "${BASH_REMATCH[2]}" -ge 1 ]; }; }; then | ||
| is_set=true | ||
| fi | ||
| [ "$is_set" = true ] \ |
There was a problem hiding this comment.
Fixed in 8a249b5. resolve-gate-platform.sh's run_number_of now also reads <major>.<minor>.<run> when (major, minor) >= (3, 1) and the patch is non-zero, the same rule as platform-version.py and PlatformReleaseOrder.SemVerEraStart. As a result the caller ordinal and installed_run_numbers (oldest/newest) see SemVer sets. New self-test cases: 5h, a 3.1.10050 caller against a volume holding 3.1.10000, must be classified AHEAD and report the volume's newest as #10000; 5i, a 3.1.10001 caller against a 3.0.0-ci.9999 volume, must be AHEAD. Negative control: with the SemVer branch disabled, 5h goes RED (it falls into the 'cannot be told apart' refusal). Self-test: OK.
Conflict: PolicyNotProse.md register — kept both rows (platform-semver-versioning
from this branch, stale-adoption-bound from main); they are independent policies.
Review fixes:
- resolve-platform.py: the line alone cannot decide the notation. parse_freeze and
the publication receipt keep the WRITTEN set name (canonical_set_name), and
compose_set_name keeps -ci.<run> for the withdrawn slip's runs (<= 7841) on the
3.1.0 line. Self-test cases added for the slip freeze and composition.
- main-cd.yml notify-platform-update: the superseded check reads both run numbers
through platform-version.py ordinal (fail-closed), not ${v##*ci.}.
- resolve-gate-platform.sh: run_number_of reads the SemVer notation from line 3.1
on; self-test cases 5h/5i (SemVer caller AHEAD, mixed-notation volume), red with
the SemVer branch disabled.
- VersionSelectTest: CutOverRegistry is an ImmutableArray<string>.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e tag listing; VersionSelect docs define Stable as deliberately cut releases Answers the two Copilot threads on this PR. The `|| true` let a failed or ordinal-free ACR listing fall through and move the line pointers without evidence this set is newest; it now refuses, as the mw-plugin-test guard does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| ## 3. Inventory: every place the old notation is produced or parsed | ||
|
|
||
| Line numbers are as of this change. **P** = produces the notation, **R** = parses it. "Handled" means | ||
| this change teaches the place both notations. "Owed" means a later step of the migration has to change it. |
There was a problem hiding this comment.
Fixed in a15a448: assert-bake-floor.py parse now reads the SemVer-era patch (line >= 3.1, patch > 0) as the run ordinal, so 3.0.0-ci.9999 <= 3.1.10000 orders instead of being an unordered mixed pair; the self-test gains cross-notation cases in both directions plus the withdrawn 3.1.0-ci.7841 slip (self-test passes, 0 failures), and the inventory in PlatformVersioning.md now lists the script as handled.
…airs self-tested Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Test Results (shard 1) 4 files ± 0 4 suites ±0 4m 58s ⏱️ -39s Results for commit a15a448. ± Comparison against base commit c375173. This pull request removes 1348 and adds 1148 tests. Note that renamed tests count towards both. |
Test Results (shard 2) 5 files ± 0 5 suites ±0 4m 52s ⏱️ +46s Results for commit a15a448. ± Comparison against base commit c375173. This pull request removes 1130 and adds 1350 tests. Note that renamed tests count towards both. |
Test Results (shard 3) 4 files ±0 4 suites ±0 6m 59s ⏱️ + 1m 2s Results for commit a15a448. ± Comparison against base commit c375173. This pull request removes 1 and adds 5 tests. Note that renamed tests count towards both. |
Test Results (shard 4) 4 files ±0 4 suites ±0 16m 49s ⏱️ -6s Results for commit a15a448. ± Comparison against base commit c375173. This pull request removes 39 and adds 20 tests. Note that renamed tests count towards both. |
feat(versioning): mint 3.<minor>.<run> — SemVer minter flip (stacked on #6208)


Readers-first half of policy
platform-semver-versioning(registered inDoc/Architecture/PolicyNotProse; manual: new pageDoc/Architecture/PlatformVersioning). This PR mints nothing new. Continuous builds keep being3.0.0-ci.<run>until the separate minter PR lands.Decisions taken (maintainer can override)
Recorded in
Doc/Architecture/PlatformVersioning§6 (formerly "Open decisions"). Each one takes the conservative option: nothing already published is renamed, the minor moves only by an explicit, governed action, and Stable keeps following what it follows today.VersionSelect.PickTargets, pinned byStable_NeverSelectsANewNotationBuild), so no Stable install starts following main. Not chosen: astablechannel pointer, or Stable as a minor-pinned Continuous pattern.release.ymlkeeps promoting and renames nothing.v<major>.<minor>.0adds the clean tag to the commit's already-published<major>.<minor>.<run>set. In the new notation it moves no-latestpointer (CD's arm already did, so a release-side move could only go backwards). GHCRlateststill follows releases. The implementation ships with the minter (feat(versioning): mint 3.<minor>.<run> — SemVer minter flip (stacked on #6208) #6209), because no new-notation set exists before it.PlatformVersion. In practice that is the next-line PRrelease.ymlalready opens after each release.3-latestalready moves today: arm phase D and control-first move3-latest 3.0-latest 3.0.0-latestfor the old notation. Seeding3-latest(step 3) therefore works before the minter flips.What it does
PlatformReleaseOrder: from line 3.1 (SemVerEraStart), a plain<major>.<minor>.<run>with a non-zero patch carries its run number in the patch. Both notations now share one lineage:3.0.0-ci.9999 < 3.1.10000 < 3.0.0-ci.10002. Zero-patch versions (3.1.0,4.0.0) are still floors or releases and are compared by their numeric core. The withdrawn slip3.1.0-ci.7841keeps its 7841.3.1.Nlands in the promotion band and ranks below every3.0.0-ci.*. The cut-over would never roll forward, even though SemVer sorts it above.VersionSelect:Stablenever admits a run-numbered tag. A new-notation build carries no pre-release label, so without this rule every Stable install, which is the seeded default, would start following main on flip day. The advisory now names the pattern3.*..github/scripts/platform-version.py(new, self-test wired intodotnet-test.yml): the one shell-facing reader (ordinal,max-ordinal,line-pointers).main-cd.ymluses it for the satellite-compat baseline, promote's never-backwards check, arm phase D, and control-first's pointers. Pointers in the new notation are3-latest 3.1-latest, with no per-build3.1.N-latest.resolve-platform.py:match_set_name/compose_set_name/notice_set_numberhandle both notations for set names, freezes, bake receipts, promotion records, notices and registry tags.arm-promoted-set.py:run_number_ofandline_pattern(3.1.10052→3.1.*).node-repo-gate.yml: theplatform-setinput accepts<major>.<minor>.<run>.Verification (local, Release
-warnaserror, 0 warnings / 0 errors)MeshWeaver.Graph.Test(PlatformReleaseOrder / PlatformFloor / TargetSet): 83/83 passed.Memex.Portal.Shared.Test(VersionSelect / SelfUpdate / OciTagLister): 240/240 passed.MeshWeaver.Documentation.Test(topic map / policy / links): 27/27 passed.SemVerBuildPatchreverted toreturn null, the interleave, transitivity andBuildOrdinalcases failed, plus 3VersionSelectcases (includingStable_NeverSelectsANewNotationBuild). The code was restored and rebuilt before commit.resolve-platform.py --self-test: 218 cases, green. With the boundary moved to 9.9, exactly the new-notation cases fail.arm-promoted-set.py,platform-version.pyandtest-gate-lane-forwards-the-callers-set.pyare green.test-cd-steps.pyand the workflow guards (shell, timeouts, yaml keys, guard masking, runners, permission pairing, PR secret preflight) are green.Known side effect
resolve-platform.pyis vendored into satellites, socheck-resolver-copy.pywill report drift on every satellite that still carries a copy until it re-copies (or deletes its copy). It reports drift for any canonical change.Not in this PR (see the doc page's migration order)
SelfUpdateRouting.BuildOrder,ImageLine,ModuleInventoryContent,DeploymentStatusand the floor scripts have their ownci.Nparsers, and none of them delegate toPlatformReleaseOrder.updatePattern: 3.0.0-ci*→3.*, the overlays,check-no-pins.py, andresolve-line-pointer.sh(seed3-latest).Pairs-with: none: no public type or member is removed.
🤖 Generated with Claude Code