New internal/reconcile package: the agent-side control core's structural half.
- Per-guest serializer Queue (doc 03 §10): the single choke point all mutation
sources funnel through; same-vmid serial in submit order, different vmids
parallel (cond-var FIFO lanes).
- Desired-state model + DesiredProvider seam; EmptyProvider is the only live
source at slice 4 (no hub serving until slice 10) so the live engine computes
an empty action set and performs zero mutations.
- Normalization layer (FieldNormalizers): normalized desired-vs-actual so
Proxmox round-trip quirks don't read as drift. normDesc promoted out of
main.go to reconcile.NormDescription; selftest uses the shared helper.
- Plan (pure diff): minimal benign action set (Start/Stop/SetConfig) for guests
in both desired and actual; provision/destroy out of scope here.
- Engine: dispatches onto the shared queue; honors the dual-mode SetConfig
contract (UPID -> WaitTask; empty UPID -> synchronous success).
- Durable op journal + idempotency store (mirrors authz.FileNonceStore):
in-flight task ids for crash detection + AlreadyApplied dedupe across restart.
- Wired into runDaemon alongside the hub loop, sharing the queue; runs cleanly
with no desired state and no signers.
Full module race-clean and vet-clean on the Linux build server.
CHECKPOINT: Phase A only. Awaiting validation before Phase B (the reversibility
gate + signed-op consuming layer, landing v0.4.0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>