# Contributing & Development Workflow How work is version-controlled for this repository. This complements the governance rules in [`AGENTS.md`](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/` — new capability or spec area - `fix/` — corrections - `docs/` — documentation-only changes - `chore/` — 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`](docs/07-security-and-secrets.md)); the [`.gitignore`](.gitignore) guards common leak paths but is not a substitute for care. ## The implementation repo The [implementation repo](https://gitea.home.keithjackson.dev/Home-Network/home-network-k3s-impl) 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`](docs/05-gitops-and-delivery.md) and [ADR-0024](decisions/adr-0024-delivery-authority-ci-gate.md). - 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`](docs/16-known-gaps.md) is a dated snapshot of the shortfalls at one point in time. [`agents/task-board.md`](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`](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`](docs/07-security-and-secrets.md), the Phase 7 entry in [`roadmap/phases.md`](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`](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`](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](AGENTS.md)) regardless of where git is hosted. - "Done" remains a **green, reproducible conformance test**, not "merged."