Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions .agents/docs/2026-08-29-build-rule-package-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
> reading anything: `role = "check"` could not be written portably, and that is
> fixed here (§9, open question 4).
>
> ⚠️ A sixth is about this document's own method. The descriptor count was
> A sixth is about this document's own method. The descriptor count was
> first taken from `mcpp-community/mcpp-index`, while `mcpp index list` reports
> `mcpplibs/mcpp-index` as the default — the right question asked of the wrong
> object. The conclusion survived (one rule package either way) and the number
Expand Down Expand Up @@ -223,7 +223,12 @@ behaviour without using a new API, is left uncovered deliberately.

### I8. `mcpp.*` is reserved for official plugins, and using it produces a warning

Official rule packages are named `mcpp.build.<x>`. In C++ this creates no
Official rule packages are named `mcpp.rules.<x>` and official build-time
utilities `mcpp.tools.<x>`; both live in the collection `mcpp:plugins`
(repository `mcpp-community/mcpp-plugins`), each member selected by a feature
(2026-09-05 revision; the first revision of this section said `mcpp.build.<x>`,
which is the engine's own module family -- `mcpp.build.plan`,
`mcpp.build.prepare` -- and was withdrawn for that reason). In C++ this creates no
relationship with the bundled `mcpp` module — a dot in a module name carries no
hierarchy — but to a reader the prefix reads as an endorsement, and that is a
supply-chain statement.
Expand Down Expand Up @@ -537,7 +542,12 @@ hazard.
10.1 row 4: the `mcpp.rules.*` decision is withdrawn. It was unimplementable
under the rule that the module name is the bare package name. It is replaced
by `mcpp.build.*` as a **module name** prefix — the distinction the original
decision lacked.
decision lacked. *Revised 2026-09-05:* with I1 implemented the objection no
longer holds, and `mcpp.build.*` names the engine's own modules; the prefix
is `mcpp.rules.*` for rules and `mcpp.tools.*` for utilities, as I8 now
states. A package may contribute every module interface unit among its
feature-resolved sources (mcpp 2026.9.5.3+), which is what lets one
collection carry them all.
2. `docs/05-mcpp-toml.md:1605` and its Chinese counterpart: the paragraph
stating that the module name is the package's `name`, and that `grpc-rules`
is therefore illegal, is rewritten under I1 and I2.
Expand Down Expand Up @@ -611,7 +621,7 @@ own.
needs no shell, no `touch`, and no per-platform spelling. A command that
already writes its own stamp is unaffected — existing files are left alone.

⚠️ **The obvious assertion does not discriminate.** Measured: ninja does NOT
**The obvious assertion does not discriminate.** Measured: ninja does NOT
fail when a declared output goes unproduced. It leaves the file absent and
re-runs that edge on every subsequent build, so the build stays green and
the only symptom is work silently redone. `tests/e2e/312` therefore asserts
Expand Down Expand Up @@ -1176,7 +1186,7 @@ subsystem that has quietly come to rely on something it does not declare
compiles in the root build and fails there, which is the reason to run both
rather than pick one.

⚠️ `mcpp test -p <member>` exits 0 for a member with no tests, so the CI loop is
`mcpp test -p <member>` exits 0 for a member with no tests, so the CI loop is
green either way and "has no tests" reads exactly like "tests pass".
`check_modules_wiring.sh` therefore prints which members have none. It does not
fail on them: a package of vendored parsers legitimately has nothing of its own
Expand Down
351 changes: 351 additions & 0 deletions .agents/docs/2026-09-05-heterogeneous-build-ecosystem-design-v2.md

Large diffs are not rendered by default.

292 changes: 146 additions & 146 deletions .agents/docs/2026-09-05-multi-device-ecosystem-design.md

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions .github/actions/bootstrap-mcpp/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ runs:
uses: actions/cache@v4
with:
path: ~/.mcpp
# ⚠️⚠️ `runner.arch` IS PART OF EVERY KEY, AND WAS NOT.
# `runner.arch` IS PART OF EVERY KEY, AND WAS NOT.
#
# These caches hold INSTALLED BINARIES — `~/.xlings`, `~/.mcpp`, and
# `target/`. Keyed on `runner.os` alone, `Linux` names two machines, and
Expand All @@ -52,7 +52,7 @@ runs:
# Cache hit for: xlings-Linux-v2-xl2026.8.17.2-…
# …/bin/xlings: cannot execute binary file: Exec format error
#
# AND IT SURVIVED THE FIX ONE LAYER DOWN. Reading `uname -m` to pick
# AND IT SURVIVED THE FIX ONE LAYER DOWN. Reading `uname -m` to pick
# the right tarball is correct and was not enough: the download never
# happened, because a cache from the other architecture was already
# there. A key that does not name the machine is a key that lets one
Expand Down Expand Up @@ -88,7 +88,7 @@ runs:
REPO_DIR="$(pwd)"
# Always install the pinned version — the cache may hold an older
# xlings whose sysroot/packages are incompatible.
# ⚠️⚠️ THE ARCHITECTURE IS READ, NOT ASSUMED. This branched on the OS
# THE ARCHITECTURE IS READ, NOT ASSUMED. This branched on the OS
# alone and named `linux-x86_64` for every non-Darwin host, which is
# invisible until a Linux runner is not x86_64. Measured on
# `ubuntu-24.04-arm`, the first time this repo scheduled one:
Expand Down Expand Up @@ -117,7 +117,7 @@ runs:
"https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${tarball}" \
"${WORK}/${tarball}"
tar -xzf "${WORK}/${tarball}" -C "${WORK}"
# ⚠️⚠️ THE TWO LINUX TARBALLS DO NOT HAVE THE SAME SHAPE, and this line
# THE TWO LINUX TARBALLS DO NOT HAVE THE SAME SHAPE, and this line
# named one of them. Measured on the 2026.8.17.2 assets:
#
# linux-x86_64 → subos/default/bin/xlings (513 entries)
Expand All @@ -126,12 +126,12 @@ runs:
# so fetching the right architecture — the fix immediately above — got
# as far as `No such file or directory`, exit 127.
#
# FOUND RATHER THAN ASSUMED, AND THE SEARCH IS BOUNDED. `-maxdepth 5`
# FOUND RATHER THAN ASSUMED, AND THE SEARCH IS BOUNDED. `-maxdepth 5`
# keeps it from wandering into the payload tree, and an empty result is
# a hard error: a bootstrap that silently continues without xlings fails
# forty lines later on something that reads like a different problem.
#
# ⚠️ CHECKED BEFORE CHANGING THE THREE HOSTS THAT ALREADY WORKED. On
# CHECKED BEFORE CHANGING THE THREE HOSTS THAT ALREADY WORKED. On
# x86_64 this now resolves `bin/xlings` where the line before named
# `subos/default/bin/xlings` — and those are the same file:
#
Expand Down Expand Up @@ -212,7 +212,7 @@ runs:
uses: actions/cache@v4
with:
path: target
# ⚠️ `modules/**` belongs here as much as `src/**` does. mcpp's own
# `modules/**` belongs here as much as `src/**` does. mcpp's own
# source lives in both since the subsystem split, and a key that hashed
# only one of them would restore a target/ built from different sources
# and report success — the failure mode a cache key exists to prevent,
Expand Down
6 changes: 3 additions & 3 deletions .github/tools/check_aarch64_llvm_deferral.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#!/usr/bin/env bash
# ⭐⭐ A DEFERRAL'S PREMISE, RECHECKED.
# A DEFERRAL'S PREMISE, RECHECKED.
#
# `available_toolchain_indexes()` omits llvm on non-x86_64 Linux because no
# linux-aarch64 llvm exists — not in xlings-res, and not upstream since 19.x.
# That is a deferral, and a deferral nobody rechecks is indistinguishable from
# a defect.
#
# ⚠️ THIS FAILS WHEN THE REASON STOPS HOLDING, which is the opposite of what a
# THIS FAILS WHEN THE REASON STOPS HOLDING, which is the opposite of what a
# check usually does. The day an aarch64 llvm is published, it goes red and
# names the gate to remove — see
# `.agents/docs/2026-08-26-aarch64-linux-ecosystem-closure.md` §P1.
#
# ⚠️ Network trouble must not be read as "it appeared". An unreadable asset list
# Network trouble must not be read as "it appeared". An unreadable asset list
# leaves the premise alone and says so: a check that turns a flaky API into a
# claim about the world is worse than no check.
set -uo pipefail
Expand Down
2 changes: 1 addition & 1 deletion .github/tools/check_modules_wiring.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ done
# report success -- the exact failure a cache key exists to prevent, arriving
# silently. Found by sweeping for stale paths after the split, not by a test.
#
# ⚠️ THE UNIT IS THE LINE, NOT THE FILE. The first version asked whether the
# THE UNIT IS THE LINE, NOT THE FILE. The first version asked whether the
# FILE mentioned `modules/**`, and passed — satisfied by the comment sitting
# above the key explaining why `modules/**` belongs there. A check that a
# comment can satisfy is checking the prose.
Expand Down
2 changes: 1 addition & 1 deletion .github/tools/check_narrow_conversions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ cd "$REPO_DIR" || { echo "FAIL: cannot cd to $REPO_DIR" >&2; exit 1; }
# So: a pass here does NOT mean "the tree is audited". It means no NEW direct
# narrowing was written where this class originates.
#
# ⚠️ `modules/manifest/src/glob.cppm` is in scope even though the rest of that
# `modules/manifest/src/glob.cppm` is in scope even though the rest of that
# package is not. It is the glob walker itself -- the file this guard's
# background note names -- and it moved out of `src/modgraph/` in the subsystem
# split. A scope written as directory names shrinks silently when a file moves,
Expand Down
2 changes: 1 addition & 1 deletion .github/tools/fetch_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# every unexplained red on this branch, always inside 12 seconds, always with no
# test name in the log.
#
# ⚠️ `curl --retry` ALONE DOES NOT COVER IT. `--retry` handles timeouts and a
# `curl --retry` ALONE DOES NOT COVER IT. `--retry` handles timeouts and a
# specific list of 5xx responses; an empty reply is a *transport* error and is
# not on that list. `--retry-all-errors` (curl 7.71+) is the flag that does, and
# it is the one that was missing. The outer loop below is not redundant with it:
Expand Down
2 changes: 1 addition & 1 deletion .github/tools/install_released_mcpp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# the version under test — and failing outright, because only the latter was
# installed:
#
# 1 package(s) installed
# 1 package(s) installed
# [error] xlings: version '2026.8.3.2' not found for 'mcpp'
# [error] available: 2026.8.3.4
#
Expand Down
4 changes: 2 additions & 2 deletions .github/tools/mirror_res.sh
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ hosts=()
[[ "${GTC_ENABLED:-0}" == 1 ]] && hosts+=("gitcode.com/$GTC_DST")
for host in "${hosts[@]}"; do
for a in "${ASSETS[@]}"; do
# ⚠️ RETRIED, BECAUSE A MIRROR CAN ANSWER 502 FOR AN ASSET IT HOLDS.
# RETRIED, BECAUSE A MIRROR CAN ANSWER 502 FOR AN ASSET IT HOLDS.
# v2026.8.25.1 failed here twice: every one of the 16 assets reported
# "already mirrored, skipping", and the gate then failed one of them on a
# single 502 from GitCode's edge. Fetched by hand a minute later it was
Expand All @@ -297,7 +297,7 @@ for host in "${hosts[@]}"; do
# HTTP codes but not the transport-layer failures this path also sees, and
# this repository has paid for that distinction before (ci-curl-52).
#
# ⚠️ `|| echo ERR` APPENDS, it does not replace — `-f` makes curl exit
# `|| echo ERR` APPENDS, it does not replace — `-f` makes curl exit
# non-zero on 502 while `-w` has already written the code, so the variable
# read `502ERR` and the log could not be grepped for a status. Substituted
# only when curl printed nothing at all.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/aur-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:
)
[[ -z "$REQUESTED_TAG" ]] || args+=(--tag "$REQUESTED_TAG")

# ⚠️ EXIT 75 IS "THE PUSH LANDED, THE AUR'S INDEX HAS NOT CAUGHT UP",
# EXIT 75 IS "THE PUSH LANDED, THE AUR'S INDEX HAS NOT CAUGHT UP",
# AND FAILING ON IT MAKES THIS REPOSITORY'S CI RED FOR SOMEBODY ELSE'S
# REFRESH SCHEDULE.
#
Expand All @@ -142,7 +142,7 @@ jobs:
# `AUR RPC did not converge to <ver>` and the AUR RPC answered with
# that exact version when asked afterwards.
#
# ⚠️ EVERY OTHER NON-ZERO CODE STILL FAILS. A refused downgrade (3) and
# EVERY OTHER NON-ZERO CODE STILL FAILS. A refused downgrade (3) and
# a permanent error (2) are this repository's problem and stay red.
set +e
python3 scripts/aur/reconcile_mcpp_bin.py "${args[@]}"
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/ci-linux-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ jobs:

- name: Install the emulator (xim:qemu-riscv)
run: |
# ⚠️ BOTH homes. The shim on PATH dispatches against whichever home
# BOTH homes. The shim on PATH dispatches against whichever home
# owns it, and `mcpp run` runs the runner through that shim — so an
# emulator installed only in the ambient xlings home answers
# "xlings: 'qemu-system-riscv64' is not installed" when mcpp asks.
Expand All @@ -153,7 +153,7 @@ jobs:
XLINGS_HOME="${MCPP_HOME:-$HOME/.mcpp}/registry" \
"$XLINGS_BIN" install xim:picolibc-riscv -y
test -d "${MCPP_HOME:-$HOME/.mcpp}/registry/data/xpkgs/xim-x-picolibc-riscv"
# ⚠️ The M-profile emulator, in BOTH homes for the reason above.
# The M-profile emulator, in BOTH homes for the reason above.
# `xim:qemu-arm` carries `qemu-system-arm` as well as
# `qemu-system-aarch64`; test 332 addresses it by absolute path out of
# the payload, so what matters is that the payload EXISTS in the home
Expand Down Expand Up @@ -211,19 +211,19 @@ jobs:
grep -q 'PASS: the freestanding std subset' \
133_freestanding_std_subset.sh.log || {
echo "133 (std subset) skipped on the runner that must run it"; exit 1; }
# ⚠️ 332 declares `# requires: qemu-arm`, which no sharded runner has
# 332 declares `# requires: qemu-arm`, which no sharded runner has
# — so on the shards it exits 0 without running. This job is the only
# place its PASS line can be demanded.
grep -q 'PASS: cortex-m rows build, boot' \
332_cortex_m_builds_and_boots.sh.log || {
echo "332 (cortex-m) skipped on the runner that must run it"; exit 1; }
# And a count, because four `grep -q` calls that each matched say
# And a count, because four `grep -q` calls that each matched say
# nothing about how many rows the script actually booted: a fixture
# that stopped iterating would still print its PASS line.
booted=$(grep -c 'booted on ' 332_cortex_m_builds_and_boots.sh.log || true)
[ "$booted" = "4" ] || {
echo "332 booted $booted rows, expected 4"; exit 1; }
# ⚠️ 336 IS HERE FOR THE SAME REASON, AND ADDING IT TO THE LOOP ABOVE
# 336 IS HERE FOR THE SAME REASON, AND ADDING IT TO THE LOOP ABOVE
# WITHOUT ADDING IT HERE WOULD HAVE BEEN THE SAME DEFECT: it declares
# `# requires: qemu-arm`, so on a shard it exits 0 having run nothing.
grep -q 'PASS: armv7-a rows build, boot' \
Expand All @@ -232,7 +232,7 @@ jobs:
a32=$(grep -c 'booted on virt' 336_armv7a_builds_and_boots.sh.log || true)
[ "$a32" = "2" ] || {
echo "336 booted $a32 rows, expected 2"; exit 1; }
# ⚠️ 338 SKIPS UNTIL `xim:picolibc-arm` IS PUBLISHED, and a skip here
# 338 SKIPS UNTIL `xim:picolibc-arm` IS PUBLISHED, and a skip here
# is legitimate rather than a defect — the payload is a separate
# release. So its PASS line is NOT demanded; what IS demanded is that
# the script either passed or said why, which is what distinguishes a
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:

# Same placement, same reason: pure text, no toolchain.
#
# ⚠️ IT PRINTS AND DOES NOT FAIL, DELIBERATELY. The three rules it carries
# IT PRINTS AND DOES NOT FAIL, DELIBERATELY. The three rules it carries
# each have real false positives — a control step legitimately pins one
# target, a `grep -q .` legitimately expects output — and the whole value
# of the thing is that somebody READS it. A hard gate would be routed
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:
- name: Per-subsystem tests (`mcpp test -p <member>`)
run: |
set -euo pipefail
# ⚠️ `$MCPP_FRESH` comes from the step above, which takes the NEWEST
# `$MCPP_FRESH` comes from the step above, which takes the NEWEST
# mcpp anywhere under target/. That is correct in this job because
# nothing between the two steps writes another one — but `mcpp pack`
# leaves a copy under `target/dist/`, and a pack step inserted above
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ jobs:
echo "--- otool -L ---"; otool -L "$BIN" || true
echo "--- rpaths ---"; otool -l "$BIN" | grep -A2 LC_RPATH || true
echo "--- statically embedded libc++? ---"
# ⚠️ `nm ... 2>/dev/null | grep -c` USED TO PRINT "0 (good)" WHEN `nm`
# `nm ... 2>/dev/null | grep -c` USED TO PRINT "0 (good)" WHEN `nm`
# ITSELF FAILED. A count of zero and a tool that never ran produce the
# same number, and the word "good" is then a claim nothing supports.
# This is diagnostic output rather than a gate, which makes it worse
Expand Down Expand Up @@ -319,7 +319,7 @@ jobs:
run: |
MCPP=/tmp/mcpp-fresh # the freshly self-hosted binary built from this PR
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
# ⚠️ THIS IS THE STEP THE RETRY WAS MEASURED ON: a macOS runner
# THIS IS THE STEP THE RETRY WAS MEASURED ON: a macOS runner
# answered `Could not resolve host: github.com` after 30s of
# resolver timeout, failing a PR check before a single line of
# mcpp had run. See .github/tools/git_clone_retry.sh.
Expand Down
Loading
Loading