# F-013: The mirror topology works exactly as documented — all six repos in sync category: works-well confidence: high evidence: - `main` heads compared between canonical git.lab and the Gitea mirror, both read live with `git ls-remote`: | repo | git.lab | rohana/Gitea | | |---|---|---|---| | management | `2f012a6cd2` | `2f012a6cd2` | in sync | | axion1337.chat-gitops | `151ef3c8d0` | `151ef3c8d0` | in sync | | ThreadNet-Web | `d3bd5b20c2` | `d3bd5b20c2` | in sync | | threadnet-call | `d13cce7337` | `d13cce7337` | in sync | | thread-net-git | `2f4a15ce85` | `2f4a15ce85` | in sync | | threadnet-operating | `32f89afebf` | `32f89afebf` | in sync | - The reasoning behind the topology is written down and is genuinely good: `CLAUDE.md:26-33` explains *why* two locations exist rather than only asserting it — the Hetzner cluster must rebuild when the lab is off — and pre-empts the tempting cleanup with a named warning: "⚠️ **Die Flux-Quelle nicht „geradeziehen"** auf git.lab: Das sähe aufgeräumter aus und würde die Verfügbarkeit der Produktion an das Lab koppeln". - The failure mode is documented with its rescue procedure, not just prohibited: `README.md:16-20` and `CLAUDE.md:45-48` — pull the `.patch` from Gitea, `git am` to preserve authorship, push via git.lab. - The one standing exception is explicit, justified, bounded, and has a live mechanism: the TURN rotation CronJob (`CLAUDE.md:53-60`), canonised daily by the scheduled CI job `canonize_rotation`, present at `.gitlab-ci.yml:51` in the gitops repo. The alarm design is stated deliberately — "diese rote Pipeline **ist** der Alarm, einen zusätzlichen Termin gibt es bewusst nicht." impact: This is the part of the current approach that must survive migration untouched. The value is not the sync itself but the form: a decision with its reason, its counter-argument, its rescue path, and its one exception each written where the next session will look. root-cause pattern: **A decision recorded with its reasoning outlives the person who made it.** Every claim in this cluster held up under measurement; the ones that failed elsewhere in this report are the ones recorded as bare assertions. neckbeard mechanism: This is what `docs/adr/` is for. `AGENTS.md:81` — "Architecture Decision Records — binding; never edited, only superseded" — and `AGENTS.md:89-90`, "Before proposing options (Gate 2), read the relevant ADRs and AARs first — past decisions and learnings are input, not trivia." The existing `decisions/0001-gitlab-kanonisch-push-mirror.md` already is an ADR in all but schema; migrating it needs frontmatter per `schema.yaml:39-52` (`type`, `id`, `status`, `date`) and nothing else. The "don't straighten this out" warning maps to the ADR Consequences section, and `WORKFLOW.md:56` ("Options & trade-offs … pro/contra each, chosen option, and why") is where the two-host reasoning belongs.