D8 — Where index/combinations/ lives
Status: decided and implemented. index/combinations/ stays in
openregs/openregs, and every combination committed there is proved to resolve
by tooling/tests/test_combinations.py in the required test context. §7 names
the one event that reopens the question, and §5 is the case against this answer,
which is real.
The question. A combination pins a set of regime releases that were validated together. Regimes now have repositories of their own, so a combination is about corpora this repository does not hold. Does the directory graduate to a repository of its own, move into a corpus repository, or stay in the engine?
Who is affected. Anyone pinning a set of releases rather than one, anyone publishing a corpus who then has to record it, and every reviewer of a pull request that changes a pin.
1. What is actually in the directory, and what reads it
Section titled “1. What is actually in the directory, and what reads it”One file: index/combinations/fixture-set.yaml, pinning fixreg@2025.02 and
fixreg@2025.04 — two of the three standing FIXREG releases, all built from this
repository’s own synthetic corpus and all committed under
regimes/fixreg/releases/. It declares the spec_schema_range they were
validated under and the commit of the eval suite that passed over them.
The pin set is two, not three, and deliberately: a combination names releases
that were validated together, and this one is the amendment pair the fixture
ground truth turns on — pre-amendment and post-amendment. The third,
fixreg@2025.06, exists so that openregs diff A..B has a range spanning more
than one release move (fixtures/MANIFEST.yaml says so where it declares it),
which is a different question from what a combination answers. Adding it here
would change what this decision decided.
No real combination exists and none can today. openregs/regime-eu,
openregs/regime-uk and openregs/regime-us-cfr are live and hold zero
canonical units between them; no real regime has published a release, so there is
no pair of real releases for a combination to name.
What reads it is this repository’s own checks. openregs index verify
(tooling/openregs/combinations.py) resolves each pin at a path under the
checkout and refuses a pin to a release that is not there or was built under a
spec version the combination’s range does not cover. The negative cases in
tooling/tests/test_combinations.py — a release outside the range, a missing
release, a file whose name disagrees with its filename, an empty range, a
release whose metadata disagrees with its own tag — are the specification of that
command, and fixture-set.yaml is the input they are written against.
2. Three homes, and what each one costs
Section titled “2. Three homes, and what each one costs”Its own repository (openregs/index). The clean answer if a combination were
only data about corpora. It would today hold one file, whose only content is a
pin to releases that live in the engine, reviewed by the engine’s maintainers
because they are the only people who can build the things it names.
Inside a corpus repository. Rejected outright, and not on cost. A combination is a claim about several regimes at once; putting it inside one of them makes that corpus the arbiter of the others, gives its reviewers a merge gate over releases they do not own, and leaves no answer to which of the two repositories a pin naming both belongs in.
The engine. What §3 and §4 argue for, at the price §5 states.
3. The fixreg test, applied honestly
Section titled “3. The fixreg test, applied honestly”docs/ARCHITECTURE.md § “fixreg is a fixture, not data”
keeps the FIXREG corpus
in this repository permanently on one distinction: FIXREG is not a small legal
corpus that happens to be ours, it is the executable statement of what the engine
must do, and moving it out would put that statement behind a release pin and a
fetch and leave it free to drift from the code it exists to hold still.
That argument transfers to fixture-set.yaml exactly. It is synthetic, it names
only releases that ship in this tree, and it is the fixture the tests of
openregs index verify are written against. Moved out, the specification of a
shipped command becomes something the engine’s test suite has to go and get,
which is also the end of the offline rule for this check.
It does not transfer to a combination pinning regime-eu@<tag> beside
regime-uk@<tag>. That file is data about corpora, changing on the corpora’s
cadence, written by whoever published them. Nothing in the fixreg reasoning
reaches it.
So the honest reading of the fixreg distinction is that it splits the directory rather than settling it: it makes the fixture combination permanent here and says nothing about a real one. The reason the decision below is still “the engine” is the second argument, in §4, and the fact that the real half of the directory is today empty.
4. Decision
Section titled “4. Decision”index/combinations/ stays in openregs/openregs. The mechanism —
the schema, openregs index verify, the directory — and the fixture combination
in it are the engine’s, the second permanently.
Three reasons, in the order they do work:
- A check the engine runs has to be a claim about one commit.
docs/ARCHITECTURE.md§ “Why the engine is one repository” states the rule the whole verification boundary rests on:spec/,tooling/,fixtures/andregimes/fixregare never split because every check here is a claim about two directories at one commit. A combination in another repository pinning releases in this one is a claim about two commits in two histories, which nothing can make true at merge time — only afterwards, and only for whoever remembers to look. - The fixture half never graduates, for §3’s reasons, so the directory could at best be split rather than moved, and a split directory means two places to look for the same kind of file and two implementations of the same check.
- A repository of its own would today hold nothing and have no reviewers. Corpora split out for a stated reason — different reviewers, different cadence — and a combination has neither yet: the only releases that exist are this repository’s own fixtures.
Consequences, stated plainly because they are the price:
- A combination committed here must resolve inside this checkout, offline. That is now enforced rather than assumed; see §6.
openregs index verifykeeps a resolver that reads paths under the checkout. Making a pin resolve by pulling and verifying a release from another repository is real work intooling/, and it is the work §7’s trigger names.docs/ARCHITECTURE.mdalready records that seam.- Re-pinning a real set will be a pull request against the engine, through the engine’s whole gate, until §7 fires. That is §5’s complaint and it is accepted knowingly, not overlooked.
5. The strongest argument against
Section titled “5. The strongest argument against”Not the friction, though the friction is real: once corpora publish, advancing a pin from one month’s EU release to the next will mean opening a pull request against the engine and passing canon rules, conformance, the golden suite and the standing-release rebuilds — none of which has anything to say about a list of tags — to change three lines. That is precisely the drag the corpus split was made to remove, felt by exactly the people it was made for.
The sharper form is a correctness argument, and it is the one that could overturn this decision. The engine cannot honestly verify a real combination at all. A pin resolves at a path under the checkout; a real pin’s releases are in other repositories; so proving that a real combination resolves means fetching a release over the network, and this repository’s tests may not go anywhere. A real combination committed here would therefore either fail CI or force CI online, and the second is not available. The acceptance criterion this document is written against — CI proves every committed combination resolves — is satisfiable in the engine only for pins the engine can resolve locally, which today is all of them and one day will be none of them.
Two things keep that from being a reason to move the directory now rather than
later. The first is that consequence 2 above is work tooling/ owes in either
home: a combination in its own repository would resolve every pin remotely, so
moving the file does not avoid building the pull-and-verify resolver, it makes it
a precondition. The second is §6.
6. What CI proves, and what it cannot
Section titled “6. What CI proves, and what it cannot”tooling/tests/test_combinations.py reads index/combinations/ through
openregs.combinations.discover and runs the shipped openregs index verify over
every file it finds. Not over a filename the test names — over the directory, so a
combination is checked by having been added. It fails closed: a missing directory
is an error rather than an empty sweep, and an entry that is neither a combination
nor .gitkeep/README.md is refused rather than skipped, because the realistic
way a check like this goes blind is one file saved as .yml.
What it proves, per committed file: the file is schema-valid and named after itself, every release it pins exists at the path the pin resolves to, every one of those releases declares a spec version inside the combination’s range, and the eval suite it cites as evidence is a file in this tree.
What it cannot prove is in §5, and it is worth being exact: it does not re-run the eval suite, does not check artifact digests — a release’s own signature answers for its bytes and a combination answers only for the set — and it cannot resolve a pin into another repository.
That last limit is enforced rather than documented. A pin naming a regime this checkout does not hold fails, and the failure says the corpus is a repository of its own and cites this document. The day somebody commits a real cross-regime pin into the engine, CI stops them and points here. The question below reopens mechanically instead of by anyone remembering it was open.
7. Trigger to revisit
Section titled “7. Trigger to revisit”Not a date, and not the creation of a corpus repository — both regime-eu and
regime-uk already exist and neither changes anything above. Revisit D8 when
a second real regime publishes a release, so that a combination could name two
releases from two corpus repositories. At that point the resolver in consequence 2
is owed regardless, and the choice between “the engine, with a pulling resolver”
and “a repository of its own” is a live one with something in it to decide about.
Until then, the answer here costs one directory in the engine, and the alternative costs a repository holding a file that must not leave.
Rendered from openregs/openregs@f3a2d10:docs/decisions/d8-combinations-home.md