← Files Context HandoffARCHIVED FILE

tests/test_context_handoff.py

21.7 KB · Oct 3, 2026 · 06:31 UTC

↓ Download file

import json
import os
import re
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "skills/context-handoff/scripts/context_handoff.py"
MANIFEST = ROOT / ".codex-plugin/plugin.json"
MARKETPLACE = ROOT / ".agents/plugins/marketplace.json"
HOOKS_CONFIG = ROOT / "hooks/hooks.json"
HOOK_SCRIPT = ROOT / "hooks/context_health.py"
SKILL = ROOT / "skills/context-handoff/SKILL.md"


def run_cli(*arguments: str) -> subprocess.CompletedProcess[str]:
    return subprocess.run(
        [sys.executable, str(SCRIPT), *arguments],
        check=False,
        capture_output=True,
        text=True,
    )


def run_hook(
    payload: dict[str, object], plugin_data: Path
) -> subprocess.CompletedProcess[str]:
    environment = os.environ.copy()
    environment["PLUGIN_DATA"] = str(plugin_data)
    return subprocess.run(
        [sys.executable, str(HOOK_SCRIPT)],
        input=json.dumps(payload),
        check=False,
        capture_output=True,
        text=True,
        env=environment,
    )


class ContextHandoffTests(unittest.TestCase):
    @staticmethod
    def complete_packet(
        text: str,
        *,
        reply_language: str = "Traditional Chinese (zh-Hant)",
        locale: str = "Asia/Taipei",
    ) -> str:
        text = re.sub(
            r"- Reply language: \[TODO:[^\]]*\]",
            f"- Reply language: {reply_language}",
            text,
        )
        text = re.sub(
            r"- Locale or time zone: \[TODO:[^\]]*\]",
            f"- Locale or time zone: {locale}",
            text,
        )
        text = re.sub(
            r"- Goal status: \[TODO:[^\]]*\]",
            "- Goal status: active",
            text,
        )
        return re.sub(r"\[TODO:[^\]]*\]", "recorded", text)

    def decision(self, *arguments: str) -> str:
        result = run_cli("assess", *arguments)
        self.assertEqual(result.returncode, 0, result.stderr)
        return json.loads(result.stdout)["decision"]

    def test_context_boundaries(self) -> None:
        self.assertEqual(
            self.decision(
                "--used-tokens", "69000", "--context-window", "100000"
            ),
            "continue",
        )
        self.assertEqual(
            self.decision(
                "--used-tokens", "70000", "--context-window", "100000"
            ),
            "checkpoint",
        )
        self.assertEqual(
            self.decision(
                "--used-tokens", "85000", "--context-window", "100000"
            ),
            "handoff-needs-authorization",
        )

    def test_compaction_authorization_and_unsafe_state(self) -> None:
        self.assertEqual(
            self.decision("--compactions", "2", "--standing-authorization"),
            "handoff-ready",
        )
        self.assertEqual(
            self.decision("--requested", "--unsafe", "test is running"),
            "handoff-deferred",
        )

    def test_packet_template_must_be_completed(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            created = run_cli("template", "--output", str(packet))
            self.assertEqual(created.returncode, 0, created.stderr)
            self.assertNotEqual(run_cli("validate", str(packet)).returncode, 0)

            completed = self.complete_packet(packet.read_text(encoding="utf-8"))
            packet.write_text(completed, encoding="utf-8")
            valid = run_cli("validate", str(packet))
            self.assertEqual(valid.returncode, 0, valid.stdout + valid.stderr)

    def test_packet_requires_communication_preferences(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            run_cli("template", "--output", str(packet))
            completed = self.complete_packet(packet.read_text(encoding="utf-8"))
            without_preferences = re.sub(
                r"(?ms)^## Communication preferences\n.*?(?=^## )",
                "",
                completed,
            )
            packet.write_text(without_preferences, encoding="utf-8")
            result = run_cli("validate", str(packet))
            self.assertNotEqual(result.returncode, 0)
            self.assertIn(
                "missing or empty section: Communication preferences",
                result.stdout,
            )

            packet.write_text(
                completed.replace(
                    "- Reply language: Traditional Chinese (zh-Hant)\n", ""
                ),
                encoding="utf-8",
            )
            missing_language = run_cli("validate", str(packet))
            self.assertNotEqual(missing_language.returncode, 0)
            self.assertIn(
                "Communication preferences must include Reply language: <value>",
                missing_language.stdout,
            )

    def test_packet_preserves_reply_language_and_locale_separately(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            run_cli("template", "--output", str(packet))
            completed = self.complete_packet(
                packet.read_text(encoding="utf-8"),
                reply_language="Traditional Chinese (zh-Hant)",
                locale="unspecified",
            )
            packet.write_text(completed, encoding="utf-8")
            result = run_cli("validate", str(packet))
            self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
            self.assertIn(
                "- Reply language: Traditional Chinese (zh-Hant)", completed
            )
            self.assertIn("- Locale or time zone: unspecified", completed)

    def test_packet_requires_workspace_routing_identity(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            run_cli("template", "--output", str(packet))
            completed = self.complete_packet(packet.read_text(encoding="utf-8"))
            packet.write_text(
                completed.replace("- Source workspace kind: recorded\n", ""),
                encoding="utf-8",
            )
            result = run_cli("validate", str(packet))
            self.assertNotEqual(result.returncode, 0)
            self.assertIn(
                "Workspace identity must include Source workspace kind: <value>",
                result.stdout,
            )

    def test_skill_forbids_approval_retry_across_workspace_boundary(self) -> None:
        skill = SKILL.read_text(encoding="utf-8")
        self.assertIn("HANDOFF NEEDS COMPATIBLE WORKSPACE", skill)
        self.assertIn("do not open the source-side backup packet", skill)
        self.assertIn("Do not request approval and do not retry", skill)

    def test_skill_requires_verified_mobile_discoverability(self) -> None:
        skill = SKILL.read_text(encoding="utf-8")
        self.assertIn("Handoff: <short goal>", skill)
        self.assertIn("pin that exact destination thread", skill)
        self.assertIn("HANDOFF MOBILE VISIBILITY UNVERIFIED", skill)
        self.assertIn("same thread ID, host ID, and title", skill)

    def test_packet_requires_explicit_source_goal_status(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            run_cli("template", "--output", str(packet))
            completed = self.complete_packet(packet.read_text(encoding="utf-8"))
            packet.write_text(
                completed.replace("- Goal status: active", "- Goal status: running"),
                encoding="utf-8",
            )
            result = run_cli("validate", str(packet))
            self.assertNotEqual(result.returncode, 0)
            self.assertIn(
                "Source lifecycle Goal status must be active, complete, blocked, none, or unknown",
                result.stdout,
            )

    def test_probable_secret_is_rejected(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            packet = Path(directory) / "handoff.md"
            run_cli("template", "--output", str(packet))
            completed = self.complete_packet(packet.read_text(encoding="utf-8"))
            completed += "\nBearer " + ("a" * 30) + "\n"
            packet.write_text(completed, encoding="utf-8")
            result = run_cli("validate", str(packet))
            self.assertNotEqual(result.returncode, 0)
            self.assertIn("probable secret detected", result.stdout)

    def test_archive_plan_allows_verified_authorized_recoverable_handoff(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-verified",
            "--destination-discoverable",
            "--packet-available",
            "--source-thread-id", "thread-real-123",
            "--source-host-id", "host-real-456",
            "--goal-status", "active",
            "--authorized",
            "--api-available",
            "--confirmation-available",
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["decision"], "archive-ready")
        self.assertTrue(payload["archive"])
        self.assertEqual(payload["lifecycle_state"], "SOURCE_ARCHIVE_READY")
        self.assertTrue(payload["goal_auto_resume_risk"])

    def test_archive_plan_rejects_unverified_or_unsafe_handoff(self) -> None:
        result = run_cli(
            "archive-plan",
            "--packet-available",
            "--source-thread-id", "thread-real-123",
            "--source-host-id", "host-real-456",
            "--goal-status", "active",
            "--authorized",
            "--api-available",
            "--confirmation-available",
            "--unsafe", "test is running",
        )
        payload = json.loads(result.stdout)
        self.assertEqual(payload["decision"], "archive-skipped")
        self.assertIn("destination has not reported HANDOFF VERIFIED", payload["blockers"])
        self.assertIn("unsafe state: test is running", payload["blockers"])
        self.assertEqual(payload["lifecycle_state"], "CHECKPOINTED")

    def test_archive_plan_requires_real_ids_authorization_packet_and_api(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-verified",
            "--destination-discoverable",
            "--goal-status",
            "active",
        )
        payload = json.loads(result.stdout)
        self.assertFalse(payload["archive"])
        self.assertIn("validated recovery packet is unavailable", payload["blockers"])
        self.assertIn(
            "surface-provided source thread and host identifiers are required",
            payload["blockers"],
        )
        self.assertIn("source archival is not authorized", payload["blockers"])
        self.assertIn(
            "thread archival API is unavailable; use manual archive fallback",
            payload["blockers"],
        )
        self.assertIn(
            "source archival cannot be confirmed on this surface",
            payload["blockers"],
        )
        self.assertEqual(
            payload["decision"], "handoff-verified-source-still-active"
        )
        self.assertTrue(payload["manual_fallback_required"])

    def test_archive_plan_never_closes_on_destination_regression(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-regression",
            "--packet-available",
            "--source-thread-id", "thread-real-123",
            "--source-host-id", "host-real-456",
            "--goal-status", "active",
            "--authorized",
            "--api-available",
            "--confirmation-available",
        )
        payload = json.loads(result.stdout)
        self.assertFalse(payload["archive"])
        self.assertEqual(payload["lifecycle_state"], "CHECKPOINTED")
        self.assertIn("destination reported HANDOFF REGRESSION", payload["blockers"])

    def test_archive_plan_treats_observed_archive_as_idempotent_success(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-verified",
            "--destination-discoverable",
            "--packet-available",
            "--source-thread-id", "thread-real-123",
            "--source-host-id", "host-real-456",
            "--goal-status", "active",
            "--already-archived",
        )
        payload = json.loads(result.stdout)
        self.assertFalse(payload["archive"])
        self.assertTrue(payload["archived_confirmed"])
        self.assertEqual(payload["decision"], "archive-confirmed")
        self.assertEqual(payload["lifecycle_state"], "SOURCE_ARCHIVED_CONFIRMED")

    def test_archive_plan_accepts_documented_standing_preference(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-verified",
            "--destination-discoverable",
            "--packet-available",
            "--source-thread-id", "thread-real-123",
            "--source-host-id", "host-real-456",
            "--goal-status", "unknown",
            "--standing-preference",
            "--api-available",
            "--confirmation-available",
        )
        payload = json.loads(result.stdout)
        self.assertTrue(payload["archive"])
        self.assertEqual(payload["decision"], "archive-ready")

    def test_archive_plan_keeps_source_when_mobile_visibility_is_unverified(self) -> None:
        result = run_cli(
            "archive-plan",
            "--destination-verified",
            "--packet-available",
            "--source-thread-id",
            "thread-real-123",
            "--source-host-id",
            "host-real-123",
            "--goal-status",
            "active",
            "--authorized",
            "--api-available",
            "--confirmation-available",
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertFalse(payload["archive"])
        self.assertEqual(
            payload["lifecycle_state"], "HANDOFF MOBILE VISIBILITY UNVERIFIED"
        )
        self.assertTrue(payload["goal_auto_resume_risk"])

    def test_archive_result_requires_observed_confirmation(self) -> None:
        confirmed = run_cli(
            "archive-result",
            "--destination-verified",
            "--goal-status", "active",
            "--archive-confirmed",
        )
        confirmed_payload = json.loads(confirmed.stdout)
        self.assertTrue(confirmed_payload["archived_confirmed"])
        self.assertEqual(
            confirmed_payload["lifecycle_state"], "SOURCE_ARCHIVED_CONFIRMED"
        )
        self.assertFalse(confirmed_payload["source_auto_resume_risk"])

        failed = run_cli(
            "archive-result",
            "--destination-verified",
            "--goal-status", "active",
            "--failure", "archive API returned an error",
        )
        failed_payload = json.loads(failed.stdout)
        self.assertFalse(failed_payload["archived_confirmed"])
        self.assertEqual(
            failed_payload["lifecycle_state"],
            "HANDOFF_VERIFIED_WITH_SOURCE_STILL_ACTIVE",
        )
        self.assertTrue(failed_payload["source_auto_resume_risk"])
        self.assertEqual(failed_payload["failure"], "archive API returned an error")

    def test_archive_result_never_claims_closure_on_regression(self) -> None:
        result = run_cli(
            "archive-result",
            "--destination-regression",
            "--goal-status", "active",
            "--archive-confirmed",
        )
        payload = json.loads(result.stdout)
        self.assertFalse(payload["archived_confirmed"])
        self.assertEqual(payload["decision"], "archive-prohibited")
        self.assertEqual(payload["lifecycle_state"], "CHECKPOINTED")

    def test_plugin_manifest_and_assets_are_consistent(self) -> None:
        manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
        self.assertEqual(manifest["name"], "context-handoff")
        self.assertRegex(
            manifest["version"], r"^\d+\.\d+\.\d+(?:\+[0-9A-Za-z.-]+)?$"
        )
        self.assertEqual(manifest["skills"], "./skills/")
        base_version = manifest["version"].split("+", 1)[0]
        self.assertGreaterEqual(tuple(map(int, base_version.split("."))), (0, 3, 2))
        self.assertNotIn("apps", manifest)
        self.assertNotIn("mcpServers", manifest)
        for key in ("composerIcon", "logo"):
            asset = ROOT / manifest["interface"][key]
            self.assertTrue(asset.is_file(), f"missing {key}: {asset}")
            png = asset.read_bytes()
            self.assertEqual(png[:8], b"\x89PNG\r\n\x1a\n")
            width = int.from_bytes(png[16:20], "big")
            height = int.from_bytes(png[20:24], "big")
            minimum = 48 if key == "composerIcon" else 256
            self.assertEqual(width, height, f"{key} must be square")
            self.assertGreaterEqual(width, minimum, f"{key} is too small")
        self.assertLessEqual(len(manifest["interface"]["defaultPrompt"]), 3)
        self.assertLessEqual(len(manifest["interface"]["shortDescription"]), 30)
        self.assertTrue(
            all(len(prompt) <= 128 for prompt in manifest["interface"]["defaultPrompt"])
        )

    def test_repo_marketplace_resolves_plugin_root(self) -> None:
        marketplace = json.loads(MARKETPLACE.read_text(encoding="utf-8"))
        entry = marketplace["plugins"][0]
        self.assertEqual(entry["name"], "context-handoff")
        self.assertEqual(entry["policy"]["installation"], "AVAILABLE")
        self.assertEqual(entry["policy"]["authentication"], "ON_INSTALL")
        plugin_root = (ROOT / entry["source"]["path"]).resolve()
        self.assertEqual(plugin_root, ROOT.resolve())
        self.assertTrue((plugin_root / ".codex-plugin/plugin.json").is_file())

    def test_plugin_bundles_compaction_lifecycle_hooks(self) -> None:
        hooks = json.loads(HOOKS_CONFIG.read_text(encoding="utf-8"))["hooks"]
        self.assertEqual(hooks["SessionStart"][0]["matcher"], "^compact$")
        for event in ("SessionStart", "UserPromptSubmit", "SessionEnd"):
            command = hooks[event][0]["hooks"][0]["command"]
            self.assertIn("$PLUGIN_ROOT/hooks/context_health.py", command)
        self.assertNotIn("Stop", hooks)

    def test_hook_records_compactions_and_reminds_each_later_turn(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            plugin_data = Path(directory)
            compact = {
                "session_id": "thread-sensitive-123",
                "cwd": "/tmp/example",
                "hook_event_name": "SessionStart",
                "source": "compact",
            }

            first = run_hook(compact, plugin_data)
            self.assertEqual(first.returncode, 0, first.stderr)
            first_output = json.loads(first.stdout)
            first_context = first_output["hookSpecificOutput"]["additionalContext"]
            self.assertIn("recorded 1 compaction(s)", first_context)
            self.assertIn("create or refresh a checkpoint", first_context)

            prompt = run_hook(
                {
                    "session_id": "thread-sensitive-123",
                    "cwd": "/tmp/example",
                    "hook_event_name": "UserPromptSubmit",
                    "turn_id": "turn-2",
                    "prompt": "continue",
                },
                plugin_data,
            )
            prompt_context = json.loads(prompt.stdout)["hookSpecificOutput"][
                "additionalContext"
            ]
            self.assertIn("At the start of this user turn", prompt_context)
            self.assertIn("recorded 1 compaction(s)", prompt_context)

            second = run_hook(compact, plugin_data)
            second_context = json.loads(second.stdout)["hookSpecificOutput"][
                "additionalContext"
            ]
            self.assertIn("recorded 2 compaction(s)", second_context)
            self.assertIn("treat this as handoff-ready", second_context)

            state_files = list((plugin_data / "context-health").glob("*.json"))
            self.assertEqual(len(state_files), 1)
            self.assertNotIn("thread-sensitive-123", state_files[0].name)
            self.assertNotIn(
                "thread-sensitive-123", state_files[0].read_text(encoding="utf-8")
            )

    def test_hook_keeps_sessions_separate_and_cleans_up_on_end(self) -> None:
        with tempfile.TemporaryDirectory() as directory:
            plugin_data = Path(directory)
            base = {
                "cwd": "/tmp/example",
                "hook_event_name": "SessionStart",
                "source": "compact",
            }
            run_hook({**base, "session_id": "session-a"}, plugin_data)
            run_hook({**base, "session_id": "session-b"}, plugin_data)
            self.assertEqual(
                len(list((plugin_data / "context-health").glob("*.json"))), 2
            )

            ended = run_hook(
                {
                    "session_id": "session-a",
                    "cwd": "/tmp/example",
                    "hook_event_name": "SessionEnd",
                    "reason": "other",
                },
                plugin_data,
            )
            self.assertEqual(ended.returncode, 0, ended.stderr)
            self.assertEqual(json.loads(ended.stdout), {})
            self.assertEqual(
                len(list((plugin_data / "context-health").glob("*.json"))), 1
            )

            no_history = run_hook(
                {
                    "session_id": "session-never-compacted",
                    "cwd": "/tmp/example",
                    "hook_event_name": "UserPromptSubmit",
                    "turn_id": "turn-1",
                    "prompt": "hello",
                },
                plugin_data,
            )
            self.assertEqual(json.loads(no_history.stdout), {})


if __name__ == "__main__":
    unittest.main()

SHA-256: f70531ab74f2d011badbbc176fec9ecbf6056b1e962fa8cc842b76034518be03