dtourolleandClaude Opus 5 fec03099bc docs: commit trailers close the traceability chain
Commits that implement, change, or withdraw a requirement carry a TRACES
trailer using the same token and syntax as the code tags, so one grep pattern
serves both.

This is the last link. Code tags say where a requirement lives; commit trailers
say when and why it changed, and `git log --grep=AR-012` then reconstructs a
requirement's whole history — which no other artifact provides.

A commit serving no requirement omits the trailer: absence is meaningful, and
inventing a tag to satisfy the form is how orphan tags get created. Withdrawing
a requirement counts as changing it, so the withdrawal stays findable.

Also updates the chain diagram, which still referenced the retired @implements
tag and the thematic A1..E8 IDs.

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

JRay

A self-hosted alternative to Amazon X-Ray. While watching, the viewer can see who is on screen — for their own library, on their own hardware, with nobody else learning what they own.

This is the project home. It owns the system specification — the requirements that span more than one component — and the tooling shared between them. The code lives in three separate repositories, linked below.


The three components

Repository Role Language
scene-actor-extraction Derives presence data from a media file C++ / Python
jRay Jellyfin plugin: surfaces it in the player, owns the truth-file format C#
JRay-public-server Exchanges presence data between instances Rust

They ship independently — the plugin to Jellyfin's catalogue, the server as a binary, the pipeline to a GPU host — which is why they are separate repositories rather than one monorepo.

media file ──► extraction ──► truth file (sidecar or pushed) ──► plugin ──► player overlay
                   ▲                          │
                   │                          ▼
              gallery                   Jmanifest ──► public server ──► other instances
             (Jellyfin + TMDB)

Two axes, deliberately separate: presence data flows outward and is shareable, being timings against public identifiers. Gallery data — the actor reference faces — is built locally and never leaves the instance (SR-005).


Setting up

Clone this repository, then the components beside it:

git clone git@gitea.tourolle.paris:dtourolle/jray-project.git
cd jray-project

git clone git@gitea.tourolle.paris:dtourolle/scene-actor-extraction.git
git clone git@gitea.tourolle.paris:dtourolle/jRay.git
git clone git@gitea.tourolle.paris:dtourolle/JRay-public-server.git

The component directories are .gitignored here, so they sit beside the system spec without this repository trying to track them. Each has its own README with build instructions.

Why not submodules for the components

A submodule pins a commit. With feature branches and worktrees in flight across the components, every component commit would leave this repository's pointer stale and its git status dirty until someone committed a pointer bump — churn that buys nothing, since the components are developed together in one directory anyway.

The dependency runs the other way instead: components pull this repository in for the shared tooling and the system spec, both of which change rarely. That is the asymmetry submodules suit.


Where to start reading

Doc Owns
SPEC.md System requirements — PR-nnn project goals, SR-nnn cross-component contracts
CLAUDE.md Working notes and the invariants that must not be violated silently
Each repo's SPEC.md That component's software requirements
Each repo's docs/requirements.md Its stable requirement IDs, status, and verification plan

Read the system spec first. Every component requirement traces up to an SR-nnn, and every SR-nnn to a PR-nnn, so the chain explains why a given piece of code exists.


Requirement traceability

Requirements are traceable up to the project goal and down to the code implementing them. A requirement nothing traces to is either unnecessary or unimplemented, and both are worth knowing.

PR-nnn   project requirement   (SPEC.md §1)   — why the system exists
 └─ SR-nnn   system requirement   (SPEC.md §3)   — what spans components
     └─ component requirement  (each repo's docs/requirements.md)
         └─ TRACES tag         (source)

Tag the code that satisfies a requirement:

/// TRACES: UR-003 | SR-004
pub fn validate_manifest(m: Jmanifest) -> VResult<ValidManifest> { … }

A pipe separates requirement types; a comma separates IDs within a type. Tag the unit that decides, not every helper it calls — a tag on every function is noise, and rots faster than it helps.

The gate reports coverage, orphan tags (an ID no register defines), and untraced requirements. Two rules it inherits from JellyTau, both learned the hard way:

  • Denominators are read from the register at run time, never hardcoded. A gate that divides by a frozen literal reported 158% coverage for months and so could never fail — worse than no gate, because it was trusted.
  • Coverage above 100% is a hard failure, not a pass. It means the computation is broken, and it is the signal that catches the above immediately.

Licence

GPLv3, matching the Jellyfin plugin it serves.

S
Description
No description provided
Readme CC0-1.0
156 KiB
Languages
Python 97.4%
Shell 2.6%