ci: make both workflows able to run at all #1

Merged
dtourolle merged 6 commits from ci/green-the-runner into master 2026-09-03 18:19:42 +00:00
Owner

Neither workflow had ever completed a step it was written to check. Six absences, none of them in the pipeline code -- every check passes on master's tree once it can run at all.

Traceability

  • No container:. The job ran in the runner's default image, which has no node. act_runner executes JS actions (checkout, upload-artifact) with the node inside the job container, so it died before checkout and every later step failed on an empty working tree. Now node:20-bookworm -- node is the part with no workaround, and bookworm brings python3.11 (tomllib) and git along with it. Nothing in it names this repo, so the file stays copyable into the other two components, which its header claims.
  • The jray-project submodule was pinned by SSH URL, which the runner has no key for. Now https, and the repo is public, so submodules: recursive can reach it.

Green in CI as of runs 1433 and 1436.

Unit tests

Each of these was only reachable once the one before it was fixed:

  1. sae-builder-cpu:v1 was pinned but never pushed -- manifest unknown on every run since the workflow landed.
  2. No replay-fixtures package existed either. Published at ff3b8eb, and the workflow now pins that version instead of latest -- the same argument DP-007 makes about the image tag, and it removes the one credential this job wanted (no GITEA_TOKEN secret is configured, so latest could never have resolved).
  3. The image had no libfftw3 (-> v2). SAE_SCENE_XGB is on by default and its find_library(... REQUIRED) runs at configure time, so v1 could not configure this repository at all. -DSAE_SCENE_XGB=OFF would also have passed; it is the wrong fix, because CI is the only place these tests run.
  4. The image had no unzip (-> v3), which pull_artifacts.sh needs to unpack the fixtures. Found by run 1437, which got all the way to the fetch.

KPN

kpn/diagnostics.hpp declared two std::vector members without including <vector>. Latent everywhere we build -- something else always dragged it in first -- and fatal under GCC 12, where it took out src/benchmark.hpp with errors that all name our file. Fixed on KPN master (af9da7d); pin bumped.

The bump also crosses the four perf/phase0-harness commits, which is a bigger move than a header fix. Checked rather than assumed: the two failing tests fail identically with the pin at 771b9f8 plus the include alone, so they are not the bump's doing.

Not fixed, and recorded rather than swept in: network.hpp names IChannelProbe without including channel.hpp -- the same latent bug.

Two stale tests

Both failed the first time anything ran this suite, and neither is a new break.

1477c53 (2026-08-09) made a dormant track associable only if it had been identified, recording a deliberate recall trade. Both tests build tracks that are never identified, so they are dropped a line before the extinction horizon they were written to exercise -- and both predate that commit (2026-07-31, 2026-08-08).

The second needed a rename as well. It was built on association and reaping answering on different clocks, which track_registry.hpp:184-203 now rules out: one clock, one threshold, so "retired from association" and "reaped" are one event and the interval its name described does not exist. Rewritten to assert what the unified clock does promise. The AR-008 tag, the late-vote check and dropped_votes() == 0 all survive.

Verification

Both jobs rehearsed end to end in the pinned images before pushing, unit-tests including the real pull_artifacts.sh against an emptied fixtures directory:

  • traceability in node:20-bookworm: 53/53 extractor tests, gate OK (42/72 traced, 73.7%% CI scope, 0 orphans), AR-024 clean
  • unit-tests in sae-builder-cpu:v3: image self-assert, fixtures fetched and verified, 151/151, job exit 0
Neither workflow had ever completed a step it was written to check. Six absences, none of them in the pipeline code -- every check passes on master's tree once it can run at all. ## Traceability - **No `container:`.** The job ran in the runner's default image, which has no `node`. act_runner executes JS actions (checkout, upload-artifact) with the node *inside* the job container, so it died before checkout and every later step failed on an empty working tree. Now `node:20-bookworm` -- node is the part with no workaround, and bookworm brings python3.11 (tomllib) and git along with it. Nothing in it names this repo, so the file stays copyable into the other two components, which its header claims. - **The `jray-project` submodule was pinned by SSH URL**, which the runner has no key for. Now https, and the repo is public, so `submodules: recursive` can reach it. Green in CI as of runs 1433 and 1436. ## Unit tests Each of these was only reachable once the one before it was fixed: 1. **`sae-builder-cpu:v1` was pinned but never pushed** -- `manifest unknown` on every run since the workflow landed. 2. **No `replay-fixtures` package existed** either. Published at `ff3b8eb`, and the workflow now pins that version instead of `latest` -- the same argument DP-007 makes about the image tag, and it removes the one credential this job wanted (no `GITEA_TOKEN` secret is configured, so `latest` could never have resolved). 3. **The image had no `libfftw3`** (-> v2). `SAE_SCENE_XGB` is on by default and its `find_library(... REQUIRED)` runs at *configure* time, so v1 could not configure this repository at all. `-DSAE_SCENE_XGB=OFF` would also have passed; it is the wrong fix, because CI is the only place these tests run. 4. **The image had no `unzip`** (-> v3), which `pull_artifacts.sh` needs to unpack the fixtures. Found by run 1437, which got all the way to the fetch. ## KPN `kpn/diagnostics.hpp` declared two `std::vector` members without including `<vector>`. Latent everywhere we build -- something else always dragged it in first -- and fatal under GCC 12, where it took out `src/benchmark.hpp` with errors that all name *our* file. Fixed on KPN master (af9da7d); pin bumped. The bump also crosses the four perf/phase0-harness commits, which is a bigger move than a header fix. Checked rather than assumed: the two failing tests fail identically with the pin at 771b9f8 plus the include alone, so they are not the bump's doing. Not fixed, and recorded rather than swept in: `network.hpp` names `IChannelProbe` without including `channel.hpp` -- the same latent bug. ## Two stale tests Both failed the first time anything ran this suite, and neither is a new break. `1477c53` (2026-08-09) made a dormant track associable only if it had been identified, recording a deliberate recall trade. Both tests build tracks that are never identified, so they are dropped a line before the extinction horizon they were written to exercise -- and both predate that commit (2026-07-31, 2026-08-08). The second needed a rename as well. It was built on association and reaping answering on *different* clocks, which `track_registry.hpp:184-203` now rules out: one clock, one threshold, so "retired from association" and "reaped" are one event and the interval its name described does not exist. Rewritten to assert what the unified clock does promise. The AR-008 tag, the late-vote check and `dropped_votes() == 0` all survive. ## Verification Both jobs rehearsed end to end in the pinned images before pushing, unit-tests including the real `pull_artifacts.sh` against an emptied fixtures directory: - traceability in `node:20-bookworm`: 53/53 extractor tests, gate OK (42/72 traced, 73.7%% CI scope, 0 orphans), AR-024 clean - unit-tests in `sae-builder-cpu:v3`: image self-assert, fixtures fetched and verified, **151/151**, job exit 0
dtourolle added 2 commits 2026-08-30 20:16:26 +00:00
The traceability job has been failing since it was written, and never on
anything it checks. It declared no `container:`, so it ran in the
runner's default image, which has no node; act_runner executes JS
actions with the node it finds inside the job container, and both
actions/checkout and upload-artifact are JS. The job died at
"Cannot find: node in PATH" before the repository was checked out, and
every later step then failed on an empty working tree -- the summary
step's "head: cannot open 'docs/traceability.md'" is that, not a missing
report.

node:20-bookworm, and the choice is not arbitrary: node is the part with
no workaround, while Debian 12 already carries python3.11 (tomllib, so
the stdlib-only extractor reads traceability.toml) and git (for the
pull_request diff step). Nothing in it names this repo, so the file
stays copyable into the other two components unedited, which its header
claims and this commit keeps true.

The kpnpp-builder and jellytau-builder images bake node in for exactly
this reason, and Dockerfile.builder-cpu says so in a comment. That
knowledge just had not reached the one job with no image of its own.

Second failure behind the first: the jray-project submodule was pinned
by SSH URL. The runner has no key, so `submodules: recursive` could not
have fetched the extractor even with node present. https, like the KPN
submodule beside it.

Gate and static check both pass locally on this tree -- 42/72 traced,
73.7% in CI scope, 0 orphans, 0 bare-cosine violations -- so what CI
reports next is a fact about CI, not about the tree.
ci(tests): publish what the job was told to pull, and pin it
Unit tests / Build and run the GPU-free suite (pull_request) Failing after 36s
Traceability Validation / Check requirement traces (pull_request) Successful in 40s
c5a8502bbb
DP-007's row says the builder image is "pinned by tag in the Gitea
container registry". The tag was pinned; the image was never pushed.
Every run since the workflow landed died at
"Error response from daemon: manifest unknown" before a single step ran,
so the tier this workflow exists to execute has still never executed.

sae-builder-cpu:v1 is now in the registry, built from ff3b8eb by
scripts/ci/build_builder_image.sh and reporting SAE_BUILDER_VERSION=v1,
which is what the job's own assert-the-image step demands. The
v1-ff3b8eb audit tag went with it.

Behind that, the same absence one layer down: no replay-fixtures package
existed either, so "Verify the fixtures actually arrived" would have
failed next. tests/fixtures/dumps is now published at version ff3b8eb.

Which makes the `latest` here worth removing rather than keeping. Two
reasons, either sufficient. It is the same argument DP-007 already
makes about the image tag -- a dump is an input to the tests, so a
re-upload under a moving `latest` retroactively changes what an earlier
green build proved. And `latest` was the only thing in this job that
wanted a credential: package downloads are anonymous while the repo is
public, and only resolving `latest` needs a token for the list endpoint.
No GITEA_TOKEN secret is configured on this repo, so that step could
never have resolved `latest` even once the image existed. Pinning
deletes the dependency instead of documenting it.

The failure message below it said the step "needs GITEA_TOKEN to resolve
'latest'"; it now says to check the pinned version still exists, which
is the thing that can actually go wrong -- pull_artifacts.sh warns and
continues on a missing version rather than failing, which is why that
verify step is there at all.

TRACES: DP-007 | PR-004
dtourolle added 2 commits 2026-08-30 20:42:39 +00:00
v1 has no libfftw3. SAE_SCENE_XGB is on by default and pulls the learned
scene-boundary detector into result_sink, whose find_library(FFTW3_LIB
fftw3 REQUIRED) at CMakeLists.txt:377 runs at CONFIGURE time -- so cmake
fails before any target is chosen, and building only `sae_tests` does not
get you past it. The image predates the detector; nothing rebuilt it when
the detector landed, which is precisely the gap DP-007's own register row
records.

-DSAE_SCENE_XGB=OFF would also have made the configure pass. It is the
wrong fix and worth saying why: CI is the only place these tests run, so
a flag that silences a subsystem there silences it everywhere, and the
job would have gone green over a detector nobody was compiling.

The image's self-check gains a line, because an image that ships a
library CMake cannot find the way CMake looks for it is the failure this
block exists to catch. FFTW is checked as a bare .so rather than through
pkg-config, since find_library is what CMakeLists.txt actually calls --
checking fftw3.pc would pass on an image whose libfftw3.so was absent.

Tag bumped v1 -> v2 here, in build_builder_image.sh and in the workflow's
run-time assert, in one commit, as this image's contract requires. v2 is
built and published. Rehearsed in the image before pinning it: configure,
build and 151 tests now run.

TRACES: DP-007 | PR-004
chore: update KPN — diagnostics.hpp includes the <vector> it uses
Unit tests / Build and run the GPU-free suite (pull_request) Failing after 40s
Traceability Validation / Check requirement traces (pull_request) Successful in 10s
5ce6394416
af9da7d on top of 5375ab4, and the reason it exists is this repository.

kpn/diagnostics.hpp declares NetworkSnapshot with two std::vector members
and has never included <vector>. It compiled everywhere we build because
something earlier in each translation unit dragged the definition in
first. src/benchmark.hpp includes <kpn/diagnostics.hpp> before its own
<vector>, and under Debian 12 / GCC 12 -- the CI image, and nothing we
develop on -- nothing supplies it, so the two members fail to declare and
every later use of .nodes or .channels fails after them. The errors all
name benchmark.hpp, so it reads as our bug until you look at the first
line of compiler output rather than the last.

This bump also crosses the four perf/phase0-harness commits between
5375ab4 and the pin, which is a larger move than a header fix and worth
being explicit about. Checked rather than assumed: the two tests failing
in CI fail identically with the pin at 771b9f8 plus the include fix
alone, so they are not this bump's doing. The perf work changes the
scheduler and pool; the failures are tracker extinction-window logic and
are reachable with no pool at all.

Also found while checking KPN's public headers standalone under GCC 12,
and NOT fixed there: network.hpp names IChannelProbe (channel.hpp:557)
without including channel.hpp -- the same latent bug, waiting for the
same kind of consumer. web_debug.hpp needs httplib.h, which is an
optional external dependency and not a defect.
dtourolle added 2 commits 2026-08-31 06:11:43 +00:00
Both failed the first time CI was able to run this suite, and neither is
a new break. They assert semantics that two deliberate changes replaced,
and nothing noticed because nothing had ever executed them.

1477c53 (2026-08-09) made a dormant track associable only if it had been
identified: an unowned dormant track has no actor to re-attach to, so it
only enlarges the matcher's comparison set and invites a new face landing
on an anonymous stub. Its message records the trade -- "a small recall
cost (~1-3pp on some films, e.g. Lord of War -2.5) for a cleaner, bounded
pool. Kept deliberately." Both tests build tracks that are never
identified, so since that commit they are dropped from the pool one line
before the extinction horizon they were written to exercise. The tests
date from 2026-07-31 and 2026-08-08 -- they are older than the gate.
Fixed by owning the track while it is still on screen, which is what a
real run does and what makes the horizon reachable at all.

The second test needed more than that, and the rename says why. It was
built on association and reaping answering on DIFFERENT clocks -- the
tracker's for "may this associate?", the watermark for "is this
finished?" -- which is exactly the arrangement track_registry.hpp:184-203
now rules out: one clock, one threshold, "nothing is offered past its
reap horizon, nothing is reaped while still offerable". So there is no
longer an interval in which a track is retired from association but still
alive, and a test named for that interval cannot pass. Rewritten to
assert what the unified clock actually promises: a tracker racing 50 s
past the horizon retires nothing while the matcher lags, the votes in
flight still land, and the watermark passing the horizon retires, reaps
and emits in one step.

Kept: the AR-008 tag, the late-vote check and dropped_votes() == 0, which
were the point of the test and still hold.

Full suite now 151/151 in sae-builder-cpu.

TRACES: AR-008, AR-013 | SR-002
fix(ci): the builder image has no unzip, so the replay tier had no input
Unit tests / Build and run the GPU-free suite (pull_request) Successful in 3m25s
Traceability Validation / Check requirement traces (pull_request) Successful in 19s
9bcc765408
Found by CI itself, on run 1437 -- the first run that ever got far enough
to try. Everything ahead of it worked: checkout brought both submodules,
v2 pulled and passed its own version assert, and the fixtures resolved at
the pinned version. Then:

    scripts/artifacts/pull_artifacts.sh: line 54: unzip: command not found

The replay fixtures ship as a zip in the generic package registry and
pull_artifacts.sh unpacks them with unzip. Without it the step exits 127
and the T2 tier has no input -- reported as a missing fixture by the
verify step below, which is a missing tool wearing the wrong label.

Worth naming why the local rehearsal missed this and CI did not: the
rehearsal had the dumps staged in the working tree by hand, so it built
and ran the tier without ever executing the script that fetches them. The
image was checked against the build, not against the job.

Tag v2 -> v3, in all three places, in one commit.

TRACES: DP-007 | PR-004
dtourolle merged commit 3a8787fc8b into master 2026-09-03 18:19:42 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dtourolle/scene-actor-extraction#1