From ef2b450e9c7ee2ceb8e0c689bf9495c0487d42d5 Mon Sep 17 00:00:00 2001 From: speak-agent Date: Sun, 20 Sep 2026 18:53:26 +0800 Subject: [PATCH 1/2] 0.15.0 --- the interfaces this implementation provides are stated, and the statement is the artefact's own answer openkal's specification names no set of interfaces: clause 3.3 withdrew the one it had named (`hosted`) because a name describing a class of environment is falsified by an environment nobody had in mind, and that one was falsified inside its own ecosystem within a release. Enumeration by the package replaced it, and a build tool reads the array at dependency resolution against the `requires-interfaces` a consumer states --- the first of the three times clause 6.2 tabulates, and the earliest at which "may this program be built against this implementation" can be answered. `[kernel-abi] provides-interfaces` lists the fifteen this implementation provides. It is GENERATED, by `check-surface.sh --toml`, and CI regenerates and diffs it against the objects. That is not a second derivation of the same fact: it is clause 9's surface comparison stopped one step earlier, so the list and the check can never answer differently. A declaration derived from the thing it describes cannot disagree with it, and an implementation that gains an interface cannot forget to say so. Backward compatible: an engine that predates the key reads `[kernel-abi]` as an unknown top-level table and ignores it, so this manifest loads unchanged everywhere it loaded before, and the absence of the resolution-time check is the behaviour that release already had. Co-authored-by: Claude Code --- .github/workflows/ci.yml | 23 ++++++++++++++++++++ mcpp.toml | 47 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf7dbc2..5cde56e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -221,6 +221,29 @@ jobs: bash .spec/tools/check-surface.sh --complete .spec/SURFACE.txt \ $(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' ! -name 'conformance*' | tr '\n' ' ') + - name: The manifest's provides-interfaces is what the artefact provides + run: | + set -euo pipefail + # The array in mcpp.toml is a declaration, and a declaration is + # checked rather than trusted. The check is clause 9's surface + # comparison stopped one step earlier: the walk that decides whether + # each group is exported whole already answers which interfaces this + # implementation provides. Regenerating and diffing is therefore not + # a second derivation --- it is the same one. + objs=$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' ! -name 'conformance*' | tr '\n' ' ') + [ -n "$objs" ] || { echo "::error::no objects to examine"; exit 1; } + bash .spec/tools/check-surface.sh --toml .spec/SURFACE.txt $objs > /tmp/derived.toml + # The manifest's own block, normalised the same way: the array body + # between `provides-interfaces = [` and the closing bracket. + awk '/^provides-interfaces = \[/{p=1} p{print} /^\]/{if(p)exit}' mcpp.toml > /tmp/declared.toml + if ! diff -u /tmp/declared.toml /tmp/derived.toml; then + echo "::error::mcpp.toml's provides-interfaces disagrees with the artefact" + echo " regenerate it with:" + echo " bash .spec/tools/check-surface.sh --toml .spec/SURFACE.txt \$(find target -name '*.o')" + exit 1 + fi + echo " ok the declaration is the artefact's own answer" + - name: The C++ declarations are complete run: | # The specification's own tool examines the C form. The module form is diff --git a/mcpp.toml b/mcpp.toml index 28e1c87..43f740d 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-linux" -version = "0.14.0" +version = "0.15.0" description = "The reference implementation of openkal for Linux, written on the kernel's own system-call interface so that it can be placed beneath a C library as well as above one." license = "Apache-2.0" @@ -17,6 +17,51 @@ provides = ["mcpp:kernel-abi=openkal"] authors = ["mcpplibs"] repo = "https://github.com/mcpplibs/openkal-linux" +# WHICH INTERFACES THIS IMPLEMENTATION PROVIDES, DERIVED FROM THE ARTEFACT AND +# NOT WRITTEN BY HAND. +# +# openkal's specification names no set of interfaces: clause 3.3 withdrew the +# one it had named (`hosted`) because a name describing a class of environment +# is falsified by an environment nobody had in mind, and that one was falsified +# inside its own ecosystem within a release. Enumeration by the package +# replaced it, and a build tool reads this array at dependency resolution +# against the `requires-interfaces` a consumer states in its own manifest -- +# the first of the three times clause 6.2 tabulates, and the earliest at which +# the question can be answered. +# +# GENERATED, AND CI DIFFS IT AGAINST THE OBJECTS: +# +# bash openkal/tools/check-surface.sh --toml openkal/SURFACE.txt \ +# $(find target -name '*.o') +# +# A declaration derived from the thing it describes cannot disagree with it, +# and an implementation that gains an interface cannot forget to say so. The +# same walk is clause 9's surface comparison stopped one step earlier, so this +# list and that check can never answer differently. +# +# BACKWARD COMPATIBLE. An engine that predates the key reads `[kernel-abi]` as +# an unknown top-level table and ignores it, so this manifest loads unchanged +# everywhere it loaded before; the absence of the check is the behaviour that +# release already had. +[kernel-abi] +provides-interfaces = [ + "openkal.abort", + "openkal.stream", + "openkal.memory", + "openkal.env", + "openkal.time", + "openkal.random", + "openkal.fs", + "openkal.process", + "openkal.task", + "openkal.exec", + "openkal.terminal", + "openkal.net", + "openkal.datagram", + "openkal.space", + "openkal.timeout", +] + [dependencies] openkal = "0.14.0" From 3f28e04d0c93afa31691e42a9ef73c2d6a7d0bba Mon Sep 17 00:00:00 2001 From: speak-agent Date: Sun, 20 Sep 2026 19:17:09 +0800 Subject: [PATCH 2/2] ci: re-run against the specification branch of the same name openkal-linux's CI checks the specification out at a branch matching this one where it exists, which is how a cross-repository change is measured before either half merges. The specification's --toml mode lives on that branch.