Files
home-network-k3s/CONTRIBUTING.md
jakman85andClaude Opus 5.5 250fb54154 docs: bring the specification in line with the accepted implementation
The operator ruled the implementation repo's main (50c8719) the latest
and accepted state. Sync the spec to it.

Accepted changes are reflected: one bare-metal environment, TrueNAS bulk
storage, R2 off-cluster backup, CloudNativePG, single-node VPN gateway
with Cilium fail-closed, inbound WireGuard, per-app auth sidecars,
Renovate, the CI gate as approver, and the pm-agent. New ADR-0017..0025;
ADR-0016 corrected and accepted; R-* IDs unchanged, eight amended.

Where the implementation has simply not met a requirement, the
requirement stands and the shortfall is recorded in docs/16-known-gaps.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-08 22:46:00 -06:00

5.2 KiB

Contributing & Development Workflow

How work is version-controlled for this repository. This complements the governance rules in AGENTS.md (what agents may/may not change) — this file covers how changes land in git.

This repo (the spec)

The spec repo is hosted on the platform's own Gitea (gitea.home.keithjackson.dev).

  • No work on main. main holds only reviewed, completed work.
  • Every change is a feature branch, merged into main by pull request. Only the human operator merges a spec change (R-TEST-06).
  • Merge a coherent batch. Every spec commit on main must be adopted by the implementation (see below), so small drive-by commits each carry a real cost.

Branch naming

  • feature/<slug> — new capability or spec area
  • fix/<slug> — corrections
  • docs/<slug> — documentation-only changes
  • chore/<slug> — tooling/repo housekeeping

The implementation repo has its own convention (feat/, fix/, docs/, chore/).

Commit hygiene

  • Small, single-responsibility commits; imperative subject lines.
  • Reference requirement IDs / ADR numbers where relevant (they're stable across file moves).
  • Never commit plaintext secrets — secrets are SOPS-encrypted only (docs/07-security-and-secrets.md); the .gitignore guards common leak paths but is not a substitute for care.

The implementation repo

The implementation repo is CI/CD-driven GitOps. Its CLAUDE.md is the delivery contract for how work lands there; intent is in docs/05-gitops-and-delivery.md and ADR-0024.

  • Every change is branch → PR → merge gate green → merge. Direct pushes to main are rejected.
  • The CI gate is the approver; sensitive paths also need a non-author review.
  • Flux reconciles the cluster from that repo's main.
  • Each unit of work records a dated handoff entry under that repo's decisions/. Those are implementation handoffs; this repo's decisions/ holds ADRs.

Where status lives

./conformance/run.sh --status in the implementation repo is the live status surface: per requirement, whether it is implemented, reconciled, has an executable test, and has recorded proof. docs/16-known-gaps.md is a dated snapshot of the shortfalls at one point in time. agents/task-board.md is a frozen historical seed.

Adopting a spec change in the implementation

The implementation pins the exact spec commit it is built against, in ci/SPEC_PIN. Its spec-immutability check (R-TEST-06) fails when a spec checkout has uncommitted changes or its HEAD differs from the pin, so every movement of spec main is an explicit, reviewed act. On every spec change:

  1. Merge to spec main. The human operator does this. Until step 2 lands, a local gate against a checkout of the new main reports blocked.
  2. Bump the pin in an implementation PR, to the new spec main commit. ci/ is a sensitive path, so the PR needs the operator's review or the operator's own override; an agent never overrides for itself.
  3. Reconcile requirement IDs in that same PR. The registry (conformance/requirements/registry.yaml) mirrors the R-* IDs in docs/00-vision-and-scope.md:
    • A new ID must arrive with a requirement-tagged test, or be listed as a documented gap in the harness. Adding the registry entry attributes that ID to the change, so an uncovered ID blocks the merge; a safety-critical ID also needs an L3 test.
    • An amended requirement needs only its abridged registry summary updated, when the meaning changed.
    • A retired ID leaves the registry, every test label, and the gate's path-to-requirement map together. IDs are never renumbered or reused.
  4. Write the handoff entry for the adoption.

Some implementation checks read spec text when a spec checkout is present: the auditability section of docs/07, the Phase 7 entry in roadmap/phases.md, and the requirement definitions in docs/00. Change those structures knowingly.

The bootstrapping caveat (self-hosted git is circular)

Gitea runs on the cluster that Flux reconciles from Gitea — a chicken-and-egg. Handling:

  • Bring the cluster up from a bootstrap source (an out-of-band copy of the repo), stand up Gitea, then cut Flux's source over to Gitea (docs/05-gitops-and-delivery.md).
  • Because a cluster loss would take its own git host with it, Gitea is DR-critical: its repos are backed up off-cluster (docs/04-storage-and-state.md), and an off-cluster mirror of the platform repo is kept so the platform can always be rebuilt from a source that outlives the cluster.

What does not change

  • Specs remain human-owned and immutable to agents (AGENTS.md §11) regardless of where git is hosted.
  • "Done" remains a green, reproducible conformance test, not "merged."