Commit Graph
3 Commits
Author SHA1 Message Date
dtourolle fb4e4d4abc ci(traceability): the job container is where act_runner looks for node
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.
2026-08-30 22:08:51 +02:00
dtourolle e1de98e783 feat(ar-024): enforce the invariant statically, and delete the fallback it caught
AR-024's register row gives its verification tier as "Static check -- no
bare cosine outside a tagged EXCEPTION". No such check existed, so the
invariant was enforced by reading, and reading had missed a live
violation.

scripts/ci/check_raw_cosine.py is that check, wired into the
traceability workflow as a blocking step. It is honest about its reach:
it catches direct cosine_similarity() uses not routed through a
calibration, and it cannot follow a cosine through a variable across
statements. That limit is documented in the script rather than left for
someone to discover after trusting a pass.

What it caught, and what this commit removes with it:

The identity matcher's no-calibration fallback thresholded raw cosine
distance (match_threshold) plus a ratio test (match_ratio,
match_ratio_ceil). Worse than the invariant breach: it fed
max(0, cosine) into TrackRegistry::observe, whose contract reads
"posterior is a calibrated probability, never a raw cosine (AR-024) ...
so the accumulation cannot be fed an uncalibrated number by a careless
caller". It could, and did. And it disagreed with the rest of the
pipeline about what "the fit failed" means -- same_person_probability
answers that with the untuned default sigmoid and a loud warning, so
association stayed in probability space while matching alone left it.
One run, two policies, no announcement.

Now one rule: cal_.probability() always, with a warning when the fit is
not real. A worse answer than a fitted calibration, a better one than a
number whose units nothing else shares.

TrackGallery::set_calibration is mandatory for the same reason. Its
default was max(0, cosine), which made expand_band_lo = 0.90 mean
"cosine > 0.9" in a test and "P(same person) > 0.9" in production.
FaceTrackerFunc already threw without one; the expansion store now
matches.

One exception is recorded, in the calibration's own dedup. It is not a
close call: at 1 - 1e-7 it asks whether two vectors are the same vector,
and it runs on the fit's input, so a calibrated comparison there would
have to be calibrated by the fit it is feeding.

Also drops seven dead keys from the optimizer's CFG_KEYS. Config keys
are read with a contains() check, so each one had been silently inert
since the field behind it was deleted -- a sweep varying one of them
measured nothing and reported an ordinary-looking F1.

TRACES: AR-024, AR-023 | SR-002
2026-08-05 15:46:33 +02:00
dtourolleandClaude Opus 5 d9aaf8fa4e build: consume the shared traceability tooling via submodule
jray-project is added at scripts/vendor/jray-project and the extractor is used
from there. Only two files are repo-local: traceability.toml, which carries
everything repo-specific, and the CI workflow that invokes the vendored gate.

The extractor is deliberately NOT copied in. One implementation, parameterised
by config — a second copy would drift from the first, and the tool already
proves it works unchanged against all three registers.

Enables system_spec so PR/SR orphan checking runs: previously uncheckable,
because the system spec lived outside every component's checkout.

Gate is green at 0.0% of 63 requirements, which is correct — nothing is tagged
yet. Eleven are flagged unverifiable on this CI host and excluded from the
numerator rather than counted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 18:58:40 +02:00