fix: integrate updater downgrade guard
This commit is contained in:
@@ -4,6 +4,28 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Integrated Through
|
||||
|
||||
- Updater downgrade-prevention source commit `2e61800` from feature task
|
||||
`20260826-fix-version-update-check-7c91a4` is integrated by task
|
||||
`20260826-recover-pi-updater-integration-8f3a6c21`. Every automatic-update
|
||||
channel assignment now immediately restores
|
||||
`autoUpdater.allowDowngrade=false`, so installed `2.0.0` does not treat an
|
||||
online `1.1.9` manifest as an available update; later explicit channel
|
||||
changes preserve the same invariant.
|
||||
- Local `main` is integrated through delivery `48a9189` by task
|
||||
`20260826-integrate-pi-provider-fix-6e4c2a91`. The strict 101-commit
|
||||
fast-forward replaces OpenCode with pinned Pi `0.84.2` as Makelore Code's
|
||||
sole production runtime, adds schema-v2 project/Agent/Conversation storage,
|
||||
persistent per-Conversation workers, product Snapshot/Patch contracts,
|
||||
`/api/coding/*`, Provider/resource isolation, extension/subagents, process
|
||||
and write budgets, and background-run uncertainty ownership. Implementation
|
||||
`a098266` additionally validates/persists an unresolved Conversation model
|
||||
before first prepare and converts the exact Works missing user-context
|
||||
response into a non-replayed Provider-auth failure after expiring the cached
|
||||
gateway credential. The final Windows installer and final packaged Pi proof
|
||||
passed; real Provider turns remain explicitly waived with
|
||||
`realTurnVerified=false`, while macOS x64/arm64 and native non-WSL Linux
|
||||
remain unverified. Older OpenCode entries below are retained only as
|
||||
historical integration evidence and are superseded for current behavior.
|
||||
- OpenCode model-switch runtime correction source commit `cce7722` from feature
|
||||
task `20260821-model-switch-runtime-fix-a83d6c91` is integrated on local
|
||||
`main` by task `20260821-integrate-model-switch-fix-8f2d6c41`. The Main-owned
|
||||
@@ -131,7 +153,7 @@ Makelore 在会话恢复、登录和刷新后由 Electron Main 请求 Works `/ap
|
||||
|
||||
AI 学习现在是已启用的运营精选项目目录,并继续受登录和 `module_access.learning` 控制。Renderer 通过 Main-owned Host API 获取分页项目卡片和 README 详情;Markdown 支持 GFM、禁用原始 HTML。服务端发布时只校验图片 URL 为无凭据、默认端口、无 fragment 且当前 DNS 结果全部为公网地址的 HTTPS URL,保留地址而不下载、识别格式、转码或镜像;客户端仅为 README 图片节点启用直连,因此 SVG 和 Electron 支持的其他格式可直接显示,单图失败不阻断详情。封面和历史发布媒体继续走受控路径。详情页的下载按钮打开系统保存对话框;Main 将 ZIP 流式写入临时文件,只允许最多五跳同 Works origin 重定向,不校验 `Content-Length`、`archiveBytes`、实际流字节数或客户端大小上限,校验 SHA-256 和 ZIP 签名后原子保存,Renderer 只接收 `saved` 或 `cancelled`。课程生成、进度、本地课程库、OpenMAIC player、Agent、ASR、课堂 runtime、Learning IPC 和 player artifact 打包已删除且没有兼容读取路径;历史课程数据保留但不再读取。服务端和客户端源码契约已完成,不代表生产部署或真实账号安装包联调已经完成。
|
||||
|
||||
AI 编程首次发送在新建 OpenCode session 已知为空时不再等待冗余历史读取,prompt 可直接进入 Host API;普通历史会话仍刷新消息。伙伴模型只作为新 Session 默认值,现有 Session 的 active model 由 OpenCode 持有;页面选择器和 `/models` / `/model` 走同一个 native Session 切换动作,Main 在 OpenCode client 边界把内部 `modelID` 映射为 1.18.9 `ModelRef.id`,后续 prompt、项目命令和上下文压缩不再用伙伴默认值覆盖选择。每个 Session 独立持有 model、run、loading、error 与内部队列;一个 Session 的回复或终止不会锁住、改写或重放另一个 Session。Host 接受或用户消息落库不算启动确认,只有明确 busy/retry、assistant、question、permission 或 typed terminal event 才确认/终结启动;独立的 10 秒 watchdog 到期时仅以 `SESSION_START_UNCONFIRMED` 终止该 Session。Main 按 Agent id 维护 desired/applied 内容状态与 runtime generation provenance;owned fresh generation 中首次出现的唯一 id 可在 live registry 暴露后启用且不阻断已有 Agent,同 id 编辑、删除后重建及 attached/unknown generation 仍保持 pending。fresh runtime 的本地 AI proxy provider 在构建时使用当前 Main Host API token;后续将该已生效 token 持久化不构成 provider/runtime 变更,attached/unknown generation 或不确定写入仍保持 pending。provider/runtime 或 Agent 未应用时在执行前返回 typed `409` 且 `promptSent:false`。普通 message、command、summarize 和后台 provider sync 不自动重启、reload 或 dispose 共享 runtime;只有显式用户 apply/lifecycle 操作可以推进运行时刷新。Main AI proxy 只把明确的上游分组饱和投影为当前 OpenCode 的终止状态,配额耗尽保持独立终止态,通用限速继续保留 `429`。上下文压缩以每个 Session 的持久时间线事件呈现:自动与手动压缩使用不同文案,运行态原位弱化显示,完成后静态保留并可从历史恢复;`session.compacted` 只完成对应事件,只有真实 idle 才结束 run 和释放排队消息。
|
||||
AI 编程已经硬切到精确 pin 的 Pi `0.84.2`,不存在 OpenCode fallback 或双 runtime。project、Agent 与 Conversation 采用本地 schema v2;旧 OpenCode 会话只做备份,不继续执行。每条 active/warm Conversation 拥有独立 persistent worker/session、generation/seq、Snapshot/Patch、model/thinking、队列、interaction 与错误状态,Composer 在 lazy prepare 期间仍可编辑。Renderer 只通过 `/api/coding/*` 和 Snapshot-first/`patch-batch` SSE 消费产品中立合同;gap/reconnect 只恢复目标 Conversation,accepted/uncertain mutation 不自动重放。未解析 Conversation 第一次选模先 validate 并持久化 resolved metadata,再 prepare;同账号模型切换使用 target `set_model`,跨账号只重建目标 worker。top-level/child 并发分别为 4,共享总进程预算 8,warm idle LRU 4;coding child 与 parent 共用项目 write lease。prompt/compact confirmation timeout 后仍保留 run/process/background ownership,迟到 success/failure/exit/abort 单调且 exactly-once 收敛,页面隐藏不会停止 active/uncertain run。Pi `0.84.2` 手动 compact 不发 `agent_settled`,由 correlated compact RPC 结果终结。Provider credential 只进入选中 worker env;确定性的 Works user-context 缺失会失效 gateway credential、fail fast、不重放并投影固定 Provider-auth 错误,不归类为 Pi worker crash。真实 Provider 验证仍为用户明确接受的未验证风险,macOS x64/arm64 与 native non-WSL Linux 也未通过平台发布门禁。
|
||||
|
||||
Updater 仍由 Electron Main 选择目标 feed、记录原始诊断并保持失败语义。正式稳定源缺少对应平台 manifest 时,设置页只显示一条简洁中文提示并允许重试,不把缺包误报为已是最新版,也不向普通界面暴露堆栈、URL、路径或错误码;签名产物发布和真实升级安装仍属于外部 Release Gate。
|
||||
|
||||
@@ -139,6 +161,7 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
|
||||
|
||||
## Recently Completed
|
||||
|
||||
- 2026-08-26: Fast-forwarded the complete Pi hard-cutover and installed-package resilience chain into local `main`, including per-Conversation workers/Snapshot projection, extension/subagents, bounded process/write/background ownership and the deterministic Works user-context Provider-auth correction. The final Windows installer, packaged Pi runtime, extension/child, 4+4 pressure, uncertainty/late-settle and zero-lingering-process proofs passed. Real Provider turns are explicitly waived rather than passed; macOS and native non-WSL Linux remain release evidence gaps.
|
||||
- 2026-08-20: Replaced AI Learning's course generation/player stack with the curated project catalog defined by ADR-005. The authenticated/module-gated client now renders project cards and safe README detail, loads validated credential-free HTTPS Markdown images directly, and saves verified ZIP archives through the native dialog. Old course/runtime/player packaging was removed; server/client regressions and full suites passed, while production deployment and real-account package smoke remain pending.
|
||||
- 2026-08-19: Integrated native password/SMS login, the temporary HTTP/2-disabled diagnostic bootstrap, and the AI Design freeze fix. Workspace JSON calls and shared token refresh now settle within 30 seconds, transport abort is paired with deterministic rejection, and implicit Electron-to-Node fallback no longer replays mutation requests. Installed-client Quote retry/confirm smoke and the final HTTP/2 policy decision remain pending.
|
||||
- 2026-08-17: Integrated application-side multi-Session isolation for AI Programming. Session A may remain busy while Session B is independently accepted or terminally rejected; errors, startup deadlines and uncertain-failure cleanup stay Session-scoped. Main now fail-closes stale Agent/provider runtime state before execution, applies bounded manager/project FIFO acceptance with revocable timeouts, and never refreshes the shared runtime automatically from ordinary execution paths. Full unit, typecheck, lint, build, focused Electron E2E and independent Sol review passed; a real paid-provider/bundled-runtime concurrency smoke remains pending.
|
||||
@@ -203,13 +226,13 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
|
||||
- AI 绘画 Main-owned Workspace JSON 请求和共享 Works token refresh 必须在 30 秒内结束并释放共同等待者;只允许 `GET`/`HEAD`/`OPTIONS` 在 Electron transport 失败后透明改走 Node fetch,PATCH/POST 等 mutation 必须由具有显式幂等身份的上层协议决定是否重试。临时 `disable-http2` 只用于安装包诊断,不能替代该有限生命周期与非重放边界。
|
||||
- 服务端持久 Conversation Session 不由客户端在注销或退出时删除;Main 只关闭本地流、清除本机缓存并撤销本地凭据。
|
||||
- 客户端对最终构建字节的 loopback 检查没有可信 receipt,且不复刻生产 opaque-origin;服务端必须独立重算 source/built/contract、校验不可变 Release,人工审核仍不可绕过。如未来需要不可绕过的 runtime gate,必须引入可信 verifier 并绑定精确构建产物。
|
||||
- AI proxy 的明确饱和 `429 → 400` 是与当前 OpenCode 重试契约匹配的内部投影;升级 OpenCode 或上游饱和错误文案变化时必须复核。不得把通用 `429` 或仅含 `rate_limit_exceeded` 的响应误分类为终止饱和。
|
||||
- AI 编程压缩事件必须按 Session、run token、runtime generation 与 native Part/event identity 关联;`session.compacted` 不等于 `session.idle`,历史 hydration 不得把 completed 降回 running,失败或中止必须清理本 run 的未完成事件。
|
||||
- AI 编程多 Session 隔离只证明应用提交、状态、错误、超时和队列互不污染,不证明 bundled OpenCode 或真实 provider 会并行执行两个模型 turn。任何产品或性能结论都必须保留上游可能串行、限流或拒绝的边界。
|
||||
- 项目 Agent 与 provider/runtime freshness 必须在 Main 的 bounded acceptance 临界区内验证。新增唯一 id 的 live discovery 只在 owned fresh generation 可接受;同 id 不能证明同内容已经加载,删除后重建及 attached/unknown runtime generation 必须 fail closed。普通 message、command、summarize、Session 模型切换和后台同步不得自动重启、reload 或 dispose 共享 runtime。升级 OpenCode 时必须复核 native Session model wire schema;不得把已注入 fresh generation 的 Main 临时 proxy token 误判为上游 provider credential rotation。
|
||||
- Pi RPC confirmation timeout 是不确定性边界,不是释放 run permit、process ownership 或 Main background lease 的依据;accepted/uncertain mutation 不得自动重放,迟到 terminal 必须 exactly-once 收敛。隐藏/显示、abort、recover、replacement 与 app quit 都必须保留可解释 reason 并最终清零 ownership。
|
||||
- Pi `0.84.2` 手动 compact 不发 `agent_settled`。只有 correlated compact RPC success 或权威 compaction failure 可以结束 compact;普通 prompt 仍需自己的 terminal/settled 语义,不能相互释放 lease。
|
||||
- 本地 provider-shaped loopback 和 4+4 process proof 证明客户端序列化、调度与隔离 seam,不证明真实 Provider 会并发、不会限流或正确隔离账号凭据。真实认证、endpoint/proxy/rate-limit、协议和图片差异仍为 `Explicitly Waived / Accepted Risk`,`realTurnVerified=false`。
|
||||
- Provider/resource freshness 属于目标 Conversation worker generation。idle stale 在下一 prompt 前重建,running stale 在 settled 后重建;同账号 refresh single-flight 且最多一次 reopen。确定性 Works user-context 缺失必须失效缓存凭据并 fail fast,不能触发无限 Pi 重试、自动 replay 或把 Provider 故障写成 runtime crash。
|
||||
- AI 绘画单图选择器仍精确匹配 quick reply `从作品列表选择图片`,用途再从当前 Brief medium 推断;本地化或协议文案变化可能破坏入口。扩展更多素材输入前应升级为结构化 action/purpose。
|
||||
- Updater 源码错误提示不能代替发布正式签名产物;稳定 feed 缺 manifest 必须保持失败,Renderer 不得展示原始堆栈、URL、路径或错误码。升级链只有在旧版本完成发现、下载、重启和安装 smoke 后才可视为生产就绪。
|
||||
|
||||
## Last Updated
|
||||
|
||||
2026-08-21
|
||||
2026-08-26
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# Task: Recover Pi integration and merge updater fix
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260826-recover-pi-updater-integration-8f3a6c21
|
||||
- Mode: Integration
|
||||
- Branch: main
|
||||
- Worktree: D:\Datas\OthersProjects\makelore
|
||||
- Base commit: 48a9189939f3f9a581a76e9d6f5ba2f49879a67c
|
||||
- Owner: codex
|
||||
- Status: Verification complete; documentation gate pending
|
||||
|
||||
## Scope
|
||||
|
||||
- Recover the abandoned Pi integration documentation already present in the
|
||||
`main` worktree and validate it against the completed Pi source-task records.
|
||||
- Integrate the updater downgrade-prevention change from source commit
|
||||
`2e61800fed793b63b3b7804a03a4c7d8617e23d7` into `main`.
|
||||
- Verify the focused updater behavior, type safety, lint, and production Vite
|
||||
build before handing back the integrated branch.
|
||||
- Preserve unrelated untracked task records byte-for-byte and outside this
|
||||
task's commits.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- User explicitly authorized force-releasing and taking over the abandoned Pi
|
||||
integration task.
|
||||
- Treat completed source task records as read-only evidence; promote only the
|
||||
canonical Pi documentation that is supported by those records.
|
||||
- Keep unverified Pi release gaps explicit: real Provider execution, macOS
|
||||
x64/arm64 packaged artifacts, and native non-WSL Linux remain unverified.
|
||||
- Apply only the two updater source/test changes from the verified feature
|
||||
commit so the feature task record remains source-owned.
|
||||
- Do not modify, delete, or commit
|
||||
`20260819-package-learning-off-115-9c4d.md` or the superseded Pi integration
|
||||
task record without separate authority.
|
||||
|
||||
## Plan
|
||||
|
||||
1. Validate the pending Pi canonical documentation against source-task facts
|
||||
and current product boundaries.
|
||||
2. Apply the verified updater downgrade guard and its focused regression tests.
|
||||
3. Run focused tests, typecheck, scoped lint, and `build:vite`; inspect the
|
||||
final diff and commit the integrated result on `main`.
|
||||
4. Run the Task Documentation Gate, release ownership, and report any remaining
|
||||
foreign-record blocker without weakening or bypassing the gate.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Recovered and semantically reviewed the pending Pi canonical documentation
|
||||
against the completed hard-cutover, provider, release-proof, legacy-removal,
|
||||
and background-run source tasks.
|
||||
- Integrated the exact updater source/test change from
|
||||
`2e61800fed793b63b3b7804a03a4c7d8617e23d7` into `main` without copying or
|
||||
editing its source-owned task record.
|
||||
- Automatic update channel selection and later channel changes now explicitly
|
||||
restore `autoUpdater.allowDowngrade = false`, preventing installed `2.0.0`
|
||||
from treating online `1.1.9` as an available update.
|
||||
- Preserved both unrelated/unregistered task records byte-for-byte and outside
|
||||
the staged integration set.
|
||||
|
||||
## Verification
|
||||
|
||||
- Exact source parity:
|
||||
`git diff --exit-code 2e61800 -- electron/main/updater.ts tests/unit/app-updater.test.ts`
|
||||
passed before task-record finalization.
|
||||
- `pnpm exec vitest run tests/unit/app-updater.test.ts`: passed, 1 file / 15 tests.
|
||||
- `pnpm run typecheck`: passed.
|
||||
- `pnpm exec eslint electron/main/updater.ts tests/unit/app-updater.test.ts`: passed.
|
||||
- `pnpm test`: passed, 181 regular files / 1543 tests passed / 2 skipped,
|
||||
followed by the pressure file with 1/1 passed.
|
||||
- `pnpm run build:vite`: passed for Renderer, Electron Main, Preload, and the
|
||||
release utility worker; existing dynamic-import and large-chunk warnings
|
||||
remain warnings only.
|
||||
- `git diff --check`: passed.
|
||||
- `check_doc_drift.py --task-id 20260826-recover-pi-updater-integration-8f3a6c21`:
|
||||
blocked only by the two preserved foreign task records listed below.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Human authorization is required to move the unregistered foreign records
|
||||
`20260819-package-learning-off-115-9c4d.md` and
|
||||
`20260826-integrate-pi-provider-fix-6e4c2a91.md` out of the `main` worktree
|
||||
into a recovery directory. Until then the Task Documentation Gate cannot
|
||||
pass and integration ownership cannot be cleanly released.
|
||||
- Real Provider execution, packaged macOS x64/arm64 artifacts, and native
|
||||
non-WSL Linux artifacts remain explicitly unverified Pi release gates.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Applied the already-supported Pi hard-cutover facts to the canonical success
|
||||
criteria, decision index/ADR, architecture, current state, business rules,
|
||||
evidence index, and commitments.
|
||||
- No additional updater promotion candidate: the updater behavior is captured
|
||||
by focused tests and does not change an architectural boundary.
|
||||
Reference in New Issue
Block a user