Skip to content

Commit ac45e1f

Browse files
committed
a sandbox verification for this wave, with its control reading
Six sections. B and C are CHANGE and must fail on the previous release; E and F are GUARD and must pass on both. Measured, on the host, against the genuine published archive of 2026.9.21.1: 2026.9.21.1 fails=2 B: no upper-case target macro C: an unanswered requirement produced no note 2026.9.21.2 fails=0 C'\''s second leg passes on both by design: it asserts the note is ABSENT when the provider does state its list. Without it, the first leg would pass against an engine that printed the line unconditionally --- a negative control is not a hole in a CHANGE section. B carries both directions in ONE translation unit, because either alone passes for the wrong reason: an engine defining NEITHER spelling satisfies "the lower-case one is gone", and one defining BOTH satisfies "the upper-case one is here". Its second leg asks a freestanding target for its own macro, which is what says the spelling is DERIVED from the triple rather than enumerated. D and F need openkal-llvm-runtime 0.14.0 from the index and reported NOT RUN rather than passing when it was not yet registered.
1 parent 5baa58b commit ac45e1f

1 file changed

Lines changed: 302 additions & 0 deletions

File tree

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
#!/usr/bin/env bash
2+
# Ecosystem verification for the 2026.9.21.2 wave against the PUBLISHED mcpp
3+
# and index, run inside a SubOS sandbox with CN mirrors for xlings and mcpp.
4+
#
5+
# B64=$(base64 -w0 .agents/docs/2026-09-21-macros-and-withdrawal-verify.sh)
6+
# xlings subos use v920 --sandbox --cmd \
7+
# "echo $B64 | base64 -d > /tmp/v.sh && MCPP_VERIFY_VERSION=2026.9.21.2 bash /tmp/v.sh"
8+
#
9+
# RUN IT AGAINST THE PREVIOUS RELEASE FIRST (MCPP_VERIFY_VERSION=2026.9.21.1):
10+
# every CHANGE section must FAIL there and pass here, and every GUARD section
11+
# must pass on both. A CHANGE section green on both measured nothing.
12+
#
13+
# The sandbox's $HOME persists between runs of one SubOS, so each section
14+
# clears its own directory. A section that cannot run says so and is listed
15+
# again at the end: a run reporting only failures cannot be told from one that
16+
# examined nothing.
17+
#
18+
# TWO RUNS AND THE READING FROM EACH (host dry run, 2026-09-21, the older one
19+
# against the genuine published archive rather than a local build):
20+
#
21+
# mcpp 2026.9.21.1 (published) fails=2
22+
# B the engine does not define the upper-case target macro
23+
# C an unanswered requirement produced no note
24+
# mcpp 2026.9.21.2 fails=0
25+
#
26+
# C's SECOND LEG PASSES ON BOTH, and that is the point of having it: it asserts
27+
# the note is ABSENT when the provider does state its list, so without it the
28+
# first leg would pass against an engine that printed the line unconditionally.
29+
# A negative control is not a hole in a CHANGE section.
30+
#
31+
# D and F needed `openkal-llvm-runtime@0.14.0`, registered after that dry run,
32+
# and both reported NOT RUN rather than passing.
33+
set -u
34+
35+
VER="${MCPP_VERIFY_VERSION:?set MCPP_VERIFY_VERSION}"
36+
STORE="${MCPP_VERIFY_BIN:-$HOME/.xlings/data/xpkgs/xim-x-mcpp/$VER/bin/mcpp}"
37+
38+
fails=0
39+
skipped=""
40+
fail() { printf 'ASSERT-FAIL: %s\n' "$1"; fails=$((fails + 1)); }
41+
ok() { printf 'ok: %s\n' "$1"; }
42+
section() { printf '\n== %s ==\n' "$1"; }
43+
skip() { printf 'NOT RUN: %s\n' "$1"; skipped="$skipped
44+
- $1"; }
45+
unset XLINGS_ACTIVE_SUBOS
46+
47+
root="$HOME/verify-9212"
48+
rm -rf "$root"; mkdir -p "$root"
49+
50+
section "A. identity and mirror"
51+
if [ ! -x "$STORE" ]; then
52+
skip "mcpp $VER is not in the store at $STORE"
53+
printf '\n-- summary --\nfails=%d\nnot run:%s\n' "$fails" "${skipped:- (none)}"
54+
exit 1
55+
fi
56+
got="$("$STORE" --version 2>&1 | head -1)"
57+
case "$got" in
58+
*"$VER"*) ok "mcpp $VER from $STORE" ;;
59+
*) fail "the binary at $STORE reports '$got'" ;;
60+
esac
61+
"$STORE" self config --mirror CN >/dev/null 2>&1 \
62+
&& ok "mcpp mirror set to CN" || fail "mcpp self config --mirror CN"
63+
64+
# ── CHANGE 1. The owned macros are spelt in upper case ──────────────────────
65+
#
66+
# BOTH DIRECTIONS IN ONE TRANSLATION UNIT, because either alone passes for the
67+
# wrong reason: an engine defining NEITHER spelling satisfies "the lower-case
68+
# one is gone", and one defining BOTH satisfies "the upper-case one is here".
69+
section "B. __MCPP_TARGET_<OS>__ replaces __mcpp_target_<os>__ (CHANGE)"
70+
b="$root/b"; rm -rf "$b"; mkdir -p "$b/src"
71+
cat > "$b/src/main.c" <<'EOF'
72+
#if !defined(__MCPP_TARGET_LINUX__)
73+
#error "__MCPP_TARGET_LINUX__ is not defined"
74+
#endif
75+
#if defined(__mcpp_target_linux__)
76+
#error "the lower-case spelling is still defined"
77+
#endif
78+
int main(void) { return 0; }
79+
EOF
80+
cat > "$b/mcpp.toml" <<'EOF'
81+
[package]
82+
name = "macro-probe"
83+
version = "0.1.0"
84+
85+
[targets.macro-probe]
86+
kind = "bin"
87+
main = "src/main.c"
88+
EOF
89+
if (cd "$b" && "$STORE" build >/dev/null 2>&1); then
90+
ok "the upper-case target macro is defined and the lower-case one is not"
91+
else
92+
out=$(cd "$b" && "$STORE" build 2>&1)
93+
case "$out" in
94+
*"__MCPP_TARGET_LINUX__ is not defined"*)
95+
fail "the engine does not define the upper-case target macro" ;;
96+
*"lower-case spelling is still defined"*)
97+
fail "the engine still defines the lower-case target macro" ;;
98+
*) fail "the probe did not build, and for neither of the two reasons" ;;
99+
esac
100+
fi
101+
102+
# THE SPELLING IS DERIVED, NOT ENUMERATED. A second target with a different
103+
# `os` says the engine reads the triple rather than carrying a table of names.
104+
b2="$root/b2"; rm -rf "$b2"; mkdir -p "$b2/src"
105+
cat > "$b2/src/main.c" <<'EOF'
106+
#if !defined(__MCPP_TARGET_NONE__)
107+
#error "__MCPP_TARGET_NONE__ is not defined for a freestanding target"
108+
#endif
109+
void _start(void) {}
110+
EOF
111+
cat > "$b2/mcpp.toml" <<'EOF'
112+
[package]
113+
name = "macro-probe-bare"
114+
version = "0.1.0"
115+
116+
[targets.macro-probe-bare]
117+
kind = "bin"
118+
main = "src/main.c"
119+
120+
[build]
121+
ldflags = ["-nostdlib", "-nostartfiles", "-static"]
122+
EOF
123+
if (cd "$b2" && "$STORE" build --target riscv64-none-elf >/dev/null 2>&1); then
124+
ok "a freestanding target spells its own macro from the triple"
125+
else
126+
skip "the freestanding toolchain did not resolve in this sandbox"
127+
fi
128+
129+
# ── CHANGE 2. A requirement nobody answered is named ────────────────────────
130+
#
131+
# Three situations exist and two build. Without this line the first and the
132+
# third produce identical output, so a consumer cannot tell "checked and
133+
# agreed" from "never asked". Both legs, because a note printed
134+
# unconditionally would satisfy the first one alone.
135+
section "C. an unanswered requirement is named (CHANGE)"
136+
c="$root/c"; rm -rf "$c"; mkdir -p "$c/impl/src" "$c/src"
137+
printf 'int fake_kernel_marker(void){return 0;}\n' > "$c/impl/src/lib.c"
138+
printf 'int main(void){return 0;}\n' > "$c/src/main.c"
139+
mk_impl() { # $1 = provides-interfaces body, or empty
140+
if [ -z "$1" ]; then
141+
cat > "$c/impl/mcpp.toml" <<'EOF'
142+
[package]
143+
name = "fakekernel"
144+
version = "0.1.0"
145+
provides = ["mcpp:kernel-abi=openkal"]
146+
147+
[targets.fakekernel]
148+
kind = "lib"
149+
sources = ["src/*.c"]
150+
EOF
151+
else
152+
cat > "$c/impl/mcpp.toml" <<EOF
153+
[package]
154+
name = "fakekernel"
155+
version = "0.1.0"
156+
provides = ["mcpp:kernel-abi=openkal"]
157+
158+
[targets.fakekernel]
159+
kind = "lib"
160+
sources = ["src/*.c"]
161+
162+
[kernel-abi]
163+
provides-interfaces = [$1]
164+
EOF
165+
fi
166+
}
167+
cat > "$c/mcpp.toml" <<'EOF'
168+
[package]
169+
name = "iface-probe"
170+
version = "0.1.0"
171+
172+
[dependencies]
173+
fakekernel = { path = "impl" }
174+
175+
[build]
176+
allow_host_libs = true
177+
178+
[kernel-abi]
179+
requires-interfaces = ["openkal.fs", "openkal.net"]
180+
EOF
181+
mk_impl ''
182+
out=$(cd "$c" && "$STORE" build 2>&1)
183+
if [ $? -ne 0 ]; then
184+
fail "a provider that states nothing must not be refused"
185+
else
186+
case "$out" in
187+
*"kernel-abi interfaces"*"states none"*"2 requirements unchecked"*)
188+
ok "the note names the implementation and how many went unchecked" ;;
189+
*"kernel-abi interfaces"*)
190+
fail "the note is printed but does not carry the count" ;;
191+
*) fail "an unanswered requirement produced no note" ;;
192+
esac
193+
fi
194+
rm -rf "$c/target"
195+
mk_impl '"openkal.fs", "openkal.net", "openkal.abort"'
196+
out=$(cd "$c" && "$STORE" build 2>&1)
197+
if [ $? -ne 0 ]; then
198+
fail "a graph whose provider states every requirement must build"
199+
else
200+
case "$out" in
201+
*"kernel-abi interfaces"*)
202+
fail "the note appeared for a graph in which everything WAS checked" ;;
203+
*) ok "a provider that states its list draws no note" ;;
204+
esac
205+
fi
206+
207+
# ── CHANGE 3. The borrowed name is withdrawn ────────────────────────────────
208+
#
209+
# `__CYGWIN__` was left defined so that code needing "PE object format with a
210+
# POSIX-presenting C environment" had a name. A 30-member measurement found
211+
# four members reading it as "Win32 is available" and reaching windows.h.
212+
# This needs a real openkal graph, so it skips rather than failing when the
213+
# sandbox cannot reach one.
214+
section "D. __CYGWIN__ is withdrawn on a Windows target presenting POSIX (CHANGE)"
215+
d="$root/d"; rm -rf "$d"; mkdir -p "$d/src"
216+
cat > "$d/src/main.cpp" <<'EOF'
217+
#if defined(__CYGWIN__) || defined(__CYGWIN32__)
218+
#error "the borrowed name is still defined"
219+
#endif
220+
#if !defined(__MCPP_TARGET_WINDOWS__)
221+
#error "mcpp's own name for the target is missing"
222+
#endif
223+
#if defined(_WIN32)
224+
#error "presents = posix must suppress _WIN32"
225+
#endif
226+
#if !defined(__OPENKAL__)
227+
#error "__OPENKAL__ is not defined over a resolved openkal layer"
228+
#endif
229+
#if defined(__openkal__)
230+
#error "the lower-case spelling is still defined"
231+
#endif
232+
int main() { return 0; }
233+
EOF
234+
cat > "$d/mcpp.toml" <<'EOF'
235+
[package]
236+
name = "withdrawal-probe"
237+
version = "0.1.0"
238+
239+
[dependencies]
240+
openkal-llvm-runtime = "0.14.0"
241+
EOF
242+
out=$(cd "$d" && "$STORE" build --target x86_64-windows-gnu 2>&1)
243+
rc=$?
244+
case "$out" in
245+
*"openkal-llvm-runtime"*"not found"*|*"did not resolve"*)
246+
skip "openkal-llvm-runtime 0.14.0 did not resolve from the index" ;;
247+
*)
248+
if [ $rc -eq 0 ]; then
249+
ok "the borrowed name is gone, mcpp's own name is there, over openkal"
250+
else
251+
case "$out" in
252+
*"borrowed name is still defined"*) fail "__CYGWIN__ is still defined" ;;
253+
*"own name for the target is missing"*) fail "__MCPP_TARGET_WINDOWS__ is missing" ;;
254+
*"__OPENKAL__ is not defined"*) fail "__OPENKAL__ is missing over openkal" ;;
255+
*"lower-case spelling is still defined"*) fail "__openkal__ is still defined" ;;
256+
*"presents = posix"*) fail "_WIN32 survived the substitution" ;;
257+
*) skip "the openkal Windows graph did not build in this sandbox" ;;
258+
esac
259+
fi ;;
260+
esac
261+
262+
# ── GUARD. A package declaring nothing is untouched ─────────────────────────
263+
section "E. a package declaring neither key builds and runs (GUARD)"
264+
e="$root/e"; rm -rf "$e"; mkdir -p "$e/src"
265+
printf '#include <cstdio>\nint main(){std::puts("plain ok");return 0;}\n' > "$e/src/main.cpp"
266+
cat > "$e/mcpp.toml" <<'EOF'
267+
[package]
268+
name = "plain"
269+
version = "0.1.0"
270+
EOF
271+
if (cd "$e" && "$STORE" build >/dev/null 2>&1) \
272+
&& "$e"/target/*/*/bin/plain 2>/dev/null | grep -q "plain ok"; then
273+
ok "a package that declares nothing builds and runs"
274+
else
275+
fail "a package that declares nothing must be untouched by this release"
276+
fi
277+
278+
# ── GUARD. An openkal program from the published index ──────────────────────
279+
section "F. an openkal program from the published index (GUARD)"
280+
f="$root/f"; rm -rf "$f"; mkdir -p "$f/src"
281+
printf '#include <cstdio>\nint main(){std::puts("openkal ok");return 0;}\n' > "$f/src/main.cpp"
282+
cat > "$f/mcpp.toml" <<'EOF'
283+
[package]
284+
name = "openkal-hello"
285+
version = "0.1.0"
286+
287+
[dependencies]
288+
openkal-llvm-runtime = "0.14.0"
289+
EOF
290+
if (cd "$f" && "$STORE" build >/dev/null 2>&1); then
291+
if "$f"/target/*/*/bin/openkal-hello 2>/dev/null | grep -q "openkal ok"; then
292+
ok "an openkal program builds and runs from the published index"
293+
else
294+
fail "the openkal program built and did not run"
295+
fi
296+
else
297+
skip "openkal-llvm-runtime 0.14.0 did not resolve from the index"
298+
fi
299+
300+
printf '\n-- summary --\nfails=%d\nnot run:%s\n' "$fails" "${skipped:-
301+
(none)}"
302+
[ "$fails" -eq 0 ]

0 commit comments

Comments
 (0)