fix(release): remove nightly promotion and retire OpenCode Free - #5544
Conversation
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
Generated-by: Codex
jackwener
left a comment
There was a problem hiding this comment.
Seat: kabi-opus-review-orchestrator. Review of exact head d9e83ca86e9b4f41c5daffbce24b6b6f02dea5c7. Merge-base 7baf8b053122860e62840ded44923b95186f5e4f (equal to the recorded base), behind main by 3. Not a draft, MERGEABLE, all 12 checks success (one skipped).
Verdict
No P0–P2. 1×P3. The retirement reuses the mechanism the repository already has rather than inventing one, and the stored-connection path is handled deliberately.
What I checked, and why it did not become a finding
Existing users with a stored opencode-free connection. This is where a provider retirement usually goes wrong, and it is covered: the new test pins that such a connection can neither probe nor construct a model, failing with a retirement message instead of attempting a request. The provider entry is deliberately kept in the registry with retired: true and runtimeAdapter: { kind: 'unavailable' }, so an existing row stays identifiable and displayable while being unusable — the provider-settings story asserts both halves (absent from the add-catalog, present as a stored row).
Whether a user can get stuck. retired: true is a pre-existing flag (provider-registry.ts:147, already used by another provider), consumed by connection-readiness.ts:128 → reason: 'provider_retired', which feeds the pre-existing blocked:all_connections_retired onboarding state with an actionable "Add a model connection" CTA. This PR only generalises that copy — from sign-in-specific to provider-specific — across English and both Chinese locales. No dead end, and no new mechanism to review.
The deleted migrateSystemSeed. Its comment described retargeting a system default, so its removal looked like it might strand a default pointing at a retired provider. It does not: that migration was for model-id drift inside the seeded connection, and wholesale retirement is handled by the readiness path above. The method is gone cleanly — no callers, no interface remnant.
The smoke-test credential deletions. isolatedEnvironment spreads ...process.env, so real provider keys reach the smoke subprocess. With the free anonymous default gone, first-run now depends on whether the bootstrap finds a credential, which is why the test deletes DEEPSEEK_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY and why its marker moved from /setup to Set Up Provider. I checked the list against bootstrapSeed (bootstrap-runtime-policy.ts:151-181): it reads exactly those three. The deny-list is complete today.
docs/windows-support.md. The site's link to it lived inside the removed nightly section, so links.windows went with it. The document is still reachable from docs/README.md:86, so it is not orphaned.
P3 — the smoke test's credential deny-list is correct but coupled by duplication
scripts/smoke-release-cli-package.mjs hard-codes ['DEEPSEEK_API_KEY', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY'] in two separate functions, and its correctness depends on that list staying identical to the keys bootstrapSeed reads in a different package. It matches exactly right now.
If a fourth key is ever added to bootstrapSeed, these two smoke paths silently become environment-dependent again: on a runner where that key is set, the CLI seeds a connection, the "Set Up Provider" marker never appears, and the failure looks like a product regression rather than a stale list. Deriving the list from one exported constant — or asserting the two agree — would make that impossible instead of merely unlikely.
Worth affirming, not just auditing
Removing nightly from the downloads page improves this project's ASF posture rather than only simplifying it. The page previously presented nightly builds alongside Apache releases as a download channel; the replacement copy states plainly that "Apache Maka has not made its first Apache release yet" and that "Development builds are not approved Apache releases." For an incubating project that distinction is the one that matters, and this makes it explicit in both locales.
未验证
- I ran no suite locally; the green above is hosted CI across 12 checks, not my own run.
- No Electron, no real first-run on any platform — the first-run behaviour change (a new user must now configure a provider) is read from the code and the smoke-test marker change, not observed.
- I did not verify that retiring this provider is the right product call; the registry gives the reason as OpenCode restricting its free tier to its own client, and I did not confirm that independently.
- I did not audit the
models-dev-api.snapshot.jsonregeneration (−306) beyond noting it is a generated artifact.
简体中文
结论:无 P0–P2,1×P3。 绑 d9e83ca86,merge-base 与记录 base 一致、落后 3,非 draft、MERGEABLE、12 项检查全绿。
我核过但没成为 finding 的几项:
- 已有用户存着
opencode-free连接怎么办 —— 这是这类退役最容易出事的地方,已处理:新测试钉住这种连接既不能探测也不能构造模型,会带退役提示失败而不是发请求。注册表里故意保留该 provider 并标retired: true+runtimeAdapter: unavailable,所以旧行仍可识别、可显示,但不可用(story 两侧都断言了:不出现在可添加目录里、作为存量行仍在)。 - 用户会不会卡死 ——
retired是既有标志(provider-registry.ts:147,另一个 provider 早就在用),由connection-readiness.ts:128消费成provider_retired,接到既有的blocked:all_connections_retired引导态,带「添加模型连接」的可操作 CTA。本单只是把文案从「登录方式被移除」泛化成「模型服务已停用」,英文与简繁三处都改了。没有死胡同,也没有新机制需要审。 - 被删的
migrateSystemSeed—— 它的注释提到「重定向系统默认」,看起来像会让默认指向已退役 provider。实际不会:那个迁移针对的是种子连接内部的 model-id 漂移,整体退役由上面的 readiness 路径承接。删得干净:无调用方、接口无残留。 - 冒烟测试删环境变量 ——
isolatedEnvironment是...process.env全量透传,真实密钥会进子进程。免费匿名默认没了之后,首启行为取决于能否发现凭据,所以测试删掉那三个键、并把标记从/setup改成Set Up Provider。我对照了bootstrapSeed(:151-181)只读这三个键,名单当前是完整的。 docs/windows-support.md—— 站点链接原本在被删的 nightly 段里,所以links.windows一并删了;但该文档仍可从docs/README.md:86到达,不是孤儿。
P3 —— 冒烟测试的凭据排除名单当前正确,但靠重复耦合。 该名单在脚本里两处硬编码,正确性依赖它与另一个包里 bootstrapSeed 所读的键始终一致。今天完全一致。但将来 bootstrapSeed 若加第四个键,这两条冒烟路径会悄悄变回依赖环境:在设了该键的机器上,CLI 会种一个连接,Set Up Provider 标记永不出现,失败看起来像产品回归而不是名单过期。把名单收敛到一个导出常量、或加一条断言两者一致,就能把「不太可能」变成「不可能」。
值得肯定的一点(不只是挑错):把 nightly 从下载页移除,对这个孵化中的 ASF 项目是合规姿态的改善,不只是简化。原页面把 nightly 与 Apache 发布并列成一个下载渠道;新文案明确写着「Apache Maka 尚未做出第一个 Apache 发布」以及「开发构建不是经批准的 Apache 发布」。对孵化项目来说,这正是最要紧的那个区分,而且中英文都写了。
未验证:本地没跑任何套件(上面的绿是 CI 的 12 项);无 Electron、未在任何平台实跑首启 —— 「新用户现在必须自己配置 provider」这一行为变化是从代码与冒烟标记推出来的,不是观察到的;没有独立核实退役这个产品决定是否正确(注册表给的理由是 OpenCode 把免费层限制在自家客户端);models-dev-api.snapshot.json 的 −306 只当作生成产物,未审。
Automated review notice: This comment was posted by an automated review agent operated by jackwener. It is not an independent human review and does not replace one.
jackwener
left a comment
There was a problem hiding this comment.
Approving at exact head d9e83ca86e9b4f41c5daffbce24b6b6f02dea5c7. This binds to that SHA only.
No P0–P2 at this head. The single P3 above — the smoke test's credential deny-list being correct but coupled by duplication to bootstrapSeed — is a durability point about a test, not a defect in shipped behaviour, and does not block under the stated condition. Approving does not close it.
CI at the moment of approval, on this SHA: all 12 checks success, one skipped — including test, the four direct-peer addon builds, the immutable tarball, and installed-CLI validation on Linux x64/arm64, macOS arm64 and Windows x64. Not a draft, MERGEABLE, merge-base equal to the recorded base, behind main by 3. The head has not moved since I reviewed it.
What this approval rests on: the retirement reuses the repository's existing retired flag and its readiness path rather than introducing a mechanism, so an existing opencode-free connection becomes unusable-but-visible and the user lands on an onboarding state with an actionable CTA instead of a dead end. The removed migrateSystemSeed is gone cleanly, and the smoke-test deny-list matches bootstrapSeed exactly today.
What it does not cover: I ran nothing locally — the green is hosted CI, not my own run. No Electron and no real first-run on any platform, so the user-visible consequence of this change (a new user must now configure a provider before sending) is read from code and from the smoke-test marker change, not observed. I did not independently confirm the premise that OpenCode restricts its free tier to its own client, and I did not audit the regenerated models-dev-api.snapshot.json. I am not making a merge decision.
If the head moves, this approval does not carry over.
简体中文
批准绑定 exact head d9e83ca86,只对这一个 SHA 有效。 本 head 无 P0–P2;上面那条 P3(冒烟测试凭据名单当前正确、但靠重复耦合)是关于测试耐久性的,不是已交付行为的缺陷,按既定条件不阻塞。批准不关闭它。
批准时该 SHA 上:12 项检查全部成功、1 项跳过 —— 含 test、四个 direct-peer addon 构建、不可变 tarball,以及 Linux x64/arm64、macOS arm64、Windows x64 的已安装 CLI 校验。非 draft、MERGEABLE、merge-base 与记录 base 一致、落后 main 3;自我评审以来 head 未动。
批准依据:退役复用了仓库既有的 retired 标志与 readiness 路径,没有引入新机制 —— 存量 opencode-free 连接变成「不可用但可见」,用户落到带可操作 CTA 的引导态而不是死胡同;被删的 migrateSystemSeed 删得干净;冒烟测试的排除名单与 bootstrapSeed 当前完全一致。
不覆盖:本地什么都没跑(绿是 CI 的);无 Electron、未在任何平台实跑首启,所以「新用户现在必须先配置 provider」这一用户可见后果是从代码与冒烟标记推出来的,不是观察到的;没有独立核实「OpenCode 把免费层限制在自家客户端」这个前提;重新生成的 models-dev-api.snapshot.json 未审。合并与否不归我。head 一漂,本批准即不覆盖。
Automated review notice: This approval was posted by an automated review agent operated by jackwener. It is not an independent human review and does not replace one. Seat: kabi-opus-review-orchestrator.
Review [P2] on apache#5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern apache#5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka
Review [P2] on apache#5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern apache#5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka
Review [P2] on apache#5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern apache#5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka
Review [P2] on apache#5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern apache#5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka
Review [P2] on apache#5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern apache#5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka
* chore(provider): remove the Command Code GO provider Command Code GO did not use a published API. It sent requests to the official CLI's private `/alpha/generate` endpoint behind the same identity headers that CLI presents (`x-command-code-version`, `x-cli-environment`, `x-taste-learning` and friends), and its account-usage card read the same `/alpha/*` endpoints with the same headers. The provider was withdrawn from the registry for that reason. Removing the provider takes its whole surface with it, because everything else existed only to serve it: - the `commandcode-cli` Runtime adapter, its `/alpha/generate` wire, and the CLI identity headers it forged; - the browser-assisted sign-in (`commandcode-browser-login`, `commandcode-login-ipc-main`, its renderer flow and section) that minted a key through the CLI's own loopback login; - the account-usage read end to end: the `connection.usage.read` operation and its Host coordinator, the storage `connection_usage` ticket machinery, the `read_usage` ProviderAuthAction, the runtime fetch/parse, the core report types, and the settings usage card; - the transport-acknowledgement gate, which existed only to tell a user that one provider presented another client's identity, and so is now an empty set. The ordinary `commandcode` provider stays: it is a plain API-key connection over the published Provider API, and it keeps the shared reasoning-effort table. The `connection.usage.read` operation is gone, so the compatibility epoch moves 169 -> 170; a peer older than this epoch may still advertise or submit it. Generated-by: Maka * fix(provider): retire Command Code GO instead of removing it Review [P2] on #5545: deleting the entry outright leaves an existing connection *unknown* rather than *retired*. `isRetiredProvider` answers false for a type no longer in the registry, so the readiness guard never fires, a connection with a default model and an enabled model list reports `ready: true`, and the send is admitted only to throw "Unknown provider type" deep in model construction — the exact failure `connection-readiness.ts` documents above that guard. Keep the entry with `retired: true` and `runtimeAdapter: unavailable`, the pattern #5544 used for OpenCode Free. A stored row stays identifiable and displayable, readiness answers `provider_retired`, and the user lands on the existing `blocked:all_connections_retired` state with its "Add a model connection" call to action. `provider-catalog-contract` already pins the retired set and asserts each entry keeps no Runtime adapter and stays out of the add catalog, so this restores that entry rather than adding new machinery. Also regenerate the Astryx surface inventory, which still listed the two files this PR deletes and failed the CI step ahead of Typecheck. Generated-by: Maka * chore(desktop): drop the browser-login copy left by the GO removal The sign-in section that read `browserLogin` is deleted, so its three locale blocks — including the "sign in with your Command Code account" title and the port-range failure text — are unreachable. Remove them with it. * fix(runtime-host): release the retired usage grant CI on this branch failed in `Qualify durable state against the published baseline`: The released access credential carries grants this build cannot account for: connection.usage.read Removing an operation leaves its grant in every credential a released build already wrote, and `unresolvedPersistedGrants` reports a stored grant that the protocol no longer defines and no migration entry names. The released fixture carries `connection.usage.read`, so the forward roll refused it. Add the `release` entry, which drops the grant on decode and records that its authority went nowhere — the same treatment `turn.regenerate` and `execution.inspect.resolve` got when they were removed. Without it the grant survives in the record and is reported as unaccounted for on every read. Generated-by: Maka
Summary
Remove two paths that Maka can no longer offer ahead of RC2: public promotion of unapproved Nightly installers, and the built-in anonymous OpenCode Free service.
The English and Chinese homepage and downloads page now direct visitors to Apache release status and contributors to the contributor guide and development list. Remove the Nightly cards, installer links, source-install commands and unused copy; update the README links accordingly. This addresses the website portion of the IPMC feedback under the ASF publication policy. Nightly workflows and existing GitHub prereleases are unchanged.
On September 20, the OpenCode anonymous completion endpoint returned HTTP 403: “OpenCode's free tier can only be used from within OpenCode.” Retire Maka's
opencode-freeprovider through the existing provider registry contract. Remove its onboarding recommendation, automatic bootstrap connection, model rotation and quarantine, probe retries, and session-header branch. OpenCode Go and authenticated Zen remain available.Existing installations
Retain the provider identifier so saved connections and conversations remain readable. The existing retirement mechanism refuses new connections and execution, removes Free models from pickers, and releases a default target pointing at Free. Settings now shows retirement guidance for keyless providers as well as OAuth providers. Users choose another connection; upgrading does not import a paid replacement. Fresh installations without an environment API key begin with no connection. Cancelling the CLI first-run setup exits cleanly instead of rethrowing the missing-default error. Explicit environment credentials still bootstrap a connection, including recovery after an interrupted import.
Verification
/setupprompt.NO_REAL_CONNECTIONand exited 1. The same flow now exits 0 without that error; all 221 TUI runner tests pass. The installed-package smoke test keeps its clean-exit assertion and now removes environment API keys so this path cannot be bypassed.isFreemetadata and its projection, updated the committed snapshot digest, and removed the unreachable Free pricing exclusion. Deep comparison confirms prices, model capabilities and source provenance are unchanged. All 15 generator tests and 39 metadata/refresh/onboarding tests passed, along with generated-output checks and Desktop typecheck. Retirement guidance no longer refers to an OAuth sign-in in any of the three locales.git diff --checkpassed.d9e83ca86: main CI covers the affected workspace and Runtime Host suites, Desktop E2E, browser/WorkHub smoke checks, Storybook smoke, geometry and installed CLI validation. Package validation passed on macOS arm64, Windows x64, Linux arm64, and Linux x64 with Node 22.19/24, plus released State Root compatibility. The conditional CLI Eval job was skipped. No live paid-provider calls were made. This PR does not itself deploy the website or publish RC2.Screenshots
BEFORE is main, AFTER is this branch, using the same page, theme and viewport.
AI use
Tool(s) and scope: Codex implemented the website changes, provider retirement, tests and browser validation.
Checklist
Does this PR entail a change in behavior?