diff --git a/README.md b/README.md index 544f68eb..f76644dc 100644 --- a/README.md +++ b/README.md @@ -543,7 +543,7 @@ clean checkout (`frontend/`): | Lint (tsc semantics + shell) | `scripts/check-lint.sh` | gated | CI runs the same gates (see `.github/workflows/ci.yml`: repo-hygiene job, -then the pinned Julia/frontend matrix). Contributor setup, commit and +then the pinned Julia and frontend jobs). Contributor setup, commit and branch conventions: `CONTRIBUTING.md`. Frontend reproducibility: `docs/reproducibility.md`. Type estate map: `docs/types/architecture.md`. Test inventory and metrics: `docs/testing/coverage.md`. diff --git a/docs/audit/type-system-reconnaissance.md b/docs/audit/type-system-reconnaissance.md index fb40a597..4e7112ee 100644 --- a/docs/audit/type-system-reconnaissance.md +++ b/docs/audit/type-system-reconnaissance.md @@ -207,7 +207,7 @@ Observations on settings (facts, with contrast against actual code): (`apt_version: 4.5.0-3.2404.0`), Bioconductor 3.22, cutadapt 5.2, MultiQC 1.33, FastQC 0.12.1, vsearch/swarm/cd-hit with SHA-256-verified archives. `test/unit/test_install_pins.jl` exists to fail CI if the pin - file, `Manifest.toml`, and the CI matrix disagree. + file, `Manifest.toml`, and the `ci.yml` setup-julia step disagree. --- diff --git a/docs/compliance/standards-alignment.md b/docs/compliance/standards-alignment.md index ecbb3d0e..447699f2 100644 --- a/docs/compliance/standards-alignment.md +++ b/docs/compliance/standards-alignment.md @@ -37,7 +37,7 @@ Reference: `hyperpolymath/standards@main` (in particular | `mise.toml` toolchain manifest, pinned to CI versions, every name verified against the registry (estate doctrine from rsr-template) | `mise.toml` — julia 1.12.5 / bun 1.3.10 / node 20.20.2 / just 1.43.1, all confirmed resolvable 2026-09-18; R absent from registry → documented system exception | ✅ | | Guix development environment (`guix.scm`, per estate REQUIRED-FILES) | `guix.scm` (dev-shell inputs: julia, r, node-lts, just, git + pipeline-tool equivalents cutadapt/multiqc/fastqc/vsearch/cd-hit; swarm documented as download-lane-only) + `channels.scm` time-machine pin (guix master 2026-09-18; `just` input sighted live at the pinned commit) | ✅ recreation on hosts/CI | | Pipeline tools byte-exact | `config/defaults/tool_versions.yml` (version + URL + sha256-of-archive per tool) fetched by `install.sh`; preflight asserts against it | ✅ upstream-designed, fork-verified | -| Pin single-sourcing (codegen, minimal duplication) | `.bun-version` is generated from `mise.toml` by `just sync-pins`; overlap copies (`tool_versions.yml`, `ci.yml` matrix) are drift-checked, not generated | ✅ `coupling-toolchain-pins` test gates it | +| Pin single-sourcing (codegen, minimal duplication) | `.bun-version` is generated from `mise.toml` by `just sync-pins`; overlap copies (`tool_versions.yml`, the `ci.yml` setup-julia step) are drift-checked, not generated | ✅ `coupling-toolchain-pins` test gates it | | direnv auto-activation (`.envrc`) | `.envrc` — mise lane first, Guix fallback, `METAMANIFOLD_REPO_DIR` export | ✅ | | Single command to stand up a bare machine | `curl https://mise.run \| sh && just bootstrap` (or the time-machine one-liner) → `just ci` green from a naked env (evidence logged in `docs/reproducibility.md`) | ✅ verified 2026-09-18 | diff --git a/docs/reproducibility.md b/docs/reproducibility.md index be68fb1f..fee9c74e 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -23,7 +23,7 @@ either lane automatically via direnv. | Component | Pin | Pinned where | Verified | |---|---|---|---| -| Julia | **1.12.5** (exact) | `mise.toml` + CI matrix | `mise install` → `julia version 1.12.5` | +| Julia | **1.12.5** (exact) | `mise.toml` + the `ci.yml` setup-julia step | `mise install` → `julia version 1.12.5` | | Bun | **1.3.10** (exact) | `.bun-version` (CI reads the same file) + `mise.toml` | `mise x -- bun --version` → `1.3.10` | | Node | **20.20.2** (LTS) | `mise.toml` | `mise x -- node --version` → `v20.20.2` | | just | **1.43.1** | `mise.toml` | `mise x -- just --version` → `just 1.43.1` | @@ -57,7 +57,7 @@ The guix inputs' versions follow the channels pin, **not** | Value | Source of truth | Generated copies | Checked copies | |---|---|---|---| | bun version | `mise.toml` | `.bun-version` — generated by **`just sync-pins`** (codegen; CI consumes it via `bun-version-file`) | `tool_versions.yml` (fork-owned overlap) | -| julia version | `mise.toml` | — | `tool_versions.yml`, `ci.yml` matrix | +| julia version | `mise.toml` | — | `tool_versions.yml`, the `ci.yml` setup-julia step | | node / just versions | `mise.toml` | — | — (single-sourced by design) | | tool set versions | `tool_versions.yml` (upstream-declared SOT, checksum-bearing) | — | — | diff --git a/frontend/tests/unit/coupling-toolchain-pins.test.ts b/frontend/tests/unit/coupling-toolchain-pins.test.ts index e8996ea4..29aa096c 100644 --- a/frontend/tests/unit/coupling-toolchain-pins.test.ts +++ b/frontend/tests/unit/coupling-toolchain-pins.test.ts @@ -10,7 +10,11 @@ // consumed by CI via bun-version-file // config/defaults/tool_versions.yml — upstream pipeline-pin SOT holding // overlapping julia/bun copies -// .github/workflows/ci.yml — hardcoded julia matrix entry +// .github/workflows/ci.yml — hardcoded julia version on the setup-julia +// step. It was a 1x1 `strategy.matrix` until 2026-09-21; +// the matrix was removed because GitHub appends the +// matrix combination to the posted check name, which +// renamed the required status check on every bump. // A bump in any one copy without the others is silent CI/local divergence; // this test makes it a build-time failure instead. import { describe, test, expect } from 'bun:test' @@ -40,10 +44,14 @@ describe('coupling/drift: toolchain pins agree across all copies', () => { expect(toolVersionsPin('bun')).toBe(pin) }) - test('julia: mise.toml == tool_versions.yml == CI matrix', () => { + test('julia: mise.toml == tool_versions.yml == CI setup-julia step', () => { const pin = misePin('julia') expect(toolVersionsPin('julia')).toBe(pin) - const ci = read('.github/workflows/ci.yml').match(/julia-version:\s*\["([^"]+)"\]/) + // Anchored on the action rather than on a bare `version:` key, so this + // cannot silently latch onto some other step's version and pass for the + // wrong reason. A missing anchor yields undefined, which fails loudly. + const ci = read('.github/workflows/ci.yml') + .match(/julia-actions\/setup-julia@[0-9a-f]{40}[\s\S]*?version:\s*"([^"]+)"/) expect(ci?.[1]).toBe(pin) })