diff --git a/.agents/docs/2026-09-21-macros-and-withdrawal-verify.sh b/.agents/docs/2026-09-21-macros-and-withdrawal-verify.sh index 0e430e04..e8098d99 100755 --- a/.agents/docs/2026-09-21-macros-and-withdrawal-verify.sh +++ b/.agents/docs/2026-09-21-macros-and-withdrawal-verify.sh @@ -30,6 +30,20 @@ # # D and F needed `openkal-llvm-runtime@0.14.0`, registered after that dry run, # and both reported NOT RUN rather than passing. +# +# THE 2026.9.21.3 WAVE, MEASURED IN SubOS `v920` WITH THE CN MIRROR, AGAINST +# THE PUBLISHED ARTEFACTS ON BOTH LEGS: +# +# mcpp 2026.9.21.2 (published) fails=2 +# G the aarch64-macos build does not complete --- `-fno-builtin- +# memset_pattern16` is accepted and ignored, so the link stops at +# `undefined symbol: memset_pattern16` +# H `--no-run` does not exist +# mcpp 2026.9.21.3 (published) fails=0, nothing skipped +# +# B, C and D pass on BOTH, and that is correct rather than a hole: they are the +# previous wave's changes, and this file keeps them as guards once their own +# release has shipped. Only G and H are CHANGE sections for this one. set -u VER="${MCPP_VERIFY_VERSION:?set MCPP_VERIFY_VERSION}" diff --git a/.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md b/.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md index b5ee2bf4..6ba7af1c 100644 --- a/.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md +++ b/.agents/docs/2026-09-21-openkal-ecosystem-completion-and-acceptance.md @@ -986,6 +986,48 @@ __APPLE__ __MACH__ __MCPP_TARGET_MACOS__ __OPENKAL__ __unix__ 直接适用),要么由生态数据回答(每个配方按 `__has_include` 逐条问)。十个红格子的修法是 **一个**问题,不是十个,而这条记录的作用是让那个问题带着数字被提出。 +### 7.3 发布与沙箱验收(2026.9.21.3) + +发布物走完整条链:合入(squash 后的树与 PR head **逐字节相同**,39 条绿因此可转移)→ +release.yml 六个 job 全绿 → 本地 `gtc` 补 GitCode(8 个资产全部 200,大小与上游一致; +linux x86_64 6.1MB 上传耗时 **5 秒**)→ 从 CN 镜像下载四个归档**独立重算 sha256**,与 +各自的 sidecar 以及 bump PR 里的四个值**全部相同** → 合入 xim-pkgindex #868 → 索引 +artifact 发布 → `xlings install mcpp@2026.9.21.3` 成功。 + +**沙箱验收在 SubOS `v920` 里跑,配 CN mirror,两条腿都用已发布物:** + +| 段 | 2026.9.21.2(已发布) | 2026.9.21.3(已发布) | +| --- | --- | --- | +| A 身份与镜像 | ok | ok | +| B/C/D(上一批的 CHANGE) | ok | ok | +| E/F(GUARD) | ok | ok | +| **G** `builtins = "iso"` | **FAIL** | ok | +| **H** `mcpp test --no-run` | **FAIL** | ok | +| | `fails=2` | **`fails=0`,无 not run** | + +⭐ B/C/D 在两条腿上都绿是**对的**:它们是上一批的 CHANGE,发布之后就转为 guard。 +本批只有 G 和 H 是 CHANGE,**而它们在旧版上都红**——这正是 CHANGE 段必须具备的性质。 + +**一个只有实测才能发现的空转,以及它已经被修掉。** 第一次本地补 GitCode 退出码为 0 +并打印「all assets mirrored + verified on 1 host(s)」,而上一行写着 +`no GITCODE_TOKEN/gtc; skipping gitcode mirror`:`mirror_res.sh` 的闸要求**环境变量** +`GITCODE_TOKEN` 非空,而 `gtc` 与 `gh` 一样自己解析凭据(先环境变量、再它 `--help` +写明的配置文件),于是**一台 gtc 完全可用的机器被判定为没有 gtc**——而那正是这个脚本 +被手动运行的那台机器。是我按判据去 GET `gitcode.com` 读到 404 才发现的。 + +⭐⭐ **更深的一层在验收环节:`verify` 只遍历「实际启用了的」host。** 分母与分子取自 +同一次枚举,于是它分不出「两个 host 都齐」和「一个 host 被跳过、另一个齐」。 +修法是把「这次必须完成哪些 host」在探测之前就声明出来(`MIRROR_HOSTS`,默认 `both`): +想只补一条腿是合法的——从 CN 宿主手动补 GitCode 正是本地运行的理由——**但它必须被要求, +不能是意外的结果**。凭据缺失现在硬退 2 并指出 token 可以放的两个位置。 + +| 情形 | 修之前 | 修之后 | +| --- | --- | --- | +| 本地,gtc 已配置、无环境变量 | **静默跳过,退 0** | 两个 host 都镜像并核验 | +| `MIRROR_HOSTS=gtc` | 无 | 明确排除 GitHub,退 0 | +| gtc 在但没有 token | **静默跳过,退 0** | **退 2**,指出两个可放 token 的位置 | +| CI(两个 token 都在环境里) | 两个 host | 不变,两个 host | + ## 8. 本方案自身的失败模式 写下来,因为它们在本轮各出现过一次。 diff --git a/.github/tools/mirror_res.sh b/.github/tools/mirror_res.sh index 96664d4a..10a8fcaa 100755 --- a/.github/tools/mirror_res.sh +++ b/.github/tools/mirror_res.sh @@ -246,22 +246,76 @@ mirror_host() { # kind(gh|gtc) base_url deadline_seconds # ── Both hosts IN PARALLEL: they are fully independent, and the gitcode # leg is cross-border-slow — serializing them doubled wall time for nothing. +# ── WHICH HOSTS THIS RUN MUST COMPLETE, STATED BEFORE ANYTHING IS PROBED ── +# +# The verify gate below iterates the hosts that turned out to be ENABLED, so +# until this variable existed its denominator came from the same enumeration +# as its numerator and could not tell "both hosts serve every asset" from +# "one host was skipped and the other serves every asset". Measured, 2026-09-21: +# a local top-up run exited 0 and printed `all assets mirrored + verified on +# 1 host(s)` with `no GITCODE_TOKEN/gtc; skipping gitcode mirror` one line +# above it, and nothing had reached GitCode at all. +# +# `both` is the default because that is what this script is for: the two hosts +# serve the GLOBAL and CN install paths, and an incomplete mirror surfaces as +# a 404 in the first user's install. Wanting one leg is legitimate --- topping +# GitCode up by hand from a CN host is the reason this runs locally at all --- +# but it has to be asked for. +: "${MIRROR_HOSTS:=both}" +case "$MIRROR_HOSTS" in + both|gh|gtc) ;; + *) echo "[mirror] MIRROR_HOSTS must be both|gh|gtc, not '$MIRROR_HOSTS'" >&2; exit 2 ;; +esac +WANT_GH=0; WANT_GTC=0 +[[ "$MIRROR_HOSTS" == both || "$MIRROR_HOSTS" == gh ]] && WANT_GH=1 +[[ "$MIRROR_HOSTS" == both || "$MIRROR_HOSTS" == gtc ]] && WANT_GTC=1 + +# CAN `gtc` AUTHENTICATE, NOT IS THE VARIABLE SET. +# +# gtc resolves its own credentials -- `GITCODE_TOKEN` first, then the config +# file its `--help` documents -- exactly as `gh` does, and the github leg below +# has always accepted either. This leg demanded the variable, so a machine with +# a working, configured gtc was told it had none. That is the machine this +# script is run on by hand. +gtc_can_auth() { + command -v gtc >/dev/null 2>&1 || return 1 + [[ -n "${GITCODE_TOKEN:-}" ]] && return 0 + local cfg="${XDG_CONFIG_HOME:-$HOME/.config}/gitcode-tool/config.json" + [[ -s "$cfg" ]] && grep -q '"token"[[:space:]]*:[[:space:]]*"[^"]\+"' "$cfg" +} + GH_ENABLED=0 -if [[ -n "${XLINGS_RES_TOKEN:-}" ]] || gh auth status >/dev/null 2>&1; then - GH_ENABLED=1 - info "GitHub $GH_DST tag $VER" - GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release view "$VER" -R "$GH_DST" >/dev/null 2>&1 \ - || GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release create "$VER" -R "$GH_DST" --title "$VER" --notes "$PROJ $VER (mirror of $SRC_REPO)" +if [[ "$WANT_GH" == 1 ]]; then + if [[ -n "${XLINGS_RES_TOKEN:-}" ]] || gh auth status >/dev/null 2>&1; then + GH_ENABLED=1 + info "GitHub $GH_DST tag $VER" + GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release view "$VER" -R "$GH_DST" >/dev/null 2>&1 \ + || GH_TOKEN="${XLINGS_RES_TOKEN:-}" gh release create "$VER" -R "$GH_DST" --title "$VER" --notes "$PROJ $VER (mirror of $SRC_REPO)" + else + echo "[mirror] FAIL: this run must mirror to GitHub and there is no auth for it." >&2 + echo "[mirror] set XLINGS_RES_TOKEN, or run \`gh auth login\`," >&2 + echo "[mirror] or pass MIRROR_HOSTS=gtc to mirror only GitCode." >&2 + exit 2 + fi else - info "no github auth; skipping github mirror" + info "MIRROR_HOSTS=$MIRROR_HOSTS: not mirroring to GitHub" fi + GTC_ENABLED=0 -if [[ -n "${GITCODE_TOKEN:-}" ]] && command -v gtc >/dev/null 2>&1; then - GTC_ENABLED=1 - info "GitCode $GTC_DST tag $VER" - gtc release create "$GTC_DST" --tag "$VER" --name "$VER" 2>/dev/null || true +if [[ "$WANT_GTC" == 1 ]]; then + if gtc_can_auth; then + GTC_ENABLED=1 + info "GitCode $GTC_DST tag $VER" + gtc release create "$GTC_DST" --tag "$VER" --name "$VER" 2>/dev/null || true + else + echo "[mirror] FAIL: this run must mirror to GitCode and gtc cannot authenticate." >&2 + echo "[mirror] put gtc on PATH and give it a token -- GITCODE_TOKEN, or" >&2 + echo "[mirror] \"token\" in ${XDG_CONFIG_HOME:-$HOME/.config}/gitcode-tool/config.json --" >&2 + echo "[mirror] or pass MIRROR_HOSTS=gh to mirror only GitHub." >&2 + exit 2 + fi else - info "no GITCODE_TOKEN/gtc; skipping gitcode mirror" + info "MIRROR_HOSTS=$MIRROR_HOSTS: not mirroring to GitCode" fi GH_PID=""; GTC_PID="" @@ -313,5 +367,5 @@ if [[ $rc != 0 ]]; then echo "[mirror] hint: if the asset above was WARNed at a leg deadline, raise MIRROR_LEG_DEADLINE_GH/GTC for this run, or push it by hand:" >&2 echo "[mirror] gh release download v$VER -R $SRC_REPO -p '' && gtc release upload $GTC_DST '' --tag $VER" >&2 fi -[[ $rc == 0 ]] && info "all assets mirrored + verified on ${#hosts[@]} host(s) in ${SECONDS}s" +[[ $rc == 0 ]] && info "all assets mirrored + verified on ${#hosts[@]} host(s) (${hosts[*]}) in ${SECONDS}s" exit $rc