Third refactor-induced defect caught from yesterday's v7+v8 →
substrate rename (`bae5caf` for the package, `209d670` for the
Makefile). Same pattern: a callsite that text-search misses
because the import path doesn't connect through Python.
CI surface (the `v8-score:` GitLab CI job) had two issues:
1. Job name `v8-score:` was a UX surface — operators see it in the
GitLab MR pipeline UI. Renamed to `substrate-score:` for
consistency with the package name + the CLI subcommand.
2. Script line called ``.venv/bin/arborist v8 score …``. Would
have failed on the next manual MR pipeline run with an
argparse "invalid choice: 'v8'" error.
Comment block (lines 80-90 + 115-125) refreshed to call out the
distinction: ``v8 paper`` (the substrate-paper version, name
preserved per published convention) vs the module location
(``arborist/substrate/fork_score.py`` post-2026-05-10 rename).
Sweep verified: ``grep -rnE "arborist v[0-9]\\b|arborist\\.v[78]\\b"``
across the entire tree returns only intentional historical-note
comments + the placeholder-seed bytestring derivation (which
cannot change without invalidating KAT vectors).
Three loose ends from one refactor:
- 85be5eb: fork_score.py import (Python imports caught by tests)
- 209d670: Makefile bench-fork-score target (would surface on run)
- this: .gitlab-ci.yml job (would surface on next MR pipeline)
Lesson written across the three commits: text-search-replace on
a CLI rename misses callsites that argparse processes at runtime.
Pre-rename checklist for next time: ``grep -rn "<cli-old-name>"
Makefile .gitlab-ci.yml .github/workflows scripts bench``.
Pipeline was disabled 2026-05-02 because CI runners overlapped
with bench infrastructure. Today the substrate is in a good
state (1,684 passing locally) and the gate has been off long
enough that drift would land silently if reintroduced.
Re-enables the workflow + adds a `test-ci` Makefile target that
skips the wikipedia ingest test files (test_wikipedia_old.py,
test_wikipedia_xml.py). Their runtime path is already exercised
end-to-end by `make ingest-*` against real shards, so the
synthetic fixtures duplicate coverage without adding signal CI
should gate on.
`make test` stays comprehensive for the local dev loop —
1,684 passed there, 1,560 passed under `make test-ci` (the
124-test delta is the wikipedia ingest fixtures).
PYTEST_XDIST_AUTO_NUM_WORKERS=4 still caps the runner's
parallelism so a re-enabled CI doesn't oversubscribe the
shared host or skew live bench latencies on the same pool.
Adds `workflow:rules: - when: never` at the top of .gitlab-ci.yml
so GitLab refuses to create any pipeline on push. The job
definitions stay in place — re-enable is a 4-line revert (delete
the workflow block) when bench infrastructure & CI runners are
decoupled.
Reason: aborist CI runners overlap with the same in-house pool
fox uses for `make bench-qa` against the live Hermes endpoint.
Auto-triggered pipelines on every push contend for the runner
& risk skewing bench latencies (already saw concurrency=4 push
mean per-call latency from 6-8s to 29s — adding background CI
jobs makes the signal noisier).
Local `make test` is unaffected — still 11s with -n auto.
`.gitlab-ci.yml` runs the unit test suite (`make test`, which uses
`-n auto`) on every push. PYTEST_XDIST_AUTO_NUM_WORKERS=4 caps the
worker count so we don't oversubscribe on shared runners — pytest-
xdist's `-n auto` reads os.cpu_count() and on cgroup-limited
containers that over-reports the host's cores. Local `make test`
stays uncapped (uses full machine).
Wall-clock on the 641-test suite:
serial: 38s
-n auto local: 11s (full machine, 8+ cores typically)
-n auto + cap 4: 22s (CI runners — 1.7× speedup, still safe)
Job structure mirrors sibling repos (unsandbox.com,
unfirehose-nextjs-logger):
- tags: build → in-house runner pool
- cache keyed on pyproject.toml, paths .venv/ + .pip-cache/
- artifacts on failure → .pytest_cache/ for triage
Excluded from CI (need live state or network access):
- make test-live → live Hermes endpoint + populated shards
- make bench-qa{,-quick,-smoke} → live LLM bench
- chain-check-shards / analyze-shards → real shard data
Optional `test-crawler` job: gated on commit-message tag
`[ci-crawler]` or manual trigger; installs `[crawler]` extras and
runs the network-bound crawler suite. allow_failure: true so it
doesn't block merges.