Skip to content

Commit d67b96f

Browse files
2026.10.28.1: emit xpkg entries xlings installs; a package's key covers every module it imports; SIGTERM's status; SPEC-014 1.2; the index bump (#854)
The 2026.10.28.1 release: what the ecosystem check of 2026.10.27.1 found. - SPEC-014 1.2: a package name carries a mode's suffix (`-bundle-all` for self-contained), a single file's launcher exits 127 on its own failure, `--merge` takes its container from `[pack] format` before `-o`, and `--linkage static` moves this machine's row and each `-linux-gnu` `--target` to musl while a project's own `[build] target` is packed as it is. - `mcpp emit xpkg --package`: packages of several systems may place the program apart (openkal-image 0.1.3's okrun: `okrun.exe` at the root on Windows, `bin/okrun` elsewhere). The entry registered the first package's directory for every system; it now writes `bindir[os.host()]` from each system's directory when they differ. A word past the options (`--package a.zip b.zip`, a shell glob) was silently left out; it is refused with the repeated form. The install looked its directory up with `os.dirs("<name>-0.1.3-*")`, which libxpkg's `os.dirs` (it lists `<base>/*`, no name matching) never matched: no xlings install of an emitted entry succeeded. The directory is now the downloaded archive's name without its extension (as `mcpp pack` names it), valid for every system, architecture and later version; a renamed archive or a non-archive is refused. Verified in a clean `XLINGS_HOME`: okrun, okld and a universal package installed from emitted entries and run. The runner dependency is written `xim:okrun`: xim-pkgindex's `check-dep-namespace` refuses a bare name once the package is published. Unit `XpkgDescriptorNamesEachSystemsProgramDirectory`; e2e 957 C. - `mcpp.run`: a build ended by SIGTERM could exit 1 instead of 143 when the main thread, woken by its killed compiler, returned from `main` before the watcher ended mcpp (main CI 40671515047, e2e 936 H, the cancelled record in place). `finish()` runs once with later callers waiting for it, and `main` ends with `end_if_requested()`. - **Cache key**: the provider of each module a package imports is an upstream of its key, a declared edge or not. The libraries of a build program import the engine interface (`mcpp`), which no manifest names; `mcpp.plugins` was served an entry compiled against another interface ("import 'mcpp' has CRC mismatch", measured in an ok-image build over a warm cache). An import a declared path runs the other way (a module generated for a dependency below its consumer, e2e 849) is not one. New e2e 959 (fails before, passes after); `ci-upgrade` gains a `programs` variant (an ok image over the previous release's cache). - `archive_directory()` is the one rule a package's directory takes from its archive (`pack -o`, `--merge -o`, `emit xpkg`); `--merge -o` names the merged directory after its output; `emit xpkg` reads `.tgz`. - `finish()` reached again from inside a cleanup returns at once. - `upgrade-lane-logs/` (committed with 2026.10.17.1) leaves the tree and is ignored. - `bump_index.sh`: the updater opens `auto/bump-xim-<project>` (no version in the branch), so the release waited for a branch that never appears; the PR is found by its `xpkgindex-update` marker (open or merged). A refused dispatch names the permission the token lacks (Actions: write on openxlings/xim-pkgindex) and the command a maintainer runs. publish-ecosystem has failed at this step since 2026.10.24.1 (403 on the dispatch). Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent e0b1133 commit d67b96f

38 files changed

Lines changed: 522 additions & 255 deletions

‎.github/tools/bump_index.sh‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
# updater does it for every package (`xpkgindex-update.yml`, pinned
66
# openxlings/xpkgindex-update): it discovers the release from the recipe's
77
# `extensions.autoupdate.source` (xlings-res/<project> releases), requires the
8-
# GLOBAL and CN resources, computes each sha256 and opens
9-
# `auto/bump-xim-<project>-<version>`. The script that used to do this here,
8+
# GLOBAL and CN resources, computes each sha256 and opens a PR whose body
9+
# starts with `<!-- xpkgindex-update: {"id":"xim:<project>","candidate":"<version>"} -->`
10+
# (its branch, `auto/bump-xim-<project>`, does not name the version, so the
11+
# marker is what identifies the proposal). The script that used to do this here,
1012
# `.github/scripts/version-check.py`, was removed from the index by that
1113
# change; 2026.10.24.1 is the release that found out (publish-ecosystem
1214
# failed on the missing file). Asking the index's own updater keeps one writer
@@ -17,27 +19,38 @@
1719
#
1820
# Usage: bump_index.sh <project> <version> # e.g. mcpp 2026.10.24.1
1921
# Auth:
20-
# PKGINDEX_TOKEN (required) -- may dispatch workflows of openxlings/xim-pkgindex
22+
# PKGINDEX_TOKEN (required) -- a token with Actions: write on
23+
# openxlings/xim-pkgindex (a workflow dispatch needs that permission;
24+
# Contents and Pull requests do not grant it)
2125
set -euo pipefail
2226

2327
PROJ="${1:?usage: bump_index.sh <project> <version>}"
2428
VER="${2:?usage: bump_index.sh <project> <version>}"
2529
INDEX_REPO="${INDEX_REPO:-openxlings/xim-pkgindex}"
26-
BRANCH="auto/bump-xim-${PROJ}-${VER}"
30+
export MARKER="<!-- xpkgindex-update: {\"id\":\"xim:${PROJ}\",\"candidate\":\"${VER}\"} -->"
2731
WAIT_S="${BUMP_WAIT_S:-1200}"
2832
export GH_TOKEN="${PKGINDEX_TOKEN:?PKGINDEX_TOKEN required (dispatch on $INDEX_REPO)}"
2933

3034
info() { echo "[bump] $*"; }
3135

32-
pr_url() { gh pr view "$BRANCH" -R "$INDEX_REPO" --json url --jq .url 2>/dev/null || true; }
36+
# The updater's PR for this version, open or merged.
37+
pr_url() {
38+
gh pr list -R "$INDEX_REPO" --state all --limit 50 --json url,body,state \
39+
--jq '[.[] | select(.state != "CLOSED" and (.body | startswith(env.MARKER)))][0].url // empty' \
40+
2>/dev/null || true
41+
}
3342

3443
if url="$(pr_url)" && [[ -n "$url" ]]; then
35-
info "PR already open: $url"
44+
info "PR already proposed: $url"
3645
exit 0
3746
fi
3847

3948
info "dispatching xpkgindex-update.yml for xim:$PROJ"
40-
gh workflow run xpkgindex-update.yml -R "$INDEX_REPO" --ref main -f "package=xim:$PROJ"
49+
if ! gh workflow run xpkgindex-update.yml -R "$INDEX_REPO" --ref main -f "package=xim:$PROJ"; then
50+
echo "[bump] PKGINDEX_TOKEN cannot dispatch on $INDEX_REPO (it needs Actions: write);" \
51+
"a maintainer runs: gh workflow run xpkgindex-update.yml -R $INDEX_REPO --ref main -f package=xim:$PROJ" >&2
52+
exit 1
53+
fi
4154

4255
deadline=$(( $(date +%s) + WAIT_S ))
4356
while (( $(date +%s) < deadline )); do
@@ -50,6 +63,6 @@ done
5063

5164
# BLOCKING: without the PR the index never learns the release exists. The
5265
# updater's run says why (a resource missing on one host, a policy refusal).
53-
echo "[bump] no $BRANCH after ${WAIT_S}s; see" \
66+
echo "[bump] no PR for xim:$PROJ $VER after ${WAIT_S}s; see" \
5467
"https://github.com/$INDEX_REPO/actions/workflows/xpkgindex-update.yml" >&2
5568
exit 1

‎.github/tools/upgrade_lane.sh‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
# revisions (llvm revision 0, gcc 16.1.0 before -r1).
1818
# orphan every payload recorded at another revision, and `c++` active at
1919
# gcc's version whose registration is gone (a reported home).
20+
# modules a module dependency the previous release compiled is served from
21+
# its cache when the spelling of its BMI has not moved.
22+
# programs the previous release builds an ok image, whose platform's build
23+
# program imports mcpp.plugins over the engine interface (`mcpp`);
24+
# this commit's mcpp builds it again over that cache, and no
25+
# library compiled against another interface is served ("CRC
26+
# mismatch").
2027
#
2128
# Asserted, every variant: the first `mcpp new && mcpp run` of the new mcpp
2229
# succeeds and downloads nothing; a second run likewise; `mcpp self doctor`
@@ -158,6 +165,12 @@ if [ "$VARIANT" = modules ]; then
158165
fi
159166
new_project p-old "$OLD"
160167
run old-run "$W/p-old" "$OLD" run || fail "the previous release cannot run a new project"
168+
case "$PLAT" in linux-x86_64) OK_TARGET=x86_64-openkal ;; *) OK_TARGET=aarch64-openkal ;; esac
169+
if [ "$VARIANT" = programs ]; then
170+
new_project k-old "$OLD"
171+
run old-programs "$W/k-old" "$OLD" build --target "$OK_TARGET" \
172+
|| fail "the previous release cannot build an ok image"
173+
fi
161174

162175
if [ "$VARIANT" = orphan ]; then
163176
"$PY" - "$REG" <<'PY' || fail "could not shape the orphan home"
@@ -238,6 +251,12 @@ if [ "$VARIANT" = modules ]; then
238251
grep -q "STAGE gcm.cache/mcpplibs.openkal/" "$W/new-modules2.log" \
239252
|| fail "the rebuilt dependency was not served from the cache"
240253
fi
254+
if [ "$VARIANT" = programs ]; then
255+
run new-programs "$W/k-old" "$NEW" build --target "$OK_TARGET" \
256+
|| fail "the ok image the previous release built does not build over its cache"
257+
grep -q "CRC mismatch" "$W/new-programs.log" \
258+
&& fail "a build program's library compiled against the previous engine interface was served"
259+
fi
241260
if [ "$VARIANT" = orphan ]; then
242261
run new-provision "$W" "$NEW" toolchain install "$TC" || fail "toolchain install could not replace the payload"
243262
grep -q "installed asset registration missing" "$W/new-provision.log" \

‎.github/workflows/ci-upgrade.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
- { host: linux-x86_64, runs-on: ubuntu-24.04, variant: snapshot }
3131
- { host: linux-x86_64, runs-on: ubuntu-24.04, variant: orphan }
3232
- { host: linux-x86_64, runs-on: ubuntu-24.04, variant: modules }
33+
- { host: linux-x86_64, runs-on: ubuntu-24.04, variant: programs }
3334
- { host: linux-aarch64, runs-on: ubuntu-24.04-arm, variant: plain }
3435
- { host: macos-arm64, runs-on: macos-15, variant: plain }
3536
- { host: windows-x86_64, runs-on: windows-latest, variant: plain }

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@ examples/*/target/
5656

5757
# Local review reports (not part of the design record).
5858
/.agents/reviews/
59+
60+
# The logs .github/tools/upgrade_lane.sh copies beside the workspace (CI uploads
61+
# them as an artifact; a local run leaves them here).
62+
/upgrade-lane-logs/

‎CHANGELOG.md‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,73 @@
44
> Each `## [<version>]` section is that release's notes. Entries are written in English
55
> from 2026.9.28.3 on; earlier entries remain as written.
66

7+
## [2026.10.28.1] - 2026-10-28
8+
9+
### Fixed
10+
11+
- **A package's cache key covers every package whose module it imports.**
12+
A BMI is bound to the BMIs it read, and the key folded in only the
13+
dependencies a manifest states. A package can import a module its manifest
14+
does not name: the libraries of a build program import the engine
15+
interface (`mcpp`), which the engine adds to the build program's graph.
16+
Such a package was served an entry compiled against another BMI of that
17+
module and failed with "CRC mismatch" (measured: `mcpp.plugins` in a build
18+
of an ok image, over a cache earlier builds had filled). The provider of
19+
each imported module is now an upstream of the importer's key, a declared
20+
edge or not; a module this build generates for a dependency below its
21+
consumer's root is not one (e2e 849). e2e 959 serves a package an
22+
interface it does not declare at two versions; the upgrade lane gains a
23+
`programs` variant that builds an ok image over the previous release's
24+
cache.
25+
- **A build ended by SIGTERM exits 143 however the race falls.** The watcher
26+
that takes a request to end over ends the programs mcpp runs, writes the
27+
cancelled record, runs the cleanups and then ends mcpp as asked; the main
28+
thread, woken by its compiler's end, could return from `main` first with
29+
the build's own failure (exit 1, seen once on CI in e2e 936 H). The end of
30+
`main` now ends mcpp as the request asks, after the watcher has finished.
31+
- **`mcpp emit xpkg --package` names each system's program directory.** The
32+
packages of one program for several systems may place it apart: a Windows
33+
package holds the program at its root, a POSIX one under `bin/` beside the
34+
root's convenience script. The entry registered the first package's
35+
directory for every system, so on Windows xvm pointed at a `bin/` the
36+
package does not have. It now writes `bindir[os.host()]` from a table of
37+
each system's directory when they differ (SPEC-014 §8).
38+
- **`mcpp emit xpkg --package` states the runner dependency with its
39+
namespace** (`deps = { "xim:okrun" }`). A bare name turns ambiguous once a
40+
second index the home lists has a package of that name, and xim-pkgindex's
41+
`check-dep-namespace` refuses it for a published package.
42+
- **The install of an `emit xpkg --package` entry finds the package.** It
43+
looked the archive's directory up with `os.dirs("<name>-0.1.3-*")`, and
44+
libxpkg's `os.dirs` lists `<base>/*` without matching names: no xlings
45+
install of such an entry succeeded. The directory is now the downloaded
46+
archive's name without its extension, which is what `mcpp pack` names it
47+
after, so it holds for every system, architecture and later version; an
48+
archive renamed since it was packed, or a file xim does not unpack, is
49+
refused when the entry is written. `mcpp pack --merge -o <archive>` names
50+
the merged package's directory after its output as `mcpp pack -o` does,
51+
where it kept the first input's, so a merged package is described as
52+
every other is.
53+
- **`mcpp emit xpkg` refuses a word that is not an option.** Each archive is
54+
its own `--package`; `--package a.zip b.zip` (a shell glob's expansion)
55+
described `a.zip` alone and left `b.zip` out without a word.
56+
- **The release proposes its index bump again.** `bump_index.sh` waited for
57+
`auto/bump-xim-mcpp-<version>`, and the index's updater opens
58+
`auto/bump-xim-mcpp`; the proposal is now found by the marker in its body.
59+
A dispatch the token is refused for (it needs Actions: write on
60+
openxlings/xim-pkgindex) names the permission and the command a maintainer
61+
runs.
62+
63+
### Changed
64+
65+
- **`upgrade-lane-logs/` is no longer in the tree.** A local run's logs were
66+
committed with 2026.10.17.1; the directory is ignored, as the lane writes
67+
it beside the workspace for CI to upload.
68+
- **SPEC-014 1.2** states what 2026.10.27.1 already does: a package's name
69+
carries its mode's suffix, a single file's launcher exits 127 on its own
70+
failure, `--merge` takes its container from `[pack] format` before `-o`, and
71+
`--linkage static` moves this machine's row and each `-linux-gnu` `--target`
72+
to musl while a project's own `[build] target` is packed as it is.
73+
774
## [2026.10.27.1] - 2026-10-27
875

976
### Added

‎docs/10-pack-and-release.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,10 +881,13 @@ package.
881881
writes the xim-pkgindex entry (spec 2) of packages this command wrote, from
882882
their `mcpp-package.json`. A universal package is one asset that `linux`,
883883
`macosx` and `windows` install alike, with the runner as a dependency
884-
(`deps = { "okrun" }`) unless the package carries it; packages of one system
884+
(`deps = { "xim:okrun" }`) unless the package carries it; packages of one system
885885
and architecture each make that system's entry, one URL with `${arch}` and a
886886
sha256 per architecture. The install moves the archive's top directory into
887-
place and registers the program with xvm (the `.cmd` launcher on Windows).
887+
place and registers the program with xvm (the `.cmd` launcher on Windows),
888+
from each system's own directory when the packages place the program apart
889+
(a Windows program at the root, a POSIX one under `bin/`). Each archive is its
890+
own `--package`.
888891

889892
### Compression and signing
890893

‎docs/90-build-from-source.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ src/
8282
8383
tests/
8484
├── unit/ 156 C++ tests, discovered by `mcpp test`
85-
└── e2e/ 645 shell scripts against a real binary
85+
└── e2e/ 646 shell scripts against a real binary
8686
```
8787

8888
## Test Organization
@@ -93,7 +93,7 @@ Two layers, and they answer different questions.
9393
discovers. They exercise a module's contract with no binary and no filesystem
9494
state.
9595

96-
**End-to-end tests** (`tests/e2e/NN_<name>.sh`, 645 files) run a real `mcpp`
96+
**End-to-end tests** (`tests/e2e/NN_<name>.sh`, 646 files) run a real `mcpp`
9797
binary against a real project. `run_all.sh` is the CI entry point. `mcpp test`
9898
does **not** run them.
9999

‎docs/specs/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
| [SPEC-011](concurrency.md) | 并发运行:三段、构建目录锁、原子发布、`mcpp.lock` 的乐观写入、取消 | 评审中 v1.0 | 2026-10-26 | mcpp >= 2026.10.26.1 |
4444
| [SPEC-012](human-output.md) | 面向人的输出:两条流、两种介质、行的种类、颜色 | 评审中 v1.0 | 2026-10-26 | mcpp >= 2026.10.26.1 |
4545
| [SPEC-013](platforms.md) | 平台:`[platform]` 的七组键、版本组与 `hosted`,三种写法与层次,目标图与宿主图的选择,`cfg(platform)`,依赖图的补全,链接、命名与封装,运行器与载体,平台阶段与协议 17 | 评审中 v1.0 | 2026-10-28 | mcpp >= 2026.10.27.1 |
46-
| [SPEC-014](packaging.md) | 打包与分发:链接、闭包、容器三个维度与构建腿,暂存树与 `mcpp-package.json`,通用包、单文件、签名、压缩、合并与分发描述 | 评审中 v1.0 | 2026-10-28 | mcpp >= 2026.10.27.1;逐条标注 |
46+
| [SPEC-014](packaging.md) | 打包与分发:链接、闭包、容器三个维度与构建腿,暂存树与 `mcpp-package.json`,通用包、单文件、签名、压缩、合并与分发描述 | 评审中 v1.2 | 2026-10-28 | mcpp >= 2026.10.28.1;逐条标注 |
4747

4848
## 文档约定
4949

0 commit comments

Comments
 (0)