← Files Grok Bot ControlARCHIVED FILE
skills/grok-bot-control/tests/test_assess_send.py
15.7 KB · Oct 3, 2026 · 06:34 UTC
#!/usr/bin/env python3
from __future__ import annotations
import hashlib
import importlib.util
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts/assess_send.py"
DELIVERY_SCRIPT = ROOT / "scripts/delivery_state.py"
SPEC = importlib.util.spec_from_file_location("assess_send", SCRIPT)
assert SPEC and SPEC.loader
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)
DIGEST = "a" * 64
def capability_snapshot(**changes):
value = {
"schema_version": 1,
"observed_at": "2026-09-08T01:58:00Z",
"run_id": "run-current",
"intent": {
"operator": "codex",
"conversation": "target-conversation",
"message_sha256": DIGEST,
},
"target_identity": {"confirmed": True, "evidence": "fresh_target_readback"},
"send_authorized": True,
"capabilities": {
"read_conversation": {"available": True, "evidence": "fresh_state_readback"},
"read_composer": {"available": True, "evidence": "fresh_state_readback"},
"write_composer": {"available": True, "evidence": "current_tool_docs"},
"activate_send": {"available": True, "evidence": "current_tool_docs"},
"read_sent_state": {"available": True, "evidence": "fresh_state_readback"},
},
}
value.update(changes)
return value
def state(**changes):
value = {
"schema_version": 1,
"phase": "drafting",
"operator": "codex",
"conversation": "target-conversation",
"last_sent": {
"message_sha256": None,
"ui_readback_confirmed": False,
"uncertain_send": False,
"bot_acknowledged": False,
},
}
value.update(changes)
return value
class DecisionTests(unittest.TestCase):
def decide(self, payload=None, operator="codex", observation="absent"):
checked = MODULE.require_state(payload if payload is not None else state())
return MODULE.decide(checked, operator, DIGEST, observation)
def test_single_writer_refuses_other_operator(self):
self.assertEqual(self.decide(operator="other")["reason"], "different_operator")
def test_whitespace_conversation_never_authorizes_send(self):
result = self.decide(state(conversation=" "), observation="matching-draft-only")
self.assertEqual(result["action"], "inspect")
self.assertEqual(result["reason"], "conversation_unset")
def test_absent_draft_can_be_pasted_once(self):
self.assertEqual(self.decide()["action"], "paste_once")
def test_matching_draft_can_be_sent_once(self):
self.assertEqual(self.decide(observation="matching-draft-only")["action"], "send_once")
def test_matching_sent_is_marked_not_resent(self):
self.assertEqual(self.decide(observation="matching-sent")["action"], "mark_sent")
def test_confirmed_digest_stops_duplicate(self):
sent = {
"message_sha256": DIGEST,
"ui_readback_confirmed": True,
"uncertain_send": False,
"bot_acknowledged": False,
}
self.assertEqual(
self.decide(state(last_sent=sent))["reason"],
"message_already_confirmed_sent",
)
def test_acknowledged_digest_stops_duplicate_without_ui_bit(self):
sent = {
"message_sha256": DIGEST,
"ui_readback_confirmed": False,
"uncertain_send": False,
"bot_acknowledged": True,
}
result = self.decide(
state(last_sent=sent),
observation="matching-draft-only",
)
self.assertEqual(result["action"], "stop")
self.assertEqual(result["reason"], "message_already_confirmed_sent")
def test_uncertain_send_requires_resolution(self):
sent = {
"message_sha256": DIGEST,
"ui_readback_confirmed": False,
"uncertain_send": True,
"bot_acknowledged": False,
}
payload = state(phase="waiting_bot", last_sent=sent)
self.assertEqual(self.decide(payload, observation="absent")["action"], "inspect")
self.assertEqual(
self.decide(payload, observation="matching-draft-only")["action"],
"send_once",
)
def test_terminal_phase_stops(self):
self.assertEqual(self.decide(state(phase="complete"))["action"], "stop")
def test_blocked_phase_never_authorizes_send(self):
for observation in ("absent", "matching-draft-only", "matching-sent"):
with self.subTest(observation=observation):
result = self.decide(state(phase="blocked"), observation=observation)
self.assertEqual(result["action"], "inspect")
self.assertEqual(result["reason"], "phase_blocked")
def test_unknown_phase_is_rejected(self):
with self.assertRaises(MODULE.InputError):
MODULE.require_state(state(phase="unknown"))
def test_different_uncertain_digest_cannot_be_bypassed(self):
sent = {
"message_sha256": "b" * 64,
"ui_readback_confirmed": False,
"uncertain_send": True,
"bot_acknowledged": False,
}
payload = state(phase="waiting_bot", last_sent=sent)
for observation in ("matching-draft-only", "matching-sent", "absent"):
with self.subTest(observation=observation):
result = self.decide(payload, observation=observation)
self.assertEqual(result["action"], "inspect")
self.assertEqual(result["reason"], "different_uncertain_send_unresolved")
def test_invalid_conflicting_state_is_rejected(self):
sent = {
"message_sha256": DIGEST,
"ui_readback_confirmed": True,
"uncertain_send": True,
"bot_acknowledged": False,
}
with self.assertRaises(MODULE.InputError):
MODULE.require_state(state(last_sent=sent))
class CliTests(unittest.TestCase):
def bound_command(self, state_path, capability_path, operator="codex"):
return [
sys.executable,
str(SCRIPT),
str(state_path),
"--operator", operator,
"--message-sha256", DIGEST,
"--observation", "absent",
"--capabilities", str(capability_path),
"--run-id", "run-current",
"--now", "2026-09-08T02:00:00Z",
]
def reserve_delivery(self, journal_path, transport="cli"):
result = subprocess.run(
[
sys.executable, str(DELIVERY_SCRIPT), "begin", str(journal_path),
"--scope", "task", "--target", "target",
"--message-sha256", DIGEST,
"--operator", "codex", "--transport", transport,
],
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertTrue(json.loads(result.stdout)["reserved"])
def journal_command(self, state_path, journal_path, observation="matching-draft-only"):
return [
sys.executable, str(SCRIPT), str(state_path),
"--operator", "codex", "--message-sha256", DIGEST,
"--observation", observation,
"--delivery-journal", str(journal_path),
"--delivery-scope", "task", "--delivery-target", "target",
]
def test_cli_is_read_only(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "state.json"
path.write_text(json.dumps(state()))
before = hashlib.sha256(path.read_bytes()).hexdigest()
result = subprocess.run(
[
sys.executable,
str(SCRIPT),
str(path),
"--operator",
"codex",
"--message-sha256",
DIGEST,
"--observation",
"absent",
],
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "paste_once")
self.assertEqual(before, hashlib.sha256(path.read_bytes()).hexdigest())
def test_bound_capability_contract_allows_existing_send_decision(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
state_path.write_text(json.dumps(state()))
capability_path.write_text(json.dumps(capability_snapshot()))
result = subprocess.run(
self.bound_command(state_path, capability_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "paste_once")
def test_bound_contract_reads_utf8_non_ascii_scope(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
operator = "協作員"
conversation = "工作對話"
payload = capability_snapshot(intent={
"operator": operator,
"conversation": conversation,
"message_sha256": DIGEST,
})
state_path.write_bytes(
json.dumps(
state(operator=operator, conversation=conversation),
ensure_ascii=False,
).encode("utf-8")
)
capability_path.write_bytes(
json.dumps(payload, ensure_ascii=False).encode("utf-8")
)
result = subprocess.run(
self.bound_command(state_path, capability_path, operator=operator),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "paste_once")
def test_bound_contract_rejects_other_intent_digest(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
payload = capability_snapshot()
payload["intent"]["message_sha256"] = "b" * 64
state_path.write_text(json.dumps(state()))
capability_path.write_text(json.dumps(payload))
result = subprocess.run(
self.bound_command(state_path, capability_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "inspect")
self.assertEqual(
json.loads(result.stdout)["reason"],
"capability_preflight:intent_mismatch",
)
def test_bound_contract_honors_revoked_authorization(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
state_path.write_text(json.dumps(state()))
capability_path.write_text(json.dumps(capability_snapshot(send_authorized=False)))
result = subprocess.run(
self.bound_command(state_path, capability_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "stop")
self.assertEqual(
json.loads(result.stdout)["reason"],
"capability_preflight:send_not_authorized",
)
def test_malformed_bound_snapshot_returns_structured_error(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
state_path.write_text(json.dumps(state()))
capability_path.write_text("[]")
result = subprocess.run(
self.bound_command(state_path, capability_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 2)
self.assertEqual(json.loads(result.stdout)["error"]["code"], "invalid_input")
self.assertNotIn("Traceback", result.stderr)
def test_invalid_utf8_state_returns_structured_error(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
capability_path = Path(tmp) / "capabilities.json"
state_path.write_bytes(b"\xff")
capability_path.write_text(json.dumps(capability_snapshot()), encoding="utf-8")
result = subprocess.run(
self.bound_command(state_path, capability_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 2)
self.assertEqual(json.loads(result.stdout)["error"]["code"], "invalid_input")
self.assertNotIn("Traceback", result.stderr)
def test_cli_uncertainty_blocks_matching_ui_draft_retry(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
journal_path = Path(tmp) / "journal.sqlite3"
state_path.write_text(json.dumps(state()), encoding="utf-8")
self.reserve_delivery(journal_path, transport="cli")
result = subprocess.run(
self.journal_command(state_path, journal_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "inspect")
self.assertEqual(
json.loads(result.stdout)["reason"],
"delivery_journal:matching_delivery",
)
def test_confirmed_journal_stops_legacy_send_resolution(self):
with tempfile.TemporaryDirectory() as tmp:
state_path = Path(tmp) / "state.json"
journal_path = Path(tmp) / "journal.sqlite3"
state_path.write_text(json.dumps(state()), encoding="utf-8")
self.reserve_delivery(journal_path)
confirmed = subprocess.run(
[
sys.executable, str(DELIVERY_SCRIPT), "confirm", str(journal_path),
"--scope", "task", "--target", "target",
"--message-sha256", DIGEST, "--transport", "ui",
],
capture_output=True,
text=True,
check=False,
)
self.assertEqual(confirmed.returncode, 0, confirmed.stderr)
result = subprocess.run(
self.journal_command(state_path, journal_path),
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout)["action"], "stop")
self.assertEqual(json.loads(result.stdout)["reason"], "delivery_journal:confirmed")
if __name__ == "__main__":
unittest.main(verbosity=2)
SHA-256: 89886fbe2617b865cca5bf03343135f40e7aa936f0e874a99e74c25072e40991