Skip to content

Latest commit

 

History

History
175 lines (140 loc) · 10.5 KB

File metadata and controls

175 lines (140 loc) · 10.5 KB

离线优先的索引刷新 + mcpp-index 发布机制

日期: 2026-06-24 范围: mcpp 侧 —— mcpp build 等命令的索引刷新策略(离线优先)、mcpp index 命令、以及 mcpp-index(mcpp 的库索引)的发布机制。 配套: xlings 侧的 xim-pkgindex 发布解耦见 xlings 仓 .agents/docs/2026-06-24-pkgindex-publish-decoupling-ci.md背景: 2026-06 Termux 适配中发现两个痛点 —— ① mcpp build 每次自动 xlings update 联网(被墙网络下卡 5 分钟,见 termux-android-adaptation §3);② 改了索引仓后默认客户端 拿不到(artifact 不刷新)。


已就绪的基础设施(2026-06-24)

  • 资源仓:xlings-res/mcpp-index(github + gitcode 两端均已创建)—— 放 mcpp 索引 artifact + 指针。 复用 xlings-res(mcpp 二进制本就在 xlings-res/mcpp),不另起 mcpp-res 组织。
  • secrets:mcpp-community/mcpp-index 仓已配 XLINGS_RES_TOKEN + GITCODE_TOKEN
  • Actions:mcpp-index 仓已启用。
  • 逐仓自文档:发布机制说明见 mcpp-community/mcpp-index.agents/docs/2026-06-24-artifact-publish-mechanism.md
  • 剩待办:① mcpp-index 仓加 publish-artifact.yml;② mcpp 侧加 artifact 拉取 + 离线优先(本文档 P0/P1)。

0. 现状

  • mcpp build 自动联网刷索引:package_fetcher 在装 xim 包前调 ensure_official_package_index_fresh() → 若 TTL 过期则 xlings update(git 同步多个 索引仓,含被墙的 github 子索引)。每次构建都可能联网,离线/弱网体验差。
  • mcpp 已有 index 子命令:mcpp index list|add|remove|update|pin|unpin(cli.cppm)。 即"显式刷新"的入口已存在,但 build 仍走"隐式自动刷新"。
  • mcpp-index 是 git-only:mcpp git-clone mcpp-community/mcpp-index~/.mcpp/registry/data/mcpplibs,受 mcpp 的 index TTL 缓存影响("改了不刷"根因)。

1. 设计原则:首次 bootstrap 保证有索引,之后离线优先

区分两个阶段:

1.a 首次初始化(必须保证有索引)

mcpp 第一次跑 / 沙盒初始化时(当前日志:Initialize mcpp sandbox layout (one-time) + Fetching package index (one-time)),必须确保本地有一份可用索引 —— 这是唯一允许 "自动联网"的时刻:

  • 优先用随发行版内置/种子索引(seed):mcpp 二进制包里捎带一份索引快照,首次直接落地, 零网络也能起步(离线装机也能用,后续再显式刷新)。
  • 无 seed 或 seed 不可用时,首次自动拉一次(指针+artifact,失败回退 git);拉不到则 明确报错"首次初始化需要网络/或提供离线索引包",而不是静默半残。
  • 首次落地后写入索引的版本/时间/sha 标记,作为后续 index status 与 TTL 的依据。

1.b 之后(steady-state):离线优先,刷新是显式动作

索引一旦存在,命令默认只用本地索引,绝不为"顺手刷新"而联网;联网刷新由用户显式触发。

命令 联网? 行为
首次 init 是(仅此一次) seed 落地 / 或自动拉一次,保证有索引
mcpp build / run / add 否(默认) 只读本地索引;缺包才提示 mcpp index update
mcpp index update [--force] 显式刷新(steady-state 唯一默认联网入口)
mcpp index status 否(可选 --check 联网比指针) 显示本地索引版本/时间/来源
mcpp index list/search 本地查询

要点:

  • build 不再自动 xlings update(首次 init 已保证有索引)。本地索引存在即用;仅当解析 失败(包/版本本地查不到)时,提示"运行 mcpp index update 刷新",而不是默默联网卡住。
  • 保留一个很长的软 TTL(如 24h)做"温和提醒"(stderr 一行 hint),但不阻塞、不自动拉
  • mcpp index status:打印本地索引的 版本/时间戳/sha/来源(seed|artifact|git), 让用户/CI 知道是否该刷。
  • 不变量:任何 steady-state 命令在离线下都能跑(只要首次 init 成功过)。

2. 自动刷新若保留,必须"低成本 + 可离线降级"

如果某些场景(如 CI 首次)仍要自动刷,刷新动作要满足:

  1. 先查轻量指针:只 GET 一个小 JSON(*-latest.json,几百字节)比对本地 sha; 命中(sha 相同)→ 零下载、零 git。这是"低成本重查"的核心,远比 git pull / 全量 xlings update 便宜。
  2. 未命中才下 artifact(整包 tar.gz,一次,带 sha 校验)。
  3. 指针/artifact 拉取失败 → 静默降级用本地(离线可用),不报错中止。
  4. 绝不在 build 主路径上做 git clone/pull(慢、易卡、被墙)。

对比现状:ensure_official_package_index_fresh → xlings update 是"全量 git 同步多个 仓",最重最易卡。改成"指针 sha 比对"后,绝大多数 build 不产生任何索引网络流量。


3. mcpp-index 发布机制:补齐 artifact + 发布 CI

现状 git-only 的两个问题:① 客户端 git clone 慢/弱网易失败;② 没有"指针 sha"可做 低成本比对(只能 git fetch)。建议与 xim-pkgindex 统一为 artifact 模型:

  1. mcpp-index 仓加 publish-artifact.yml(push paths pkgs/** + workflow_dispatch
    • 可选 schedule):打包 pkgs/ → 生成 mcpp-index-<gitsha>.tar.gz + manifest
    • 更新指针 mcpp-index-latest.json,发到资源仓(github + gitcode,复用 XLINGS_RES_TOKEN/GITCODE_TOKEN 或 mcpp-res 等价物)。改索引 push → 自动发布, 不必发 mcpp 版本。
  2. mcpp 侧加 artifact 拉取:mcpp index update 优先拉指针+artifact(命中 sha 跳过), git clone 仅作回退(MCPP_INDEX_SOURCE=artifact|git|auto,默认 auto),对齐 xlings 的 XLINGS_INDEX_SOURCE 模型。
  3. artifact 按内容哈希命名(解绑 mcpp/xlings 版本),指针随改随移。

收益:① 改 mcpp-index 即时生效(不绑发版);② build 的自动刷新可降级成"指针 sha 比对", 离线可用;③ 两套索引(xim-pkgindex / mcpp-index)发布+拉取模型统一,维护成本低。


4. 落地顺序(建议)

  1. P0(离线优先):① 首次 init 保证有索引(优先内置 seed,否则自动拉一次,失败明确报错); ② mcpp build 去掉"自动 xlings update",改为"本地优先 + 解析失败提示 mcpp index update"; ③ 加 mcpp index status纯 mcpp 改动,立刻提升弱网/离线体验。
  2. P1(低成本刷新):mcpp index update 走"指针 sha 比对 → 命中跳过 / 未命中下 artifact"。 依赖 mcpp-index 有指针(见 P2)。
  3. P2(发布解耦):mcpp-index 仓加 artifact 发布 CI + mcpp 侧 artifact 拉取(与 xim-pkgindex 对齐)。

4.1 实现进度(WS3)

  • ✅ P0②(build 离线优先 + 缺包触发刷新):ensure_official_package_index_fresh(src/xlings.cppm) 不再因 TTL 过期就跑联网 xlings update。改为 miss-triggered:
    • 依赖在本地索引里 → 直接用,零网络(常态 build,消除 Termux 首跑/构建卡几分钟的根因);
    • 依赖在本地索引里查不到 → 自动刷新一次去拉它(mcpp build 路径以 quiet=false 调用, 打印一行 Refreshing package index — \` not found locally`,让一次性网络停顿不像卡死)。
    • 防重:刚刷过(<120s)且包仍缺失 → 不再重复跑 xlings update(上游确实没有,重拉无益), 避免一个 build 里多个缺包各跑一遍全量 git 同步。 commit f0f57ae(初版纯离线)→ 增补 miss-triggered + 防重 + 可见提示。

    即"完全不联网"过严;稳态(依赖齐全)不联网,缺包则联网刷一次,二者兼得。

  • ✅ P0③(mcpp index status):新增只读、全程不联网mcpp index status,显示 xim/mcpplibs 两索引的 present/fresh/age/path;缺索引时提示显式 mcpp index update,否则确认本地可离线用。 src/xlings.cppm 导出 IndexStatus + {default,official}_index_status;src/pm/index_management.cppm index_status();CLI 接线 + e2e tests/e2e/75_index_status_offline.sh(commit ba92265)。
  • P0①(seed 内置索引):暂沿用"缺则自动拉一次"(已满足首次保证有索引);随发行版捎带 seed 快照为后续优化。
  • P1 / P2(指针 sha 比对 + mcpp 侧 artifact 拉取):mcpp-index 发布侧已就绪(WS2,资源仓 xlings-res/mcpp-index push 触发发 artifact + 指针);mcpp 客户端的 artifact 拉取/比对为后续 PR。 当前闭环经 git 路径已可用(稳态离线、缺包显式刷新)。

4.5 追加计划:first-init 细粒度带时间戳 debug log(WS5)

动机:mcpp 第一次运行常卡很久(Termux 实战),但日志太粗,看不出卡在哪一步。 需要在首次 init 全过程--verbose 才可见的细粒度 debug log,且每条带时间戳, 方便事后定位"卡很长时间"的具体步骤与耗时。

要覆盖的步骤(日志现状只有一行,需细化):

Initialize mcpp sandbox layout (one-time)
Fetching package index (one-time)
Bootstrap patchelf into mcpp sandbox (one-time)     ← 重点
Bootstrap ninja into mcpp sandbox (one-time)        ← 重点
First run no toolchain configured — installing gcc@15.1.0-musl ...  ← 重点

每个步骤前后打 [verbose][HH:MM:SS.mmm] <step> start/done (Δ=<ms>),尤其:

  • 每个 bootstrap(patchelf/ninja)的下载 URL、镜像、connect/下载/解压各阶段用时;
  • toolchain 安装的 resolve / download / extract 各阶段用时;
  • 索引 fetch 的 pointer 比对 / 下载 / git 各阶段用时。

约束:

  • --verbose(或 MCPP_LOG=debug)可见,日常用户输出不变。
  • 时间戳统一(单调时钟取 Δ,墙钟取绝对时间)。
  • 和最新版一起发布(随 mcpp 下个版本)。

配套铁律(已并入发布流程):每次 xlings / mcpp 发新版,对应索引也要更新到 latest —— xim-pkgindex(xim:mcpp/xim:xlings 版本块 + artifact)、mcpp-index(若涉及库)都要随发版同步, 否则默认客户端装不到新版(见本仓 + xim-pkgindex 仓发布机制文档)。现已有 push 触发的 publish-artifact CI,改索引即自动发 artifact;版本块(mcpp.lua/xlings.lua 的 latest ref) 仍需在发版流程里 bump。

5. 一句话

首次 init 保证有索引(内置 seed 优先,否则自动拉一次);之后离线优先(默认不联网刷索引, 缺包才提示显式 mcpp index update),刷新走"轻量指针 sha 比对"而非全量 git;mcpp-index 补齐 artifact + push 触发发布 CI,与 xim-pkgindex 统一模型。

相关:.agents/docs/2026-05-31-index-refresh-cache-labels-plan.md.agents/docs/2026-05-08-package-index-config.md;Termux 背景见 .agents/docs/2026-06-23-termux-android-adaptation.md §3。