1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
name: CI
on:
push:
branches:
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
fmt:
name: cargo fmt --check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --check
clippy:
name: cargo clippy (${{ matrix.features == '' && 'default' || matrix.features }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Same reasoning as build-and-test's matrix below: each feature config is its own
# compilation unit (see Cargo.toml's [features]), so each needs its own clippy pass, not
# just a single default-feature run.
features:
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
key: clippy-${{ matrix.features }}
- run: cargo clippy --tests --features "${{ matrix.features }}" -- -D warnings
audit:
name: cargo audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: audit
- run: cargo install cargo-audit --locked
# RUSTSEC-2026-0195/-0194 (quick-xml, pulled in via syntect -> plist): both are DoS vectors
# in untrusted-XML parsing. codediff only ever calls syntect's ThemeSet::load_defaults()
# (bundled themes baked into the syntect binary - see src/tui/widgets/code_viewer.rs), never
# feeds any external/user-supplied plist/XML into it, so this code path is unreachable here.
# Can't fix directly: syntect 5.3.0 (latest as of this writing) pins plist ~1.9, which pins
# the vulnerable quick-xml; blocked on syntect bumping its own plist dependency upstream.
# Re-check by removing these --ignore flags occasionally.
- run: cargo audit --ignore RUSTSEC-2026-0195 --ignore RUSTSEC-2026-0194
mapping-site-js:
name: human_mapping site JS tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
# Both scripts. viewer.js is the larger of the two and went untested until 2026-08-27; see
# the Makefile's `test-mapping-site-js` target for what these do and do not cover.
- run: node assets/mapping_site/index.test.js
- run: node assets/mapping_site/viewer.test.js
# The analysis scripts under research/ compute the numbers that go into the papers, and until
# 2026-08-27 nothing checked them at all while the Rust half had clippy -D warnings across three
# feature configs. The ruff version is pinned for the same reason the rule set is pinned in
# research/pyproject.toml: an unpinned linter turns CI red on a day nobody touched the code.
python-lint:
name: ruff (research/)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: astral-sh/ruff-action@v3
with:
version: 0.16.4
args: check
src: research
- uses: astral-sh/ruff-action@v3
with:
version: 0.16.4
args: format --check
src: research
# The release gate, run on every push rather than only at deploy time - a regression is far
# cheaper to find on the commit that caused it than in the middle of a release. Safe to gate in
# CI because it is algorithm-only: mismatch counts against the human mapping do not vary by
# machine (unlike the runtime figure, which `make check-quality` only warns on).
quality:
name: quality gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: quality
- run: make check-quality
build-and-test:
name: build + test (${{ matrix.features == '' && 'default' || matrix.features }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# "" = default features (tui only). test-fixtures and stats are each their own
# compilation unit - see Cargo.toml's [features] - so each needs its own build+test pass,
# not just a single default-feature run.
features:
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.features }}
- name: Build
run: cargo build --release --features "${{ matrix.features }}"
- name: Test
run: cargo test --release --features "${{ matrix.features }}"