The spine repo — the constellation parent witnesses exactly what belongs to no member

Accepted

ontoref
ADR-048 moved the protocol spine out of code/ and up to the constellation parent, on the argument

Context

ADR-048 moved the protocol spine out of code/ and up to the constellation parent, on the argument that "the spine governs the project, not the implementation — it belongs at the level that encompasses all sub-repos". The same decision text describes the parent as "a non-versioned parent directory (no .git/)". The constellation declaration repeats it: `.ontoref/ontology/constellation.ncl` comments its `spine_overlay` field with "The parent stays a non-git spine; this is a private bare overlay git-dir, not a repo".

Both statements are false of ontoref today, and have been for as long as the spine has lived there. Measured 2026-07-25:

ontoref/ IS a git repo remote ssh://git@repo.jesusperez.pro:2222/ontoref/ontoref.git tracked: .ontoref 891 files the spine assets 51 files the Projection(copy) canonical source scripts 7 files + README.md, justfile, CHANGELOG.md, .gitignore ignored: code desktop outreach vault examples resources .coder .claude .internal.git

That is not a monorepo and not a wrapper over the sub-repos. Its tracked extent is precisely the content that belongs to NO member, and it ignores every member by name. The arrangement is coherent, proven in daily use, and unnamed — which is why the declaration could contradict it without anyone noticing.

The cost of leaving it unnamed is not theoretical. Two constellations copied the layout and not the witness:

rustelo/.ontoref no .git, no overlay — spine unversioned stratumiops/.ontoref no .git, no overlay — spine unversioned

Session 2026-07-25 wrote three backlog items, one qa entry and two connection repairs into those two spines. None of it can be recovered if the directory is lost, and none of it can be reviewed as a diff. A third case is mid-flight: workspaces/libre-wuji re-initialized its repo the same day and tracks one file, README.md, with .ontoref/ untracked — bit for bit the starting condition ADR-070 diagnosed on outreach ("git was not a witness … the recovery was archaeology, not verification").

ADR-048's "non-versioned" was true of the parent it inherited: a directory holding nothing but structure. ADR-048 itself is what stopped it being true, by moving the project's most durable content there. The clause was never revisited, so the layout propagated with a witness gap written into its own definition.

And the unnamed repo left a second mark, found by running this ADR's own check before declaring it gate-worthy. `constellation.ncl` declares member `code` with

canonical_url = ssh://git@repo.jesusperez.pro:2222/ontoref/ontoref.git

which is the PARENT's remote. code/'s actual remote is `ontoref/ontoref-code.git`. The spine repo exists, has a URL, and — having no field to be declared in — that URL was recorded against a member. A repo with no name in the model does not disappear from the model; it attaches itself to the nearest thing that has one. (Corrected in the declaration the same day, against the live remote; the constraint below is what keeps it corrected.)

Decision

The constellation parent IS a git repo — the SPINE REPO — and its tracked extent is exactly the content that belongs to no member:

TRACKED .ontoref/ the protocol spine (ontology, adrs, reflection, positioning) non-repo Projections whose canonical source sits at the parent (assets/) constellation chrome README, justfile, CHANGELOG, scripts/ IGNORED every declared member, by name — and .coder/ .claude/ .internal.git/

It is member-less by construction. No path under a declared member is ever tracked by it, so it is neither a monorepo nor a parent that pins its children: the members remain independent repos with their own remotes and visibility, exactly as ADR-048 established. What changes is only that the parent stops pretending to hold nothing.

The obligation this ADR creates is a PROPERTY, not a topology: **every spine has a witness**. A project whose spine lives inside its single repo (the flat, tier-0 adoption shape) already satisfies it and acquires no new work. The spine repo is how a CONSTELLATION satisfies it — and a constellation is already the opt-in, higher-formalization layout.

Two mechanisms carry it:

1. `constellation.ncl` declares `spine_repo` alongside the existing `spine_overlay`. The overlay stays what it is — the PRIVATE bare git-dir for .coder/.claude, never mirrored (ADR-062). The spine repo is PUBLIC: the spine is the project's declared self-description, not process memory. Two witnesses, two visibilities, one working tree — the plane-habitability pattern already proven by the dev-internal overlay.

2. `constellation-sync` gains the check. This ADR does not ship as a declaration alone: an unenforced constraint about missing enforcement would be the very defect it names.

Constraints

  • Hard A project's .ontoref/ spine MUST be tracked by some version-controlled repository. In the flat layout that is the project's own repo; in a constellation it is the spine repo at the parent. A spine directory reachable by no `git ls-files` is malformed.
  • Hard The spine repo MUST NOT track any path under a member that owns its own repo (any member whose category is not 'Projection). Projections whose canonical source sits at the parent — assets/ — are precisely what the parent DOES track: they own no repo, so their content belongs to no member's history.
  • Hard The spine repo's remote MUST NOT be any member's canonical_url. Parent and member are distinct repositories with distinct histories; sharing a URL means two working trees pushing one history.
  • Hard A constellation MUST declare its spine's witness in constellation.ncl (`spine_repo`), distinct from `spine_overlay`. The declaration is what makes the witness checkable by constellation-sync.
  • Hard The spine repo carries the public visibility of the project's self-description; the dev-internal overlay stays private and never mirrored (ADR-062). The spine MUST NOT be routed through the private overlay.
  • Soft The clause 'a non-versioned parent directory (no .git/)' in ADR-048's decision, and the equivalent comment in constellation.ncl, are withdrawn by this ADR. ADR-048 otherwise stands: the spine lives at the parent, members are independent repos, assets/ is not a member repo.

Alternatives considered

  • Keep the parent non-git and give the spine a PUBLIC bare overlay, mirroring the dev-internal mechanismrejected: It preserves ADR-048's letter at the cost of its purpose. The mechanism would be identical to a plain repo in everything that matters (a git-dir whose work-tree is the parent, tracking a fixed set of paths) while being unfamiliar to every tool and every collaborator: clone, browse-on-forge, CI and `git log` all expect a repo. The overlay's peculiar shape is justified for .coder because those paths must be HIDDEN from a repo that already exists on the same tree; the spine has no such repo to hide from. Choosing it would be formalization bought with adoption friction and no gain — the wrong side of the tension this project names.
  • Move the spine back inside code/ so the existing member repo witnesses itrejected: This is ADR-048 reversed, and it reintroduces exactly what that ADR removed: the spine scoped to the Rust implementation repo while its authority covers outreach/ and vault/. It would also break ADR-028 (the ontology must be addressable independently of the project filesystem) for every consumer that verifies ontoref by witness rather than by cloning code/.
  • Track the members from the parent as submodules so one repo covers everythingrejected: Forbidden by ADR-062 (`no-submodules-as-structure`, Hard). A submodule is clone-and-pin, which contradicts witness-not-clone (ADR-028). It would also make the parent a wrapper over its children — the precise thing this decision defines the parent as NOT being.
  • Leave it undeclared and let each constellation improviserejected: That is the status quo, and it is what produced three unwitnessed spines from one unstated rule. The layout propagated by copying directory structure; the witness did not propagate because nothing said it existed.

Anti-patterns

  • Spine without witness — A project's .ontoref/ lives in a directory no repository tracks — typically because the constellation layout was copied (parent + code/ sub-repo + spine at parent) while the parent was left unversioned. Ontology, ADRs and backlog become unrecoverable and unreviewable, and edits made by another session leave no diff.
  • Parent absorbs a member — A member is added to the constellation and not to the parent's .gitignore, so the spine repo starts tracking files that belong to that member's own repo. The parent silently becomes a wrapper over its children and the member's history forks in two places.
  • Spine hidden in the private overlay — The spine is committed through the dev-internal bare overlay because it is already there and already works, putting the project's public self-description behind a never-mirrored private remote. Cross-project verification by witness (ADR-028) becomes impossible for anyone outside that remote.

Related ADRs

ADR-048 · ADR-062 · ADR-070 · ADR-028 · ADR-045 · ADR-032

Was this useful? Rate it
Got something to add? Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
· reads

We use cookies to help this site function, understand service usage, and support marketing efforts. Cookie Policy for more info.