diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbac0df..a53b601 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,35 @@ env: JULIA_VERSION: '1.12.6' jobs: + changes: + runs-on: ubuntu-latest + outputs: + execution: ${{ steps.diff.outputs.execution }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: {fetch-depth: 0} + - name: Select execution checks from the whole PR diff + id: diff + env: + EVENT: ${{ github.event_name }} + BASE: ${{ github.event.pull_request.base.sha }} + HEAD: ${{ github.event.pull_request.head.sha }} + shell: bash + run: | + execution=true + if [[ "$EVENT" == pull_request ]] && git cat-file -e "$BASE^{commit}" && git cat-file -e "$HEAD^{commit}"; then + git diff --no-renames --name-only -z "$BASE...$HEAD" > "$RUNNER_TEMP/localmath-changed-paths" + execution=false + while IFS= read -r -d '' path; do + case "$path" in + AGENTS.md|CONTRIBUTING.md|README.md|LICENSE|CITATION.cff|spec/*.md|design/*.md) ;; + *) execution=true; break ;; + esac + done < "$RUNNER_TEMP/localmath-changed-paths" + fi + printf 'execution=%s\n' "$execution" >> "$GITHUB_OUTPUT" + git rev-parse HEAD + package: runs-on: ubuntu-latest steps: @@ -28,8 +57,13 @@ jobs: run: julia --project=. --startup-file=no -e 'using Pkg; Pkg.instantiate(); Pkg.test(; test_args=["--jobs=2", "--verbose"])' scientific: + needs: changes + if: always() && (needs.changes.result != 'success' || needs.changes.outputs.execution != 'false') runs-on: ubuntu-latest steps: + - name: Require a valid change selection + if: needs.changes.result != 'success' || (needs.changes.outputs.execution != 'true' && needs.changes.outputs.execution != 'false') + run: exit 1 - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: julia-actions/setup-julia@fa02766e078afaaf09b14210362cee14137e6a32 # v3 with: {version: '${{ env.JULIA_VERSION }}'} @@ -38,6 +72,7 @@ jobs: run: julia --project=test/scientific_witnesses --startup-file=no -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate(); include("test/scientific_witnesses/runtests.jl")' macos-smoke: + if: github.event_name == 'pull_request' runs-on: macos-15 steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 @@ -69,8 +104,13 @@ jobs: run: julia --project=docs --startup-file=no -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate(); include("docs/make.jl")' metal: + needs: changes + if: always() && (needs.changes.result != 'success' || needs.changes.outputs.execution != 'false') runs-on: macos-15 steps: + - name: Require a valid change selection + if: needs.changes.result != 'success' || (needs.changes.outputs.execution != 'true' && needs.changes.outputs.execution != 'false') + run: exit 1 - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: julia-actions/setup-julia@fa02766e078afaaf09b14210362cee14137e6a32 # v3 with: {version: '${{ env.JULIA_VERSION }}'} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 60290ec..0360e16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -135,29 +135,36 @@ julia --project=docs -e 'using Pkg; Pkg.instantiate()' julia --project=docs docs/make.jl ``` -The manual executes bounded serial Wortel and Merks integration programs. The -separate Makie package and backend suites exercise rendering; the published- -model documentation does not claim to render figures or reproduce the papers. +The manual executes LocalMath examples for relations, storage, scientific +recipes and domain compilers. Complete CPM models belong to PottsModels; +visualization belongs to MakiePotts. ## Continuous integration -Pull requests target the four package suites, independently runnable -integration families, applicable platform installation smokes, and the active -documentation build. Real-GPU hardware tests are manual commands when suitable -hardware is available; the hosted workflow does not currently provide Metal -hardware. Benchmarks remain diagnostic and are run when their measured path -changes. +Every pull request runs the complete owning package suite and strict manual +build. Scientific and real-Metal checks run unless the whole PR diff contains +only the explicitly listed non-executable prose/metadata paths. Unknown paths, +executable documentation, source, tests, examples and dependency/workflow changes +retain the broader checks. Manual dispatch and main pushes run those checks too. +The workflow records the selected checkout revision; dispatch can select a +candidate branch without changing main. Ordinary dependency compatibility stays +broad rather than becoming an exact-replay claim. + +Hosted `macos-15` runners execute the Metal suite, which rejects unavailable +hardware. PRs run the macOS API smoke; main and manual runs use the complete +macOS suite instead of duplicating that smoke. Benchmarks remain diagnostic +and run when their measured path changes. Run real-Metal semantic tests independently from performance measurements: ```sh -julia --project=benchmark/backends/metal --startup-file=no benchmark/backends/metal/runtests.jl +julia --project=test/metal --startup-file=no -e 'using Pkg; Pkg.develop(path="."); Pkg.instantiate(); include("test/metal/runtests.jl")' ``` -The runner includes the active semantic, parity, lifecycle, native-component, -and extension-load witnesses; performance campaigns remain separate. Use the repository Julia version for these commands. The root `.julia-version`, -root manifest, and Metal manifest all select Julia 1.12.6; do not invoke the -Metal environment through a separate Julia release channel. +The runner includes LocalMath stage, publication, correctness and scientific +recipe witnesses; performance campaigns remain separate. Use Julia 1.12.6 for +this Metal profile. The runner owns the test inventory; do not duplicate it in +a separate orchestration script. Current specifications and decisions live under `spec/`. Historical interviews and evidence under `design/audits/`, and retired qualification scripts under `scripts/archive/`, document earlier