Hive
fix(infra): parse tart get’s string Size so the golden warm-path probe stops re-pulling
GitHub issue · Closed
What this fixes
The root cause of “the golden base re-materializes on every recycle” — found in production within minutes of the warm-path-miss logging from #11517 going live.
tart encodes a VM’s Size field inconsistently across subcommands:
tart list --format json→"Size": 72(integer)tart get --format json→"Size": "72.660"(quoted decimal string)
The Go VM struct declared Size int64, so json.Unmarshal of a tart get response errored on every call. Client.Get() returns that error, and ensureGolden treats any non-nil Get error as “golden absent” → cold path → full multi-GB re-pull. So the per-host golden was rebuilt on essentially every provision even though it was sitting on disk.
The asymmetry is why this was so hard to spot from metrics/static analysis: the GC and node-label path read tart list (integer Size) and parsed fine — goldens were correctly kept and advertised — while only the warm-path probe (tart get) failed. On-host, tart get <golden> “worked” when run by hand (I was reading the JSON myself); it’s the Go unmarshal that broke.
The new warm-path-miss log from #11517 surfaced it directly on the first updated host:
parse tart get tuist-golden-29a6ff6e...: json: cannot unmarshal string
into Go struct field VM.Size of type int64
The fix
Make Size a small custom type whose UnmarshalJSON accepts Tart’s integer, quoted-decimal, and bare-decimal forms (and null). Size is never read anywhere in the codebase — the type exists purely to keep VM unmarshal (and therefore Get) from failing on either encoding.
Impact
Once deployed, ensureGolden’s warm-path probe will actually find the on-disk golden, so recycles clone from it (APFS clonefile, no network) instead of re-pulling. This is the change that makes the golden-base scheme finally deliver: golden_base_reused_total should climb, golden_base_materialized_total should go flat, and provision delay should drop from minutes to seconds. (Combined with #11517, which already stopped the GC from deleting the cached OCI image and made the cold path cheap — verified on the fleet: OCI churn stopped, cached image now survives GC passes.)
Validation
go build,go vet,gofmt, full module test suite pass.- New
TestVMUnmarshalSizeAcceptsListAndGetEncodingspins both real Tart encodings (72and"72.660") plus quoted-integer and bare-decimal.
🤖 Generated with Claude Code
Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.
Start a Flight and preserve its objective, outcome, and session here.
No GitHub comments yet.