Skip to content

Commit 9d337bd

Browse files
speak-agentclaude
andcommitted
the wave's sandbox verification, and the reading from each of its two runs
Every CHANGE section is run against the published engine first and must fail there. Recorded in the script: 2026.9.17.1 reports fails=3 and 2026.9.20.1 reports fails=0, and the one leg that passes on both is named together with why that is the documented behaviour rather than a hole. Co-authored-by: Claude Code <noreply@anthropic.com>
1 parent 10fa191 commit 9d337bd

1 file changed

Lines changed: 224 additions & 0 deletions

File tree

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#!/usr/bin/env bash
2+
# Ecosystem verification for the 2026.9.20.1 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-20-cenv-interfaces-verify.sh)
6+
# xlings subos new v920
7+
# xlings subos use v920 --sandbox --cmd \
8+
# "echo $B64 | base64 -d > /tmp/v.sh && MCPP_VERIFY_VERSION=2026.9.20.1 bash /tmp/v.sh"
9+
#
10+
# Run it once against the PREVIOUS release first
11+
# (MCPP_VERIFY_VERSION=2026.9.18.3): every section marked CHANGE must fail there
12+
# and pass here; every section marked GUARD must pass on both. A section that
13+
# passes on both releases in a CHANGE section measured nothing.
14+
#
15+
# The sandbox's $HOME persists between runs of one SubOS, so each section clears
16+
# its own directory. A section that cannot run says so and is listed again at
17+
# the end, because a run that reports only failures cannot be told from one that
18+
# examined nothing.
19+
# TWO RUNS, AND THE READING FROM EACH (host dry run, 2026-09-20):
20+
#
21+
# mcpp 2026.9.17.1 (published) fails=3
22+
# B a requirement the implementation does not provide must be refused
23+
# C a declared absence with a known shape must be accepted
24+
# C the refusal does not name the shapes -- "[c-abi] has no member 'absent'"
25+
# mcpp 2026.9.20.1 fails=0
26+
#
27+
# B's FIRST leg passes on both, and that is the documented behaviour rather
28+
# than a hole: `[kernel-abi]` is an unknown top-level table to an older engine
29+
# and is ignored, so a graph that satisfies its requirements builds either way.
30+
# The leg that distinguishes the releases is the refusal. C fails outright on
31+
# the older engine because `[c-abi.absent]` is a new key inside a table it
32+
# knows, where an unrecognised key is a parse error -- the asymmetry docs/22
33+
# records.
34+
set -u
35+
36+
VER="${MCPP_VERIFY_VERSION:?set MCPP_VERIFY_VERSION}"
37+
STORE="${MCPP_VERIFY_BIN:-$HOME/.xlings/data/xpkgs/xim-x-mcpp/$VER/bin/mcpp}"
38+
39+
fails=0
40+
skipped=""
41+
fail() { printf 'ASSERT-FAIL: %s\n' "$1"; fails=$((fails + 1)); }
42+
ok() { printf 'ok: %s\n' "$1"; }
43+
section() { printf '\n== %s ==\n' "$1"; }
44+
skip() { printf 'NOT RUN: %s\n' "$1"; skipped="$skipped
45+
- $1"; }
46+
unset XLINGS_ACTIVE_SUBOS
47+
48+
root="$HOME/verify-920"
49+
rm -rf "$root"; mkdir -p "$root"
50+
51+
section "A. identity and mirror"
52+
if [ ! -x "$STORE" ]; then
53+
skip "mcpp $VER is not in the store at $STORE"
54+
printf '\n-- summary --\nfails=%d\nnot run:%s\n' "$fails" "${skipped:- (none)}"
55+
exit 1
56+
fi
57+
got="$("$STORE" --version 2>&1 | head -1)"
58+
case "$got" in
59+
*"$VER"*) ok "mcpp $VER from $STORE" ;;
60+
*) fail "the binary at $STORE reports '$got'" ;;
61+
esac
62+
"$STORE" self config --mirror CN >/dev/null 2>&1 \
63+
&& ok "mcpp mirror set to CN" || fail "mcpp self config --mirror CN"
64+
65+
# ── CHANGE 1. A package states which interfaces of the layer it requires ─────
66+
#
67+
# The engine knows no interface name: it compares two sets and refuses before
68+
# anything is compiled. Both legs are here because only the second says the
69+
# comparison happened -- a build that succeeds proves nothing about a check
70+
# that never ran.
71+
section "B. requires-interfaces is answered at resolution (CHANGE)"
72+
b="$root/b"; rm -rf "$b"; mkdir -p "$b/impl/src" "$b/src"
73+
printf 'int fake_kernel_marker(void){return 0;}\n' > "$b/impl/src/lib.c"
74+
printf 'int main(void){return 0;}\n' > "$b/src/main.c"
75+
cat > "$b/impl/mcpp.toml" <<'EOF'
76+
[package]
77+
name = "fakekernel"
78+
version = "0.1.0"
79+
provides = ["mcpp:kernel-abi=openkal"]
80+
81+
[targets.fakekernel]
82+
kind = "lib"
83+
sources = ["src/*.c"]
84+
85+
[kernel-abi]
86+
provides-interfaces = ["openkal.abort", "openkal.stream", "openkal.memory"]
87+
EOF
88+
mk_root() { # $1 = requires-interfaces body
89+
cat > "$b/mcpp.toml" <<EOF
90+
[package]
91+
name = "iface-probe"
92+
version = "0.1.0"
93+
94+
[dependencies]
95+
fakekernel = { path = "impl" }
96+
97+
[build]
98+
allow_host_libs = true
99+
100+
[kernel-abi]
101+
requires-interfaces = [$1]
102+
EOF
103+
}
104+
mk_root '"openkal.stream"'
105+
rm -rf "$b/target"
106+
if (cd "$b" && "$STORE" build >/dev/null 2>&1); then
107+
ok "a requirement the implementation provides builds"
108+
else
109+
fail "a requirement the implementation provides must build"
110+
fi
111+
mk_root '"openkal.stream", "openkal.net"'
112+
rm -rf "$b/target"
113+
out="$(cd "$b" && "$STORE" build 2>&1)"
114+
if [ $? -eq 0 ]; then
115+
fail "a requirement the implementation does not provide must be refused"
116+
else
117+
case "$out" in
118+
*openkal.net*iface-probe*|*iface-probe*openkal.net*)
119+
ok "the refusal names the interface and the package" ;;
120+
*) fail "the refusal does not name both: $(printf '%s' "$out" | head -3 | tr '\n' ' ')" ;;
121+
esac
122+
if [ -d "$b/target" ] && find "$b/target" -name '*.o' -print -quit 2>/dev/null | grep -q .; then
123+
fail "the refusal arrived after something was compiled"
124+
else
125+
ok "nothing was compiled before the refusal"
126+
fi
127+
fi
128+
129+
# ── CHANGE 2. A C library states what it does not supply ────────────────────
130+
section "C. [c-abi.absent] is read, and a bad shape is refused (CHANGE)"
131+
c="$root/c"; rm -rf "$c"; mkdir -p "$c/libc/src" "$c/src"
132+
printf 'int fake_libc_marker(void){return 0;}\n' > "$c/libc/src/lib.c"
133+
printf 'int main(void){return 0;}\n' > "$c/src/main.c"
134+
cat > "$c/mcpp.toml" <<'EOF'
135+
[package]
136+
name = "absent-probe"
137+
version = "0.1.0"
138+
139+
[dependencies]
140+
fakelibc = { path = "libc" }
141+
142+
[build]
143+
allow_host_libs = true
144+
EOF
145+
mk_libc() { # $1 = the form value
146+
cat > "$c/libc/mcpp.toml" <<EOF
147+
[package]
148+
name = "fakelibc"
149+
version = "0.1.0"
150+
provides = ["mcpp:c-abi=musl"]
151+
152+
[targets.fakelibc]
153+
kind = "lib"
154+
sources = ["src/*.c"]
155+
156+
[c-abi]
157+
presents = "posix"
158+
data-model = "arch-default"
159+
wchar = 32
160+
161+
[c-abi.absent]
162+
fork = { form = "$1", note = "no process image duplication" }
163+
EOF
164+
}
165+
mk_libc link
166+
rm -rf "$c/target"
167+
if (cd "$c" && "$STORE" build >/dev/null 2>&1); then
168+
ok "a declared absence with a known shape is accepted"
169+
else
170+
fail "a declared absence with a known shape must be accepted"
171+
fi
172+
mk_libc sometimes
173+
rm -rf "$c/target"
174+
out="$(cd "$c" && "$STORE" build 2>&1)"
175+
if [ $? -eq 0 ]; then
176+
fail "an absence with an unknown shape must be refused"
177+
else
178+
case "$out" in
179+
*accepted-no-effect*) ok "the refusal names the shapes that exist" ;;
180+
*) fail "the refusal does not name the shapes: $(printf '%s' "$out" | head -2 | tr '\n' ' ')" ;;
181+
esac
182+
fi
183+
184+
# ── GUARD. A package that declares neither key is untouched ─────────────────
185+
section "D. a package declaring neither key is unchanged (GUARD)"
186+
d="$root/d"; rm -rf "$d"; mkdir -p "$d/src"
187+
printf '#include <cstdio>\nint main(){std::puts("plain");return 0;}\n' > "$d/src/main.cpp"
188+
cat > "$d/mcpp.toml" <<'EOF'
189+
[package]
190+
name = "plain"
191+
version = "0.1.0"
192+
EOF
193+
if (cd "$d" && "$STORE" build >/dev/null 2>&1) \
194+
&& "$d"/target/*/*/bin/plain 2>/dev/null | grep -q plain; then
195+
ok "a package declaring nothing builds and runs"
196+
else
197+
fail "a package declaring nothing must build and run unchanged"
198+
fi
199+
200+
# ── GUARD. openkal from the published index ─────────────────────────────────
201+
section "E. an openkal program from the published index (GUARD)"
202+
e="$root/e"; rm -rf "$e"; mkdir -p "$e/src"
203+
printf '#include <cstdio>\nint main(){std::puts("openkal ok");return 0;}\n' > "$e/src/main.cpp"
204+
cat > "$e/mcpp.toml" <<'EOF'
205+
[package]
206+
name = "openkal-hello"
207+
version = "0.1.0"
208+
209+
[dependencies]
210+
openkal-llvm-runtime = "0.12.0"
211+
EOF
212+
if (cd "$e" && "$STORE" build >/dev/null 2>&1); then
213+
if "$e"/target/*/*/bin/openkal-hello 2>/dev/null | grep -q "openkal ok"; then
214+
ok "an openkal program builds and runs from the published index"
215+
else
216+
fail "the openkal program built and did not run"
217+
fi
218+
else
219+
skip "openkal-llvm-runtime 0.12.0 did not resolve from the index"
220+
fi
221+
222+
printf '\n-- summary --\nfails=%d\nnot run:%s\n' "$fails" "${skipped:-
223+
(none)}"
224+
[ "$fails" -eq 0 ]

0 commit comments

Comments
 (0)