R-444: hub half — the System page shows each box's last disk trim
sysfacts reads the agent's top-level guest_disk_trim stanza (schedule + per-guest last attempt: vmid, last_attempt_at, ok, bytes_trimmed, mounts, duration_seconds, last_ok_at, error) into a field-by-field mirror. The System page's new 'Last disk trim' column shows the last successful trim and the GiB it freed; amber when the newest attempt failed (error shown) or last_ok_at is older than 14 days (judged on the success time, never the attempt time); '—' when the agent sends no stanza. wire_contract_gate: SUBTREE_MIRRORS checks guest_disk_trim field by field BOTH ways against sysfacts.DiskTrim; decoys (ok renamed, last_ok_at dropped) in test_gate_decoys.py. Decision 139. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -63,7 +63,9 @@ COVERS = {
|
||||
"must convict (it passed for months as `language` did); the genuine article — the same "
|
||||
"name in a struct tag beside a `//` inside a string literal — must pass; and R-315: the "
|
||||
"agent RENAMING its mirror's `superseded_at` tag (the old name still occurs as a local-API "
|
||||
"map key) must convict on the field-by-field mirror check"),
|
||||
"map key) must convict on the field-by-field mirror check; and R-444: the agent renaming "
|
||||
"`guest_disk_trim.guests.ok` to `succeeded` (a name the hub carries elsewhere) or DROPPING `last_ok_at` (a field the "
|
||||
"hub reads and would show as never-ok for ever) must convict on the subtree mirror"),
|
||||
"stands": ("R-819: a stand citing a register id that exists in NEITHER register, and a stand "
|
||||
"marked 'walked' whose only source is a register row (a green dot from a label); "
|
||||
"plus the genuine article — a stand citing only a CLOSED row, which must PASS"),
|
||||
@@ -750,6 +752,47 @@ for _mode, _want in (("renamed", 10), ("genuine", 0)):
|
||||
print(" ok %-20s %s" % ("wire-mirror/" + _mode,
|
||||
"decoy rejected" if _want else "genuine accepted"))
|
||||
|
||||
# ── wire-contract subtree mirror (R-444) ─────────────────────────────────────────────────────────
|
||||
#
|
||||
# `guest_disk_trim` is checked field by field BOTH ways against hub sysfacts.DiskTrim. Two decoys on the agent's parsed
|
||||
# GuestDiskTrim body (no tree copy): `ok` renamed to `succeeded` — the name check passes it, since `succeeded` occurs in the hub — and
|
||||
# `last_ok_at` dropped, which only the reverse direction can see. The genuine article must pass.
|
||||
_WCS = r"""
|
||||
import os, sys
|
||||
sys.path.insert(0, "scripts")
|
||||
import wire_contract_gate as g
|
||||
mode = sys.argv[1]
|
||||
orig, agent = g.build_index, os.path.abspath(g.REPOS["agent"])
|
||||
def patched(root):
|
||||
by_dir, by_name = orig(root)
|
||||
if mode != "genuine" and os.path.abspath(root) == agent:
|
||||
k = ("internal/hub", "GuestDiskTrim")
|
||||
b = by_dir[k]
|
||||
if mode == "renamed":
|
||||
assert 'json:"ok"' in b, "mutation target missing"
|
||||
b = b.replace('json:"ok"', 'json:"succeeded"')
|
||||
else:
|
||||
assert 'json:"last_ok_at' in b, "mutation target missing"
|
||||
b = "\n".join(l for l in b.split("\n") if 'json:"last_ok_at' not in l)
|
||||
by_dir[k] = b
|
||||
by_name["GuestDiskTrim"] = [(d, b if d == k[0] else x) for d, x in by_name["GuestDiskTrim"]]
|
||||
return by_dir, by_name
|
||||
g.build_index = patched
|
||||
rc, conv = g.run(quiet=True)
|
||||
want = {"renamed": "guest_disk_trim.guests.succeeded", "dropped": "guest_disk_trim.guests.last_ok_at"}.get(mode)
|
||||
hit = any(d == want for _, _, m in conv for _, d in m)
|
||||
print("rc=%d convicted=%s" % (rc, hit))
|
||||
sys.exit(0 if rc == 0 else (10 if hit else 11))
|
||||
"""
|
||||
for _mode, _want in (("renamed", 10), ("dropped", 10), ("genuine", 0)):
|
||||
ran += 1
|
||||
_p = subprocess.run([sys.executable, "-c", _WCS, _mode], cwd=ROOT, capture_output=True, text=True)
|
||||
if _p.returncode != _want:
|
||||
fails.append("wire-trim/%s: rc=%d, want %d (10 = the mutated trim field convicted, 0 = passed)\n%s"
|
||||
% (_mode, _p.returncode, _want, (_p.stdout + _p.stderr)[-500:]))
|
||||
else:
|
||||
print(" ok %-20s %s" % ("wire-trim/" + _mode, "decoy rejected" if _want else "genuine accepted"))
|
||||
|
||||
# ── stands (R-819) ───────────────────────────────────────────────────────────────────────────────
|
||||
#
|
||||
# check_stands.py was red and in no runner. Its decoys are stand files written as a session would write
|
||||
|
||||
@@ -105,6 +105,17 @@ MIRRORS = {
|
||||
"hub -> controller (report ACK, `escrow` object)": ("internal/report", "EscrowStatus"),
|
||||
}
|
||||
|
||||
# R-444 (2026-10-06): a SUBTREE of a name-checked root whose receiver decodes it into one named mirror type gets the
|
||||
# field-by-field check in BOTH directions — every emitted path under it must be a json path of the mirror, AND every
|
||||
# mirror path must be emitted (a field the hub reads and the agent never sends would leave the page on "—" for ever).
|
||||
# Both directions, because some leaves here are short names (`ok`, `error`, `vmid`) the name check cannot judge:
|
||||
# `ok` occurs everywhere, so a renamed `ok` would pass it. Keyed by (root label, dotted subtree path):
|
||||
# (receiver package dir, receiver type). A subtree the emitter does not carry YET prints PENDING — the receiver was
|
||||
# built first, against a provisional shape — and is neither a pass nor a conviction of the subtree.
|
||||
SUBTREE_MIRRORS = {
|
||||
("agent -> hub (POST /host-report)", "guest_disk_trim"): ("internal/sysfacts", "DiskTrim"),
|
||||
}
|
||||
|
||||
# Tag names whose literal string carries no information in a repo-wide search. NOT CHECKED.
|
||||
# Listed rather than silently skipped: each one is a hole.
|
||||
GENERIC = {
|
||||
@@ -630,6 +641,29 @@ def run(root_override=None, quiet=False):
|
||||
convictions.append((label, receiver, missing))
|
||||
continue
|
||||
kinds.append((label, "name-reachability only (a tag found ANYWHERE in %s passes)" % receiver))
|
||||
emitted_paths = {d for _, d in tags}
|
||||
for (slabel, sub), (mdir, mtype) in sorted(SUBTREE_MIRRORS.items()):
|
||||
if slabel != label:
|
||||
continue
|
||||
rby_dir, rby_name = indexes[receiver]
|
||||
if (mdir, mtype) not in rby_dir:
|
||||
die("wire-contract gate INCONCLUSIVE: declared subtree mirror %s.%s not found in %s/%s\n"
|
||||
" A mirror that cannot be resolved is not a pass — fix SUBTREE_MIRRORS or the type."
|
||||
% (receiver, mtype, receiver, mdir))
|
||||
if sub not in emitted_paths:
|
||||
kinds.append((" └ " + sub, "PENDING — the emitter does not carry `%s` yet; %s.%s is unchecked"
|
||||
% (sub, mdir, mtype)))
|
||||
continue
|
||||
want = {sub + "." + d for _, d in walk(rby_dir, rby_name, mdir, mtype)}
|
||||
got = {d for d in emitted_paths if d.startswith(sub + ".")}
|
||||
for d in sorted(got - want):
|
||||
checked += 1
|
||||
missing.append((d.split(".")[-1], d))
|
||||
for d in sorted(want - got):
|
||||
checked += 1
|
||||
missing.append((d.split(".")[-1] + " (read by the receiver, never emitted)", d))
|
||||
kinds.append((" └ " + sub, "FIELD-BY-FIELD both ways against %s %s.%s (%d path(s))"
|
||||
% (receiver, mdir, mtype, len(want | got))))
|
||||
for tag, dotted in sorted(seen_tags.items()):
|
||||
if tag in GENERIC:
|
||||
skipped += 1
|
||||
|
||||
Reference in New Issue
Block a user