name: CI # The QUICKSTART requires Agent F's conformance suite to run in CI "from the day # Agent A lands" — it is the architecture's tripwire. This workflow runs the # whole workspace's checks plus the testkit's conformance suite on every push and # pull request. on: push: branches: [main, master] pull_request: schedule: # Nightly soak at 04:17 UTC. - cron: "17 4 * * *" env: CARGO_TERM_COLOR: always RUSTFLAGS: -D warnings # Every blocking job pins an exact toolchain. With `-D warnings` and a # floating `stable`, a Rust release turns this gate red with no repo change — # which is exactly how it first failed, eight days after 1.97.1 added # `float_literal_f32_fallback`. Worse, the developer machine cannot install # arbitrary toolchains, so such a failure is unreproducible locally and the # local gate stops meaning anything. Pinned here to the version developed # against; bump it deliberately, as its own commit, with the lints it # introduces fixed in that commit. The nightly soak floats on `stable` and is # the drift detector. PINNED_STABLE: "1.95.0" jobs: # Style and lint policy runs on exactly ONE toolchain, the pinned stable. # # It used to run on the MSRV toolchain as well, and that is not a stricter # gate — it is a different one. Two clippy versions have two lint sets, and # they can disagree in opposite directions: clippy 1.85 demands # `.and_then(seg_pos)` where 1.95 is silent, while 1.97 rejects a bare `2.0` # that 1.95 accepts. Satisfying the union is not a quality bar, it is a # coincidence, and no developer can reproduce it locally without installing # every toolchain in the matrix. Lints here; the MSRV job proves the floor # compiles and passes its tests, which is the only thing an MSRV can mean. lint: name: fmt / clippy / doc (pinned stable) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust (pinned stable) uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ env.PINNED_STABLE }} components: rustfmt, clippy - name: Install GUI build dependencies run: | sudo apt-get update sudo apt-get install -y \ libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \ libxkbcommon-dev libssl-dev - name: Cache cargo uses: Swatinem/rust-cache@v2 - name: Formatting run: cargo fmt --all -- --check # The whole workspace, GUI crate included: on the pinned stable there is # no toolchain reason to split it out. - name: Clippy (all targets) run: cargo clippy --workspace --all-targets -- -D warnings # Deny rustdoc warnings (broken/private intra-doc links, etc.). `RUSTFLAGS` # does not cover rustdoc, so `RUSTDOCFLAGS` is set explicitly. - name: Doc warnings (workspace) env: RUSTDOCFLAGS: -D warnings run: cargo doc --workspace --no-deps # The floor, and only the floor: does the code this repository claims to # support on 1.85 actually build and pass its tests there? No lints — see the # `lint` job's comment. check: name: MSRV build + test (1.85) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust (pinned MSRV) uses: dtolnay/rust-toolchain@stable with: toolchain: "1.85" - name: Cache cargo uses: Swatinem/rust-cache@v2 # The demo GUI crate (eframe/resvg) pulls `image`, which declares 1.88, so # it cannot build at the floor and is excluded here. It is linted in # `lint` and tested in `editor-gui`, both on the pinned stable. - name: Test (workspace) run: cargo test --workspace --exclude epiphany-editor-gui --all-targets - name: Doc tests run: cargo test --workspace --exclude epiphany-editor-gui --doc # The demo GUI crate's tests, kept as their own job so a GUI break is its own # attributable signal rather than a regression buried in the core crates. Its # eframe/resvg tree pulls `image`, which declares 1.88 — three releases above # the workspace floor — so it cannot run in the MSRV job. Linting for this # crate lives in `lint` with the rest of the workspace. editor-gui: name: editor GUI tests (pinned stable) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust (pinned stable) uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ env.PINNED_STABLE }} - name: Install GUI build dependencies run: | sudo apt-get update sudo apt-get install -y \ libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \ libxkbcommon-dev libssl-dev - name: Cache cargo uses: Swatinem/rust-cache@v2 - name: Test (GUI) run: cargo test -p epiphany-editor-gui # Assertion-message artifact paths (`target/golden-failures//actual.png` # etc.) name the ephemeral runner's filesystem — a local-reproduction aid, not # a reviewable record on CI. This is the reviewable record: on a golden # mismatch, the three per-test images (actual/expected/diff) upload so a # reviewer can see the failure without reproducing it locally. - name: Upload golden failure artifacts if: failure() uses: actions/upload-artifact@v4 with: name: golden-failures path: target/golden-failures/ if-no-files-found: ignore conformance: name: conformance suite (testkit) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ env.PINNED_STABLE }} - name: Cache cargo uses: Swatinem/rust-cache@v2 # The full conformance suite at scale 1: Agent A's 1,000,000-iteration # determinism gate, the round-trip corpus, the crash-recovery and # manifest-selection gates, convergence / reduction-determinism / # equivocation against the real epiphany-ops, and the layout round-trip. - name: Run conformance suite run: cargo run --release -p epiphany-testkit --example conformance_suite 1 # The Chapter 10 performance-budget gates (Phase 2 worklist F1), in # release with reduced sampling (EPIPHANY_BENCH_QUICK): the 1K and 10K # reduction points and both bundle budgets must pass; known-pending # points are documented xfails inside the benches ("F surfaces, K # fixes"). The heaviest (50K) reduction point runs only in the nightly # soak below. - name: Performance budget gates (quick) env: EPIPHANY_BENCH_QUICK: "1" run: cargo bench -p epiphany-testkit # Track A, Agent H's merge gate (Phase 2). A discrete job so a spelling / # decomposition pre-pass regression is attributable to H, not buried in the # workspace test run. Asserts H's PHASE2_QUICKSTART acceptance criterion: the # representative-corpus eligibility taxonomy (F3) and the pre-pass harness (F4 — # determinism, spelling correctness, decomposition reconstruction, RespellPitch # precedence, non-vacuity). The same gate also runs inside the conformance # suite's stage [7b]; this job isolates it for fast, attributable feedback. prepass-harness: name: Agent H pre-pass gate (testkit) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ env.PINNED_STABLE }} - name: Cache cargo uses: Swatinem/rust-cache@v2 - name: H spelling + decomposition merge gate run: cargo test -p epiphany-testkit --test prepass # A longer soak, scheduled nightly, exploring a wider seed space at scale. # This job deliberately floats on `stable` while every blocking job is pinned: # it is where toolchain drift surfaces, on a schedule, instead of in a push # that has nothing to do with it. A red soak against a green push means Rust # moved, not that the change did. soak: name: conformance soak (nightly) if: github.event_name == 'schedule' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Run conformance soak run: cargo run --release -p epiphany-testkit --example conformance_suite 10 # The full budget-gate run, including the minute-scale 50K reduction # point (a documented xfail until the O(n²) reducer fix lands). - name: Performance budget gates (full) run: cargo bench -p epiphany-testkit