From 4eaabb21d4c2362ec76e1e02dc064e36e88480e6 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 11 Jul 2026 13:55:37 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20publish-train=20rules=20=E2=80=94=20cou?= =?UTF-8?q?pled-release=20gates=20codified=20(option-2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit manifest-before-floor; floor field LAST (hub_settings DB row overrides env, acts immediately — the 0.81/0.113 9-minute skew incident); MinAgent fleet gate (controller CHANGELOG header convention from ctrl v0.114.0); the controller capability gate as box-level backstop. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6 --- CONTEXT.md | 9 ++++ documentation/runbooks/publish-train-rules.md | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 documentation/runbooks/publish-train-rules.md diff --git a/CONTEXT.md b/CONTEXT.md index 32c2498..310dd4f 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -3,6 +3,15 @@ > Created with the REUSE.md rollout (2026-07-03). Authoritative history: `hub/CHANGELOG.md` (hub), > `website/CHANGELOG.md`, `scripts/CHANGELOG.md`; end-of-task detail in `REPORT.md`. +- **2026-07-11 — PUBLISH-TRAIN RULES CODIFIED** (`documentation/runbooks/publish-train-rules.md`, + option-2 of the skew answer): 1. manifest before floor; 2. the manifest screen carries the LIVE + DB floor (`hub_settings.min_controller_version` overrides env, acts immediately) — save the floor + field LAST; 3. MinAgent fleet gate (controller CHANGELOG header convention from ctrl v0.114.0; + floor may not rise past an unmet MinAgent — hub dashboard check, manual at current fleet size; + hub-enforced per-box gating = deferred option-3); 4. box-level backstop = controller v0.114.0's + agent-capability gate (route probe, felhom-controller `internal/agentapi/features.go`). Hub + UNTOUCHED (floor-UI separation = its own future task). + - **2026-07-11 — PUBLISH TRAIN 0.81/0.113 COMPLETE — PETI LIVE on agent 0.81.0 + controller 0.113.0.** Record: `documentation/pilot/RUNBOOK-publish-0.81-0.113-2026-07-11.md`. Agent 0.81.0 published (sha `914bb3b5…30df0b`, live-bytes, anon-verified) + golden 0.113.0 baked/published (sha diff --git a/documentation/runbooks/publish-train-rules.md b/documentation/runbooks/publish-train-rules.md new file mode 100644 index 0000000..ac9fae2 --- /dev/null +++ b/documentation/runbooks/publish-train-rules.md @@ -0,0 +1,47 @@ +# Publish-train rules — coupled controller/agent releases + +Standing gates for every artifact publish train (agent binary + controller golden + Day-0 manifest + +floor). Each rule cites the incident that created it. The box-level backstop (rule 4) exists because +rules 1–3 are operator discipline and discipline fails; the rules stay the primary control. + +## 1. Manifest before floor (the GL-1 rule, restated) + +Publish and vouch the artifacts in the Day-0 manifest **before** any floor movement. A floor that +points at an unvouched (or unpublished) version bricks self-updates: boxes are told to move to a +version they cannot verify. (GL-1 supply-chain arc; see the go-live package records.) + +## 2. The manifest screen carries the LIVE DB floor — save the floor field LAST + +The hub's Day-0 manifest UI also persists the global floor as a DB row +(`hub_settings.min_controller_version` — `hub/internal/store/store.go`, +`GetGlobalMinControllerVersion`). **The DB row overrides the env floor and acts immediately on the +next report cycle** — it is not staged by the manifest vouch. + +**Incident:** publish train 0.81/0.113 (2026-07-11, +`documentation/pilot/RUNBOOK-publish-0.81-0.113-2026-07-11.md`): the operator saved the manifest +screen with the floor field filled; the floor acted at once and controller 0.113.0 reached Peti's +box ~9 minutes **before** agent 0.81.0 — the exact forbidden skew, benign only because the box had +zero NAS shares. + +**Rule:** fill the floor field **last**, in a separate save, only after rule 3's fleet check passes. + +## 3. MinAgent fleet gate + +A controller release that depends on coupled agent behavior declares `MinAgent: X.Y.Z` in its +CHANGELOG entry header line (felhom-controller convention, since v0.114.0; retroactively, 0.113.0's +effective MinAgent was 0.81.0 for the NAS add). **The floor may not rise past a controller version +whose MinAgent is not yet met fleet-wide:** check the hub dashboard — every reporting box must show +agent ≥ MinAgent before the floor save. Manual at the current fleet size; hub-enforced per-box +gating is the deferred option-3. + +## 4. Box-level backstop: the controller's capability gate + +Since controller v0.114.0, a coupled feature entry point probes the agent's capability +(`controller/internal/agentapi/features.go` — route probe: 2xx ⇒ supported, 404 ⇒ older agent, +transport/5xx ⇒ indeterminate, never "too old") and refuses up front with an honest Hungarian +message instead of failing mid-pipeline. This turns a violated ordering into a graceful refusal — +it does **not** license sloppy trains: rules 1–3 remain the primary control. + +Convention for new coupled features: add a row to the `featureProbes` table + a `Supports` gate +call at the feature's entry point, and declare MinAgent per rule 3. When the agent someday reports +an explicit version in its envelope, `Supports` should prefer the version comparison (roadmap).