Commit Graph
2 Commits
Author SHA1 Message Date
dtourolle faaa71fa09 refactor(traceability): parameterise the extractor for all three components
The tool is moving into the jray-project submodule to be shared by
scene-actor-extraction (C++/Python), jRay (C#) and JRay-public-server
(Rust). Two constants blocked that: LOCAL_TYPES and SOURCE_SUFFIXES were
hardcoded to this repo, so either sibling parsed zero requirements and
scanned zero files. Both, plus the register path, scan roots, system-spec
path, exclude list and CI-executable tier set, are now configuration.

One implementation, parameterised. A second copy for "the other language"
is how two implementations start drifting apart, so there is exactly one -
the same code path now produces:

  scene-actor-extraction  AR/DP/IR/GR/VR   59 defined   0 tagged    0.0%
  jRay                    JR               46 defined  24 covered  52.2%
  JRay-public-server      UR/DR            32 defined  23 covered  71.9%

Configuration is traceability.toml at the component repo root, CLI flags,
or both (flags win). Its directory defines the repo root, so the gate works
from any subdirectory. `--print-example-config` emits the annotated schema.
The JSON report echoes the settings it ran with, since a shared tool's
output is otherwise ambiguous about which repo it describes.

The refusal behaviour is kept and sharpened, because parameterising is
exactly what makes it easy to point a repo at the wrong prefixes or the
wrong suffixes. Zero requirements parsed or zero files scanned is still a
hard failure, and the message now names the setting that is wrong rather
than printing a plausible 0%. Config errors exit 2, not 1: a broken config
is not a coverage failure, and conflating them makes CI logs lie about why
the job went red.

Also fixed while adapting to the sibling registers, which are read but not
modified here:

  * escaped `\|` inside a markdown cell no longer shifts every later column
    (the server's register contains `small-\|M\|`);
  * a tag above an attribute-decorated declaration attributes to the
    declaration, not to `[HttpGet(...)]` or `#[derive(...)]` - the gap
    jRay's register calls out;
  * Rust and C# declaration patterns for context extraction;
  * the missing-tier warning is suppressed for a register that assigns no
    tiers at all, rather than listing every requirement in it.

The workflow is now component-agnostic too: the changed-file check reads
its extension list out of the report the gate just wrote, so the definition
of "source file" lives in one place.

79 tests, still fixture-based, now including the cross-repo cases: the same
parser over JR and UR/DR registers, the same scanner over Rust and C#, and
both misconfigurations failing loudly.
2026-07-30 18:35:56 +02:00
dtourolle 054c4c8b8f build: requirement traceability extractor, gate, and CI workflow
Ports JellyTau's traceability tooling, rewritten in stdlib Python because
this repo is C++/Python and adding a bun/node toolchain to check source
comments would be a worse trade than writing the scanner.

scripts/traceability/extract_traces.py scans .cpp/.hpp/.py under src, tests,
scripts, experiments and eval for the house tag format

    /// TRACES: AR-012, AR-013 | SR-002

and reports EXCEPTION tags separately. An exception is a recorded decision to
depart from an invariant, so folding it into coverage would invert its
meaning; it is listed with its reason, and a missing reason is flagged.

Two rules carried over from JellyTau's gate repair:

  * Denominators are parsed out of docs/requirements.md at run time. A
    requirement is defined only by a row in a table whose header is
    `| ID | Requirement | ... |`, so references in the Traces to column, in
    prose, and in the verification-plan table do not inflate the count.
    Adding a register row lowers coverage until it is traced - the property
    that dies the moment a denominator is frozen.
  * Coverage above 100% is a hard failure. It cannot happen through the
    intersection, which is the point: if it ever does, the arithmetic is
    broken and the run must not be reported as a pass.

One rule specific to this repo: CI is an Intel N100 with no discrete GPU. The
extractor reads each requirement's verification tier from requirements.md and
reports T4/GPU-only requirements as tagged but unexecuted, never as covered.
Counting a test that can never run is the same failure mode as the 158% bug.

MIN_COVERAGE starts at 0 because almost nothing is tagged yet - tags are added
as the pipeline is built. That is not a gate that cannot fail: orphan tags, a
>100% ratio, a register that parses to nothing, and an empty source scan are
all hard failures from day one. The threshold lives in traceability-gate.sh
alone, never duplicated into the workflow YAML.

53 tests over fixture strings, so their meaning does not drift as requirements
are added.
2026-07-30 18:16:58 +02:00