validation.md (68029B)
Testing
Use the Haskell host and route builds, linking, and tests through Nix. See
build/run for guide selection and the language-feature
inventory before .tri edits. For
representation-sensitive work, see Compiler architecture.
Fast gates
The Haskell lexer/parser/compiler/source loader, recovery AST, and recovery workspace resolver have been removed. Executables, tests and benchmarks share the source-free runtime; the Nix boundary check rejects reintroduction of the retired frontend files. Host/test dependencies follow this source-free boundary. Runtime-presentation tests use independent constructor-display goldens; runtime demand tests exercise the same reducer used by production. Portable source tests provide the active language oracles: explicit expected values, locations, diagnostics, and negative controls. Representation tests cover retained portable artifacts. Historical Haskell frontend and self-hosting differential tests are retired.
nix flake check
python3 test/unit.py
The CLIs in test/stable_bundle.py and test/stable_costs.py are retired and
fail before writes. Their preparation relied on implicit recovery compilation;
keep those guards intact, including when old support/cache stamps are present.
stable_bundle’s pure importable wire helpers remain supported. For current
benchmarks, use the separately defined artifact-based Criterion workload below
and collect fresh measurements.
Artifact-based Criterion benchmarks (opt-in)
nix build .#tricu-bench -o result-bench
nix build .#benchmarkWorkers -o result-benchmark-workers
nix build .#benchmarkSmoke --no-link
result-bench/bin/tricu-bench result-benchmark-workers/workers.arboricx \
"$(cat result-benchmark-workers/sha256)" --verify-only
# Omit --verify-only for Criterion, or use --list / --help.
benchmarkWorkers builds bench/workers.tri and its explicit current-source
library dependencies with the packaged stable compiler. It retains the staged
sources, compiler metadata, CAS/receipts, bundle and whole-bundle SHA256.
Preparation is bounded to 900 seconds compiling, 930 seconds externally, and an
8 GiB managed heap. Preparation builds benchmark applications; compiler
generations and fixture publication follow their own workflows.
The Haskell runner consumes an explicit precompiled bundle and expected digest. Loading validates bundle structure, execution ABI and the exact export interface. A 120-second deadline covers loading and checking all 27 cases against independent complete expected values. Workers, inputs and expected values are fully constructed before timing; use external process/heap limits for actual timing runs. The digest authenticates selected bytes. Behavioral correctness depends on the independent expected-value checks.
The contract group measures precompiled application plus complete result
equality; the registry group observes canonical Booleans in the same way.
Parsing, compilation and publication are excluded. Historical contract
benchmarks included recovery parsing/evaluation; compare timings only within the
same workload definition. benchmarkSmoke checks expected results, wrong
hashes, malformed bundles, incorrect interfaces, Criterion listing, and a
one-iteration invocation of every case. Use repeated Criterion measurements for
statistical performance analysis.
Interaction-tree inspection
nix flake check includes the Haskell Interaction inspection unit group and
test/interaction_inspection.py in the host-policy check. The CLI fixtures
build indexed bundles independently of the inspector, check outline/JSON
identities and exit behavior, retain malformed/unknown/oversized input controls,
and verify that inspection of effectful trees preserves files and leaves absent
stores absent. The unit group covers all current host IO action tags, opaque
continuations, exact export aliases, preview/depth/occurrence limits, and
reachable exponentially shared values.
For the focused CLI check after building the Haskell host:
nix build .#
PYTHONDONTWRITEBYTECODE=1 python3 test/interaction_inspection.py result/bin/tricu
The compiled-source smoke example is in read-only interaction-tree inspection. It checks the native compiler-to-inspector path separately from independent wire fixtures; inspection reads the exported tree as data directly from its bundle.
Host loading and compiler supervision
The default Haskell tests directly exercise the production loader with flat and indexed objects: digest and ABI rejection, malformed and missing objects, manifest rejection, retained sharing, profiling-stage order, and selected exports with reads confined to their selected objects. Whole-interface loading retains manifest order.
Supervisor tests use constructed ABI workers. They check explicit selection, option validation, Result and publication validation, source-write denial, and a deadline that interrupts a sleeping worker. The default-frontend and portable-CLI probes additionally exercise real source compilation, REPL transactions, cache identities and compiler profiling:
nix build .#
python3 test/executable_arguments.py result/bin/tricu
python3 test/default_frontend.py result/bin/tricu
python3 test/portable_cli.py result/bin/tricu \
--compiler-bundle bootstrap/build-stable.arboricx
These checks exercise the selected compiler and leave published fixtures unchanged.
IO permissions and run lifetime
The default IO ownership and path boundaries tests exercise new-file writes
through escaping parent symlinks, ordinary allowed writes, and CAS rejection
without forcing unpublished trees. Listening-socket rebinding checks run after
normal completion, abort and timeout; blocked accept is also cancelled. FIFO
writers establish that asynchronous OS work has started, stop draining until the
run ends, then verify that the writer cannot finish its payload after run exit.
These checks observe actual resource lifetime and effects alongside scheduler
state.
See the host ABI for cancellation semantics and the limits of path-based permissions and timeout enforcement.
Current-source IO dependencies
nix build .#
PYTHONDONTWRITEBYTECODE=1 python3 test/io_dependencies.py result/bin/tricu
This opt-in probe compiles current io, base, and native_math sources with
only those modules present in a temporary workspace. It checks IO constructor
and conditional results and rejects an explicit import of the absent patterns
module. Published compiler/support fixtures remain unchanged. The fast host
policy tests separately check that the working compiler map is an exact closure
and that IO depends only on base.
Batch development loop
Agree on a substantial related module group, its intended interface/behavior changes and a focused-test budget before starting. Compile candidates with the accepted stable toolchain and link affected consumers against that candidate. Reuse authenticated unchanged inputs to keep iteration focused on affected modules. Commit reviewable slices with explicit unpublished candidate status. Keep published fixtures unchanged until the batch's agreed acceptance checkpoint.
Start with a few complete-result/demand/effect probes and representative callers; expand coverage where the edit changes behavior or exposes a defect. Bound each compilation/run and the combined probe job. Record modest, justified adjustments to initial budget estimates. Unexpectedly costly or repeatedly exhausted jobs require diagnosis before another bounded attempt; exhausted jobs remain failed checks. Broader matrices and repeated performance studies need an explicit reason and budget; full-generation resource ceilings still apply.
Classify differential mismatches against intended requirements. Preserve meaningful requirements and intensional behavior; deliberately replace insecure/incoherent behavior or poor interfaces, updating callers and independent expected results with a stated rationale. Retain historical oracles and negative controls, and derive expectations independently of candidate output. Git provides source rollback; behavioral correctness requires tests.
Run the full compiler gate at the agreed batch checkpoint, using focused checks between drafts. A verified compiler checkpoint may explicitly defer publication: retain the audited fresh pair and generation-two native-import/recursion/program smoke coverage, leaving reference fixtures and working-source freshness pending. This permits subsequent candidate work with the verified compiler. Final compiler/support-cohort publication remains pending. See compiler rebuilding.
Three distinct checks
- Reference-artifact tests (
nix flake check): current Haskell runtime, retained compiled compiler/support implementations, and their authenticated source snapshots. Edited.triimplementations require candidate tests. - Candidate tests: explicitly compile the changed implementation with the retained stable compiler and run focused semantics/integrity/integration checks against the resulting artifact. Record candidate identity and preparation scope.
- Final batch acceptance: for compiler-affecting batches, the fresh stable generation/self-rebuild gate; genuinely rebuilt current fixtures, explicit working-source freshness and the fast suite. Support-only batches still need candidate/publication validation; compiler generations are required for compiler-affecting changes.
The Haskell gate loads fingerprinted, full compiler/support artifacts. Source
bytes are stored by their existing arboricx.source.v1 digest under
test/fixtures/reference-source/; the .v1 fixture metadata remains
authoritative. The loader authenticates those bytes, including the headers used
for import binding. Missing/corrupt snapshots fail. Library inputs come
exclusively from authenticated snapshots. Unmapped test programs remain live
test inputs. Bundle, receipt, namespace, kernel, and ABI checks remain.
test/ReferenceFixtures.hs owns authenticated artifact loading and direct
published-interface selection. test/LibraryValueTests.hs invokes byte-list and
HTTP exports with host-constructed inputs, without source wrappers or recovery
compilation. test/ParserValueTests.hs does the same for binary and
finite-stream parser protocols, including consumed/committed flags, rollback,
zero-width repetition, and poisoned-field controls. HTTP framing/error
expectations and no-socket-access controls remain independent of the compiled
implementations. Mixed-cohort reuse verification in SupportFixture compares
complete provider identities directly.
test/IODriverTests.hs uses explicit ABI trees for primitive/scheduler controls
and portable-compiled programs for library sequencing, state, concurrency and
socket integration. Its source scope contains only published io, prelude and
socket interfaces. The shared ScriptedEffects interpreter checks exact effect
order and complete replies without real filesystem/network access; live IO tests
retain their permission and failure checks.
Unit runs reuse authenticated library artifacts with their recorded source
identities. Compiler conformance wrappers use test/PortableTestCompiler.hs:
the retained stable unit compiler receives explicit published fixture imports
and a definition body. This test-only header adapter binds explicit fixture
imports and returns only local definitions. Native module resolution has
separate coverage. Preparation has a 30-second deadline and checks
Result/list/name structure without forcing unused definition values. Invalid
source and import shadowing fail without fallback. Useful library program tests
use the same bounded portable compilation route with an explicit published
prelude. div and mod zero-divisor expectations follow the checked numeric
contract. All source tests use portable compilation with explicit imports.
# Verify reference-source/bundle fingerprints; check working-source freshness below.
python3 test/fixture_sources.py verify
# Required at final batch acceptance; exits nonzero and lists stale/missing
# source inputs or changed compiler-map membership/order.
python3 test/fixture_sources.py current
Working-source freshness and candidate behavior are separate checks. Pending freshness blocks final publication acceptance; an explicitly scoped verified compiler checkpoint may defer it. Failed reference integrity, candidate correctness, or generation verification blocks further feature work until repaired. Compiler edits require candidate tests and the generation acceptance gate.
To capture reference sources after a verified fixture publication (or to recover missing snapshots), select the source root that matches the fixture metadata:
python3 test/fixture_sources.py capture --source-root "$FIXTURE_SOURCE"
Capture authenticates all inputs before writing, only adds digest-named files, and refuses changed source or an existing corrupt snapshot. Existing fingerprints and compiled artifacts remain unchanged. Keep the snapshots with fixture publications and manage retirement of old digest-named files explicitly. Changed sources require genuine candidate compilation and fixture publication with fingerprints matching the actual inputs.
nix flake check also runs cheap artifact-only CLI checks and unit.py
provenance/header, selector/reexport, RSS, prepared-session, native-scope,
fixture-projection and reference/freshness separation controls. Its filtered
source excludes archive/. It builds through Nix and tests retained compiler
and library artifacts. Library-source compilation and compiler-generation checks
are opt-in workflows.
Focused checks
Use new output directories and explicitly selected candidate artifacts. Record source, compiler, dependency, and export identities during preparation, and relink affected consumers before testing.
Artifact-only runners execute selected bundles and report their identities. Authenticate compilation provenance separately during preparation. The focused checks below supply candidate coverage; final batch acceptance follows the three-check workflow.
Digest and dependency analysis
The fast digest-hex checks compare the reference fixture worker with the
immutable pre-optimization implementation in
test/fixtures/hash-hex-reference.arboricx, including all byte values and
malformed/noncanonical inputs. Preserve that reference unchanged. Select a
genuinely compiled candidate object module for focused checks of edits:
python3 test/digest_hex.py result/bin/tricu \
--subject "$CANDIDATE_OBJECT_BUNDLE" --directory /tmp/digest-hex-check
The directory must be fresh. This runner is artifact-only.
Focused name/dependency-analysis checks require explicitly selected, precompiled candidate modules:
python3 test/source_order.py result/bin/tricu \
--order-bundle "$CANDIDATE_ORDER_BUNDLE" \
--stable-bundle "$RELINKED_STABLE_BUNDLE" \
--unit-bundle "$RELINKED_UNIT_BUNDLE" \
--directory /tmp/source-order-check
The directory must be fresh. Prepare those full-export modules with the retained
stable compiler, linking source_stable and source_unit against the changed
source_order manifest (and unit against the relinked stable manifest). Record
source hashes and dependency manifests during preparation. This artifact-only
runner compares complete order/diagnostic/graph results and, with the optional
unit bundle, complete stable compiled results for 38 cases. Reference sources
and artifacts are authenticated independently; the report records every selected
artifact identity.
HTTP syntax and framing
HTTP syntax checks are opt-in and artifact-only:
python3 test/http_headers.py "$TRICU" --subject "$HTTP_CANDIDATE" \
--directory /tmp/http-syntax-check
The candidate must contain the full unqualified HTTP exports. The default corpus
checks strict CRLF lines, complete header blocks, token names, value byte
classes, SP/HTAB trimming, exact error progress, opaque body remainders, and
shared request-line scanning. Deliberate semantic changes carry explicit reasons
and independent complete expected trees; unaffected cases still compare against
the immutable pre-rewrite reference. --legacy-behavior reproduces the earlier
readability-only corpus against historical artifacts. Use the default corpus for
the corrected parser. The byte domain is canonical naturals in 0..255.
Historical out-of-domain cases have separate historical records; current
expectations use the canonical byte domain. All byte classes and exact
progress/remainder checks remain active. The frozen reference is independent of
the candidate.
Content-Length/body-length selection has a separate artifact-only check:
python3 test/http_lengths.py "$TRICU" --subject "$HTTP_CANDIDATE" \
--directory /tmp/http-length-check
It checks bounded decimal decoding through the 1 MiB body limit, all byte values,
long digit/zero runs and malformed suffixes after overflow. Header selection
rejects duplicate Content-Length (even identical), comma lists, and any unsupported
Transfer-Encoding with 400; valid oversized lengths return 413. Names passed
directly to contentLength must already be normalized by parseHeaders.
Complete inert readBody error trees prove rejection before requesting body IO.
Optional --reference selects an explicit previous HTTP bundle for small unchanged cases only: its old unbounded
decoder cannot safely serve as the oracle for costly inputs. Every candidate case
has an independent complete expected tree. The header regression above still
applies.
The broader HTTP pipeline also has an opt-in artifact-only suite:
# Prepare test/httpEffects.tri explicitly with native_library_migration.py:
# --backend stable --library tests.httpEffects (plus normal selected dependencies).
python3 test/http_pipeline.py "$TRICU" --subject "$HTTP_CANDIDATE" \
--reference "$PREVIOUS_HTTP" --driver "$HTTP_EFFECTS_DRIVER" \
--directory /tmp/http-pipeline-check
Without --driver, this runs only pure validation/buffer/framing probes. With
it, a test-only interpreter runs the actual selected HTTP functions, interprets
Pure/Bind and supplies scripted primitive replies. Independent complete trees
check results, every recv/router/send/close payload and ordering, and unused
script entries. Interpreter controls exercise sequencing, missing/wrong/extra
operations, fuel exhaustion, and abort; a wrong selected subject must fail.
Optional --reference checks unchanged behavior and explicitly characterized old
outputs for intentional corrections (EOF retry, receive-error shadowing, lost 431
status and the 413 reason phrase). For a reference that already includes those
corrections, add --reference-current: every result and trace must then agree
unchanged with the independent oracle AND the reference. Prepare the opt-in test
driver separately from the support-fixture cohort.
The driver uses scripted effects. HTTP cleanup attempts close after an ordinary send Result and preserves the primary failure; terminal aborts and host exceptions are separate. Expectations include error precedence, EOF, bucketed reads, exact body lengths, binary suffixes, and the whole-buffer receive cap described in Parser.
For receiver changes, evaluate ordinary headers, fragmented reads, near-limit success/failure, and representative concurrent IO. Preserve limit-before-acceptance behavior, suffixes, errors, and complete receive/send/close traces. Measure time and memory together, including concurrent workloads when assessing throughput.
Exact package registry checks
nix flake check runs Haskell codec/publication tests (including concurrent
identical publishers) and test/package_registry.py against a controlled
loopback HTTP peer. This checks explicit trust, lock identity and mutation
controls, redirects, metadata bounds, corrupt transport, module mismatches,
offline reuse/binding, and local corruption using prebuilt wire fixtures.
For the full current-source vertical slice on the Haskell host:
nix build .#
python3 test/package_registry.py result/bin/tricu \
--prepare-server /tmp/package-registry-candidate
The preparation directory must be new. Preparation compiles the current native
server with the packaged stable compiler, retains source copies, source hashes,
command and build log, and limits compilation to 900 seconds / 8 GiB heap. The
runner then compiles a small two-export library, publishes it locally, serves it
through the actual native HTTP routes, fetches into a fresh store, stops the
server, generates a pinned workspace binding and compiles a consumer yielding
42. Invalid package route components must receive HTTP 400. Runtime children
have a 2 GiB heap limit and bounded subprocess deadlines.
To reuse an already prepared server artifact:
python3 test/package_registry.py result/bin/tricu \
--native-server /tmp/package-registry-candidate/server.arboricx
That module must export main root port, returning the IO-wrapped server
action. These checks cover real loopback HTTP. HTTPS/certificate infrastructure,
hostile-filesystem containment, and crash durability require separate
validation.
Registry server pipelines (opt-in)
Prepare tests.httpEffects and tests.registryEffects explicitly through the
stable native-library preparation route. The registry adapter reuses the same
fuel-bounded Pure/Bind interpreter. Both modules are prepared as test-only
artifacts, separately from the support fixture cohort. Select full unqualified
registry and optional demo artifacts:
python3 test/registry_server.py "$TRICU" --subject "$SERVER_CANDIDATE" \
--reference "$PREVIOUS_SERVER" --driver "$REGISTRY_EFFECTS_DRIVER" \
--demo "$SERVER_DEMO" --previous-demo "$PREVIOUS_SERVER_DEMO" \
--directory /tmp/registry-server-check
The runner executes selected artifacts through pure/scripted effects. Without a
driver it checks pure hash/contract/path/prefix operations only. With it,
independent complete trees check attempted action payloads/order, errors, unused
replies, initialization, uploads/downloads, routes, the actual HTTP adapter and
listener startup. Optional demo artifacts check initialization failure prevents
listening, and successful initialization proceeds to listening. --baseline
checks explicit historical expectations against an old subject including
inert unsafe write requests. Candidate runs retain their independent
current-behavior oracles. Reference comparisons characterize each intentional
behavior change. Wrong-subject selection must fail. Reports record selected
artifact identities; preparation provenance and publication are separate checks.
The server validates exact 64-character lowercase hexadecimal hashes before
filesystem IO, including the digest reply used for upload. The old public
unchecked hash-taking writer and shared <hash>.tmp staging are removed. Upload
publication uses atomicWriteBytes, whose host-owned unique temporary file is
in the destination directory. Publication replaces existing objects. Uploads
accept arbitrary opaque bytes; consumers must validate bundle format before use.
A post-publication sync error may leave the new file visible. Initialization now
propagates errors and stops immediately. Bind/listen errors attempt close once
and preserve the original error even if close fails.
The fast Haskell gate separately exercises bounded malformed-tree rejection (including unevaluated oversized suffixes), complete primitive traces, and small real-filesystem checks: initialization, binary round-trip, replacement, concurrent same-object uploads and absence of temporary residue. These use authenticated reference fixtures. Edited-source coverage, live-network behavior, scheduler fairness, crash injection, and terminal-abort/host-exception cleanup require separate checks.
Store root remains trusted configuration. Identifier validation checks spelling;
host permissions control IO access, and symlink/race safety requires a trusted,
stable store filesystem. Pure path helpers
remain unguarded constructors. Hash predicates retain arbitrary-tree rejection;
stripPrefix requires a proper list prefix and returns the exact suffix.
Support fixture publication
Support fixture v3 retains immutable original compiler/support snapshots and per-module provenance. Its 39-module reference cohort has stable-rebuilt native receipts, full manifests, and a separate compiled-root snapshot. Original snapshots preserve their recorded compiler identities. Rebuilt modules may change bodies and exports: their source fingerprints must match the actual compiled source/receipt, and their full export sets must match their new manifests. Tests still check receipt identities and published/rebuilt kernel equality. Support-provider manifests in receipts must match the selected cohort. Reusing an artifact requires matching provider interfaces as well as an unchanged consumer body.
Origin-retained modules require unchanged source fingerprints/output trees and identical complete interfaces of every imported or reexported provider. Comparison uses exact constructor/child interning across the bundles, independently of local node indices. Provider membership, every export name and every executable tree must match; this also preserves namespace and collision outcomes. Unrelated providers may change. Changes to unused or shadowed imports now require rebuilding: the former free-name-based reuse optimization is retired.
This proves identity relative to an authenticated, accepted original cohort.
Source validation and new compilation receipts require compilation. The verifier
recognizes the fixture's simple named-provider imports and reexports;
unsupported directives, including build-only !source dependencies, fail closed
and require rebuilding. The verifier compares recorded provider interfaces
directly. Prefer rebuilding affected consumers to relaxing these checks. The
current 39-module cohort is entirely rebuilt and already satisfies this policy.
Future source changes still need candidate coverage and genuine publication at
acceptance.
For a justified narrow repair, test/repair_support_dependencies.py
materializes full original dependency manifests (and asserts their original
identities), and test/native_library_migration.py builds the affected aliases
with stable lowering. For a full support rebuild, explicitly select all current
support modules and let their dependencies compile in the fresh candidate store.
Use --backend stable --capabilities 8 --memory-mib 65536; candidate commands
default to a 20-minute guard, and --batch-seconds 7200 permits a bounded full
cohort. For compiler-affecting work, acceptance additionally requires the
generation workflow below.
test/repair_support_fixture.py creates a new candidate directory,
preserves published fixtures, and reproduces every candidate’s complete native
manifest before accepting its kernels against the compilation receipt:
python3 test/repair_support_fixture.py "$TRICU" "$SUPPORT_CANDIDATES" \
--output-directory "$SUPPORT_PUBLICATION" \
--capabilities 8 --verification-memory-mib 65536
The publisher also accepts multiple preparation directories. To replace a prior
candidate explicitly, supply its directory first, the new preparation later, and
repeat --replace ALIAS for each duplicate alias. It checks the retained
records against their own source bytes, compiler identities, and receipts.
Repacking preserves those original compilation claims. Include genuinely rebuilt
affected consumers in the selection: stale support dependency pins fail before
metadata is published. Cohort membership/alias/path changes remain a separate
operation. Rebuilt modules may deliberately change source and exports, with
callers and expectations updated. The explicit --relocate-patterns operation
adds only patterns at lib/patterns.tri, requires its genuine native rebuild,
and refuses publication while it still belongs to the compiler fixture. V3
records this relocation without changing the immutable origin membership. Use
that option when publishing the current 39-module support set; ordinary
candidate replacement preserves cohort membership.
Current indexed native-manifest reproduction uses indexed import and exact
manifest comparison. Reproducing retained flat manifests expands trees: its
default audit RSS/heap
limits are 8/4 GiB, with an explicitly selectable RSS cap up to 64 GiB and heap
cap half that value. The large staged-conditional fixture needs more than the
default heap. Indexed bundle packing/import validation retains 1 GiB RSS / 512
MiB heap limits. Each audit child has a 300-second deadline; the complete
publication job is bounded to 20 minutes. verification.json records the actual
checks. Failed candidates remain unpublished.
After successful candidate validation, install only support-library.arboricx,
support-rebuilt.arboricx, support-library.v1, and support-receipts/,
preserving the immutable origin files. Capture the matching reference sources,
then run python3 test/fixture_sources.py current and nix flake check before
accepting the fixture. Preserve actual compiler identities and original
snapshots when repairing failures. Label backend-sensitive tree-shape goldens by
their backend and check them independently. Extensional equivalence requires
separate evidence.
SCP: archived experiment
SCP sources, commands, tests, demos, and the mixed workspace dispatcher are
under archive/scp/ as historical material.
Active builds and tests use the native module tooling. Historical commands in
the SCP reference require a historical
checkout.
The original fixture projection is recorded in test/fixtures/support-projection.json.
Its immutable origin fingerprints remain checked inputs; rebuilt outputs are
instead authenticated by native receipts and current cohort metadata. To reproduce
that historical extraction, use test/project_support_fixture.py with explicit
--original, --compiler, --source-root, --aliases, and new --output paths.
Projection compares exact kernels and dependency closure without source compilation.
Keep its historical ledger distinct from later compilation publications.
Compiler, transport, and publication
See compiler rebuilding for artifact prerequisites, backend selection, guarded generations, and independent closure audits. Runners default to stable; select it explicitly in recorded commands.
python3 test/source_equations.py result/bin/tricu \
--generation "$GENERATION" --timeout 180
python3 test/portable_cli.py result/bin/tricu --indexed \
--compiler-bundle "$GENERATION/build-stable.arboricx"
bash test/source_map_end_to_end.sh result/bin/tricu "$GENERATION" \
.bootstrap-run/nested-map
Check each probe's --help for its other required prepared artifacts. Equation
coverage has independent AST/diagnostic controls; module/map probes use native
artifacts. verified_tree_loading.py covers verified transport and bounded
loading/publication measurements, outside the default checks.
Header-only equivalence uses the explicit --native-header-equivalence option
of refresh_compiler_fixture.py. It authenticates exact staged bytes and
previous receipts and requires unchanged bodies and dependencies. It records
header equivalence; new generations follow the generation runner workflow. For a
support change, rebuild only the justified affected cohort and prove reuse for
the rest. Record actual compiler pins and rebuild consumers whose dependency
identities changed. Archive creation consumes existing accepted artifacts and
their matching fixtures.
refresh_compiler_fixture.py and refresh_support_fixture.py publish artifacts
after validation. refresh_compiler_fixture.py --output-directory DIR stages a
compiler candidate without replacing the reference cohort, allowing pre-
publication comparisons. Publish the compiler before the final support publisher
run: support metadata binds the compiler fixture present during publication.
They authenticate completed preparation receipts, current source fingerprints,
full dependency manifests, and the packed fixture. Explicit --completed-only /
--replace ALIAS select explicit, reviewable publication policies; failed
preparation requires separate repair. Streaming publication retains tighter
600-second / 1 GiB RSS / 512 MiB managed-heap guards.
native_library_migration.py prepares explicit candidates, preserving
definition bodies and dependency/import policy. Bare terminal-selector
conversion and import-only reexports require explicit flags; arbitrary
expressions and namespace widening fail. Candidate jobs / batches default to 20
minutes; an explicitly selected full cohort may use a two-hour batch ceiling.
--memory-mib sets both the sampled direct-child RSS guard and host heap
ceiling, up to 64 GiB. Full dependency manifests are mandatory; authored source
and published fixtures remain unchanged.
Research and costs
Native math checks, formatter tooling, stable abstraction/bundles, and staging experiments remain opt-in; use their retained compiler and support artifacts. Compile current compiler libraries through the selected portable toolchain.
python3 test/staging_experiment.py result/bin/tricu \
--prepared "$STAGING_PREPARATION" --prepared "$UPDATED_FIXTURE_PREPARATION" \
--compiler-bundle "$GENERATION/build-stable.arboricx" \
--directory .bootstrap-run/staging-runtime --skip-measurements
python3 test/staged_conditional.py result/bin/tricu \
--prepared "$STAGING_PREPARATION" --prepared "$UPDATED_FIXTURE_PREPARATION" \
--compiler-bundle "$GENERATION/build-stable.arboricx" \
--directory .bootstrap-run/staging-source --source-only \
--case yes --case closed-unselected --case ordinary \
--case list-advance --case slice-unicode
Both research harnesses cap whole runs and children at 1200 seconds. Prepared fixture selections reuse authenticated trees; generated case data is compiled in batches. Explicit scalar fixture data supplies Unicode codepoints directly; native source-file loading remains restricted to ASCII. Run formatter integration separately.
Report preparation, loading, compilation, publication, allocation, RSS, logical size and DAG size separately. Direct-child RSS covers only the child process; measure descendants separately. Guard stops and missing measurements are failures. Research-profile contracts are in Compiler architecture.
Local-control candidates (opt-in)
Select genuinely rebuilt source_unit and source_program candidate bundles,
plus a stable-prepared tests.localControlEffects driver and fresh output
directories. The driver depends on the existing tests.httpEffects interpreter;
prepare it through the native library preparation tool with that dependency
selected explicitly. Keep test drivers in a separate test-only preparation.
python3 test/local_control.py "$TRICU" --unit "$UNIT" --program "$PROGRAM" \
--directory "$SYNTAX_CHECK"
python3 test/local_control_consumers.py "$TRICU" --unit "$UNIT" \
--driver "$LOCAL_CONTROL_DRIVER" --directory "$CONSUMER_CHECK"
The first check compares complete located AST replies, complete diagnostic records, independent values, and a wrong-compiler negative control. Compiler private diagnostic remainders are retained as implementation-level evidence; language-level oracles cover the public diagnostics. The second compiles and serializes small HTTP/registry replacement functions before invoking them, compares both candidate and authenticated retained kernels to independent complete values/effect traces, and records expanded wire-tree sizes and guarded whole-process costs. Authenticate driver source, receipts, and dependencies during preparation. The default Nix check runs cheap harness controls; run these compilations explicitly.
Arboricx reader rewrites (opt-in)
python3 test/arboricx_readers.py "$TRICU" \
--subject "$CANDIDATE_MODULES" --reference "$RETAINED_MODULES" \
--directory "$FRESH_PROBE_DIRECTORY"
Both directories contain full arboricx_common, arboricx_nodes and
arboricx_manifest bundles. Independent complete-result oracles cover field
reads, every truncation of representative records, opaque suffixes, counted
records, node payload/index validation, and error precedence. Differential shape
probes cover selected malformed trees. A wrong-export control must fail the
independent oracle.
Prepare candidates separately with the portable stable compiler, rebuild dependent
Arboricx consumers, authenticate receipts and prove tested/published kernel
identity before refreshing fixtures.
binary.bindParser threads the successful value and remaining input to its
continuation and supports do directly. The
full readManifest entrypoint historically returns unit in both its extension
slot and successful remainder, even with trailing input. This is explicitly
characterized separately from the remainder-preserving field readers. The
current suffix-preserving behavior is covered by bundle_batch.py below.
Socket convenience cleanup (opt-in)
python3 test/socket_conveniences.py "$TRICU" \
--subject "$CANDIDATE_SOCKET" --reference "$RETAINED_SOCKET" \
--driver "$REGISTRY_EFFECT_DRIVER" --directory "$FRESH_PROBE_DIRECTORY"
Checks complete primitive payloads/order and exact Result remainders. The retained reference predates cleanup: successful acquisition followed by failed bind, listen or connect intentionally adds one close; the original error survives close failure. Acquisition failure returns directly; success transfers ownership. Terminal aborts and host exceptions follow host lifetime handling, separately from ordinary Result cleanup. The scripted test records socket actions as data. The Haskell gate separately exercises a real ephemeral listener and successful loopback connection, plus exact scripted cleanup paths.
Parser control rewrites (opt-in)
python3 test/parser_control.py "$TRICU" \
--subject "$CANDIDATE_PARSER" --reference "$RETAINED_PARSER" \
--driver "$PARSER_CONTROL_DRIVER" --directory "$FRESH_PROBE_DIRECTORY"
Compile test/parserControl.tri explicitly through the stable portable
toolchain. Its higher-order wrappers receive the selected compiled parser export
after wrapper construction. Independent full replies cover repetition,
zero-width success, failure progress, bind/lexer flag propagation, and non-Leaf
truthiness. Divergent ignored fields and unselected handlers must remain
unforced. A same-arity wrong-export control uses parserOptional in place of
parserMany. Record/authenticate driver source, receipts, compiler/options,
dependencies and complete manifest separately. Parser edits are
compiler-affecting: acceptance also requires the fresh stable
generation/self-rebuild and publication steps in compiler
rebuilding.
Foundational list workload comparisons (opt-in)
Use an authenticated pre-adoption fixture directory, including bundle metadata and source snapshots, for historical manual-worker comparisons:
python3 test/base_workloads.py result/bin/tricu \
--compiler "$STABLE_BUNDLE" --directory "$FRESH_OUTPUT" \
--reference-fixtures "$REFERENCE_FIXTURES" \
--sizes 64 1024 8192 --repetitions 7
python3 test/base_readable.py result/bin/tricu \
--compiler "$STABLE_BUNDLE" --reference-source "$REFERENCE_BASE_SOURCE" \
--directory "$OTHER_FRESH_OUTPUT"
The first compares published/manual fixed points, direct recursion, patterns, and captured local recursion over protocol/log-like workloads. It authenticates manual/published kernel equality and checks independent complete results, edge cases, ignored-field demand, and a wrong-subject control. Its whole-job budget is 30 minutes with 8 GiB child RSS/heap guards.
The second compiles complete reference/current base modules and linked drivers, then checks independent edge/demand/effect cases and a smaller workload screen. Its whole-job budget is five minutes, compilation 60 seconds, and ordinary calls 20 seconds. Effects are interpreted interaction trees with scripted replies.
Use fresh processes, interleaved variants, discarded warmups, and recorded raw
samples. arboricx run --repeat can reuse an evaluated application; use a fresh
process for each independent invocation. Loading-to-WHNF,
invocation-through-rendered-output, and explicit full-result forcing measure
different work; the latter two include deferred evaluation and their respective
observer costs. See the profile phase
definitions; ordinary --profile leaves discarded
result fields lazy. Report preparation separately. Sampled RSS can miss
short-lived peaks, and small timing differences require broader evidence before
generalizing. Partial matrices remain incomplete. These probes leave accepted
compiler and support fixtures unchanged.
Pattern lowering comparison (opt-in)
python3 test/pattern_lowering.py result/bin/tricu \
--reference-unit "$RETAINED_SOURCE_UNIT_BUNDLE" \
--directory /tmp/tricu-pattern-candidate
The probe authenticates the shipped compiler and complete unchanged reference
modules. It stages the source lowerer and rebuilds its affected compiler
consumers through source_unit; receipts, source bytes, exported objects, and
exact dependency pins are audited before execution. Only unchanged dependency
boundaries use full retained-module facades. Accepted artifacts remain
unchanged.
The Haskell control driver is compiled through Nix. Checks reuse the 75-case independent equation corpus, exercise constructor/equality workloads on finite and poisoned inputs, and verify split-column ordering, nested failure, unreached pins and whole-child captures. Two exact code-generation targets compare ordinary equations with independently authored direct dispatchers; the retained compiler must fail those optimization targets. Non-pattern controls must retain their original trees. Optimized-backend function trees must also remain identical; stable function construction must tolerate unselected closed divergence while application to the divergent branch must not return. The existing 46-case local-control suite also runs on the candidate.
Select an authenticated retained source_unit bundle with unqualified exports
for --reference-unit; its digest is recorded separately from the shipped
compiler used to construct the candidate. --prepare-worker additionally
rebuilds all affected consumers through source_map and emits a pruned stable
transition worker.arboricx for subsequent generation acceptance. --resume
permits diagnostic checkpoint reuse only.
Fresh-process cost probes interleave reference/candidate executions, discard a warmup, and retain three samples per role. Identical explicit recursion and full output oracles isolate dispatch costs. Separate small compiler probes force the complete returned definition trees. Both use explicit full-result profiling: reduction plus DAG traversal, excluding load and rendering. Allocation is GC-sampled; peak residency and reduction counts require separate measurements. Reports retain raw profiles, source/compiler/artifact identities, receipts, controls, and medians.
Limits: 20 minutes overall, 600 seconds for native compilation with an 8 GiB
heap, 180 seconds / 4 GiB for the Haskell controls, and 20-second / 512 MiB
workload calls (30 seconds / 1 GiB for construction probes). --resume
authenticates native checkpoints and preserves the previous report for
diagnostic reuse. --skip-costs retains semantic/integrity controls without
timing runs. Compiler acceptance additionally requires a fresh
generation/self-rebuild pair.
Sharing characterization (opt-in)
python3 test/sharing_probes.py result/bin/tricu \
--directory /tmp/tricu-sharing-probe
Use a fresh directory. The probe compiles tiny import-free programs with the shipped stable compiler and runs only the Haskell host. It compares a bound shared computation with two separately written calls, checks their complete small outputs against an independent oracle, and compares a shared DAG with itself using an ordinary TC structural comparator. Input DAGs contain depth+1 physical nodes and 2^(depth+1)-1 logical occurrences. It also checks that ordinary profiling ignores a divergent Result remainder while explicit full-result forcing hits a resource bound.
Runs use fresh processes, three samples by default, a 512 MiB child heap cap,
20-second commands (three seconds for the expected noncompletion), and a
180-second whole-job budget. report.json retains commands, source/artifact
hashes, manifest pins, raw profiles, and medians. The measured interval is
force-begin through force-end: reduction plus sharing-aware traversal,
excluding loading and rendering. Allocation counters are GC-sampled; reduction
counts and peak residency require separate measurements. Results characterize
these particular examples. Universal binding sharing, eager compatibility, and
general compiler speedups require broader evidence. Published compiler/support
artifacts remain unchanged.
Collections, contracts, and ordinary cleanup candidates (opt-in)
The three library batch runners below require REFERENCE_FIXTURES:
authenticated pre-rewrite fixtures, including their reference-source
snapshots, selected from frozen 1f24085:test/fixtures (or the identical
foundations publication). Historical correction/API-delta controls require those
pre-rewrite fixtures. Sources under test still come from the current checkout;
the reference flag selects only historical controls and cost/API comparisons.
python3 test/collections_batch.py "$TRICU" \
--reference-fixtures "$REFERENCE_FIXTURES" \
--compiler "$GENERATION/build-stable.arboricx" --directory "$PROBE_DIRECTORY"
The directory must be fresh. --resume explicitly reuses diagnostic compilation
checkpoints; native receipt keys invalidate changed inputs. The whole-job limit
is twenty minutes, with thirty seconds per ordinary call. The descriptive cost
screen uses two sizes and three post-warmup samples.
Preparation stages the affected foundations, contracts, IO, HTTP/socket, drivers, and demo consumers. It authenticates every source, stable producer/options receipt, full manifest, dependency receipt, and export pin. Independent complete Results cover transformed collection/proxy values, malformed inputs, short-circuit demand, effect ordering, and ordinary cleanup. Historical correction controls and a same-arity wrong-subject control remain required. Published fixtures stay untouched.
Numeric and decimal candidates (opt-in)
python3 test/numeric_batch.py "$TRICU" \
--reference-fixtures "$REFERENCE_FIXTURES" \
--compiler "$GENERATION/build-stable.arboricx" --directory "$PROBE_DIRECTORY"
Stages base, bytes, conversions, prelude, native math, and a driver with the selected
stable producer. Authenticates source/options/dependency/export receipts and the
driver's full native manifest. The source map must match headers and retain full
compiler-root reachability. --resume is diagnostic cache reuse.
Independent complete outputs cover saturation, ordering, carry/borrow, random bit patterns, zero divisors, powers, decimal boundaries, classifiers, malformed encodings, and demand. Operand-swapped and historical zero-divisor negative controls must fail the current oracle. The small interleaved cost screen is descriptive. Run affected collection/HTTP consumers separately. Budgets: fifteen minutes overall, thirty seconds per ordinary invocation, and 8 GiB sampled child RSS.
Binary and bundle candidates (opt-in)
python3 test/bundle_batch.py "$TRICU" \
--reference-fixtures "$REFERENCE_FIXTURES" \
--compiler "$GENERATION/build-stable.arboricx" --directory "$PROBE_DIRECTORY"
Stages current binary/bundle dependencies and its driver with authenticated
source/options/producer receipts, complete manifests, export pins, and reimported
driver identity. --resume explicitly reuses diagnostic checkpoints. Budgets:
fifteen minutes overall, thirty seconds per ordinary invocation, and 8 GiB
sampled child RSS.
Independent complete Results cover truncations/remainders, UTF-8, manifest versions, suffixes, section ranges, export contracts, roots, node payloads/edges/duplicates, typed codecs, and early rejection. Existing executable fixtures are reconstructed as complete trees. Historical correction and wrong-reader controls prevent an old implementation from satisfying a new oracle accidentally.
The bounded cost screen uses two fork-spine sizes, one warmup, and alternating
samples. Report stronger validation's allocation and timing costs honestly.
Use this runner for current suffix-preservation checks; arboricx_readers.py
compares a historical cohort.
Compiler candidate checks
Independent compiler models, cases, and probe templates live in
test/tooling_batch_models.py and test/source_*_models.py; test/unit.py checks
the models and corpus invariants. Use compiled candidate artifacts to test edited implementations, alongside the
reference and acceptance checks described above.
Current formatter preparation is documented in tri-tools
and uses test/prepare_formatter.py, without historical reference inputs.
python3 test/shipped_compiler.py checks the shipped accepted builder against its
recorded sources and published executable tree, without generating a compiler.
Module/object candidate (opt-in)
test/source_modules.py "$TRICU" --compiler "$STABLE_COMPILER" --seed "$LOWERING_CANDIDATE_DIRECTORY" --directory "$NEW_DIRECTORY" exercises current
codecs, native headers, demand, and scripted complete IO traces. The seed is
optional, explicit, and reauthenticated. The shared compiler_candidate.py
links immutable CAS objects only, copies mutable checkpoints and reaudits all
staged current sources/receipts/exports after the build. Existing directories
require --resume. Limits remain 1500s overall, 900s per compilation and 65536
MiB sampled child/heap. The seed remains unchanged.
Build/publication candidates (opt-in)
test/source_building.py "$TRICU" --compiler "$STABLE_COMPILER" --seed "$MODULE_CANDIDATE_DIRECTORY" --directory "$NEW_DIRECTORY" checks complete
bundle bytes against a Python postorder-interning model, integer field
boundaries, lock rows, source maps, receipts, and empty/memo/cycle demand. It
emits an audited source_map-selected.arboricx exposing both explicit backends.
Use it as the --worker-bundle for test/bootstrap_generation_cli.py with a
verified previous generation, selected standard adapter and --backend stable;
this separately checks live publication, invalidation, interruption, corruption,
and failure of unavailable compiler selections.
test/source_export_cache.py uses the same options, with the build candidate as
seed, and checks complete scripted cache-hit/miss/storage/error/selection traces.
Both use the shared candidate limits and provenance rules above and report
diagnostic reuse explicitly.
Stable construction/publication shards (opt-in)
Use both bounded groups for the complete 28-case stable abstraction corpus:
for GROUP in core sequences; do
python3 test/stable_abstraction.py "$TRICU" --generation "$GENERATION" \
--case-group "$GROUP" --directory "$PROBE_DIRECTORY/$GROUP" \
--memory-mib 65536 --wall-seconds 1500
done
The core group covers 20 construction/application/diagnostic/demand cases; the
sequence group covers eight slice/repetition cases. Whole-job and sampled child
RSS guards remain active. A single unsharded run can exceed the whole-job budget
because each distinct program is separately published; shard the corpus while
keeping the limit fixed. complete.json binds selected/completed names and
compiler/harness hashes. Unicode sequence fixtures contain explicit scalar cells
and test codepoint operations. UTF-8 native-source transport has separate
coverage below. Bounded expected divergence records noncompletion within the
selected budget; proving nontermination requires separate analysis.
Native source UTF-8 boundary (opt-in focused probe)
python3 test/native_source_utf8.py "$TRICU" --generation "$PREVIOUS" \
--compiler "$MATCHING_RETAINED_COMPILER" --directory "$PROBE_DIRECTORY"
This transition probe requires a matching retained flat-native compiler and
support closure. Use a Nix-built Haskell host and a new output directory. It
compiles current read/stage and map consumers with that retained compiler and
authenticated support exports. The published frontend is checked separately by
test/default_frontend.py, including Unicode source, raw-byte receipts, stdin,
and malformed/BOM rejection. It checks exact input/overlay octets, source-domain
fingerprints, ASCII parity, multibyte strings/comments, scalar coordinates, and
malformed UTF-8/BOM rejection. Host unit tests separately cover binary IO
parity, permissions and invalid encoder scalars. Existing scalar-list fixtures
cover scalar operations; file decoding requires the byte-level cases above.
Limits are 8192 MiB, 900 seconds for compilation, 180 seconds per smoke and 1500
seconds for the whole job. Generation acceptance and fixture publication follow
their separate workflows.
Published-library consumer (opt-in)
Builds three curated libraries through the shipped stable compiler, publishes
exact releases in a new local registry directory, fetches them into an empty
consumer CAS over a controlled GET peer using one project declaration/lock,
closes that server, and binds/checks/compiles demos/package-inspector/main.tri
offline. The consumer receives library inputs exclusively through fetched
packages. The native registry route itself is covered by the separate
package-registry checks above.
nix build .#
nix build .#inspectorOracle --out-link result-inspector-oracle
WORK=$(mktemp -d)
nix shell --inputs-from . nixpkgs#python3 -c python3 test/library_inspector.py \
result/bin/tricu --oracle result-inspector-oracle/bin/inspector-oracle \
--directory "$WORK/inspection"
inspectorOracle is a test-only Haskell executable using Wire.decodeBundle
and verifyBundle to inspect export records as data independently of the
compiled inspector. Complete reports must match, including whole-file hash,
record count, export order, root indices, kind/ABI and percent escaping.
Fixtures cover invalid headers, truncation, malformed manifests, invalid
unselected roots/ABIs, duplicate exports/nodes, forward edges,
terminal-control/UTF-8 names, and 41 stored nodes representing more than a
trillion logical occurrences. An IO export that aborts if executed is inspected
successfully. The published libraries and inspector itself are inputs too.
Missing files and denied reads must fail nonzero.
On the validation host, the full 18-input publication/consumer check took about five minutes: offline consumer compilation was about 1.5 seconds, while inspecting the roughly 221 KiB inspection library or consumer bundle took about a minute each. These timings describe that validation host and workload; measure other environments independently. The in-memory portable parser is significantly more expensive than the native Haskell report oracle.
It then publishes a local test-only foundation revision with one additional
export, changes only the foundation selection, and explicitly updates that one
binding. The other two lock rows must stay byte-identical. Stale checks and
binding before fetch fail. After fetching, the registry is stopped again and the
unchanged consumer is rebound, checked and recompiled offline; its output must
still match the independent oracle. The update diff and resulting inspector
identity are recorded; the test release stays confined to the local registry.
With the registry still closed, project explain must report verified local
evidence and project diff must identify the added revision export and
structurally identical common foundation exports. Both human-readable reports
are retained in the JSON.
The preparation retains artifacts, the initial/current project locks and
generated bindings/ownership state, separate producer and consumer stores,
compiler/source hashes, command logs and outcomes in report.json as local
validation evidence. Signing and distributing provenance requires a separate
workflow. Current bounds: 8 GiB GHC heap per tricu child, 900-second compile
deadline, 180-second inspection deadline and 2400-second overall command budget.
Heap bounds cover managed heap; total process RSS requires separate controls. It
remains opt-in; default checks exercise cheap CLI --no-result controls and
site-staging immutability without recompilation.
test/project_dependencies.py runs in the default host-policy check with small
wire fixtures and a controlled GET peer. It covers frozen/no-network resolution,
scoped updates/additions/removals, late-resolution failure preserving the whole
lock, registry equivocation (including renames), origin mismatch,
missing/corrupt CAS objects, authored/edited/symlink binding collisions, journal
recovery, removal of owned bindings only, input/output collisions and offline
retries. Inputs are prebuilt wire fixtures and networking is confined to the
controlled peer; each CLI child has a 1 GiB GHC heap limit and a 30-second
deadline. Haskell tests separately check the metadata codecs, canonicalization,
name bounds and duplicate/conflicting selections.
test/project_inspection.py is another default host-policy check. Independently
assembled wire/CAS fixtures prove ordered structural equality despite changed
physical numbering/object hashes, unequal trees, 81-node exponential DAGs,
unreachable records, interface/ABI/kind changes, terminal-safe metadata, and
missing/corrupt/malformed evidence even under unchanged pins. Files and mtimes
are snapshotted around every report; absent stores must remain absent. Each CLI
child has a 512 MiB GHC heap guard and a 30-second deadline. Small Haskell
comparisons also agree with independently evaluated constructor equality;
large-DAG expected answers preserve sharing. A focused byte-budget test confirms
that repeated object references share inspection results and additional objects
become unavailable when the retained-byte allowance is exhausted.
The default command preserves checked-in site files. To additionally stage
accepted library releases for the existing static-site/dependency-pack pipeline,
add --stage-site ext/demo-site to a fresh run. Staging authenticates the
bundle bytes, preserves existing versions, refuses conflicts, writes bundles
before index entries, and leaves public deployment to a separately authorized
operation. --version LABEL selects a new exact release label for the library
set; changing executable bytes under an existing name/version is rejected. Use
an exclusively owned local site workspace and serialize staging operations to
preserve index consistency.
Retained provenance (opt-in)
First retain a successful published-library inspector run as described above. Then capture/rebuild the actual three library modules and inspector:
nix build .#
WORK=$(mktemp -d)
nix shell --inputs-from . nixpkgs#python3 -c python3 test/provenance.py \
result/bin/tricu --accepted "$INSPECTOR_ACCEPTANCE_DIRECTORY" \
--directory "$WORK/provenance"
The harness copies producer workspaces/stores to a disposable location, captures four self-contained input packs, deletes that producer copy, and rebuilds in fresh directories from the packs only. It runs outside the checkout, with the packaged compiler data path deliberately unavailable and the registry offline. Each native module and compiler-returned receipt must reproduce exactly. The initial validation host took about 3.5 minutes total: roughly 31/35/139 seconds for foundation/file IO/inspection libraries and 2 seconds for the inspector. These timings describe that validation host and workload; measure other environments independently.
An additional genuine build adds an ignored source comment: source, receipt and pack identities must change while the executable stays identical. That history must also reproduce after its disposable producer is deleted.
A separate negative fixture changes the inspector's source and native receipt to
claim the old output, authenticates every changed object, and includes a
matching poisoned producer cache. Byte/receipt verification must succeed as
claims only; a fresh rebuild must ignore that cache, produce different code,
and report a mismatch. This guards the distinction between integrity and actual
reproduction. Artifacts, pack pins, commands, timings and outcomes are retained
in report.json. Children use an 8 GiB GHC heap ceiling, 900-second compiler
deadline and bounded subprocess deadlines within a 2400-second overall budget.
Total RSS requires separate controls.
The default test/provenance.py run (wired into nix flake check) uses
independent wire/CAS/native-receipt fixtures. These cover no-execution
verification with a non-compiler tree, stale source refusal, explicit receipt
selection without a cache, immutable capture destinations, incorrect pins,
missing/corrupt sources, options, receipts and executables, malformed
inventories, path traversal, symlinked CAS directories, an unauthorized
compiler, and verification after all producer files have been removed.
Verification snapshots require unchanged files and mtimes. Each child has a 512
MiB GHC heap ceiling and a 30-second deadline.
CLI workspace source locations
nix flake check includes declaration parsing, ancestor discovery, nearest-file
boundaries, collision/missing-file rejection, and temporary snapshot cleanup.
For real packaged-compiler coverage on the Haskell host:
nix build .#
python3 test/workspace_compile.py result/bin/tricu
nix build .#arboricxServerTest --no-link
The focused harness compiles a nested application with transitive reexports from
an unrelated working directory, compares its bundle byte-for-byte with a flat
workspace build, captures and independently replays the mapped inputs beneath a
conflicting parent declaration, verifies cache invalidation after a source edit, and retains
negative cycle, missing-import, and source-collision controls. The deployment
check compiles the actual repository application via tricu.workspace and
exercises its server behavior.
Constructor-only K pruning (opt-in source check)
This check rebuilds source_stable and source_unit from the working source
with the packaged compiler, authenticating unchanged fixture dependencies. It
checks the rebuilt source implementation using independent expectations:
nix develop -c python3 test/stable_constructor_k.py result/bin/tricu \
--directory "$WORK/constructor-k"
Use a fresh output directory. GHC and its dependencies are selected through Nix. The harness adds probe-only exports in its disposable workspace; cached residual helpers remain private in production. The independent Haskell oracle uses full free-variable sets; the implementation uses a minimum-index summary. Checks cover successive annotated abstractions, sparse indices, constructor and unsafe-call classification, complete application results against a no-shortcut baseline, opaque arguments, closed-divergence construction, and diagnostic/remainder preservation. It also runs the local control corpus against the rebuilt unit compiler and audits native dependency pins and receipts. Children have explicit heap and time bounds.
These finite controls establish behavior for the tested cases. General termination and demand equivalence require separate proof. Compiler publication additionally requires the full reproduction, cross-host checks, and retention workflow in compiler rebuilding.
Digest-byte validation (opt-in source check)
Rebuild the current source_object module against source-authenticated fixture
dependencies and check its private byte guard and public digest predicate:
nix develop -c python3 test/digest_byte.py result/bin/tricu \
--directory "$WORK/digest-byte"
Use a fresh directory. The harness adds private probe exports only in its disposable workspace, audits native manifests and receipts, and builds the independent Haskell observer through Nix. Canonical bytes are checked against a bounded structural model; malformed trees retain the separately modeled legacy predecessor/comparison behavior. Cases cover all byte values, out-of-range naturals, malformed bits/tails, the eight-bit boundary, complete 64-byte digests, wrong lengths, and ignored/demanded poison payloads. Each observed result is compared completely, not by a prefix or hash alone.
These finite controls are not compiler acceptance or a general demand-equivalence proof. Publication still requires the reproduction, cross-host, site-refresh and retention workflow in compiler rebuilding.
ASCII classifiers (opt-in source check)
native_math's digit, letter, and lowerHex operate on canonical naturals,
not arbitrary trees. The focused check compiles current source using the
packaged stable compiler, audits its native receipt, and compares complete
Boolean trees against independent Integer predicates:
nix develop -c python3 test/ascii_classifiers.py result/bin/tricu \
--directory "$WORK/ascii-classifiers"
Use a fresh directory. Coverage includes every byte and BMP code point, Unicode boundaries, naturals up to 1025 bits with ASCII low bits, deterministic larger samples, and a wrong-subject rejection control. Malformed/partial-tree results and demand are outside this numeric fast path's contract. The digest consumer's canonical guard and arbitrary-tree fallback require the separate digest-byte checks above. Changes also require compiler source/diagnostic, HTTP header and UTF-8 boundary checks; classifier tests alone are not consumer or generation acceptance. Performance measurements must use matched complete workloads, not only individual predicates.
Compiler name-index controls (opt-in)
python3 test/name_index.py result/bin/tricu --directory "$FRESH_CHECK"
# Also select a rebuilt source_unit bundle, with unqualified export names:
python3 test/name_index.py result/bin/tricu --directory "$FRESH_UNIT_CHECK" \
--unit "$UNIT_BUNDLE" --reference "$REFERENCE_COMPILER_LIBRARY"
The first rebuilds source_index and its current prelude dependencies through
an authenticated packaged compiler. It checks complete results against host
first-match lookup, persistent overrides, misses, opaque values, partial-key/tail
demand controls, and a deliberately wrong worker. The optional module check uses
75 independent source outcomes (shared with source_equations.py), compares
complete reference/candidate results, and checks environment precedence and
demand. Selected unit/reference artifacts are fingerprinted, not source-freshness
certified by this option; select audited rebuilt artifacts. Finite poison tests
are not a general termination-equivalence proof. This check neither accepts a
generation nor publishes fixtures.