Skip to content

feat(vigil): core runtime and --vigil-once headless driver (slice 2 of 5) #2482

feat(vigil): core runtime and --vigil-once headless driver (slice 2 of 5)

feat(vigil): core runtime and --vigil-once headless driver (slice 2 of 5) #2482

Workflow file for this run

name: CI
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
rustfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
components: rustfmt
- name: Check formatting
run: cargo fmt --all --check
# dirge-clippy: lint gate. CI already promotes rustc warnings to errors
# via the top-level `RUSTFLAGS: "-D warnings"`, but clippy was never run,
# so clippy lints (incl. the deny-by-default `correctness` group) had no
# gate and accumulated. We lint the two configs CI actually ships:
# the batteries-included default set, and the Janet-free `windows-default`
# set (the only non-`plugin` / `loop` code path). `-D warnings` fails the
# build on any clippy lint. `sandbox-microvm` is linted too: it was skipped
# as needing native deps, but clippy only checks and never links, so libkrun
# / libkrunfw are not required — build.rs just warns and carries on, exactly
# as the existing `build (sandbox-microvm)` job already does. Without this
# gate the feature accumulated 50 findings unnoticed (dirge-xw43), and
# `--all-features` had gone the same way by the time it was measured — 17
# findings across 8 files (dirge-9m05).
#
# `--all-features` is one step rather than one per feature: it subsumes `dap`,
# `plugin`, `semantic` and the rest, and `--features dap` alone was clean once
# the all-features findings were fixed. The three narrower configs stay
# because `--all-features` cannot reach a `cfg(not(feature = …))` path —
# `windows-default` in particular is subtractive, not additive.
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
components: clippy
- name: Clippy (default features)
run: cargo clippy --all-targets -- -D warnings
- name: Clippy (windows-default)
run: cargo clippy --no-default-features --features windows-default --all-targets -- -D warnings
- name: Clippy (sandbox-microvm)
run: cargo clippy --features sandbox-microvm --all-targets -- -D warnings
- name: Clippy (all features)
run: cargo clippy --all-features --all-targets -- -D warnings
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# Shared with the Release workflow's `preflight` gate — see
# .github/actions/audit. Keep the steps there, not here, so the gate
# cannot drift from what CI actually runs.
- uses: ./.github/actions/audit
# The `validate_all_plugins_compile` Rust test (mod_tests.rs) loads every
# plugin against the full dirge harness surface. It runs in the
# --all-features test variant below. That's the canonical gate; there is
# no standalone janet -k check because the plugins reference harness/* and
# dap/* symbols that only exist inside the dirge Janet runtime.
#
# dirge-9wtb: feature matrix.
#
# Default `cargo build` only compiles the code paths reachable
# with no optional features. Optional features (acp/plugin/lsp
# /loop/mcp/semantic-*) each open a separate code path the
# default build never sees. We've already had two regressions
# slip through this gap: ACP broke when build_agent gained
# session_id, plugin_hooks_tests broke when run_agent_loop
# gained memory_provider. The matrix below catches the next
# one before merge.
#
# Strategy: one job per logical feature group + one all-features
# job that exercises feature interaction. RUSTFLAGS="-D warnings"
# promotes warnings to errors so dead-code regressions also
# fail CI instead of silently accumulating.
build:
name: build (${{ matrix.name }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: default
features: ""
- name: acp
features: "--features acp"
- name: plugin
features: "--features plugin"
- name: dap
features: "--features dap,plugin"
- name: mcp
features: "--features mcp"
- name: lsp
features: "--features lsp"
- name: loop+git-worktree
features: "--features loop,git-worktree"
- name: semantic-bash
features: "--features semantic-bash"
- name: sandbox-microvm
features: "--features sandbox-microvm"
- name: all-features
features: "--all-features"
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Build
run: cargo build --bin dirge ${{ matrix.features }}
# nextest runs the suite in parallel per-test-process; faster and
# clearer failures than `cargo test` on our ~4400-test suite. dirge
# is a bin-only crate (no lib), so `cargo test --bin` never ran
# doctests and nextest drops no coverage. Installed via prebuilt
# binary only on the variants that actually test.
- name: Install nextest
if: matrix.name == 'default' || matrix.name == 'plugin' || matrix.name == 'dap' || matrix.name == 'all-features'
uses: taiki-e/install-action@v2
with:
tool: nextest
- name: Test
# Skip tests for matrix variants where `cargo build` alone
# is the canary — they share most code with the default
# config, and running every test suite per variant doubles
# CI time without commensurate coverage gain. Run tests on
# default, plugin (covers plugin-only hook tests), and
# all-features (worst-case interaction).
if: matrix.name == 'default' || matrix.name == 'plugin' || matrix.name == 'dap' || matrix.name == 'all-features'
run: cargo nextest run --bin dirge ${{ matrix.features }}
# Windows is only built at release time (release.yml, tag-triggered),
# so platform-specific breakage used to slip through until a release.
# The Janet `plugin` feature can't build on MSVC (evil_janet/_setjmp,
# janetrs fseek i64), so Windows ships the `windows-default` set
# (default minus plugin). Mirror release.yml — BUILD only — to catch
# build regressions in that configuration before they reach a release.
#
# Tests are intentionally NOT run here: the suite still assumes Unix
# semantics (symlinks, `/tmp`, path separators) and fails broadly on
# Windows. Making it Windows-clean is tracked separately; release.yml
# only builds, so build-only coverage matches what actually ships.
windows:
name: build (windows-default)
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Build
run: cargo build --bin dirge --no-default-features --features windows-default
# macOS ships as a release target (aarch64-apple-darwin and
# x86_64-apple-darwin in release.yml, plus a Nix bin.nix platform) and had
# NO CI coverage at all — not build, not test. dirge-u35k: the dead-tty
# watchdog was unusable on macOS in 0.19.24 AND again in 0.19.25, exiting
# 129 within seconds of every TUI startup, and nothing caught it across two
# releases. A first-class target with zero CI is how that happens twice.
#
# Unlike the Windows job this RUNS THE SUITE. The tests assume Unix
# semantics, which macOS has, and the bugs worth catching here are runtime
# behaviour (poll/ioctl/tty semantics differ from Linux) rather than
# compilation. A build-only job would not have caught the watchdog bug.
macos:
name: build (macos)
runs-on: macos-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Build
run: cargo build --bin dirge
- name: Install nextest
uses: taiki-e/install-action@v2
with:
tool: nextest
- name: Test
run: cargo nextest run --bin dirge