Skip to content

Emit direct JS WAM ops and cheap ITE for mixed-mode helpers. #15085

Emit direct JS WAM ops and cheap ITE for mixed-mode helpers.

Emit direct JS WAM ops and cheap ITE for mixed-mode helpers. #15085

Workflow file for this run

name: UnifyWeaver Tests
# Run on every push and pull request
# Does NOT block pushes - just provides feedback
on:
push:
branches: ['**'] # All branches
pull_request:
branches: ['**']
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install SWI-Prolog
run: bash scripts/ci/install_swi_prolog.sh
- name: Verify SWI-Prolog installation
run: swipl --version
- name: Create output directories
run: |
mkdir -p output
mkdir -p output/advanced
- name: Run constraint analyzer tests
run: |
swipl -g "use_module('src/unifyweaver/core/constraint_analyzer'), test_constraint_analyzer, halt."
- name: Run stream compiler tests
run: |
swipl -g "asserta(user:file_search_path(library, 'src/unifyweaver/core')), use_module('src/unifyweaver/core/stream_compiler'), test_stream_compiler, halt."
- name: Run recursive compiler tests
run: |
swipl -g "asserta(user:file_search_path(library, 'src/unifyweaver/core')), use_module('src/unifyweaver/core/recursive_compiler'), test_recursive_compiler, halt."
- name: Run ClojureScript target tests (codegen)
run: |
swipl -q -g "consult('tests/core/test_clojurescript_target'), (test_clojurescript_target -> halt(0) ; halt(1))" -t "halt(1)"
- name: Run ClojureScript recursive-compiler tests (codegen)
run: |
swipl -q -g "consult('tests/core/test_clojurescript_recursive'), (test_clojurescript_recursive -> halt(0) ; halt(1))" -t "halt(1)"
- name: Install nbb (Node ClojureScript runtime for CLJS smoke)
run: npm install nbb
- name: Run ClojureScript runtime smoke tests (nbb)
run: |
NBB="$PWD/node_modules/.bin/nbb" swipl -q -g "consult('tests/core/test_clojurescript_runtime_smoke'), (test_clojurescript_runtime_smoke -> halt(0) ; halt(1))" -t "halt(1)"
- name: Run advanced recursion tests (24 tests)
run: |
swipl -g "use_module('src/unifyweaver/core/advanced/test_advanced'), test_all_advanced, halt."
- name: Run constraint integration tests
run: |
swipl -g "use_module('src/unifyweaver/core/test_constraints'), test_constraints, halt."
- name: Run control plane tests
run: |
swipl -g "asserta(user:file_search_path(library, 'src/unifyweaver/core')), asserta(user:file_search_path(library, 'tests/core')), use_module(library(test_policy)), test_policy, halt."
- name: Run root-metric directive tests
run: |
swipl -q -g run_tests -t halt tests/core/test_root_metric.pl
# Every goal below is invoked explicitly as -g: a swipl load-time
# initialization error does NOT set the exit status, so relying on
# the mirror's load-time check alone would let a stale mirror pass
# CI (PR #4095, report finding 4). The mirror-verify goal makes a
# PR that changes process_cards.py's registry fail here until the
# mirror is regenerated.
- name: Run pattern_stache suites and registry-mirror drift check
run: |
swipl -g "use_module('prototypes/mu_cosine/pattern_stache/pe_registry_mirror'), pe_registry_mirror:pe_mirror_verify" -t halt
swipl -q -g run_tests -t halt tests/core/test_pattern_stache.pl
swipl -q -g run_tests -t halt tests/core/test_pattern_stache_whitespace.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pattern_stache.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_constraint_dispatch.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_number.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_interpret.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_emit.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_where.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_elaborate.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_error_fixtures.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_mode_classification.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pe_canonical.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/test_pstate_views.pl
swipl -q -g run_tests -t halt prototypes/mu_cosine/pattern_stache/probe_residual_order.pl
- name: Verify pattern_stache tutorial outputs
run: python3 docs/tutorials/check_tutorial.py docs/tutorials/TUTORIAL_pattern_stache.md
- name: Run C# query target tests (codegen only)
run: |
SKIP_CSHARP_EXECUTION=1 swipl -q -f init.pl -s tests/core/test_csharp_query_target.pl -g "test_csharp_query_target:test_csharp_query_target" -t halt
- name: Run C# query calibration wrapper contract tests
run: |
python3 -m unittest tests/test_csharp_query_source_mode_policy.py
python3 -m unittest tests/test_csharp_query_calibration_refresh_wrapper.py
python3 examples/benchmark/refresh_csharp_query_source_mode_calibration.py --dry-run
python3 -m unittest tests/test_csharp_query_scan_calibration_refresh_wrapper.py
python3 examples/benchmark/refresh_csharp_query_scan_source_mode_calibration.py --dry-run
python3 -m unittest tests/test_csharp_query_calibration_ci_contract.py
python3 -m unittest tests/test_csharp_query_policy_report_ci_contract.py
python3 -m unittest tests/test_csharp_query_policy_review_wrapper.py
python3 examples/benchmark/review_csharp_query_effective_distance_policy.py --dry-run
- name: Set up .NET (for F# WAM target tests)
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Install Python test dependencies (LMDB + grounded graph diffusion)
run: python3 -m pip install --user lmdb "numpy>=1.24" pytest
- name: Run grounded semantic diffusion tests
run: |
python3 -m pytest -q tests/test_leaky_diffusion.py \
tests/test_local_grounded_diffusion.py
python3 prototypes/mu_cosine/benchmark_local_grounded_diffusion.py --smoke
- name: Run filing path decoder Stage A tests
# Stage A is provenance/schema logic over a routed-task.v2 parent: it
# needs only numpy (via routed_policy) and pytest, no embedder, no
# corpus. The other mu_cosine suites import the filing/embedding stack
# and stay out of CI for that reason.
run: |
python3 -m pytest -q prototypes/mu_cosine/test_filing_path_decision.py
- name: Run process-expression contract fixture tests
# Identity helpers plus the frozen AST/token/role-path golden vectors.
# The modules under test import only process_cards; the suite also
# imports process_expression_p1_protocol in one test, to prove the
# digest matches the frozen P1 convention, which pulls numpy via
# routed_policy. numpy is installed above. No embedder, torch, or
# corpus either way.
run: |
python3 -m pytest -q prototypes/mu_cosine/test_process_expression_contract.py \
prototypes/mu_cosine/test_process_expression_envelope.py \
prototypes/mu_cosine/test_process_cards.py \
prototypes/mu_cosine/test_process_expression_p1_protocol.py \
prototypes/mu_cosine/test_process_expression_vnext_frontend.py \
prototypes/mu_cosine/test_process_expression_vnext_patterns.py \
prototypes/mu_cosine/test_process_expression_tokenizer.py \
prototypes/mu_cosine/test_registry_v04_obligations.py \
prototypes/mu_cosine/test_registry_v04_migration.py \
prototypes/mu_cosine/test_registry_v04_stage5.py \
prototypes/mu_cosine/test_process_expression_enumerator.py \
prototypes/mu_cosine/test_process_expression_split.py \
prototypes/mu_cosine/test_registry_v05_migration.py
- name: Run F# WAM target tests (codegen + dotnet smoke + LMDB conformance)
env:
DOTNET_CLI_TELEMETRY_OPTOUT: '1'
DOTNET_NOLOGO: '1'
# Belt-and-suspenders: the generated fsproj targets net8.0 and
# setup-dotnet installs the matching runtime, but Major roll-forward
# keeps the dotnet legs launchable if the runner's SDK ever drifts.
DOTNET_ROLL_FORWARD: 'Major'
run: |
swipl -q -g main -t halt tests/run_wam_fsharp_tests.pl
- name: Run root-metric prototype tests (scoping + node-DP + query)
# One step on purpose: these four modules build tiny hand-checked LMDB
# fixtures (diamond/tree DAGs) and finish in ~1.7s total, each skipping
# when python-lmdb is absent. Folded into a single unittest invocation
# to avoid per-step runner overhead. The materialisers under test live
# in benchmarks/root-metrics/prototype/ (hand-coded pending generation
# from the root_metric/2 directive); see that dir's README.
run: |
python3 -m unittest \
tests.test_build_scoped_subtree_lmdb \
tests.test_query_root_metric \
tests.test_effective_distance_nodedp \
tests.test_max_distance_nodedp
- name: Run root-metric query tool test
run: |
python3 -m unittest tests.test_query_root_metric
- name: Run effective-distance node-DP test
run: |
python3 -m unittest tests.test_effective_distance_nodedp
- name: Run WAM Rust matrix-bench demand-flag codegen test
run: |
python3 -m unittest tests.test_wam_rust_matrix_demand_flag
- name: Generate and run inference test runner
run: |
swipl -g "use_module('src/unifyweaver/core/advanced/test_runner_inference'), generate_test_runner_inferred('output/advanced/inferred_test_runner.sh'), halt."
chmod +x output/advanced/inferred_test_runner.sh
cd output/advanced && bash inferred_test_runner.sh
- name: Validate generated bash scripts (syntax check)
run: |
for script in output/advanced/*.sh; do
if [ -f "$script" ]; then
echo "Checking syntax: $script"
bash -n "$script" || exit 1
fi
done
- name: Run visualization glue tests (478 tests)
run: |
swipl -g "consult('tests/integration/glue/test_visualization_glue.pl'), run_tests, halt(0)" -t "halt(1)"
- name: Test summary
if: always()
run: |
echo "=========================================="
echo "UnifyWeaver Test Suite Complete"
echo "=========================================="
echo "✓ Constraint analyzer tests"
echo "✓ Stream compiler tests"
echo "✓ Recursive compiler tests"
echo "✓ Advanced recursion tests (24/24)"
echo "✓ Constraint integration tests"
echo "✓ Control plane tests (5/5)"
echo "✓ F# WAM target tests (codegen + dotnet smoke + LMDB conformance)"
echo "✓ Inference test runner generation"
echo "✓ Generated bash script validation"
echo "✓ Visualization glue tests (478 tests)"
echo "=========================================="
wam_conformance_smoke:
name: WAM Conformance Smoke (${{ matrix.target }})
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
target: [scala, elixir, wat, haskell, python, go, rust, c, cpp]
env:
CONFORMANCE_TARGETS: ${{ matrix.target }}
CONFORMANCE_PROGRAMS: member,builtins
CONFORMANCE_SAMPLE: 2
CONFORMANCE_SEED: ${{ github.run_number }}
UW_SMOKE_TMPDIR: /tmp/unifyweaver-smoke
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install SWI-Prolog
run: bash scripts/ci/install_swi_prolog.sh
- name: Create smoke temp root
run: mkdir -p "$UW_SMOKE_TMPDIR"
- name: Run sampled WAM conformance
run: |
swipl -q -f init.pl -s tests/test_wam_cross_target_conformance.pl -g "seed_sampler,run_tests" -t halt
wam_r_conformance:
name: WAM R Conformance (interpreter + functions)
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 30
env:
CONFORMANCE_TARGETS: r,r_functions
CONFORMANCE_PROGRAMS: member,fib,ack,append,reverse,builtins
UW_SMOKE_TMPDIR: /tmp/unifyweaver-smoke
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install SWI-Prolog
run: bash scripts/ci/install_swi_prolog.sh
- name: Install R
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends r-base-core
- name: Create smoke temp root
run: mkdir -p "$UW_SMOKE_TMPDIR"
- name: Run R focused regressions (switch-index + LMDB)
run: |
swipl -q -f init.pl -s tests/test_wam_r_generator.pl -g "run_tests([wam_r_generator:switch_on_constant_fallthrough_is_linear_noop,wam_r_generator:switch_on_term_a2_is_switch_on_term_noop,wam_r_generator:switch_on_constant_fallthrough_preserves_backtracking,wam_r_generator:r_a2_switch_hints_are_linear_noop,wam_r_generator:r_a2_fallthrough_preserves_backtracking,wam_r_generator:lmdb_r0_source_dispatch_selection,wam_r_generator:lmdb_arg1_v1_mock_adapter_lookup_and_stream,wam_r_generator:lmdb_arg1_v1_real_binding_e2e_rscript,wam_r_generator:lmdb_r1_materialisation_codegen,wam_r_generator:lmdb_r1_eager_lazy_runtime_parity,wam_r_generator:lmdb_r2a_cached_codegen,wam_r_generator:lmdb_r2a_cached_runtime,wam_r_generator:lmdb_r2b_auto_materialisation_codegen])" -t halt
- name: Run R ISO-R-0 unit + smoke
run: |
swipl -q -f init.pl -s tests/test_wam_r_iso_unit.pl -g "run_tests, halt" -t "halt(1)"
swipl -q -f init.pl -s tests/test_wam_r_iso_smoke.pl -g main -t halt
- name: Run R effective-distance generator + runtime smoke
run: |
swipl -q -f init.pl -s tests/test_wam_r_effective_distance_generator.pl -g "run_tests, halt" -t "halt(1)"
- name: Run R aggregate lowering contract suite
run: |
swipl -q -f init.pl -s tests/test_wam_r_aggregate_lower.pl -g "run_tests, halt" -t "halt(1)"
- name: Run R bulk-reduce plan contract suite
run: |
swipl -q -f init.pl -s tests/test_wam_r_bulk_reduce_plan.pl -g "run_tests, halt" -t "halt(1)"
- name: Run R direct arg1 lookup contract suite
run: |
swipl -q -f init.pl -s tests/test_wam_r_ca_direct_lookup.pl -g "run_tests, halt" -t "halt(1)"
- name: Run R native CA hop kernel contract suite
run: |
swipl -q -f init.pl -s tests/test_wam_r_native_hops.pl -g "run_tests, halt" -t "halt(1)"
- name: Run full R classic conformance
run: |
swipl -q -f init.pl -s tests/test_wam_cross_target_conformance.pl -g "run_tests" -t halt
csharp_query_runtime_smoke:
name: C# Query Runtime Smoke
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 45
env:
CSHARP_QUERY_SMOKE_OUTPUT_DIR: tmp/csharp_query_smoke_ci
CSHARP_QUERY_SMOKE_SUMMARY_PATH: tmp/csharp_query_smoke_ci/cache_smoke_sequence_summary.md
CSHARP_QUERY_SMOKE_JSON_SUMMARY_PATH: tmp/csharp_query_smoke_ci/cache_smoke_sequence_summary.json
CSHARP_QUERY_SMOKE_FAILURE_ARTIFACT_NAME: csharp-query-smoke-artifacts
CSHARP_QUERY_SMOKE_JSON_ARTIFACT_NAME: csharp-query-smoke-summary-json
# Pin the Prolog harness's TargetFramework probe to the SDK installed
# by the setup-dotnet step below, so generated .csproj's land their
# build output in a predictable bin/Debug/<framework>/ directory.
# The PS smoke runner now discovers the framework dir at runtime
# too, but pinning makes it deterministic regardless of which
# SDKs the runner has pre-installed.
UNIFYWEAVER_DOTNET_FRAMEWORK: net9.0
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install SWI-Prolog
run: bash scripts/ci/install_swi_prolog.sh
- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Verify toolchain
run: |
swipl --version
dotnet --version
pwsh -v
- name: Run C# query cache smoke sequence
run: |
pwsh -NoProfile -File scripts/testing/run_csharp_query_cache_smoke_sequence.ps1 -OutputDir "$CSHARP_QUERY_SMOKE_OUTPUT_DIR" -SummaryPath "$CSHARP_QUERY_SMOKE_SUMMARY_PATH"
- name: Upload C# query smoke artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: ${{ env.CSHARP_QUERY_SMOKE_FAILURE_ARTIFACT_NAME }}
path: ${{ env.CSHARP_QUERY_SMOKE_OUTPUT_DIR }}
if-no-files-found: ignore
retention-days: 7
- name: Upload C# query smoke JSON summary
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ env.CSHARP_QUERY_SMOKE_JSON_ARTIFACT_NAME }}
path: ${{ env.CSHARP_QUERY_SMOKE_JSON_SUMMARY_PATH }}
if-no-files-found: ignore
retention-days: 7
- name: Summarize C# query cache smoke slices
if: always()
shell: pwsh
run: |
if (Test-Path $env:CSHARP_QUERY_SMOKE_SUMMARY_PATH) {
Get-Content $env:CSHARP_QUERY_SMOKE_SUMMARY_PATH | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
} else {
@(
"## C# Query Runtime Smoke",
"",
"- Summary file not found at `"$($env:CSHARP_QUERY_SMOKE_SUMMARY_PATH)`""
) | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
}
@(
"",
"### Artifacts",
"",
"- JSON summary artifact: `"$($env:CSHARP_QUERY_SMOKE_JSON_ARTIFACT_NAME)`"` (uploaded on every run)",
"- Full smoke output artifact: `"$($env:CSHARP_QUERY_SMOKE_FAILURE_ARTIFACT_NAME)`"` (uploaded on failure only)"
) | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append