From fe49665409061e4656b1274b9b6be5094e029b80 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:08:32 +0800 Subject: [PATCH 1/2] the readings the release produced, recorded where they were promised MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sandbox verification of 2026.9.21.3 in SubOS v920 with the CN mirror, both legs against published artefacts: mcpp 2026.9.21.2 (published) fails=2 G and H mcpp 2026.9.21.3 (published) fails=0, nothing skipped B, C and D pass on both, which is correct rather than a hole: they are the previous wave's changes and stay as guards once their own release has shipped. Only G and H are CHANGE sections for this one, and both are red on the older engine. The plan gains the whole publish chain — squash tree byte-identical to the PR head, six release jobs green, eight GitCode assets serving with sizes matching upstream, all four sha256 independently recomputed from the CN mirror and equal to both the sidecars and the bump PR's values. It also records a no-op that only a measurement could have caught: the first local GitCode top-up exited 0 and reported "all assets mirrored + verified on 1 host(s)" while the line above said `no GITCODE_TOKEN/gtc; skipping gitcode mirror`. The gate wants the environment variable and `gtc` keeps its token in its own config, so the one leg that had to run was skipped behind a success message. A GET against gitcode.com returned 404, which is how it was found. --- ...2026-09-21-macros-and-withdrawal-verify.sh | 14 +++++++++ ...kal-ecosystem-completion-and-acceptance.md | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+) 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..f2264323 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,35 @@ __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` 把 token 放在自己的配置文件里,于是 +**唯一要做的那条腿被跳过,包在一条成功消息后面**。是我按判据去 GET +`gitcode.com` 读到 404 才发现的——**退出码不是判据,资产能不能被取回才是**。 + ## 8. 本方案自身的失败模式 写下来,因为它们在本轮各出现过一次。 From 1886bb26af15a9a2d5249bee353ebfbfbfe34da6 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Mon, 21 Sep 2026 09:15:08 +0800 Subject: [PATCH 2/2] a configured gtc is authentication, and a skipped host was not a pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TWO DEFECTS, ONE MEASUREMENT. A local top-up exited 0 and printed `all assets mirrored + verified on 1 host(s)` while `no GITCODE_TOKEN/gtc; skipping gitcode mirror` sat one line above it, and nothing had reached GitCode. FIRST: the gate asked the wrong question. `gtc` resolves its own credentials — `GITCODE_TOKEN` first, then the config file its `--help` documents — exactly as `gh` does, and the github leg 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, which is the whole reason it can be run by hand: the cross-border upload from a GitHub runner is the shaped path that has cost four releases their aarch64 asset. SECOND, AND WORSE: `verify` iterates the hosts that turned out to be ENABLED, so its denominator came from the same enumeration as its numerator. It could not tell "both hosts serve every asset" from "one host was skipped and the other serves every asset" — the skip was invisible to the only check that could have reported it. `MIRROR_HOSTS` states the required set before anything is probed, and defaults to `both`. Wanting one leg stays possible, because topping GitCode up by hand is legitimate, but it has to be asked for rather than being what happened. Missing credentials for a required host now exit 2 and name both places a token can live. Measured, four paths: local, gtc configured, no env var skipped silently, exit 0 -> 2 hosts MIRROR_HOSTS=gtc n/a -> 1 host, stated gtc present with no token skipped silently, exit 0 -> exit 2 CI (both tokens in the environment) 2 hosts -> unchanged The third case had to be isolated with a config home carrying gh and not gtc: emptying the whole config home fails the upstream download instead and never reaches the gate, which is a test that would have passed for the wrong reason. --- ...kal-ecosystem-completion-and-acceptance.md | 25 ++++-- .github/tools/mirror_res.sh | 78 ++++++++++++++++--- 2 files changed, 85 insertions(+), 18 deletions(-) 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 f2264323..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 @@ -1008,12 +1008,25 @@ artifact 发布 → `xlings install mcpp@2026.9.21.3` 成功。 ⭐ 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` 把 token 放在自己的配置文件里,于是 -**唯一要做的那条腿被跳过,包在一条成功消息后面**。是我按判据去 GET -`gitcode.com` 读到 404 才发现的——**退出码不是判据,资产能不能被取回才是**。 +**一个只有实测才能发现的空转,以及它已经被修掉。** 第一次本地补 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