Lift ops-warden's binding rules into owned ADRs
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Five rules that governed this repo lived in wiki prose, a workplan, and a
comment at the top of catalog.yaml. All were followed; none was addressable.
A reader outside ops-warden could not cite one, could not tell whether it was
current, and — the point of this change — could not tell whether it was ours
to change or someone else's that we merely obey.

  ADR-0001  The routing catalog is a pointer layer, never a second copy
  ADR-0002  ops-warden is a transparent conduit, never a secret broker
  ADR-0003  Cover gaps, but never silently own them
  ADR-0004  High-risk lanes refuse raw value streaming to agent sessions
  ADR-0005  Implement one lane narrowly, route everything else

Each carries owner: ops-warden, which is the load-bearing field. It says we
follow the rule AND we are responsible for changing it — by superseding ADR,
never an in-place edit. The failure this prevents runs both ways: a rule we own
mistaken for inherited canon never gets fixed, because we wait for an owner who
does not exist; inherited canon mistaken for ours gets quietly bent, and the
drift is invisible until it breaks a repo that trusted the canonical version.

Rules we follow but do not own — NetKingdom canon, the IAM profile, the
credential-management standard, the-custodian's ADR-001 workplan convention —
are cited, never copied into docs/adr/. Copying them would recreate exactly the
second-source-of-truth failure ADR-0001 exists to prevent. architecture.md also
now flags the three-digit/four-digit ADR-001 vs ADR-0001 collision, which is
itself an ours-versus-inherited confusion waiting to happen.

Publication verified rather than assumed: all five render through policy-nexus
tools/render.py, and owner reaches the reader in three places — the page eyebrow
(render.py:346), the index Owner column (build_site.py:123,137), and the
publication manifest. build_site.py:179 makes title/status/owner required, so
ownership cannot be dropped on the way out. policy-nexus publishes and never
writes back; docs/adr/ stays the source of truth.

Documentation adapted: SCOPE.md gains a Governing rules section and an orientation
entry; .claude/rules/architecture.md replaced its stub with the ADR index, the
owned-versus-inherited rule, and ADR-over-wiki precedence; finding-routing.md's
ADR-gap section closed; catalog.yaml's no-double-source header now cites ADR-0001
rather than the originating workplan.

uv run pytest -q → 338 passed, 4 deselected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-18 13:35:13 +02:00
parent faa4f2c23e
commit 35aff380a3
10 changed files with 601 additions and 13 deletions

View file

@ -1,7 +1,54 @@
## Architecture
<!-- TODO: Describe the key design decisions and component structure.
Key modules, data flows, external integrations, state machines, etc. -->
### Our rules are ADRs — `docs/adr/`
The decisions that govern this repo live in `docs/adr/` as addressable records,
not in wiki prose. Read `docs/adr/README.md` first; it explains the one
distinction that matters here.
| ADR | Rule |
| --- | --- |
| `ADR-0001` | The routing catalog is a pointer layer, never a second copy of an owner's procedure |
| `ADR-0002` | ops-warden is a transparent conduit, never a secret broker |
| `ADR-0003` | Cover gaps, but never silently own them |
| `ADR-0004` | High-risk lanes refuse raw value streaming to agent sessions |
| `ADR-0005` | Implement one lane narrowly, route everything else |
### Owned versus inherited — check `owner:` before changing anything
Every ADR carries `owner:` in its frontmatter, and it decides what you are allowed
to do with the rule:
- **`owner: ops-warden`** — ours. We are bound by it *and* we may change it. Changing
one means writing a superseding ADR, not editing the decision in place.
- **any other owner** — inherited. We follow it; we do not own it. Dispute it through
that owner's process; never amend it here.
Everything in `docs/adr/` today is `owner: ops-warden`. Rules we merely follow —
NetKingdom canon, the IAM profile, the credential-management standard — are cited,
never copied in. Copying them would recreate the second-source-of-truth failure
`ADR-0001` exists to prevent.
**Naming collision, worth knowing.** `ADR-001` (three digits) in
`workplan-convention.md` and `session-protocol.md` is **the-custodian's** ADR
establishing the workplan convention across the whole estate. It is inherited and
not ours to change. Our records are four-digit — `ADR-0001``ADR-0005` — and live
in this repo. When writing, say "the-custodian's ADR-001" if that is what you mean.
### Precedence
If a wiki page, playbook, or `.claude/rules/` file disagrees with an ADR, **the ADR
is right and the other file is a defect** — fix it rather than working around it.
The rule files are agent-facing operational instructions derived from these
decisions; they should cite an ADR rather than restate its reasoning.
### Publication
These ADRs are publishable through `policy-nexus` at `policy.coulomb.social`, which
requires `title`, `status` and `owner`, renders owner in the page header and in the
index, and records source repo, path and revision digest in its manifest. Ownership
survives the repo boundary. `policy-nexus` publishes and never writes back: the file
here is the source of truth.
## Quick Reference

View file

@ -80,15 +80,25 @@ the surface that actually executes the act. The transferable design properties:
Offer this rather than let a second, incompatible escalation vocabulary grow.
Do not implement it for them — routing work is theirs to own.
## ADR gap (open, not yet resolved)
## Policy publication (closed 2026-08-18)
`policy-nexus` publishes canon and ADRs — roughly 68 ADRs across 18 repos.
**ops-warden has none**, and it carries binding rules that govern other repos'
behaviour: the no-double-source catalog rule (CI-enforced), conduit-not-broker,
interim-by-default with a named owner, the agent read-boundary on `risk: high`
lanes. These live in wiki prose and workplan files, so they are unaddressable
and unpublishable — a reader outside ops-warden cannot cite them or tell whether
they are current.
This section previously recorded that ops-warden had no ADRs and that its binding
rules — the no-double-source catalog rule, conduit-not-broker, interim-by-default,
the agent read-boundary — sat in wiki prose, unaddressable and unpublishable.
Do not create an ADR corpus unilaterally; it is a structural decision for the
operator. Raise it when ops-warden next records a rule of that kind.
**That is now resolved.** They live in `docs/adr/` as `ADR-0001``ADR-0005`, each
carrying `owner: ops-warden`, and each verified to render through `policy-nexus`'s
own `tools/render.py`. See `.claude/rules/architecture.md` for the owned-versus-
inherited rule and the three-digit/four-digit ADR naming collision.
What matters when routing something to `policy-nexus`: it requires `title`,
`status` and `owner` on every published document (`tools/build_site.py:179`),
renders owner in both the page eyebrow and the index Owner column, and records
source repo, path, revision and content digest in its manifest. Ownership survives
publication — a reader landing on the URL can tell the rule is ours.
`policy-nexus` publishes and never writes back. The file in `docs/adr/` is the
source of truth; if the site disagrees, the site is the defect.
**When you record a new binding rule, write the ADR.** Not a wiki section — that is
the habit this whole rule file exists to correct, in the other direction.