99 lines
6.5 KiB
Markdown
99 lines
6.5 KiB
Markdown
# REPORT — felhom-agent v0.90.0 (agent train: guest RAM resize R-24 + fast-tick R-28)
|
|
|
|
**Date:** 2026-07-17 · **Baseline:** v0.89.0 (`9127f54`) → **v0.90.0** (`ac112c9`, pushed) · **MinAgent coupling:** felhom-controller v0.143.0 gates its guest-memory-resize UI on this agent.
|
|
|
|
## 1. What shipped
|
|
|
|
Two ruled features on one train (Viktor's one-train/one-floor ruling), plus a diagnosis passenger.
|
|
|
|
- **R-24 guest RAM resize (controller-direct)** — new self-scoped local-API surface `GET`/`POST /guest/memory`
|
|
(`internal/localapi/guestmemory.go`). The agent is the security boundary: bounds recomputed FRESH per
|
|
request from a live read; applies via PVE `SetConfig` (live cgroup apply, no reboot); verify-after-apply.
|
|
- **R-28 fast-tick-until-first-convergence** — `internal/fasttick/`, wired over four cached sources; pulses
|
|
the shared out-of-band trigger every 30 s while unapplied, self-disarms on convergence. Seams added:
|
|
`reconcile.Engine.LastResult()`, `wgtunnel.Manager.TunnelConvergence()`.
|
|
- **Guests-0/0** — diagnosed live, hypothesis REFUTED (no code change).
|
|
|
|
## 2. Phase-0 probe (the gate — PASSED)
|
|
|
|
Prerequisite: prove `PUT /nodes/{node}/lxc/{vmid}/config memory=X` hot-applies under the AGENT token. Run on
|
|
the nested demo box `demo-vm-felhom-4846bc` (hostname `felhom-appliance`, guest LXC 9201) — reached via the
|
|
hub-vaulted G1 break-glass root credential (the box's root PW was unknown; retrieved operator-side from the
|
|
hub SQLite `host_recovery` table, then shredded). Transcript:
|
|
|
|
```
|
|
node=felhom-appliance vmid=9201 token_user=felhom-agent@pve
|
|
BEFORE config.memory=2890 MB | status.maxmem=3030384640 B (2890 MB) | status=running | host-uptime=8226s
|
|
BEFORE guest MemTotal: 2959360 kB | guest /proc/uptime=8227.76
|
|
--- PUT memory=3146 (agent token) --- PUT data field: None (empty == synchronous apply, no UPID)
|
|
AFTER config.memory=3146 MB | status.maxmem=3298820096 B (3146 MB) | status=running | host-uptime=8229s
|
|
AFTER guest MemTotal: 3221504 kB | guest /proc/uptime=8231.54
|
|
VERDICT maxmem_grew=True guest_running=True guest_not_rebooted=True
|
|
REVERT memory=2890 → maxmem 3030384640 B (2890 MB), running; guest MemTotal 2959360 kB
|
|
```
|
|
|
|
Proven: live cgroup apply (maxmem moves, guest running), **no reboot** (guest /proc/uptime keeps climbing),
|
|
synchronous (no UPID), agent token has the privilege (no 403), and **/proc/meminfo ripples via lxcfs** — the
|
|
mechanism that makes the controller's deploy-page memory math follow for free. The gate PASSED → the resize
|
|
leg was implemented.
|
|
|
|
## 3. Files created / modified
|
|
|
|
- `internal/localapi/guestmemory.go` (new) + `guestmemory_test.go` (new); `internal/localapi/server.go`
|
|
(Options.Memory + fields + routes); `cmd/felhom-agent/main.go` (wire Memory=px; construct + launch fasttick).
|
|
- `internal/fasttick/fasttick.go` + `fasttick_test.go` (new).
|
|
- `internal/reconcile/engine.go` (`LastResult`/`recordResult`) + `lastresult_test.go` (new).
|
|
- `internal/wgtunnel/manager.go` (`TunnelConvergence` + cached snapshot refresh in `Apply`).
|
|
- `CHANGELOG.md`, `REPORT.md` (this), `CONTEXT.md`, `REUSE.md`.
|
|
|
|
## 4. Tests + red-proofs (all restored green)
|
|
|
|
- localapi memory: GET fields, grow, shrink-above-floor, the three refusals (each asserting **SetConfig
|
|
count == 0**), cross-guest 403, fresh-bounds-per-request, verify-not-reflected 502, nil-config 503.
|
|
- fasttick: pulse-while-unconverged, silent-when-converged, the ruled disarm-on-convergence, full-channel
|
|
non-blocking drop, first-reason. reconcile: `LastResult` effect + pre-first-run ok=false.
|
|
- **Red-proofs (run-fail-restore):** (i) floor guard removed → below_usage_floor 412 test fails; (ii) max
|
|
guard removed → above_max test fails; (iii) fast-tick ignores convergence (always pulse) → the silent +
|
|
disarm tests fail. All confirmed red, then restored. Full suite: `go build ./... && go vet ./... &&
|
|
go test ./...` — all 28 packages pass.
|
|
|
|
## 5. Guests-0/0 diagnosis — hypothesis REFUTED, no fix
|
|
|
|
Live read-only checks on the nested box: pool `felhom` `members: [9201]`; the agent token's ListLXC sees
|
|
`[9201]` (VM.Audit comes from the `/pool/felhom` grant — so pool membership IS the visibility mechanism);
|
|
hub reports 1/1. The agent log shows the observed 0/0 was the **pre-provision window**: `16:11 stale-lock …
|
|
pool=felhom listed=0` + `desired … guests=0`, then `16:16 lanresolver … vmid=9201` (guest created). No guest
|
|
existed yet → empty list, no error (the silent shape) — correct, not a bug. The existing `PoolAddVMID`
|
|
re-assert (`bringup.go:498`) already covers the known restore-over-existing edge (campaign-2 R2). **Item 2's
|
|
fast-tick is precisely the mitigation** — it shortens the pre-provision reporting window from ≤15 min to ~30 s.
|
|
|
|
## 6. Deploy verification (BOTH hosts)
|
|
|
|
Built on 180 (`go build -ldflags -X main.version=0.90.0`), deployed to both Proxmox hosts (backup + install +
|
|
restart):
|
|
|
|
- **felhom-pve** (the N100): `felhom-agent 0.90.0` active; `capabilities self-check ok=63 total=63 degraded=0`;
|
|
**`fast-tick armed: 30s out-of-band cadence while desired-state is unapplied`**; poke listener + local-api up.
|
|
- **demo-vm-felhom-4846bc** (nested, 192.168.0.135): `felhom-agent 0.90.0` active; `capabilities self-check
|
|
ok=63 degraded=0`; `fast-tick armed: 30s …`; local-api on 192.168.0.135:8443. (Converged box → fast-tick
|
|
quiet after the startup line, as designed.)
|
|
|
|
## 7. NOT yet live-validated / operator GO
|
|
|
|
- **Fast-tick real-onboarding proof:** the fast-tick's value shows on a REAL fresh box's pre-tunnel window
|
|
(the rehearsal S5 bind sequence should now be visibly instant). Not manufacturable non-destructively here;
|
|
both agents show the armed startup line + the unit tests prove the pulse/disarm.
|
|
- **Floor LAST (operator GO):** both demo agents verifiably run 0.90.0 (the safety gate) and the controller
|
|
coupling is PROVEN LIVE via the X-Felhom-Agent-Version header (see the controller REPORT's live refusals).
|
|
Publishing 0.90.0 to Gitea + the hub Day-0 manifest **vouch + MinAgent-floor raise to 0.90.0** are set via
|
|
the operator-password-gated Day-0 manifest UI (CC cannot log in) — the operator (Viktor) GO step, matching
|
|
the v0.89 train's "publish/vouch = operator follow-up".
|
|
|
|
## 8. Observations
|
|
|
|
- The nested demo host is tiny (4 GB): its resize bounds are degenerate (`max_mb 1866 < min_mb 2048 <
|
|
current 2890`) — no resize *succeeds* through the bounded endpoint there (all refused correctly). The
|
|
successful apply is Phase-0-proven at the agent layer; the controller live-validation exercised the
|
|
refusals (above_max, below_min) end-to-end.
|
|
- REUSE.md gained the fasttick Source pattern + the localapi MemoryOps seam.
|