adr-052: constellation umbrella model
This commit is contained in:
parent
d57ebd9ea6
commit
d37b3575be
1 changed files with 123 additions and 0 deletions
123
.ontoref/adrs/adr-052-constellation-umbrella-model.ncl
Normal file
123
.ontoref/adrs/adr-052-constellation-umbrella-model.ncl
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
let d = import "adr-defaults.ncl" in
|
||||
|
||||
d.make_adr {
|
||||
id = "adr-052",
|
||||
title = "Constellation umbrella model: a public root repo tracks .ontoref, members are gitignored repos-within-repo",
|
||||
status = 'Proposed,
|
||||
date = "2026-07-09",
|
||||
|
||||
context = "The constellation schema and declaration asserted a NON-GIT spine model (flat sibling code repos under a non-git root, the root's .ontoref/.coder/.claude tracked by a single private, never-mirrored bare overlay prvng_internal). This is the first ADR to record the constellation LAYOUT itself — the earlier 'ADR-048 layout / ADR-062 taxonomy' citations in the schema are cross-layer references to the ontoref protocol, not provisioning ADRs (provisioning's adr-048 is the desktop native shell). Materializing that declaration into real repos surfaced two defects the paper design hid. (1) Publication boundary: the entire root .ontoref — the ontology (core/state/gate/manifest), 40+ ADRs, and the reflection protocol — was pushed into the PRIVATE overlay, so every public member repo (code, core, catalog, platform, outreach) exposed ZERO architecture. ADRs exist to be read by contributors; burying them in a private repo defeats their purpose. A non-git spine can track nothing publicly, so there was no public home for the shared ontology at all. (2) Naming asymmetry: the sibling layout put the `code` member at the flagship name `provisioning` while every other member carried a `prvng_` prefix, so the member→repo mapping needed a special case, and `prvng_` duplicated the org name once the repos moved under a dedicated `provisioning` Forgejo org. An attempt to derive the fix from the ontoref sibling was itself unreliable — ontoref's repo is mid-migration with 257 deleted-but-still-indexed `.ontology/`/`.ontoref/` paths, so `git ls-files` reported a `code/.ontology` public layout that does not exist on disk. The user's constraint settled it: the project ROOT must hold `.ontoref` and that `.ontoref` must be PUBLIC.",
|
||||
|
||||
decision = "The constellation root becomes a PUBLIC umbrella git repo `provisioning/provisioning` that tracks the shared `.ontoref` (ontology + ADRs + reflection) and gitignores every member directory (code, core, catalog, platform, outreach, vault, assets) plus `.coder`, `.claude`, `.internal.git`. Members keep their own `.git`; the umbrella never tracks them — repos-within-repo, NO gitlinks (mode 160000), NO submodules. The member gitignores in the umbrella are load-bearing: they are the only thing preventing the umbrella from swallowing a member if that member's `.git` were removed. Every repo is renamed to a uniform `provisioning-<member>` scheme (code→provisioning-code, core→provisioning-core, catalog→provisioning-catalog, platform→provisioning-platform, outreach→provisioning-outreach, vault→provisioning-vault); the `prvng_*` prefix and the `code`-as-flagship exception are both dropped — the flagship name `provisioning` now belongs to the umbrella root, not to a member. The root's PRIVATE dev-internal `.coder/.claude` remain a separate never-mirrored overlay (`provisioning-internal`); `.ontoref` is NOT in that overlay (removed via amend of its single clean-start commit). Runtime journals (`.ontoref/logs/`, `.ontoref/ontoref.jsonl`, `.ontoref/locks/`) are gitignored from the public umbrella so session noise is not published; the durable ontology/ADRs/reflection are. The constellation schema gains a `root_repo` type (canonical_url, mirror, ci, tracks) and `spine_overlay.paths` drops to `[.coder, .claude]`. This REPLACES the non-git-spine model previously asserted in the constellation schema; it keeps the established forge rule (Forgejo canonical, vault never mirrored, projection owns no repo), extended to cover the umbrella. Provisioning is the PILOT — ontoref and stratumiops adopt the same model afterward, not before.",
|
||||
|
||||
rationale = [
|
||||
{
|
||||
claim = "Architectural knowledge is product, not dev-internal — ontology and ADRs must be publicly visible",
|
||||
detail = "The `.coder`/`.claude` dirs are genuinely private (session plans, agent config); the `.ontoref` ontology, the 40+ ADRs, and the reflection protocol are the durable architecture contributors must read and follow. Lumping all three into one private overlay was a category error: it made every public repo architecture-blind. Splitting `.ontoref` (public) from `.coder/.claude` (private) restores the intended boundary.",
|
||||
},
|
||||
{
|
||||
claim = "The root is the only correct home for the whole-constellation ontology, and a public umbrella repo is the only way to track it there",
|
||||
detail = "constellation.ncl describes ALL members; core/state/gate/manifest describe the project as a whole; the ontoref CLI resolves `.ontoref` from the root. That content is spine-level, not member-level — moving it into `code` would put whole-topology declarations inside one member (wrong layer). A non-git spine cannot publish anything, so making the root a real public repo is the minimal mechanism that keeps `.ontoref` at the root AND public.",
|
||||
},
|
||||
{
|
||||
claim = "Gitignoring every member neutralizes the repos-within-repo risk — no gitlinks, no submodule confusion",
|
||||
detail = "The failure mode we already eliminated once was mode-160000 gitlinks-without-.gitmodules. A naive root `.git` would reintroduce it by swallowing members as gitlinks. Because the umbrella gitignores each member dir, the members are neither tracked as files nor as gitlinks — they are simply invisible to the umbrella. Cloning `provisioning/provisioning` yields `.ontoref` + README + assets and empty member dirs; members are cloned separately. This is the standard meta/umbrella-repo pattern.",
|
||||
},
|
||||
{
|
||||
claim = "Uniform provisioning-* naming removes the flagship special-case and the redundant prefix",
|
||||
detail = "With a dedicated `provisioning` Forgejo org, `prvng_` duplicated the org name, and `code`-as-`provisioning` forced the member→repo map to special-case one member. Moving the flagship name to the umbrella root and naming every member `provisioning-<name>` (and every overlay `provisioning-<name>-internal`) makes the mapping a single mechanical rule with no exception.",
|
||||
},
|
||||
{
|
||||
claim = "Runtime journals are excluded from the public repo while the architecture is published",
|
||||
detail = "`.ontoref/logs/*.jsonl`, `ontoref.jsonl`, and `locks/` are session action journals — noise, not architecture. Gitignoring them from the umbrella keeps the public repo to durable ontology/ADRs/reflection, so 'public .ontoref' means 'public architecture', not 'public session logs'. The CLI still writes/reads these on disk; only their tracking is dropped.",
|
||||
},
|
||||
],
|
||||
|
||||
consequences = {
|
||||
positive = [
|
||||
"Public repos now expose the architecture: ontology + 40+ ADRs + reflection are visible at provisioning/provisioning.",
|
||||
"One mechanical member→repo mapping (provisioning-<name>), no flagship exception, no prvng_ prefix.",
|
||||
"The gitlink disease stays dead: members are gitignored, tracked neither as files nor mode-160000 entries.",
|
||||
"Private dev-internal (.coder/.claude) stays isolated in a never-mirrored overlay; .ontoref is no longer duplicated into it.",
|
||||
"'Public .ontoref' excludes session journals — the public surface is durable architecture only.",
|
||||
],
|
||||
negative = [
|
||||
"Repos-within-repo is non-standard: a clone of the umbrella yields empty member dirs; members must be cloned separately (or via a bootstrap that clones each provisioning-<member>).",
|
||||
"The umbrella's member gitignores are load-bearing — deleting one (or a member losing its .git) risks the umbrella swallowing that member's tree; this must be guarded and documented.",
|
||||
"Supersedes ADR-048's non-git-spine assumption: the schema (root_repo type), the constellation-sync mode, and any spine-dependent tooling must follow the new model.",
|
||||
"Sibling divergence: ontoref and stratumiops still use their older layouts until they adopt this model; the constellation is temporarily non-uniform (provisioning is the pilot).",
|
||||
],
|
||||
},
|
||||
|
||||
alternatives_considered = [
|
||||
{
|
||||
option = "Keep .ontoref (with .coder/.claude) in the single private spine overlay (status quo of ADR-048)",
|
||||
why_rejected = "Buries the ontology and every ADR in a private repo; public members expose no architecture. Directly contradicts the purpose of ADRs (to be read) and the user's constraint that .ontoref be public.",
|
||||
},
|
||||
{
|
||||
option = "Give .ontoref its own dedicated PUBLIC overlay (a second bare git-dir) at a still-non-git spine root",
|
||||
why_rejected = "Keeps the root non-git but needs two bare git-dirs coexisting at one worktree and the overlay driver repurposed for a public remote — more exotic and more moving parts than a plain public repo, for no benefit.",
|
||||
},
|
||||
{
|
||||
option = "Move .ontoref into the code member so it is tracked publicly there",
|
||||
why_rejected = "constellation.ncl and the project-level ontology are whole-constellation, spine-level artifacts; nesting them inside one member is the wrong layer and contradicts 'the project root holds the ontology'. The CLI also resolves .ontoref from the root.",
|
||||
},
|
||||
{
|
||||
option = "Keep code as the flagship `provisioning` repo with members as prvng_*",
|
||||
why_rejected = "Asymmetric: special-cases the member→repo mapping and duplicates the org name in the prefix. Uniform provisioning-* with the flagship on the umbrella root is simpler and exception-free.",
|
||||
},
|
||||
],
|
||||
|
||||
constraints = [
|
||||
{
|
||||
id = "root-umbrella-tracks-ontoref-public",
|
||||
claim = "The constellation root is a public git repo (provisioning/provisioning) that tracks .ontoref (ontology + ADRs + reflection). The durable ontology and ADRs must be present in the public umbrella, not only in a private overlay.",
|
||||
scope = "provisioning/.git, provisioning/.ontoref/",
|
||||
severity = 'Hard,
|
||||
check_hint = "git -C <root> ls-files .ontoref | grep -E '(adrs|ontology|reflection)/' must be non-empty; the umbrella origin resolves to .../provisioning/provisioning.git.",
|
||||
rationale = "The whole point of the umbrella model is that architecture is publicly visible; a root repo that does not track .ontoref defeats it.",
|
||||
},
|
||||
{
|
||||
id = "members-gitignored-no-gitlinks",
|
||||
claim = "The umbrella must gitignore every member directory (code, core, catalog, platform, outreach, vault, assets) and .coder/.claude/.internal.git. No member may appear in the umbrella as a tracked path or as a mode-160000 gitlink.",
|
||||
scope = "provisioning/.gitignore, provisioning/.git",
|
||||
severity = 'Hard,
|
||||
check_hint = "For each member m: git -C <root> check-ignore m must succeed; git -C <root> ls-files -s | awk '$1==\"160000\"' must be empty.",
|
||||
rationale = "The member gitignores are the only barrier preventing the umbrella from swallowing a member as files or gitlinks; they are load-bearing, not cosmetic.",
|
||||
},
|
||||
{
|
||||
id = "ontoref-not-in-private-overlay",
|
||||
claim = "The root spine_overlay (provisioning-internal) tracks only .coder and .claude. .ontoref must not be re-added to the private overlay (it is public in the umbrella).",
|
||||
scope = "provisioning/.internal.git, provisioning/.ontoref/reflection/schemas/constellation.ncl (spine_overlay.paths)",
|
||||
severity = 'Hard,
|
||||
check_hint = "git --git-dir=<root>/.internal.git --work-tree=<root> ls-files | grep -c '^\\.ontoref/' must be 0; spine_overlay.paths == [\".coder\", \".claude\"].",
|
||||
rationale = "Tracking .ontoref in both the public umbrella and the private overlay duplicates it and would re-publish architecture into the private tier on push.",
|
||||
},
|
||||
{
|
||||
id = "uniform-provisioning-naming",
|
||||
claim = "Every repo is named provisioning (umbrella), provisioning-<member> (public member), or provisioning-<member>-internal / provisioning-internal (private overlay). No prvng_* names and no code-as-flagship exception.",
|
||||
scope = "provisioning/.ontoref/ontology/constellation.ncl, every member .git/config, every .internal.git remote",
|
||||
severity = 'Hard,
|
||||
check_hint = "grep -r 'prvng_' constellation.ncl must be empty; every canonical_url/overlay_url matches ^.../provisioning/provisioning(-[a-z]+)?(-internal)?\\.git$.",
|
||||
rationale = "A single mechanical member→repo mapping with no special case; the prefix is redundant under a dedicated provisioning org.",
|
||||
},
|
||||
{
|
||||
id = "runtime-journals-not-public",
|
||||
claim = "Session runtime under .ontoref (logs/, ontoref.jsonl, locks/) is gitignored from the public umbrella; only durable ontology/ADRs/reflection are tracked publicly.",
|
||||
scope = "provisioning/.gitignore, provisioning/.ontoref/logs, provisioning/.ontoref/ontoref.jsonl",
|
||||
severity = 'Hard,
|
||||
check_hint = "git -C <root> ls-files '.ontoref/logs/*' '.ontoref/*.jsonl' must be empty; those paths are listed in the root .gitignore.",
|
||||
rationale = "'Public .ontoref' means public architecture, not public session journals; publishing the journals is noise and a minor information leak.",
|
||||
},
|
||||
],
|
||||
|
||||
ontology_check = {
|
||||
decision_string = "Make the constellation root a public umbrella repo that tracks .ontoref and gitignores every member (repos-within-repo, no gitlinks); rename all repos to provisioning-*; keep .coder/.claude in a private never-mirrored overlay; exclude runtime journals from the public umbrella. Replaces the non-git-spine model previously asserted in the constellation schema.",
|
||||
invariants_at_risk = ["config-driven-not-hardcoded"],
|
||||
verdict = 'Safe,
|
||||
},
|
||||
|
||||
tags = [],
|
||||
|
||||
related_adrs = [],
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue