fix(release): pin the Windows upgrade baseline to a published build - #4412
Conversation
The gate downloaded `v0.1.9`, whose GitHub Release — like every other `v0.1.x` — no longer exists: the tags remain on `apache/maka`, but the binary releases were removed when the project moved to ASF incubation, where only a voted source release is official. `gh release download` answered `release not found`, so `package` failed on every pull request that touched the Windows release path. Repin to the newest published Windows build, the `v0.2.0-dev.11.20260831` Nightly prerelease, verified by its own SHA-256. That build postdates the removal of bundled Git (#3457), so the reduced baseline artifact contract can no longer require it. The `legacy-required` bundled-Git branch is unreachable — no published build carries Git — and is removed, making the absence rule apply to every artifact this verifier can be pointed at. The contract's remaining relaxations still hold: a baseline may predate resources the candidate must carry, and it carries its own update channel and dependency closure, so it is renamed from `legacy-baseline` to `upgrade-baseline`. Generated-by: Claude Code
`RELEASE_CONTRACT_FILES` named a `prepare-windows-upgrade-baseline.test.mjs` that has never existed — added speculatively in #3222 — and `STORAGE_STRESS_FILES` still named `agent-run-store.test.ts`, deleted by #1994 a month ago. A path that cannot match is dead weight nothing reports. In the other direction, three of the tests `check:release` runs reached no lane that runs it — `verify-packaged-app.test.mjs`, `third-party-closure.test.mjs`, and `qualify-released-cli-state-root.test.mjs` — so each could be edited green. `source-legal-inventory.test.mjs` and `sync-model-metadata.test.mjs` reach the ASF source lane, which runs them too, and stay as they are. Both directions are now derived rather than restated: one test walks the gate scripts in `package.json` and requires every test they name to select a lane that runs it, and one requires every path the planner names to still exist. Generated-by: Claude Code
jackwener
left a comment
There was a problem hiding this comment.
I reviewed this at a162216ce1873b950119f105f47ef229c87648de. No P0, P1, P2, or P3.
The old pin is gone: GET /repos/apache/maka/releases/tags/v0.1.9 is 404, while the tags remain. The only published Windows installer is the Nightly prerelease v0.2.0-dev.11.20260831. GitHub's asset digest for Maka-0.2.0-dev.11.20260831-win-x64.exe is sha256:0c5362707776af9a6146b55e3284dc0a2389b3329e2bed94cfc386b0eac86709, which matches the manifest. SemVer treats that Nightly as older than the candidate 0.2.0, so the upgrade-baseline age check still holds.
Changing only the pin is not enough. That Nightly does not ship bundled Git; #4418 downloaded the same asset and then failed looking for resources/bundled-git.json. This PR drops the unreachable legacy-required Git branch so the absence rule applies to every artifact the verifier can be pointed at, and keeps the other baseline relaxations (disclaimer, icon, peer, update channel, dependency closure). Hosted package on this head ran the full Windows path — download, checksum, install, smoke, in-place upgrade, uninstall, autoupdate, mid-install rollback — and passed.
The planner change is the same cut: delete paths that cannot match, put check:release's own tests on a lane, and fail when that set drifts again.
Pinning a Nightly is a CI input, not a redistribution of an Apache release. It is also ephemeral; the Nightly doc now says deleting that prerelease reproduces this outage. That is an honest trade for unsticking the gate today. This PR is still a draft. I am not merging it.
简体中文
我审的是 a162216ce1873b950119f105f47ef229c87648de。没有 P0/P1/P2/P3。
v0.1.9 的 GitHub Release 已经 404,tag 还在。现在能下到的 Windows 安装包只有 Nightly v0.2.0-dev.11.20260831,资产 SHA-256 和清单一致。它按 SemVer 比候选 0.2.0 旧,升级门禁的版本比较仍然成立。
只改 pin 不够:这份 Nightly 不带 bundled Git,#4418 下到同一文件后在 bundled-git.json 上红了。这个 PR 删掉已经走不到的 Git 必选分支,其它基线放宽还在。这份 head 上 hosted package 把下载、校验、安装、smoke、原地升级、卸载、自动更新、中途失败回滚都跑绿了。
规划器那边删了匹配不到的路径,把 check:release 自己跑的测试挂上路,并防止再漂。Nightly 当 CI 基线不是把预发布当 Apache 发行物对外分发。PR 还是 draft,我不合入。
Automated review notice: This comment was posted by an automated review agent operated by WAWQAQ. It is not an independent human review and does not replace one.
me2seeks
left a comment
There was a problem hiding this comment.
Reviewed at a162216.
The retained Nightly pin is checksum-pinned and semver-valid as an upgrade predecessor. The upgrade-baseline contract correctly keeps the baseline-specific relaxations while applying the now-universal bundled-Git absence rule. I also verified the hosted Windows run completed the real install, in-place upgrade, uninstall, automatic-update, and rollback paths.
Approve.
M4n5ter
left a comment
There was a problem hiding this comment.
Reviewed at exact head a162216ce1873b950119f105f47ef229c87648de: no P0, P1, or P2; one P3 is inline. The pinned Nightly asset exists and GitHub's SHA-256 matches the manifest. The baseline keeps the pre-existing historical-resource relaxations while applying the Git-absence rule that the selected artifact actually shipped under. The exact-head Windows job installed and verified that baseline, upgraded it in place to 0.2.0, verified and uninstalled the candidate, and completed the automatic-update and rollback paths. The reviewed blobs are identical in the squash merge da84f88de0ba77fcbaa816728faf58efc9f12a93.
Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.
| // #1994 deleted it. | ||
| test('the planner names no path that no longer exists', () => { | ||
| const source = readFileSync(new URL('ci-test-plan.mjs', import.meta.url), 'utf8'); | ||
| const paths = [...source.matchAll(/^ {2}'([\w.-]+(?:\/[\w.-]+)+)',$/gmu)].map(([, path]) => path); |
There was a problem hiding this comment.
[P3] This matcher excludes every root-level exact path because (?:\/[\w.-]+)+ requires a slash. The planner currently still names components.json in TYPECHECK_ONLY_FILES, even though that file is absent from both the tree and git ls-files; this test passes anyway. That leaves the claimed no-dead-path invariant false and makes future root-level deletions invisible. Please include root-level exact filenames while excluding prefix/suffix sentinels, remove the existing dead entry, and pin this counterexample.
Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.
Summary
Release Windows checkfailed on every pull request touching the Windows release path, and onmain, long before any current PR (run 33460508694; the previousmainrun on 2026-08-21,92da51d99, failed the same way). The stepDownload and verify the pinned Windows upgrade baselinerangh release download v0.1.9and gotrelease not found.The baseline is repinned to the newest published Windows build, the
v0.2.0-dev.11.20260831Nightly prerelease, verified by its own SHA-256:0.1.90.2.0-dev.11.20260831v0.1.9v0.2.0-dev.11.20260831Maka-0.1.9-win-x64.exeMaka-0.2.0-dev.11.20260831-win-x64.exeebda293a…0c536270…Repinning alone is not enough, which is the non-obvious part. The new baseline postdates #3457, which stopped distributing bundled Git, but the reduced baseline artifact contract still required it (
bundledGitContract: 'legacy-required'→resources/bundled-git.json,licenses/git/*,licenses/dugite/LICENSE,resources/git/cmd/git.exe), so the run would clear the download and then fail inExercise pinned-version upgrade and uninstall. That branch is unreachable now that no published build carries Git, so it is removed and the absence rule applies to every artifact the verifier can be pointed at. The contract's other relaxations still hold — a pinned baseline may predate resources the candidate must carry, and it ships its own update channel (channel: dev) and dependency closure — so it is renamedlegacy-baseline→upgrade-baseline. The gate is not relaxed: it still installs the baseline, smokes it, upgrades in place, smokes the candidate, waits for exit, and runs the real uninstaller.The second commit fixes drift in the CI planner found while auditing the paths around this gate, in both directions. Dead entries, which can never match and which nothing reports:
scripts/prepare-windows-upgrade-baseline.test.mjshas never existed (added speculatively in #3222; that script's tests live inverify-windows-harness.test.mjs, whichci.ymlruns unconditionally), andpackages/storage/src/__tests__/agent-run-store.test.tswas deleted by #1994 on 2026-08-03. Coverage gaps, where a test could be edited green:verify-packaged-app.test.mjs,third-party-closure.test.mjs, andqualify-released-cli-state-root.test.mjsare run bycheck:releasebut reached no lane that runs it. Both directions are now derived rather than restated — one test requires every test a gate script names to select a lane that runs it, one requires every path the planner names to still exist — so the same drift fails instead of accumulating.Refs #4418, which pins the same Nightly without the contract change.
Verification
Release Windows checkpasses on the head commita162216ce1in 24m4s (run 33462799148) — the gate that was red, now green end to end on a real Windows runner.CIpasses in 22m47s.node scripts/prepare-windows-upgrade-baseline.mjs 0.2.0 <dir>— the previously failing command — downloads and checksums the new baseline.shasum -a 256on the downloaded asset matches both the manifest and GitHub's own asset digest.win-unpackedresources from the published ZIP and checked them againstassertPackagedResourcesunder the reduced contract: every required path present;git,bundled-git.json,licenses/git,licenses/dugiteall absent.node --testoververify-packaged-app.test.mjs product-release.test.mjs verify-windows-harness.test.mjs windows-test-inventory.test.mjs ci-test-plan.test.mjs desktop-nightly-workflow-policy.test.mjs script-entrypoints.test.mjspasses. In a tree withoutnpm run build,product-release.test.mjsalso fails one unrelated case (@maka/eval release file is missing: dist); it passes in CI.npx biome checkclean on every changed file.The pin itself is data, so no unit test fails without it; the
packagerun above is its evidence. The contract change is covered byverify-packaged-app.test.mjsandproduct-release.test.mjs, and the planner change by the two derived tests it adds.Root cause
v0.1.9was published, then removed. Everyv0.1.xtag is still onapache/maka(git ls-remote --tags origin 'v0.1*'listsv0.1.0throughv0.1.11), butGET /repos/apache/maka/releases/tags/<tag>returns 404 for all of them, andgh release listshows only the three Desktop Nightly prereleases. The pin was introduced on 2026-08-12 in #2658 against the 0.1.9 release of 2026-08-09 and passed CI then, so the release existed and its assets were reachable.The removal is consistent with the move to ASF incubation: a podling may only distribute a release the IPMC has voted on, and
.github/ASF_SOURCE_RELEASE.mdnow states that the source release is the official one while npm, Desktop, and other convenience artifacts sit outside it. There is nov0.1.xpayload on any ASF distribution channel either.Review focus
Two judgment calls in this PR:
.github/DESKTOP_NIGHTLY.mdalready says not to delete old ones; this PR adds that one of them is pinned by the Windows upgrade gate, so deleting it reproduces exactly this failure. A durable fix would be for the release process to publish a long-lived upgrade baseline, or for the pin to move forward automatically.Two further findings from the same audit are reported without being changed here, because both are cost or policy calls rather than defects:
paths:filter:release-version.mjs,desktop-update-contract.mjs,desktop-nightly.mjs,product-release-identity.mjs,third-party-closure.mjs.release-version.mjsownscompareProductReleaseVersions, which validates this very baseline. The workflow's own comment scopes the filter to "every input whose correctness can only be observed on Windows", and all five are gated bycheck:release, so this may be deliberate; adding them costs a 45-minute Windows job per edit.docs/windows-support.mdhas no download anyone can follow. It tells readers to fetch the.exeand its matching.sha256from a Maka GitHub Release.product-release-artifacts.mjsdoes produce that.sha256, but only the formal Desktop release channel publishes it, and no formal release currently exists; the Nightly prereleases ship an attestation bundle and no.sha256. Pointing preview users at Nightly is a distribution decision, so the section is left describing the formal channel.AI use
Select exactly one:
Tool(s) and scope: Claude Code. It investigated the missing release, chose and verified the new baseline, wrote the contract and planner changes and their tests, and drafted this description. Both commits carry a
Generated-by: Claude Codetrailer and the squash commit retains it.Checklist
Does this PR entail a change in behavior?