From f4e8fb5dea6c4d8e6aea9eacb324b3a621418414 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Thu, 30 Jul 2026 21:20:57 +0200 Subject: [PATCH] Adopt the config-driven extractor jray-project replaced the extractor's per-repo CLI flags with a traceability.toml at each component root, so the invocation this repo documented -- --types, --suffixes, --scan-roots -- no longer exists. Bumps the submodule to 17106f3 and moves those settings into config. The gate is now `extract_traces.py --root . --format coverage`, with nothing per-repo on the command line to drift between a developer's shell and CI. Two settings carry reasons worth keeping. Source roots are listed individually rather than as "scripts", because the latter walks scripts/vendor and harvests the AR-nnn examples in the extractor's own docstrings as orphan tags. ci_executable_tiers omits T4: tiers are per-repo now, but T4 keeps the meaning it has in scene-actor-extraction -- "no CI host can run this" -- so a tier number reads the same across repos. Drops the note about the tool expecting jRay to use UR/DR. Its example config now names jRay: ["JR"], so the prefix is settled in all three repos. Same numbers as before the change: 21 tags, 25/46, 0 orphans. TRACES: JR-021 | PR-004 Co-Authored-By: Claude Opus 5 --- docs/requirements.md | 59 ++++++++++++++++--------------------- scripts/vendor/jray-project | 2 +- traceability.toml | 31 +++++++++++++++++++ 3 files changed, 58 insertions(+), 34 deletions(-) create mode 100644 traceability.toml diff --git a/docs/requirements.md b/docs/requirements.md index be920b7..65bf9f1 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -179,13 +179,12 @@ every requirement above except the live-integration ones is executable in CI. | **T4 — Live** | **No** | Real Jellyfin + File Transformation + web client; real manifest server round-trip | | **static** | Yes | Grep/analyzer checks — e.g. no injection path into `index.html` (JR-021) | -**T3 is deliberately unused.** The gate's `CI_EXECUTABLE_TIERS` treats T1/T2/T3 -as CI-runnable and T4 as not, which is right for extraction (where T3 is slow CPU -inference and T4 is GPU). jRay has only two CI tiers and one live tier, so its -non-CI tier is numbered **T4** to match that shared constant rather than -renumbering it. Calling jRay's live tier "T3" would make the gate count -live-only requirements as covered — the exact class of error the 158% coverage -bug belongs to. +**T3 is deliberately unused.** Executable tiers are declared per repo in +[`../traceability.toml`](../traceability.toml), so the numbering is a local +choice — but jRay keeps **T4** for "no CI host can run this" because that is +what T4 means in `scene-actor-extraction`. A tier number should mean the same +thing when read across repos; reusing T3 for a live tier here would make a +cross-repo reader count live-only requirements as covered. `Jellyfin.Plugin.JRay.Tests` (xUnit, in the solution) carries the T1 tier. It builds clean alongside the plugin. @@ -275,38 +274,32 @@ which is exactly why it can be the binding check rather than an aspiration. ## Running the gate -The shared extractor now takes the three things that vary per repo as arguments, -so this repo needs **no fork of it** — there must only ever be one -implementation: +The extractor is shared and vendored, never forked — there must only ever be one +implementation. Everything that varies per repo lives in +[`../traceability.toml`](../traceability.toml), so the invocation carries no +flags to drift out of sync between a developer's shell and CI: ```sh python3 scripts/vendor/jray-project/scripts/traceability/extract_traces.py \ - --root . \ - --requirements docs/requirements.md \ - --system-spec scripts/vendor/jray-project/SPEC.md \ - --types JR \ - --suffixes .cs,.js,.sh \ - --scan-roots Jellyfin.Plugin.JRay,Jellyfin.Plugin.JRay.Tests,scripts/checks \ - --format coverage + --root . --format coverage ``` -`scripts/checks` is scanned so the static checks carry their own TRACES tags — -an enforcement script is evidence for a requirement exactly as a unit test is. -The scan root is `scripts/checks` and **not** `scripts`, because the latter would -walk `scripts/vendor/jray-project` and harvest the `AR-nnn` examples in the -extractor's own docstrings as orphan tags. - -`--root` must be **absolute or `.`**; the scan roots resolve beneath it. Both the -extractor and the system spec come from the submodule, so the only thing this -repo supplies is its own register and the three per-repo arguments. +That config declares the `JR` prefix, the languages, the source roots, the +CI-executable tiers, and the path to the vendored system spec. Refresh the pinned tooling with `git submodule update --remote scripts/vendor/jray-project`. -**Naming conflict to resolve.** The tool's header comment expects -`jRay → UR/DR`. This register uses `JR`, decided deliberately: `JRay-public-server` -already ships `UR-001…018` and `DR-001…014`, so a second repo using the same -prefixes would make `UR-007` ambiguous across registers — and `UR-007` is -precisely the ID the server's own register asks the plugin to cross-reference -(see JR-025). Either the comment or this register is wrong; the comment is the -cheaper of the two to change. +Two choices in it are worth knowing about. `scripts/checks` is scanned so the +**static checks carry their own TRACES tags** — an enforcement script is +evidence for a requirement exactly as a unit test is. And the source roots are +listed individually rather than as `scripts`, because the latter would walk +`scripts/vendor/jray-project` and harvest the `AR-nnn` examples in the +extractor's own docstrings as orphan tags. + +`JR` is now what the shared tooling expects too — its example config names +`jRay: ["JR"]` — so the prefix is settled across all three repos. It was chosen +because `JRay-public-server` already ships `UR-001…018` and `DR-001…014`, and a +second repo reusing those prefixes would make `UR-007` ambiguous across +registers, which is precisely the ID the server's own register asks this one to +cross-reference (see JR-025). diff --git a/scripts/vendor/jray-project b/scripts/vendor/jray-project index 041961c..17106f3 160000 --- a/scripts/vendor/jray-project +++ b/scripts/vendor/jray-project @@ -1 +1 @@ -Subproject commit 041961c8c63bf37fa220dfa1f39858ca9830a84e +Subproject commit 17106f337074753698454ccaf9c739cb6d0b4d79 diff --git a/traceability.toml b/traceability.toml new file mode 100644 index 0000000..a3ea6e7 --- /dev/null +++ b/traceability.toml @@ -0,0 +1,31 @@ +# traceability.toml — per-repo configuration for the shared trace extractor. +# The extractor itself is vendored at scripts/vendor/jray-project. + +# Flat, rather than split by theme as scene-actor-extraction is. The plugin is +# one deployable with one audience, and JRay-public-server already ships UR/DR +# — a second repo using those prefixes would make UR-007 ambiguous across +# registers, and UR-007 is precisely the ID the server asks this register to +# cross-reference (see JR-025). +requirement_types = ["JR"] + +languages = ["csharp", "javascript"] + +# The static checks carry TRACES tags of their own. An enforcement script is +# evidence for a requirement exactly as a unit test is — JR-021 is a +# prohibition, and a prohibition can only be verified by absence. +source_suffixes = [".sh"] + +# Explicit roots rather than "scripts", which would walk scripts/vendor and +# harvest the AR-nnn examples in the extractor's own docstrings as orphan tags. +source_roots = [ + "Jellyfin.Plugin.JRay", + "Jellyfin.Plugin.JRay.Tests", + "scripts/checks", +] + +# jRay has two CI tiers and one live tier. T3 is deliberately unused: T4 keeps +# the meaning it has in scene-actor-extraction — "no CI host can run this" — +# so a tier number means the same thing when read across repos. +ci_executable_tiers = ["T1", "T2", "static"] + +system_spec = "scripts/vendor/jray-project/SPEC.md"