You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(design): the criteria table carries what was measured, and the implementation's own review
The plan's nine-angle self-review was written before any of this was built.
This adds the review of the IMPLEMENTATION, whose unit is a measured defect
rather than an angle: nineteen findings, nine of them in mcpp itself, each with
the reading that made it visible and the class it belongs to.
Four classes account for most of them. A decision written in several places
with all but one repaired (the install path composed <root>/bin itself). One
question with two inputs of which one was read (the payload name was filled and
never consulted). A branch selected by the HOST serving a target it would get
wrong -- three findings, and the note that already said so had been read as a
statement about openkal rather than about every target that branch would serve.
And a criterion whose object was wrong: DEVELOPER_DIR=/nonexistent did not make
the SDK unlocatable, so the host-surface claim measured nothing.
The criteria table now carries the reading beside each claim, including the two
the measurement changed: simctl-run is a boot-and-spawn wrapper and not a
bundle builder, and openkal.task on Emscripten cannot be exercised end to end
because -pthread is a whole-graph ABI switch mcpp has no channel for.
Four gaps are recorded and deliberately not closed, each with a measurement
behind it: no per-target tool axis, no whole-graph flag channel,
xim:e2fsprogs's debugfs, and a device runner that needs a signature.
@@ -484,24 +484,187 @@ two `cfg` lines in `E4b`'s example.
484
484
Each claim below fails when its subject is removed, which is the only reason to
485
485
write it down.
486
486
487
-
| claim | criterion |
487
+
| claim | criterion | measured |
488
+
|---|---|---|
489
+
| A: the device row runs | qemu-user run in CI on a Linux runner, asserting `1-2-3` and exit 0; the extraction is the packaged 7zip, not a host tool | yes -- and the packaged tool is `xim:7zip`, not `xim:e2fsprogs`, whose `debugfs` SIGFPEs on every filesystem-opening command |
490
+
| B: one spelling |`toolchain = "ndk@…"` is refused AT PARSE with "unknown toolchain", not by the capability gate | yes, with an A/B: re-adding the alias turns the assertion red |
491
+
| C: the engine stops knowing | delete `ndk_host_tag()`'s call site and the build still resolves, because the descriptor answered; and a malformed descriptor is refused naming the file | yes -- a descriptor naming `oddly/named/clang++` resolved there, a path no engine derivation produces; a non-string `platform_floor` was refused naming the file and the key |
492
+
| C: no flag day | a payload with no descriptor resolves exactly as today -- asserted against the released android-ndk | yes, against the installed r30 payload: with the file removed the resolution line and the effective triple are byte-identical |
493
+
| C: the floor and the defines travel | not in the original list, and each needs its own reading or it is carried by the frontend's | yes -- `platform_floor = "26"` gave `…-android26` while `meta/platforms.json` says 21; an added define appeared in the std module's command AND in its cache identity |
494
+
| D: iOS builds | macOS runner, `xim:llvm` plus the located SDK, artefact is Mach-O arm64 with the iOS platform in `LC_BUILD_VERSION`| yes -- `platform 2` (IOS) for the device and `platform 7` (IOSSIMULATOR) for both simulator rows, `minos 18.0`, `sdk 18.5`|
495
+
| D: the simulator runs | macOS runner, `mcpp run --target aarch64-ios-sim` prints `1-2-3`| yes, through the `runner` and `xim:apple-simulator-tools`; and separately under a bare `simctl spawn`, which is what proved a bundle is not needed |
496
+
| D: the host surface is bounded | on a macOS runner with `xcode-select` pointing nowhere, both iOS rows fail with a message naming the SDK -- and no other row changes | THE CRITERION WAS WRONG AND WAS REPLACED. `DEVELOPER_DIR=/nonexistent` did not make the SDK unlocatable -- `xcrun` ignores an invalid developer directory and falls back -- so the iOS build SUCCEEDED and the step asserted nothing. The claim now lives where the SDK is genuinely absent: e2e 641 on every non-Apple host, with the refusal required to name the SDK, the `xcrun` command, the Command-Line-Tools note and the compiler, and to arrive before any payload is resolved |
497
+
| E1: Android shares the implementation | merged and green against the RELEASED engine: both ABIs build, objects name no C library symbol, and a program over openkal alone ran on an emulator | yes (openkal-linux 0.12.0) |
498
+
| E2: iOS reuses it |`openkal-macos` compiles for the three iOS rows on a macOS runner, and its objects name no C library symbol -- the same check the Android leg applies, against a third libc | the `cfg` line is in `examples/portable`; the compile leg belongs to openkal-macos's own CI and is not in this batch |
499
+
| E3: the Web implementation conforms | the conformance suite passes for the groups it provides; and a program using `kal_process_spawn` fails at LINK naming the symbol, which is the criterion that the absent groups are absent rather than present-and-failing | yes -- 86 held, 0 did not hold, 13 not observed; and `wasm-ld: error: obj/main.o: undefined symbol: kal_process_spawn`|
500
+
| E4: the examples build |`examples/portable` builds for the host and for all five platforms it names -- it currently builds for NONE, which is why this is a criterion and not an assumption | host, both Android ABIs: yes. The Web leg resolves once `openkal-emscripten` is in the index, which is the ring this ecosystem cannot untangle: the example is always second |
501
+
502
+
**The premise held.** A macos-15 runner ships Xcode 16.4 with both located SDKs
503
+
at 18.5 and five bootable iOS simulator runtimes (18.5, 18.6, 26.0, 26.1,
504
+
26.2). So D1, D2 and D4 are all CI claims and none of them is local-only.
505
+
506
+
**Two things the measurement changed about this design.**
507
+
508
+
`simctl-run` is a boot-and-spawn wrapper and not a bundle builder. This record
509
+
said a bare Mach-O "cannot be launched by `simctl`, so the program wraps it in
510
+
a minimal bundle" -- true of `simctl launch`, which needs an installed `.app`,
511
+
and false of `simctl spawn`, which takes an executable. Measured against an
512
+
artefact with no bundle, no signature and no `Info.plist`: `1-2-3`, exit 0.
513
+
514
+
`openkal.task` on Emscripten is behind a feature and cannot yet be exercised
515
+
end to end. `-pthread` selects a different C library build, memory model and
516
+
loader contract, so it is a property of the WHOLE LINK -- and mcpp has no
517
+
channel for a flag that applies to a whole dependency graph, so the
518
+
specification package's own modules compile without it and the module cache
519
+
refuses the mix. The interface is therefore absent at link rather than present
520
+
and failing, which is what clause 6.1 asks for, and the gap is recorded in
521
+
openkal-emscripten's README as the engine change it is.
522
+
523
+
## What the implementation found, and what each finding is about
524
+
525
+
The plan's self-review is above and was written before any of this was built.
526
+
This section is the review of the implementation, and its unit is a measured
527
+
defect rather than an angle: each row is something that was wrong, the reading
528
+
that made it visible, and the class it belongs to. Nineteen, of which nine are
529
+
in mcpp itself.
530
+
531
+
### A decision written in several places, all but one repaired
532
+
533
+
| finding | reading |
534
+
|---|---|
535
+
|`mcpp toolchain install emsdk` and `… android-ndk` had never worked |`error: installed package has no known C++ frontend in '.../xim-x-emsdk/6.0.9/bin'`|
536
+
537
+
`payload_frontend`'s own comment records that five callers composed
538
+
`<root>/bin` themselves and so could not see where the package says its
539
+
compiler is. Four were repaired when that function was written; the install
540
+
path was not, so both SDK payloads fetched correctly and then looked for
541
+
`clang++` in a directory neither keeps it in. The install and the build now ask
542
+
one function, which is what makes them unable to disagree.
543
+
544
+
### One question with two inputs, of which one was read
545
+
546
+
| finding | reading |
547
+
|---|---|
548
+
| the same install failure, second cause |`emsdk@6.0.9` resolved the generic llvm shape |
549
+
550
+
`to_xim_package` decided the payload from the TARGET. That is right for the
551
+
spelling a build uses and there is no target at all in an install, so a spec
552
+
that NAMED the payload was answered by a field nobody had filled. `payloadName`
553
+
now decides first and the target remains the answer for a spec that names no
554
+
payload -- which is the escape-hatch spelling the capability gate has to be
555
+
able to refuse, so both inputs are still read and neither is guessed.
556
+
557
+
### A special case that was a table
558
+
559
+
| finding | reading |
560
+
|---|---|
561
+
|`em++`'s C compiler became `em`|`/bin/sh: 1: .../emscripten/em: not found`|
562
+
563
+
Dropping `++` is clang's rule and was being applied as the rule; `g` was
564
+
already a special case for exactly this reason. The property is "this driver
565
+
names its C compiler with a different word", and a table can be read as the
566
+
list of drivers for which that is true. Found by the conformance suite's one C
567
+
translation unit -- the only C in this ecosystem's openkal work.
568
+
569
+
### A value that acquires the receiving layer's semantics
570
+
571
+
| finding | reading |
572
+
|---|---|
573
+
| a descriptor naming `/usr/bin/g++` passed the guard on Windows |`path("/usr/bin/g++").is_absolute()` is FALSE there |
574
+
575
+
Windows calls that path root-relative: it has a root directory and no root
576
+
name. `payloadRoot / "/usr/bin/g++"` then resolves to `C:/usr/bin/g++` -- a
577
+
host compiler chosen by a package, on the one host where the guard did not
578
+
look. The field is one shape on every host, so it is validated as a STRING and
579
+
positively. Asking a path type whether it is absolute is asking a question
580
+
whose meaning the host supplies.
581
+
582
+
### A branch selected by the host, serving a target it gets wrong
583
+
584
+
Three findings, one class, and the class is the sharpest thing in this batch.
585
+
`flags.cppm` and `hostflags.cppm` both branch on `needs_explicit_libcxx` --
586
+
which asks where mcpp was built. That was the same question as "which platform
587
+
is this for" while macOS was the only Apple target mcpp could serve.
588
+
589
+
| finding | what it would have produced |
590
+
|---|---|
591
+
| the macOS link branch carried no `--target` at all | a macOS binary from objects compiled as iOS |
592
+
| the Mach-O distribution cell chose the self-contained contract | a link of the payload's macOS `libc++.a` into an iOS artefact, which ld64 refuses |
593
+
|`hostflags` emitted `-mmacosx-version-min` whenever the host was macOS |`error: invalid argument '-mmacosx-version-min=14.0' not allowed with 'arm64-apple-ios18.0'`|
594
+
595
+
The note two hundred lines below the first one already said "ONLY THE THIRD
596
+
BRANCH EVER CONSUMED `link_toolchain_flags`, WHICH IS WHERE `--target=`
597
+
LIVES" -- correct, and read as a statement about openkal rather than as a
598
+
statement about every target that branch would ever serve.
599
+
600
+
### A per-machine artefact read before the command line
601
+
602
+
| finding | reading |
603
+
|---|---|
604
+
| an iOS-simulator link with the right `-isysroot` used the macOS SDK |`ld64.lld: error: .../MacOSX.sdk/usr/lib/libc++.tbd(...) is incompatible with arm64 (iOS Simulator18.0.0)`|
605
+
606
+
`post_install` writes the located macOS SDK into the payload's `clang++.cfg` so
607
+
that a native build is deterministic, and that file is read for search purposes
608
+
before the command line. An Apple cross therefore has to suppress it, which
609
+
mcpp's cross path already did and a hand-written probe did not. The probe was
610
+
wrong and the engine was right, and finding out which took one CI run.
611
+
612
+
### A criterion whose object was wrong
613
+
614
+
| finding | reading |
615
+
|---|---|
616
+
| the host-surface claim measured nothing | with `DEVELOPER_DIR=/nonexistent`, the iOS build SUCCEEDED |
617
+
618
+
`xcrun` ignores an invalid developer directory and falls back to the recorded
619
+
one, so the environment change did not make the SDK unlocatable. The predicate
620
+
was right and the object was wrong -- the class this repository records most
621
+
often. The claim now lives where the SDK is genuinely absent, which is every
622
+
non-Apple host, and it asserts four things about the message plus that the
623
+
refusal arrives before any payload is resolved.
624
+
625
+
### A fifth copy of a table that a checker covered four of
626
+
627
+
| finding | reading |
488
628
|---|---|
489
-
| A: the device row runs | qemu-user run in CI on a Linux runner, asserting `1-2-3` and exit 0; the extraction is the packaged 7zip, not a host tool |
490
-
| B: one spelling |`toolchain = "ndk@…"` is refused AT PARSE with "unknown toolchain", not by the capability gate |
491
-
| C: the engine stops knowing | delete `ndk_host_tag()`'s call site and the build still resolves, because the descriptor answered; and a malformed descriptor is refused naming the file |
492
-
| C: no flag day | a payload with no descriptor resolves exactly as today -- asserted against the released android-ndk |
493
-
| D: iOS builds | macOS runner, `xim:llvm` plus the located SDK, artefact is Mach-O arm64 with the iOS platform in `LC_BUILD_VERSION`|
494
-
| D: the simulator runs | macOS runner, `mcpp run --target aarch64-ios-sim` prints `1-2-3`|
495
-
| D: the host surface is bounded | on a macOS runner with `xcode-select` pointing nowhere, both iOS rows fail with a message naming the SDK -- and no other row changes |
496
-
| E1: Android shares the implementation | merged and green against the RELEASED engine: both ABIs build, objects name no C library symbol, and a program over openkal alone ran on an emulator |
497
-
| E2: iOS reuses it |`openkal-macos` compiles for the three iOS rows on a macOS runner, and its objects name no C library symbol -- the same check the Android leg applies, against a third libc |
498
-
| E3: the Web implementation conforms | the conformance suite passes for the groups it provides; and a program using `kal_process_spawn` fails at LINK naming the symbol, which is the criterion that the absent groups are absent rather than present-and-failing |
499
-
| E4: the examples build |`examples/portable` builds for the host and for all five platforms it names -- it currently builds for NONE, which is why this is a criterion and not an assumption |
500
-
501
-
**One premise needs measuring before D is scheduled**: that GitHub's macOS
502
-
runners ship both an iOS SDK and a bootable simulator. If they ship the SDK but
503
-
no simulator, D1/D2 are still verifiable in CI and D4 is a local-only claim,
504
-
which changes the tier the sim rows can reach and nothing else in this design.
629
+
|`test_toolchain_triple.cpp` asserted `preview` after the row and four documents said `verified`| the suite went red; `check_target_tiers.py` said "OK: 29 target tiers agree across 4 documents" |
630
+
631
+
A literal in a test is in neither the engine's table nor the documents, so a
632
+
checker over documents cannot see it. The test's tier claims are now one-line
633
+
pairs -- a shape the checker can read -- and it reads the test file as a fifth
634
+
document. Removing the fix makes the checker fail, which is the only reason to
635
+
add one.
636
+
637
+
### And the platform refused two mechanisms outright
638
+
639
+
`openkal-emscripten` is where the specification met a platform that says no
640
+
rather than differently.
641
+
642
+
| finding | reading |
643
+
|---|---|
644
+
|`.init_array` with `(argc, argv, envp)`|`wasm-ld: error: constructor functions cannot take arguments`|
645
+
|`EM_ASM` using `stringToUTF8` into a `_malloc` buffer |`Aborted(malloc() called but not included in the build)`|
646
+
|`handle.h` copied from openkal-linux |`handle.h:22: warning: shift count >= width of type`|
647
+
|`kal_node_info::self_size` ignored |`DID NOT HOLD an enquiry writes no more of the structure than the caller stated`|
648
+
649
+
The first is not a calling-convention difference to be careful about -- wasm's
650
+
start section takes no arguments, so the mechanism does not exist. The second
651
+
is the rule that a library cannot require an export list from every program
652
+
that uses it. The third is a constant that was a property of the machine the
653
+
file was written on, travelling as if it were a property of the scheme. The
654
+
fourth is a field the caller sets and the implementation must honour, and the
655
+
suite passes a deliberately short structure to find out.
656
+
657
+
## Gaps this batch recorded and did not close
658
+
659
+
Each is an engine or package change with a measurement behind it, and each was
660
+
left rather than worked around.
661
+
662
+
| gap | measurement | why it was left |
663
+
|---|---|---|
664
+
| no per-target tool axis |`error: [target.aarch64-ios-sim.xlings] does not accept 'deps'`| a runner's program belongs beside the row that names it; declaring it at the top level makes `examples/13`'s Linux build depend on a macOS-only package, so the example asks the reader to install it |
665
+
| no whole-graph flag channel |`error: POSIX thread support was disabled in precompiled file '.../openkal.types.pcm' but is currently enabled`|`-pthread` is an ABI switch for every unit in the link including a dependency's; `openkal.task` is gated behind a feature so the absence is a link error rather than a present-and-failing operation |
666
+
|`xim:e2fsprogs`'s `debugfs`| SIGFPE on every filesystem-opening command, while dumpe2fs/e2fsck/tune2fs from the same build work | recorded in that recipe; nothing else in the index depends on it, and `android-system-image` now reads ext4 with `xim:7zip`|
667
+
| a device runner for `aarch64-ios`| none -- it needs a signature the developer owns | R12's subject, and a package cannot supply a signature |
0 commit comments