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]>
93 lines
5.2 KiB
Markdown
93 lines
5.2 KiB
Markdown
# 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/<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`](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."
|