internal-tests.sh runner#Scope: every project-internal test asset — the ones that check this
repository's own code against its own expectations, not against a W3C
test manifest. The W3C conformance suites (RDF, SPARQL, OWL, SHACL,
CSVW, JSON-LD, XSLT, ...) already have a runner (w3c-tests.sh /
formal/fstar/generate-report.sh for the F* tree; per-suite dispatch
via tools/dispatch_test_suites.sh for suites whose manifest spec:
field is a real W3C/OGC/IETF URL) and a score. This document and
tools/internal-tests.sh cover what did not have either: internal
regression scripts, Lean corpus probes, and the Node test suites.
Method: read the tree at the date of this note (2026-09-03,
claude/main, darwin-arm64), plus one real run of every suite found.
Where a suite could not run in this environment, the reason is stated;
where it ran and failed, the cause is stated to the depth the task
allowed (root-caused where cheap, named as an open question otherwise).
Reproduce with tools/internal-tests.sh --list (derives the same list
from the tree) and tools/internal-tests.sh (runs it).
internal-tests TOTAL: 70 pass, 40 fail, 16 skip (out of 126)
--quick (60s per-suite budget): 68 pass, 40 fail, 18 skip (out of
126) — the two extra skips are lean-probe-l4rdfs-semi (92s) and
w3c-persisted-census (54s), both of which pass when given the full
budget.
shellcheck is not installed in this environment; the shellcheck tools/internal-tests.sh gate could not be run.
| Category | What it is | How invoked | Typical time | This run | In .github/workflows/? |
|---|---|---|---|---|---|
lean-guard-build |
Every #guard in formal/lean4 (build-time check) |
lake build in formal/lean4/ |
a few seconds, warm cache | PASS — 7,026 #guard declarations across 281 modules |
yes, verify-lean4.yml (lake build L4Factoidal) |
lean-wasm-native-smoke |
Checks of every Wasm dispatch ABI op | formal/lean4/Wasm/native-smoke.sh |
~5s | PASS — 120 pass, 0 fail (out of 120), re-measured 2026-09-07 | no |
lean-wasm-cli-smoke |
Every verb of the l4factoidal CLI |
formal/lean4/Wasm/cli-smoke.sh |
~1s | PASS | no |
lean-probe-* (30 zero-arg probes) |
Corpus census/conformance probes declared lean_exe in formal/lean4/lakefile.lean (OWL, Turtle, RDFC-1.0, JSON-LD ×3, CSVW ×3, SPARQL syntax, VC, SHACL ×3, XML conf, XSLT, GRDDL, ShEx ×2, RIF, RML, Schematron, MathML, JSON Schema, property-based, HDT, RDFS semi-naive) |
lake exe <name>, no arguments |
most <5s; l4owl-probe ~30s, l4rdfs-semi ~90-115s |
27 PASS, 3 FAIL (l4owl-probe, l4xslt, l4grddl — see Findings), 2 SKIP (l4w3c, l4diff — these take required arguments, see below) |
no |
lean-pin-l4geo |
formal/lean4/Harness/GeoRun.lean, the Lean twin of the F* unit pin tests/unit/geosparql_v0_unit.ml — WKT parse/serialize round trip, Simple Features predicates (including a point exactly on a polygon edge), geof:distance/geof:envelope |
lake exe l4geo, no arguments |
<1s | PASS — geosparql-v0: 37 pass, 0 fail, 0 skip (out of 37), HARNESS-DIAG geosparql-v0: registered=37 |
no |
lean-pin-l4rdf-semantics |
formal/lean4/Harness/RdfSemanticsRun.lean, the Lean twin of the F* --rdf12entail runner — walks the real W3C RDF 1.2 Semantics entailment manifest (third_party/testing/w3c/rdf/rdf12/rdf-semantics/manifest.ttl, 47 entries: 32 mf:PositiveEntailmentTest + 15 mf:NegativeEntailmentTest) via the shared Harness.loadManifest / Harness.runTest (Mode.rdf12) |
lake exe l4rdf-semantics, no arguments (or a manifest path) |
<1s | FAIL (has failures) — rdf-semantics: 40 pass, 7 fail, 0 skip, 0 unsupported (out of 47) (2026-09-07, up from 21 pass / 15 unsupported); F* comparison point (bin/w3c-runner/w3c_runner.ml --rdf12entail): 41 pass, 3 fail, 3 skip. The 15 unsupported are CLOSED: xsd:double, xsd:float and rdf:JSON now carry lexical spaces in RDF/Datatypes.lean and are in modelledDatatypes, and Regime.literalEq's .rdf arm uses dtValueLeq. The 7 remaining fails and their causes are listed by test id in docs/designissues/2026-09-07-rdf12-sparql12-semantics.md § Status: 2 need DInterpCond clause 2 narrowed to the asserted object position, 1 needs the literal-typing RDF rule, 2 need an IRI reifier from the `{ |
|
lean-pin-l4csvw-validate |
formal/lean4/Harness/CsvwValidateRun.lean, walking the real W3C CSVW VALIDATION manifest (third_party/testing/csvw/tests/manifest-validation.jsonld, 282 entries: 76 csvt:PositiveValidationTest, 61 csvt:WarningValidationTest, 145 csvt:NegativeValidationTest) against L4Factoidal.CSVW.Validate's structural (raw-JSON shape) and data-level (cell format/facets, required, primaryKey, schema/CSV width) checks. Landed after the 2026-09-03 snapshot this document is otherwise dated to — the placeholder lean_exe this superseded was counted, trivially passing, inside the lean-probe-* row's "CSVW ×3" tally above; it is broken out here instead, the same way lean-pin-l4rdf-semantics is broken out |
lake exe l4csvw-validate, no arguments (or a tests-dir path) |
<1s | FAIL (has failures) — csvw-validation: 266 pass, 14 fail, 2 skip (out of 282) (positive 76/76, warning 59/61, negative 131/145); F* comparison point (bin/csvw-runner/csvw_runner.ml --validate): 281 pass, 1 fail (out of 282). Gap: foreign-key schemaReference resolution (test034/035) and cross-table referential integrity (test257/258) not yet ported, plus assorted structural/title-compatibility gaps (test094, test100, test107, test109, test111, test124, test127, test147, test148); test308 is a documented shared limit, not a Lean-specific gap (.github/test-suites/csvw-validation.yaml) |
no |
lean-probe-* (31 zero-arg probes) |
Corpus census/conformance probes declared lean_exe in formal/lean4/lakefile.lean (OWL, Turtle, RDFC-1.0, JSON-LD ×3, CSVW ×3, SPARQL syntax, VC, SHACL ×3, XML conf, XSLT, GRDDL, ShEx ×2, RIF, RML, Schematron, MathML, TOAN, JSON Schema, property-based, HDT, RDFS semi-naive) |
lake exe <name>, no arguments |
most <5s; l4owl-probe ~30s, l4rdfs-semi ~90-115s |
27 PASS, 3 FAIL (l4owl-probe, l4xslt, l4grddl — see Findings), 2 SKIP (l4w3c, l4diff — these take required arguments, see below). Those counts are the 2026-09-03 run of the then-30 probes and were NOT re-measured when l4toan was added; l4toan has its own row below with its own run |
no |
lean-probe-l4toan |
The "Think of a Number" parity battery: every check of the F* consumer test tests/unit/toan_tests.ml, run against the Lean Math/* and MathML/* functions, plus four operator-token checks read off MathML.Present.fst directly |
lake exe l4toan, no arguments |
<1s | PASS — 114 pass, 0 fail (out of 114) | no |
node-hub-tests |
tests/hub/*_test.mjs, one per docs-hub post, against the JS/wasm bundle |
node --test tests/hub/*.mjs |
~25-40s | PASS — 415 pass, 0 fail, 1 skip (out of 416) | no |
node-npm-tests |
npm/factoidal/test/*.test.js |
node --test npm/factoidal/test/*.test.js |
~5-10s | PASS — 252 pass, 0 fail, 2 skip (out of 254) | no (a subset, test/l4-core.test.js, runs in npm-publish-lean.yml) |
node-tests/lws/server |
The Linked Web Storage 1.0 host: a Create/Read/Update/Delete sequence over a socket, Last-Modified on GET and HEAD, the PATCH blank-node refusal |
node tests/lws/server.mjs (Node drives Deno too) |
<5s | 0 pass, 0 fail, 8 skipped (out of 8) — the committed WebAssembly module does not carry lwsOpen/lwsStep/lwsClose yet |
no |
node-tests/solid/server/protocol |
The Solid Protocol v0.11.0 server host, replaying the specification's own HTTP examples: storage discovery, Allow/Accept-*, containment after PUT and POST, 409 on a containment edit, 405 on root DELETE, the auxiliary lifecycle, N3 Patch, CORS, LDN inbox |
node tests/solid/server/protocol.mjs |
<5s | 0 pass, 0 fail, 12 skipped (out of 12) — the module does not carry solidOpen/solidStep/solidClose yet |
no |
node-tests/solid/client/against-own-server |
The Solid client host against an in-process instance of our own server: discoverStorage, replace, read, create, delete | node tests/solid/client/against-own-server.mjs |
<5s | 0 pass, 0 fail, 7 skipped (out of 7) — the module does not carry solidClientRequest/solidClientResponse yet |
no |
| Solid interop scripts (3) | solid-crud-tests and web-access-control-tests against our server; our client against Community Solid Server; the Gherkin conformance harness (Docker) |
bash tools/solid-server-interop.sh, bash tools/solid-client-interop.sh, bash tools/solid-conformance-harness.sh |
minutes when they run | all three exit 2 ("could not run") — the module carries none of the ops; the two access-control suites additionally need an external Solid-OIDC issuer, which our server does not verify yet | no |
blockengine-*-smoke (16 non-Postgres) |
Shardborough pack/activate/query/compact/delta regressions | bash tools/blockengine-*-smoke.sh |
<15s each | 12 PASS, 4 FAIL (see Findings) | no |
blockengine-postgres-*-smoke (2) |
PostgreSQL bytea host-boundary smoke | bash tools/blockengine-postgres*-smoke.sh |
needs a live psql server |
SKIP — no PostgreSQL server reachable on 127.0.0.1 in this environment | no |
w3c-persisted-census |
Executability + row-agreement census of W3C SPARQL QueryEvaluationTests through the persisted (pack→activate→query) path — NOT a conformance score | bash tools/w3c-persisted-census.sh |
~55-80s | PASS — 564 of 570 eligible entries executed, 564/564 matched the reference engine, 6 refused at query (named-graph subset) | no |
podman-fly-smoke |
UK Parliament dataset bundle smoke via Podman | sh tools/podman-fly-smoke.sh |
needs a running podman machine | SKIP — podman machine not started in this environment | no |
| F* internal suite registry (20 manifests) | Every .github/test-suites/*.yaml whose spec: field is internal (as opposed to a W3C/OGC spec URL) — tests/unit, the tests/local/*_regressions.sh COTTAS/parser/serializer/graph suites, toan-matrix, check-pages-links, negative-test-vacuity |
tools/dispatch_test_suites.sh --list + --field <suite> spec/runner/runner_args, then run the named runner |
most <5s | 6 PASS, 13 FAIL, 1 SKIP (see Findings) | not directly; this is the registry the W3C-tests workflow dispatches from, per suite, on path triggers |
Orphaned tests/*/run.sh (4: known-defects, vc-api-shim, rdf-mt-generated, shexc-treesitter) |
Standalone regression harnesses that are not the runner: of any .github/test-suites/*.yaml manifest |
bash tests/<name>/run.sh |
<10s | 3 PASS, 1 FAIL (known-defects — by design when a tracked defect stops reproducing; see Findings) |
no |
Orphaned tests/local/*.sh (35 of 52; the other 17 are registered runners in the F* internal suite registry above) |
Ad hoc regression scripts covering CLI parity, CoTTAS storage stages, durable-update crash/compaction, RDFS entailment regimes, Turtle/TriG undeclared-prefix handling, full-text, geo, RML pushdown, SPARQL client protocol | bash tests/local/<name>.sh |
<2s each | 16 PASS, 19 FAIL (see Findings — dominated by two environment gaps, not per-test logic bugs) | no |
tests/web-demos/*.sh (10) |
Headless-Chromium (Playwright) smokes of the docs-hub pages | bash tests/web-demos/<name>.sh |
needs Playwright + a built site | SKIP — no node_modules/ (Playwright) installed at the repository root in this environment |
no |
tests/beyond-w3c parity |
Demo-query row-set parity across runtimes (native/JS/wasm) for the public site's live query cells | python3 tests/beyond-w3c/bin/run-parity.py --manifest tests/beyond-w3c/fixtures/index.json --runners native |
~1-3s (native only; JS/wasm runners exist but were not exercised here) | PASS — 2 of 2 fixed queries | no |
tests/did, tests/did-local, tests/local-overrides, tests/qudt, tests/compat/rdf12 |
Fixture directories | consumed by bin/did-runner, bin/qudt-runner, and the F* w3c_runner's local-override mechanism |
n/a | out of scope here — already run by w3c-tests.sh |
yes, via w3c-tests.yml |
tests/parity/run_backend_parity.py |
Full corpus-driven in-memory-vs-COTTAS parity | invoked WITH the required --manifest/--bin/--pycottas-python args by tests/local/backend_parity_regressions.sh and tests/local/backend_parity_full.sh (both already counted above) |
n/a standalone | not run directly — it is a library the two registered wrapper scripts call | no |
tests/perf/l4_vs_fstar_wasm_bench.mjs |
Lean-wasm vs F*-wasm/js query-time benchmark | node tests/perf/l4_vs_fstar_wasm_bench.mjs |
a benchmark, not a pass/fail test | out of scope here — see skills/perf-benchmarking |
no |
Total suite count this run: 126 (from tools/internal-tests.sh --list,
2026-09-03). This number moves as scripts are added or removed; treat
the count in this document as a snapshot, and --list as the source
of truth.
Ordered by how many suites they explain, most first. None of these were fixed in this landing; each is either a filed defect (VC. GitHub issue numbers are named where one already exists) or a plain environment gap.
formal/fstar/ocaml-output/<tool>
(17 of 52 tests/local/*.sh, plus local-graphs-api,
local-jsonld-regressions, local-parquet-footer-version-gate,
local-parser-unicode, local-sparql-parser, local-turtle-pretty,
local-serializer-unicode, rdf-mt-generated). CLAUDE.md iron
rule #9 states these symlinks "point at the current platform's
bin/ dir". In this darwin-arm64 checkout they were committed
pointing at bin/linux-x86_64/* (git show HEAD:formal/fstar/ ocaml-output/factoidal → ../../../bin/linux-x86_64/factoidal, an
ELF binary; running it gives Exec format error).
tools/sandbox-bootstrap.sh has the correct repair logic (lines
~73-79) but only acts if [[ ! -e ... ]] — it will not repoint a
symlink that already exists and is simply wrong for this platform.
Repointing the 11 of 12 affected symlinks that have a
bin/darwin-arm64/ counterpart (working-tree only, not committed —
see below) turned six previously-failing suites to PASS in this
run. bin/darwin-arm64/factoidal-dump-nq is missing outright (no
darwin-arm64 build of that consumer tool is committed), so
local-serializer-unicode still fails for that reason alone.
Separately, tools/negative-test-vacuity.py and
tests/local/rdfs_schema_split_regressions.sh /
turtle_undeclared_prefix_regression.sh hardcode
bin/linux-x86_64/factoidal directly rather than going through the
symlink, so repointing the symlink does not fix them — 17 of the 52
tests/local/*.sh scripts hardcode a linux-x86_64 path this way.
Not fixed here: the committed symlink target is a CI-vs-local
trade-off (CI runs ubuntu-latest), not a one-line "correct" value,
and the hardcoded paths are a separate, larger cleanup._tmp.junk/pycottas-venv/bin/python not provisioned (16 of 52
tests/local/*.sh, plus local-backend-parity,
local-backend-parity-full, local-cottas-ask-decode-failure,
local-cottas-corpus, local-cottas-groupby-counts,
local-cottas-row-order, local-graph-default-semantics,
local-parquet-footer, dict_global_cache_parity,
durable_update_stage3, and others). The session bootstrap hook
provisions this venv; a worktree built only from
tools/ensure-test-env.sh (this task's instructed setup) does not
get it. Environment gap, not a defect — same root cause across all
of these.open-mode descriptor strings have drifted from three
blockengine-*-smoke.sh assertions.
blockengine-ibk3-w3c-disk-query-smoke.sh expects
open-mode=ibk3-paged-merkle-full-manifest(3) and gets
open-mode=ibk3-sri2-tli1-subject-point(3);
blockengine-sbm6-synthetic-smoke.sh expects
open-mode=ibk3-sri2-tli1-oli2-object-subject-join(2) delta=base
and does not find it in the actual output;
blockengine-shard-merkle-scan-smoke.sh's final grep -q 'open-mode=predicate-selective-merkle-limit-prefix(1)' does not
match either. Rows returned are correct in all three; the query
planner now names its access path differently (a new
subject-point/join index mode superseding what these scripts still
name). Test staleness against a planner improvement, not a
correctness regression — needs a decision on whether to update the
three scripts' expected strings.blockengine-shard-session-smoke.sh checks for
store/manifest.sbm1; l4block-shard-pack now writes
manifest.sbm2. Confirmed by running l4block-shard-pack
directly: it reports format=predicate-ibk2-merkle-v2-streaming ... manifest=manifest.sbm2 wire-version=2. The script's test -s .../manifest.sbm1 assertion is checking a filename the packer
stopped writing; per shardborough-storage, a wire-format version
bump should update every consumer, and this script was missed.tests/unit/run-all.sh fails at the ocamlfind ocamlopt build
step for all 50 files with line 262: TEST_CMX[@]: unbound variable, even though TEST_CMX=() is set immediately before the
loop that populates it (line 242) and bash 5.3 (confirmed on this
host) does not reproduce the empty-array-under-set -u bug that
affected older bash. Root cause not found within this task's time
box — it is a harness bug (every file fails identically at the
build step, before any file-specific compilation is attempted), not
50 independent regressions. Needs its own investigation.tests/known-defects/run.sh: 3 of 5 tracked defects no longer
reproduce (XPASS), 2 probes errored. XPASS on
#324 (sameTerm
case-folding), #334
(Turtle silently drops undeclared-prefix statements — now exits
126), and #275
(syntax-error message). ERROR on
#336 (probe
produced no rows — query or binary changed) and
#337 (BGP itself
did not match; probe invalid). The suite is designed to fail loudly
on exactly this signal (its own header: "not automatically good
news ... either somebody fixed it ... or the probe has drifted").
This needs an owner decision per issue, not a fix inside this task.tests/local/cottas_corpus_regressions.sh is missing the
executable bit (-rw-r--r--, siblings are -rwxr-xr-x). A direct
exec ("$runner" args, the pattern tools/dispatch_test_suites.sh-
style dispatch would use) fails with Permission denied;
internal-tests.sh invokes every runner via bash "$runner" for
this reason, which works. Not fixed in the tree (a one-line chmod +x, left for a dedicated hygiene commit).local-check-pages-links needs docs/_site built
(cd docs && npx @11ty/eleventy --output=_site) and
local-sparql-negative needs a Jena ARQ checkout at
/tmp/jena/jena-arq/testing/DAWG-Final — both external build/
fixture prerequisites, not provisioned by
tools/ensure-test-env.sh. Environment gaps.l4owl-probe, l4xslt, l4grddl fail with known, already-scored
gaps, not new regressions: l4owl-probe reports TOTAL: 1131 pass, 316 fail, 2 skip, 8 unsupported (out of 1457) — closure gaps
already tracked in the probe's own per-catalog breakdown against
docs/test-results/latest.json; l4xslt reports 84 pass, 3 fail (out of 87 decided); l4grddl reports 19 pass, 22 fail (out of 41 decided), of which 7 failures are stated upstream http/https
vendoring drift and 17 cases are unavailable (documents not
fetched, by design — the runner makes no network request).w3c-tests.sh,
formal/fstar/generate-report.sh, and every .github/test-suites/ *.yaml whose spec: is a real spec URL) — those have their own
runner and score already.tests/perf/* — a benchmark, not a pass/fail gate
(skills/perf-benchmarking).tests/vc-di-eddsa/run.sh and tests/vc20-api/run.sh — registered
in the W3C-suite dispatch registry (spec: is a real
w3c.github.io test-suite URL), already excluded for the same
reason as the conformance manifests. Both also need npm install in
their vendored submodule directories, not run in this environment.Add a internal-tests-quick job to a new or existing workflow, gated
the same way verify-lean4.yml is (push to claude/main, PR,
workflow_dispatch):
internal-tests-quick:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { submodules: recursive }
- run: bash tools/ensure-test-env.sh
- run: bash tools/internal-tests.sh --quick
On ubuntu-latest the bin/linux-x86_64/* symlinks are already
correct, so Findings 1 and most of Finding 2's provisioning gap would
not appear there — CI would measure closer to the suites' real
pass/fail than this darwin-arm64 run did. Left as a proposal, not
landed, per this task's scope.