Accepted adr-021 · 2026-10-08

Each Project Declares Its Governance Levels, a Script Collects Them Into the File a Service Reads, Each Project Is Shown With Its Logo and Levels, and ontoref's Panel and SpecDossier Link to Each Other

Context

A service reads the levels its service.ncl declares, each `{ project, path }` written by whoever deploys it (adr-002, adr-014); its menu offers those projects and nothing else. The principal's reader declared one level, `code`, so no other project could be reached from the face. The principal asked, 2026-10-08, where the projects SpecDossier may read are declared, and then set the direction: «each project should declare its governance folders, and a script (Nushell) collect them to tell the SpecDossier server which projects to use and which governances, with the mode and authority each one has — ontoref already does something like it, collecting from an NCL and passing it as JSON to the ontoref daemon; this could be changed to something better and more fitting»; «as in ontoref's daemon, changing project changes the logo in the top left corner, and each project's logo is shown on its card on the home page, where its governance folders are shown too»; «the governance of the project itself that ontoref does with its panel and SpecDossier's could communicate, for now at least, as links opening in separate windows».

What exists, measured 2026-10-08: - ontoref's machine registry, `~/.config/ontoref/projects.ncl`, generated by `ontoref project-add` and the daemon's boot (gen-projects.nu), never edited by hand; each entry's root is the registry's, never the project's (ontoref adr-129). The daemon reads it, with ~/.config/ontoref/config.ncl (`daemon.port` 7890), and offers every registered project. ontoref publishes of it only `ontoref project root <id>`; a listing was asked of ontoref, in session, 2026-10-08. - A project's identity, its logo included, is declared on its beacon, `.ontoref/card.ncl`, typed by ontoref's ProjectCard (specdossier: `logo = "assets/branding/specdossier-logo-light.svg"`); `.ontoref/config.ncl` `ui.logo` is the daemon's configuration. Neither is a published surface: card.ncl imports its schema through a layout-specific relative path that differs between ontoref's checkout and a consumer install; the published surface is `ontoref describe project --fmt json`, which carries no logo yet — its publication there is asked of ontoref (ontoref-6d, 2026-10-08). - ontoref's panel serves each project at `/{slug}/` (ontoref ui/mod.rs:75): a link to it needs nothing from ontoref but the project's id. - A name ontoref holds (ontoref-6d, 2026-10-08): `reflection/levels.ncl` is ontoref's level source registry (ontoref adr-045, adr-046), so a second file named levels.ncl breaks one name per tree (ontoref adr-116). ontoref adr-124 holds the SOW, its schema and the acts that move it as ontoref's — not every file of a governance level — and leaves open how a project declares the channel it grants; `.governance/dossiers.ncl` (adr-002) is plausibly that grant, an open question for the principal, not a violation. - A governance level already says its own mode: `authority/offline.ncl` and `witness.pub` (offline) or `authority/pins.json` (an authority's project and keys), and whether it holds dossiers (`dossiers.ncl`, adr-002). No project says which levels it has: specdossier has two (the spine's `.governance/` and code's), found by hand. - Twenty projects are registered on the principal's machine; eight hold a `.governance/` at their root. - The spine's reader recipe (`just reader members="code ."`) declares several levels by hand — the deployer's list, kept in step by hand.

Decision

EACH PROJECT DECLARES ITS GOVERNANCES, IN SPECDOSSIER'S NAMESPACE. A project that SpecDossier may read writes `.specdossier/governances.ncl` at its root, typed by SpecDossier's `schemas/governances.ncl`: each governance level's path relative to the project's root (`.governance`, `code/.governance`) and its name. It lives in SpecDossier's own directory, under a name no other tool holds, so it neither shadows ontoref's `levels.ncl` nor adds a SpecDossier file to a level whose files ontoref's formats read. The project declares which levels it has and what they are called — nothing it could only repeat: each level's mode, its authority and its dossiers are read from the level's own files, as they are today.

A SCRIPT COLLECTS THEM INTO THE FILE THE SERVICE READS. `scripts/governances.nu collect` (Nushell) takes the projects to read — ontoref's published listing when ontoref publishes it, else the list the operator gives — reads each project's `.specdossier/governances.ncl`, and writes one generated file, `governances.generated.ncl`, that a service.ncl imports (`levels = import "governances.generated.ncl"`): for each level its project, root, path, name, mode (offline or authority) and authority (endpoint, the pins' project), and the project's identity — its name, description and logo — as `ontoref describe project --fmt json` publishes it; the collector reads no file of `.ontoref/`, and a project whose logo ontoref does not publish is shown with SpecDossier's. The file is generated, never edited by hand, and typed: exporting the service.ncl checks it against `Service`. Running the script is the deployer's act, where the projects are; its file is carried to where the service runs. The service still searches nothing and reads only what it declares (adr-002, adr-014).

A PROJECT IS SHOWN WITH ITS LOGO AND ITS LEVELS. The main menu shows the logo of the project being read in its top left corner, changing with the project; with none, SpecDossier's own. Each project's card on the home page shows its logo, its description and each of its levels — its name, its mode, its authority, its SOWs in force, in draft and archived — each level linking to its list. The logo is the file the generated declaration names, served from it; the service reads nothing of `.ontoref/`.

ONTOREF'S PANEL AND SPECDOSSIER LINK TO EACH OTHER, AND ONLY LINK. Where the deployment declares ontoref's panel (`ontoref_panel = "<url>"` in service.ncl), each project's card and the menu link to that project's page on the panel, `<panel>/{id}/`, opening in another window; that ontoref's panel links back to SpecDossier is ontoref's to decide. Neither reads the other's data through the link.

WHAT THIS AMENDS: it settles adr-002's open question — a deployed service learns which projects and levels to read from the generated declaration its service.ncl imports; levels declared by hand in service.ncl stay valid beside it, a level declared by hand winning over a collected one with the same project and path.

WHAT THIS DOES NOT DECIDE: the listing of projects, which is ontoref's to publish; whether ontoref publishes which governance levels a project has (a question for the principal in ontoref) — until then the project declares them in SpecDossier's namespace; where `.governance/dossiers.ncl` belongs (adr-002), an open question under ontoref adr-124's undecided channel grant; which levels a service that acts may answer for — its authority's projects bind it (adr-004); a dashboard across projects; any exchange between ontoref's panel and SpecDossier beyond links.

Constraints

Alternatives considered