Files
owui-tools/tests/test_vm_finish_shapes.py
T
2026-09-15 15:24:03 -04:00

90 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""`finish` must accept what the model actually sends, not only the schema.
python3 tests/test_vm_finish_shapes.py
WHY
A session wrote the script, syntax-checked it, built a fourteen-file test
tree with awkward filenames, cross-checked its output against an
independent listing, demonstrated the error paths, committed, and passed
its own verification command. Then it could not close.
`finish` declares `verification` as an object - `{command, expected}` -
and the model sends the command as a bare string often enough to matter.
`v_finish` called `.get` on it, which raised
AttributeError: 'str' object has no attribute 'get'
out of the verb. The agent saw only "the supervisor refuses the call",
tried seven times with varying arguments, then marked the task blocked
and gave up. All the work was done and committed; the session simply
could not be ended.
The identical mistake had already been found and fixed in the live view's
renderer. That one cost a line of output. This one cost the end of a
session - so the rule is the same wherever a model-supplied value is
read: take what arrives, not what was asked for.
"""
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
VMD = os.path.join(HERE, "..", "vm", "vmd")
FAILS: list[str] = []
def check(label: str, condition: bool, detail: str = "") -> None:
if condition:
print(f"ok {label}")
else:
FAILS.append(label)
print(f"FAIL {label}\n {detail}")
SRC = open(os.path.join(VMD, "vmd.py"), encoding="utf-8").read()
body = SRC[SRC.index("def v_finish"):SRC.index("def v_report")]
def normalise(value):
"""The shape-tolerant read, lifted out of v_finish so it can be tested."""
check_ = value
if isinstance(check_, str):
check_ = {"command": check_}
elif not isinstance(check_, dict):
check_ = {}
return str(check_.get("command", "")).strip(), str(check_.get("expected", "")).strip()
# --- what the model sends -------------------------------------------------
check("the documented shape works",
normalise({"command": "pytest -q", "expected": "0 failed"})
== ("pytest -q", "0 failed"))
check("a bare string is taken as the command",
normalise("bash -n topfiles.sh") == ("bash -n topfiles.sh", ""),
"this is the one that raised AttributeError and ended the session")
check("a missing verification is empty, not an exception",
normalise(None) == ("", ""))
for junk in (12, [], ["a"], True):
got = normalise(junk)
check(f"{type(junk).__name__} does not raise", got == ("", ""), str(got))
# --- and the real verb does the same --------------------------------------
check("v_finish normalises before reading",
"isinstance(check, str)" in body and 'check = {"command": check}' in body,
"the verb itself has to do this, not just this test")
check("it no longer calls .get on whatever arrived",
'(args.get("verification") or {}).get(' not in body,
"that is the exact expression that raised")
check("a verification with no command is still refused clearly",
"finish needs a verification" in body,
"tolerating the shape must not mean accepting nothing")
print()
if FAILS:
print(f"FAILED {len(FAILS)}")
raise SystemExit(1)
print("finish takes what the model sends, and a finished session can end")