Skip to content

ci: execution routes, affected-package tests, and one guards job - #1841

Merged
timohueser merged 7 commits into
developfrom
ts-b/execution-routes
Sep 16, 2026
Merged

timohueser merged 7 commits into
developfrom
ts-b/execution-routes

Conversation

@timohueser

@timohueser timohueser commented Sep 16, 2026

Copy link
Copy Markdown
Owner

TS-B of epic #1816. All six numbered sections of the issue are done.

What changed, in plain English

Every test now has one explicit route, and the routes are written down. There is no expensive
tier and nothing to build one for: the whole repository has three ignored tests and five manual
Cargo-example commands, and each already had a route. docs/testing.md now carries the complete
table. The words "heavy" and obc test heavy appear nowhere in docs/testing.md or
CONTRIBUTING.md, as the issue predicted — confirmed by grep, nothing to remove.

A missing fixture now fails with the command that fixes it. obc_fixtures::file() used to
return None, and it only panicked with a helpful hint when OBC_REQUIRE_FIXTURES was set. All
sixteen call sites turned that None into an .expect whose message named no setup command, so a
plain local run panicked with no way forward. file() now returns the path or panics with
Run \obc fixtures sync test`; file_in(profile, …)names a different profile for the one caller outside thetestprofile. The environment variable is gone from the loader,tools/justfile, the workflow, the registry command and fixtures/verify-assistant-places.py. sim-peak-view(98 MiB) leaves thetestsync profile: no test reads it, only the simulator does at run time, and it stays in thesim` profile.

The test job does not narrow what it compiles, and it cannot yet. The first round of this
pull request compiled only the packages the plan selected. That breaks the per-pull-request
coverage ratchet: tools/coverage_report.py walks git ls-files for the five critical components
(format-protocol-codecs, crc, storage, dfu, boot) and fails any file the run never compiled, so a
leaf-crate plan such as -p obc-bench -p obc-formats -p obc-vectors, which omits obc-link and
obc-storage outright, reports them as unmeasured and fails the job. The epic's rule is to keep the
ratchet as TS5 accepted it, so the narrowing is gone: both nextest steps and the doctest step are
--workspace --all-features with the tier filter, and tools/ci/rust_packages.py is deleted. The
measured 302 s to 153 s comes from the serial-path split, not from compiling less. Whether the
ratchet moves to develop pushes, which would unlock narrowing, is deferred to TS-C2 and the owner.

One job body file. tools/ci/test.sh holds the test job's five sections (fast nextest,
fixture nextest, doctests, default-feature formats, bench golden). CI runs one section per step so
each keeps its own step name and result artifact; obc check test runs the same file (all
sections except the fixture tier, which needs a download).

Job shape. Seven guard jobs, each paying for a checkout to run one fast Python script, are now
seven steps of one unconditional guards job, which also carries the registry drift check, the
registry unit tests and the fixture policy. No guard's logic moved. The UI sweep and the builder
pytest left the test job's serial path for ui-snapshots and builder-python. The builder job
now fails when the packer binary or the corpus is missing instead of skipping its packer half.

Local runner and the attribution move. obc test -p PKG runs nextest — the runner CI uses —
and then the same scope's doctests. obc test -p PKG --lib is the library-only loop: one target,
no doctests; Cargo itself rejects --lib on a package with no library, so no extra check was
needed. COPERNICUS_ATTRIBUTION and SOURCE_DATASET moved from host/obc-dem to the
firmware/obc-elevation leaf every consumer already depends on, and obc-app dropped the
obc-dem dev-dependency that existed only so one unit test could read the wording.

Expected job sets that changed, and why

tools/tests/test_suite_registry.py asserts exact job sets per change class. Every change below
follows from the job split; none of them is a policy decision I made on my own.

Expectation Before After
route of python.repository-tools ["fixture-registry", "selection"] ["guards", "selection"]
route of python.builder ["test"] ["builder-python"]
route of ci.ui-snapshots (not asserted) ["ui-snapshots"] — added
route of rust.obc-sim (not asserted) ["clippy", "fmt", "test", "ui-snapshots"] — added
class "foundational Rust crate" 10 jobs the same 10 plus builder-python and ui-snapshots
class "workflow" 16 jobs the same 16 plus builder-python and ui-snapshots
class "nextest configuration" 16 jobs the same 16 plus builder-python and ui-snapshots

The sweep's selection budget is unchanged. The ui-snapshots job gates on its own job name,
so every suite that routes to it can start the job — and because the job compiles the simulator,
that includes each package the simulator is built from. The sweep step carries
contains(fromJSON(needs.selection.outputs.plan).selected_suite_ids, 'ci.ui-snapshots'), exactly
where that condition lived before, so the render and manifest check still runs only for the suite
that owns the rendering triggers. workflow_jobs() reads job-level keys only, so routing,
validate-filters and the aggregate see no change, and decision D5 is preserved as written.

Accepted costs

  • A failing guard step hides the other six until it is fixed. Seven separate jobs reported every
    failure at once; one job stops at the first. The trade is six runner set-ups per pull request
    against a second iteration when two guards break together.
  • The ui-snapshots and builder-python jobs start for every package they compile, so a
    foundational Rust change now provisions two more runners. ui-snapshots skips its own sweep
    step unless ci.ui-snapshots is selected, so what it costs in that case is the set-up, not the
    106 s render.

Registry changes (small, and TS-C replaces them)

  • scan_workflow reads a tools/ci/*.sh script as the job body it is and records its command
    lines, applying the same export/assignment/comment rules the workflow loop already applied.
    Without this the extracted commands would vanish from discovery and their suites would go dead.
    Scope is deliberately tools/ci/ only: builder/build-wasm-bridges.sh and friends are build
    tools, and their invocation line stays the owned unit.
  • The shell-assignment regex became a module constant shared by both readers, so a line such as
    OBC_FIXTURE_ROOT="$(python3 …)" inside the job body is read as shell state, not as a command.

run --level, run --affected, gates and cargo-filter are untouched and still pass their
tests.

Measurements

llvm-cov instrumentation, on this machine, final head. Both runs used the same fixed package
set (obc-app obc-route obc-render obc-reader obc-storage obc-link obc-formats) and the same fast
filter. I did not measure the whole workspace: 19 GiB free with three agents building, and a
second instrumented workspace build was not a risk worth taking for a ratio. Reported as measured,
not extrapolated.

Run Plain Under cargo llvm-cov show-env
Warm, nothing changed 6 s 6 s
After touching firmware/obc-app/src/lib.rs 12 s 41 s

Instrumentation costs nothing measurable at execution time. It costs on compilation:
cargo-llvm-cov sets cfg(coverage) and coverage RUSTFLAGS, so the instrumented artifacts are a
separate build, and a one-crate edit cost 3.4× here. CI caches the instrumented artifacts under
the shared host-tests key, so a pull request restores them and pays the incremental figure, not
the cold one. The instrumentation stays; TS5's ratchet keeps it.

llvm-cov scope. Instrumentation is on the two nextest steps only. A local run of the
formats-default section added zero target/*.profraw files, which is the shape every
uninstrumented section now has; previously the flag was job-wide and the bench gate's release
binary wrote profile data into the ratchet's evidence.

Verification

Commands run, all from the worktree, all passing unless noted:

python3 tools/suite_registry.py check            # 83 suites, 285 discovered execution units
python3 tools/suite_registry.py validate-filters # 21 workflow jobs, 15 audited selection classes
python3 -m unittest discover -s tools/tests      # Ran 205 tests ... OK
obc test -p obc-fixtures                         # 1 test run: 1 passed
obc test fixtures -p obc-route --test nav_fixtures  # 4 passed
obc test -p obc-elevation                        # 44 passed, doctests 0
obc test -p obc-dem                              # passed
obc test -p obc-app --lib                        # 933 tests run: 933 passed
cargo test -p obc-reader  --features external-fixtures --test poi_fixtures   # 1 passed
cargo test -p obc-host-core --features external-fixtures --test altitude_fusion  # 2 passed
cargo test -p obc-dem --features external-fixtures --test assets             # 2 passed
cargo test -p obc-sim --features external-fixtures --test present_fixtures   # 4 passed
cargo clippy -p obc-elevation -p obc-dem -p obc-bake -p obc-pack -p obc-app --all-targets --all-features --locked -- -D warnings
cargo fmt --all --check
python3 firmware/tools/check_dependencies.py     # 143 production local edges
python3 tools/check_fixture_policy.py
python3 docs/build_docs.py --check-links         # all internal anchor links resolve

python3 -m unittest discover -s tools/tests needs tools/requirements-test.txt installed;
without it three unrelated tests error on missing tree_sitter and xmlrunner on this machine.
I ran the whole set in a scratch virtual environment with those pinned requirements.

Acceptance check: grep -rn OBC_REQUIRE_FIXTURES over the tree returns nothing, and
cargo test -p obc-route --features external-fixtures --test nav_fixtures with an empty fixture
root fails with

OBC fixture is missing: …/sim-grimsel/grimsel.obcm. Run `obc fixtures sync test`.

No UI sweep was run: no rendering file changed.

Line counts

32 files changed, 391 insertions, 256 deletions. The one new file is tools/ci/test.sh (80);
.github/workflows/ci.yml is 123 added against 132 deleted, and tools/suite_registry.py is
19 against 3.

Left out, deliberately

  • The selector itself. tools/suite_registry.py stays authoritative; TS-C1/TS-C2 replace it.
  • The registry's exception fields, the desktop launch smoke, the sweep script and the manifest —
    all out of scope for this issue.
  • obc check test does not run the fixture tier. It runs the same file, not every section: the
    fixture tier needs a sync, and a local gate should not start a download.

Corrections to the issue

  • Section 3's package narrowing is not implementable while the coverage ratchet runs per pull
    request; it needs one LCOV report over the whole workspace. The narrowing is dropped here and
    the question is deferred, as described above.
  • fixtures/verify-assistant-places.py also set OBC_REQUIRE_FIXTURES; the issue did not list it.
    The acceptance grep would have failed without it.
  • host/obc-bake had no obc-elevation dependency, so the attribution move adds one.

Closes #1820

🤖 Generated with Claude Code

timohueser and others added 5 commits September 16, 2026 11:39
The fixture loader returned `None` for a missing package and only panicked
with a hint when `OBC_REQUIRE_FIXTURES` was set, so every one of the sixteen
call sites turned that `None` into an `.expect` message that named no setup
command. `file()` now returns the path or panics with the exact
`obc fixtures sync` command, `file_in` names a profile outside `test`, and the
environment variable is gone from the loader, the justfile, the workflow, the
registry command and the assistant-places verifier.

`sim-peak-view` leaves the `test` sync profile: no test reads it, only the
simulator does at runtime, and it stays in the `sim` profile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both nextest steps and the doctest step ran `--workspace --all-features` and
then filtered execution, so a three-crate change still built every crate. The
plan already names the selected suites; `tools/ci/rust_packages.py` turns it
into `-p NAME` flags for one tier, prints `--workspace` when the change can
alter what any package compiles to, and prints nothing when the tier selected
no package. An empty set skips the tier; it never falls back to the workspace.

`tools/ci/test.sh` carries the job's body, one section per step, so the same
file serves CI and a local run. The registry reads a `tools/ci/*.sh` script as
the job body it is, and a computed package list counts as the whole root
workspace for job coverage, which is what it is on a foundation change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seven guard jobs each paid for a checkout to run one fast Python script. They
are now seven steps of one `guards` job, which also carries the registry drift
check, its unit tests and the fixture policy. No guard's logic moved and each
step keeps its own name, so a failure still reads the same.

The UI snapshot sweep and the builder pytest leave the `test` job's serial path
for `ui-snapshots` and `builder-python`, each gated on its own job name and
each restoring the shared host-tests cache. The builder job now fails, rather
than silently skipping its packer half, when the binary or corpus is missing.

Routing expectations that changed, all from the split:
- python.repository-tools now routes to `guards`, python.builder to
  `builder-python`.
- `builder-python` compiles obc-pack and `ui-snapshots` compiles obc-sim, so
  both are routes for those packages, exactly as `clippy` and `fmt` are. A
  foundational Rust change therefore starts both jobs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`obc test -p PKG` ran Cargo's harness while CI ran nextest, so a developer and
CI could disagree about a merged target. The focused arm now runs nextest and
then the same scope's doctests. `obc test -p PKG --lib` is the library-only
loop: one target, no doctests, and Cargo itself rejects a package with no
library.

`COPERNICUS_ATTRIBUTION` and `SOURCE_DATASET` move from the host DEM tool to
the `obc-elevation` leaf every consumer already depends on. The application
drops its `obc-dem` dev-dependency, which existed only so one unit test could
read the wording.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Names the one explicit route for each of the three ignored tests and the five
manual commands, and says there is no expensive tier. Records that bounded
fixture suites are ordinary work that fails with the sync command, that the
`test` job compiles the packages the plan selected, that the sweep is its own
job with a wider job-level trigger than its suite, and that a focused
`obc test -p` runs on nextest with a `--lib` form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 6 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f38274f8-e64d-486d-9075-f59fa3ea15ef

📥 Commits

Reviewing files that changed from the base of the PR and between dba3cf0 and 3094435.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (31)
  • .github/workflows/ci.yml
  • CONTRIBUTING.md
  • apps/obc-sim/tests/present_fixtures.rs
  • docs/testing.md
  • firmware/README.md
  • firmware/obc-app/Cargo.toml
  • firmware/obc-app/src/screen/settings/about.rs
  • firmware/obc-elevation/src/lib.rs
  • firmware/obc-reader/tests/poi_fixtures.rs
  • firmware/obc-route/tests/nav_fixtures.rs
  • fixtures/catalog.toml
  • fixtures/sources/peak-view/README.md
  • fixtures/verify-assistant-places.py
  • host/obc-bake/Cargo.toml
  • host/obc-bake/assets/README.md
  • host/obc-bake/src/main.rs
  • host/obc-bake/src/terrain.rs
  • host/obc-bake/tests/cell_bakery.rs
  • host/obc-dem/src/lib.rs
  • host/obc-dem/src/main.rs
  • host/obc-dem/tests/assets.rs
  • host/obc-fixtures/src/lib.rs
  • host/obc-host-core/tests/altitude_fusion.rs
  • host/obc-pack/src/catalog/terrain.rs
  • host/obc-pack/src/contour.rs
  • host/obc-pack/tests/assistant_places.rs
  • testing/suites.toml
  • tools/ci/test.sh
  • tools/justfile
  • tools/suite_registry.py
  • tools/tests/test_suite_registry.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@timohueser

Copy link
Copy Markdown
Owner Author

CI evidence — run 35080781943, conclusion success

This run is the gate for the workflow shape. It selects --workspace, by design: the pull
request changes the workflow and the registry, so no narrowed package set would be trustworthy.
The narrowing itself is shown by the local plan figures in the description.

Job list

guards replaces seven jobs. ui-snapshots and builder-python are new and both reached the
ci aggregate, which passed.

Job Result Seconds
selection success 18
guards success 42
ui-snapshots success 144
clippy success 75
ios-app success 975
wasm-bridges success 81
test success 153
ios-unit success 155
device success 29
deny success 114
builder-python success 151
fmt success 14
boot success 29
wasm success 83
docs success 5
embedded (clippy (default = LS021/FLPR), cargo clippy --locked -- -D warnings) success 37
embedded (build (default = LS021/FLPR, release), set -o pipefail; cargo build --release --locked ... success 188
embedded (clippy (debug-uart), cargo clippy --locked --features debug-uart -- -D warnings) success 37
desktop-frontend success 22
web success 89
desktop (macos-latest, macos-arm64, obc-desktop) success 122
desktop (windows-latest, windows-x86_64-msvc, obc-desktop.exe) success 233
desktop (ubuntu-latest, linux-x86_64, obc-desktop) success 99
desktop-launch success 96
ci success 7

test job steps

Every step is bash tools/ci/test.sh SECTION, the same file obc check test runs. The
captured-fixture step passed without OBC_REQUIRE_FIXTURES, which is the acceptance for the
loader change.

# Step Result Seconds
1 Set up job success 3
2 Run actions/checkout@v4 success 2
3 Run actions-rust-lang/setup-rust-toolchain@v1 success 7
4 Run Swatinem/rust-cache@v2 success 14
5 Run ./.github/actions/setup-host-deps success 17
6 Install native LLVM coverage tools success 2
7 Run taiki-e/install-action@v2 success 2
8 Cache content-addressed developer fixtures success 0
9 cargo nextest (fast hermetic binaries) success 64
10 cargo nextest (captured fixture binaries) success 7
11 cargo test --doc (selected packages, all features) success 3
12 cargo test (obc-formats, default features = the device's shape) success 1
13 Run actions/setup-python@v5 success 0
14 Install Python test reporter success 5
15 firmware resource/dependency tool unit tests success 1
16 firmware production dependency direction success 0
17 obc-bench --check (render + read-counter golden gate) success 7
18 firmware-tools coverage success 0
19 Upload firmware-tools coverage success 1
20 Upload firmware-tools Python test results success 1
21 Rust component coverage success 7
22 Publish Rust coverage summary success 0
23 Upload Rust coverage and remaining native logs success 1
24 Upload Rust test results success 1
25 Upload Rust fixture test results success 1

Measured against the epic's baseline

The epic recorded the test job at 302 s and 304 s, with the fast tier at 97 s and 99 s and the
sweep at 66 s inside the job.

Measure Epic baseline This run
test job, whole 302 s / 304 s 153 s
fast nextest step 97 s / 99 s 64 s
captured-fixture nextest step 14 s 7 s
sweep, on the test job's serial path 66 s 0 s (own 144 s job, in parallel)
builder pytest preparation, on that serial path 33 s 0 s (own 151 s job, in parallel)

Both nextest steps still compiled the whole workspace on this run, so the fast tier's 64 s is a
cache-warmth difference, not the narrowing. What the job shape bought is the 99 s of sweep and
builder preparation that left the serial path. guards runs the seven guard scripts, the
registry drift check, the registry unit tests and the fixture policy in 42 s on one runner,
where seven jobs each paid for their own checkout.

@timohueser

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

timohueser and others added 2 commits September 16, 2026 12:19
The per-pull-request ratchet reads one LCOV report over the whole workspace and
fails any critical file it never compiled, so compiling only the selected
packages made `tools/coverage_report.py` report the five critical components as
unmeasured and fail the job. A leaf-crate plan omits obc-link and obc-storage
outright. Both nextest sections and the doctest section go back to
`--workspace --all-features` with the tier filter, `tools/ci/rust_packages.py`
is deleted, and the registry's unexpanded-variable accommodation goes with it.
Reading a `tools/ci/*.sh` script as a job body stays: the commands live there.

llvm-cov instrumentation is now on the two nextest steps only. It was job-wide,
so the doctests, the default-feature formats run and the bench golden gate were
instrumented too, and the bench release binary's profile data would have merged
into the ratchet's evidence. Each section also runs in a subshell, so one
section's environment cannot reach the next.

The sweep step carries its own `ci.ui-snapshots` condition again. The job still
gates on its own name, so routing, `validate-filters` and the aggregate are
unchanged, but the sweep itself runs only for the suite that owns the rendering
triggers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… suite

Replaces the package-narrowing description with the reason it cannot narrow:
the coverage ratchet needs one report over the whole workspace. Records that
only the two nextest sections are instrumented, and that the sweep step runs
for `ci.ui-snapshots` alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@timohueser

Copy link
Copy Markdown
Owner Author

Review round 1 addressed — run 35084445187 on 3094435b2, conclusion success

Blocker. The CI-side package narrowing is gone. Both nextest sections and the doctest section
are --workspace --all-features with the tier filter again, tools/ci/rust_packages.py is
deleted, and the registry's unexpanded-variable rule in _cargo_packages went with it. Reading a
tools/ci/*.sh script as a job body stays, because the commands themselves now live there and the
registry has to see them. testing/suites.toml's three ownership patterns are back to their
--workspace text. Section 3 of the description is rewritten: the ratchet needs one LCOV report
over the whole workspace, the 302 s to 153 s came from the serial-path split, and whether the
ratchet moves to develop pushes is deferred to TS-C2 and the owner.

1 — sweep breadth. contains(fromJSON(needs.selection.outputs.plan).selected_suite_ids, 'ci.ui-snapshots') is back on the ui-snapshots manifest check step. The job keeps its own
job-name gate, so workflow_jobs(), routing, validate-filters and the aggregate are untouched
and every routing expectation in the description's table still holds. D5 is restored exactly: the
render and manifest check runs for ci.ui-snapshots and nothing else.

2 — instrumentation scope. OBC_COVERAGE: "1" is on the two nextest steps only, not the job.
Each section of tools/ci/test.sh also runs in a subshell, so an exported coverage environment
cannot reach a later section in the same invocation. Verified locally: running the
formats-default section left target/*.profraw unchanged at 1038 files, so the bench gate's
release binary no longer contributes profile data to the ratchet's evidence.

3 — stale names after the attribution move. about.rs's doc comment no longer claims a
dev-dependency the device build never sees, and its test is now
copernicus_wording_matches_obc_elevation. The two comments in obc-pack/src/contour.rs and
obc-bake/src/main.rs name obc-elevation. A grep for obc_dem::COPERNICUS over firmware/ and
host/ returns nothing.

4 — accepted cost. Recorded in the description: a failing guard step hides the other six until
it is fixed, and the ui-snapshots / builder-python jobs start for every package they compile
(the sweep step itself then skips unless its suite is selected).

test job steps

# Step Result Seconds
9 cargo nextest (fast hermetic binaries) success 76
10 cargo nextest (captured fixture binaries) success 10
11 cargo test --doc (workspace, all features) success 3
12 cargo test (obc-formats, default features = the device's shape) success 1
15 firmware resource/dependency tool unit tests success 0
16 firmware production dependency direction success 1
17 obc-bench --check (render + read-counter golden gate) success 7
21 Rust component coverage success 9
24 Upload Rust test results success 1
25 Upload Rust fixture test results success 1

Whole job 178 s against the epic's 302 s and 304 s baseline. guards 34 s, ui-snapshots 157 s
and builder-python 157 s in parallel. Every job in the run succeeded and the ci aggregate
passed.

Checks re-run on this head

python3 tools/suite_registry.py check            # 83 suites, 285 discovered execution units
python3 tools/suite_registry.py validate-filters # 21 workflow jobs, 15 audited selection classes
python3 -m unittest discover -s tools/tests      # Ran 205 tests ... OK
bash -n tools/ci/test.sh
cargo check -p obc-app -p obc-pack -p obc-bake --locked
cargo test -p obc-app --lib copernicus           # copernicus_wording_matches_obc_elevation ... ok
cargo fmt --all -- --check
python3 docs/build_docs.py --check-links         # all internal anchor links resolve

Line counts for the branch: 32 files changed, 391 insertions, 256 deletions.

@timohueser

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@timohueser
timohueser merged commit 9b6b986 into develop Sep 16, 2026
28 checks passed
@timohueser
timohueser deleted the ts-b/execution-routes branch September 16, 2026 10:41
timohueser added a commit that referenced this pull request Sep 16, 2026
Two wording errands from the review.

The Outcome section reported the `test` job as "302 s to 178 s". 178 s was
not a recorded measurement. The record now carries all three measured
figures: 302 s before the epic, 153 s on TS-B's head when it shipped
(#1841), and 177-194 s on `develop` push runs after every child landed,
measured 2026-09-16.

"The docs job still runs on them" read as though `build_docs.py` checks
`CLAUDE.md` and `AGENTS.md`. It does not read them at all. They are owned
by the documentation route so the paths are not unowned; the check that
actually reads them is the unconditional `guards` job — the planner's own
`check` plus the tool unit tests, which pin the agent-prose change class.
Corrected in the `ci.docs` comment, the `TEST_POLICY_PATTERNS` comment and
the change-selection table.

Validation: `python3 tools/test_plan.py check` OK; `validate-filters`
agrees on 22 jobs over 15 audited paths; `python3 -m unittest discover -s
tools/tests` 159 tests OK; `python3 docs/build_docs.py --check-links` all
internal anchor links resolve.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TS-B: Execution routes, affected-package nextest, sweep and pytest off the serial path, one guards job

1 participant