aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-16 23:40:42 -0500
committerCraig Jennings <c@cjennings.net>2026-06-16 23:40:42 -0500
commite1933fe685a3e15d001552537df90e33ba00b83a (patch)
tree4b6435152b6605a96c0cc7a3f3b1dcadd4fc6a02 /.ai/scripts/tests
parent4e2db8f20a259d43d2198b120ac32660298d0d63 (diff)
downloadrulesets-e1933fe685a3e15d001552537df90e33ba00b83a.tar.gz
rulesets-e1933fe685a3e15d001552537df90e33ba00b83a.zip
refactor: remove unused cross-agent-comms subsystem
Nothing used the cross-agent message system (send/recv/watch/status/discover/halt/resume over the inbox/from-agents/ file-IPC protocol). Every cross-project handoff goes through inbox-send instead. I removed the scripts, READMEs, workflow, tests, INDEX entry, the three startup.org wirings, and the legacy bin symlinks, then repointed helper-mode's escalation to inbox-send and noted the removal in the generic-agent-runtime spec.
Diffstat (limited to '.ai/scripts/tests')
-rw-r--r--.ai/scripts/tests/test_cross_agent_discover.py204
-rw-r--r--.ai/scripts/tests/test_cross_agent_halt.py204
-rw-r--r--.ai/scripts/tests/test_cross_agent_recv.py176
-rw-r--r--.ai/scripts/tests/test_cross_agent_send.py210
-rw-r--r--.ai/scripts/tests/test_cross_agent_status.py165
-rw-r--r--.ai/scripts/tests/test_cross_agent_watch.py155
6 files changed, 0 insertions, 1114 deletions
diff --git a/.ai/scripts/tests/test_cross_agent_discover.py b/.ai/scripts/tests/test_cross_agent_discover.py
deleted file mode 100644
index f0d2bb7..0000000
--- a/.ai/scripts/tests/test_cross_agent_discover.py
+++ /dev/null
@@ -1,204 +0,0 @@
-"""Tests for cross-agent-discover (TDD: tests written before implementation)."""
-
-from __future__ import annotations
-
-import json
-import os
-import subprocess
-import textwrap
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-discover"
-
-
-def _run(args: list[str], env: dict | None = None) -> subprocess.CompletedProcess:
- return subprocess.run([str(SCRIPT), *args], capture_output=True, text=True, env=env)
-
-
-@pytest.fixture
-def fake_home(tmp_path, monkeypatch):
- home = tmp_path / "home"
- home.mkdir()
- monkeypatch.setenv("HOME", str(home))
- return home
-
-
-def _make_project(home: Path, name: str) -> Path:
- proj = home / "projects" / name
- (proj / ".ai").mkdir(parents=True)
- return proj
-
-
-def _write_peers_toml(home: Path, content: str) -> Path:
- cfg = home / ".config" / "cross-agent-comms"
- cfg.mkdir(parents=True, exist_ok=True)
- peers = cfg / "peers.toml"
- peers.write_text(content)
- return peers
-
-
-def test_discover_help(fake_home):
- result = _run(["--help"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- assert "discover" in result.stdout.lower() or "enumerate" in result.stdout.lower()
-
-
-def test_discover_local_only_no_projects(fake_home):
- """Empty home → reports zero local projects, zero peers."""
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- # No crash; mentions local somehow.
- assert "local" in result.stdout.lower() or "0 project" in result.stdout.lower()
-
-
-def test_discover_lists_local_projects(fake_home):
- _make_project(fake_home, "homelab")
- _make_project(fake_home, "career")
- _make_project(fake_home, "claude-templates")
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- assert "homelab" in result.stdout
- assert "career" in result.stdout
- assert "claude-templates" in result.stdout
-
-
-def test_discover_excludes_dirs_without_ai_subdir(fake_home):
- """Directories under ~/projects/ that lack .ai/ are NOT projects."""
- _make_project(fake_home, "real-project")
- (fake_home / "projects" / "not-a-project").mkdir(parents=True)
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- assert "real-project" in result.stdout
- assert "not-a-project" not in result.stdout
-
-
-def test_discover_no_peers_toml_just_local(fake_home):
- _make_project(fake_home, "homelab")
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- # No peers section since no toml.
- assert "homelab" in result.stdout
-
-
-def test_discover_lists_peers_from_toml(fake_home):
- _write_peers_toml(fake_home, textwrap.dedent("""\
- [peers.velox]
- host = "velox"
- ssh_user = "cjennings"
-
- [peers.bastion]
- host = "bastion.local"
- ssh_user = "cjennings"
- """))
- _make_project(fake_home, "homelab")
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- assert "velox" in result.stdout
- assert "bastion" in result.stdout
-
-
-def test_discover_malformed_peers_toml_errors_clearly(fake_home):
- _write_peers_toml(fake_home, "not valid toml at all = = =")
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode != 0
- assert "peers.toml" in result.stderr or "TOML" in result.stderr or "parse" in result.stderr.lower()
-
-
-def test_discover_json_output_schema(fake_home):
- _make_project(fake_home, "homelab")
- _make_project(fake_home, "career")
- _write_peers_toml(fake_home, textwrap.dedent("""\
- [peers.velox]
- host = "velox"
- """))
- result = _run(["--json", "--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- assert "local" in payload
- assert "peers" in payload
- assert isinstance(payload["local"], list)
- assert isinstance(payload["peers"], list)
- assert "homelab" in payload["local"]
- assert "career" in payload["local"]
- velox = next((p for p in payload["peers"] if p["name"] == "velox"), None)
- assert velox is not None
- # Reachability is a key — value depends on actual SSH state.
- assert "reachable" in velox
-
-
-def test_discover_peer_scope(fake_home):
- _write_peers_toml(fake_home, textwrap.dedent("""\
- [peers.velox]
- host = "velox"
-
- [peers.bastion]
- host = "bastion.local"
- """))
- result = _run(["--peer", "velox", "--no-cache", "--json"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- peer_names = [p["name"] for p in payload["peers"]]
- assert "velox" in peer_names
- assert "bastion" not in peer_names
-
-
-def test_discover_unreachable_peer_marked(fake_home):
- """A peer with a definitely-unreachable host gets reachable=False."""
- _write_peers_toml(fake_home, textwrap.dedent("""\
- [peers.bogus]
- host = "definitely-not-a-real-host.invalid"
- ssh_user = "nobody"
- """))
- result = _run(["--no-cache", "--json"], env={**os.environ, "HOME": str(fake_home)}, )
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- bogus = next((p for p in payload["peers"] if p["name"] == "bogus"), None)
- assert bogus is not None
- assert bogus["reachable"] is False
-
-
-def test_discover_cache_hit_within_window(fake_home):
- """Second invocation within 5 min reads cache (skip the SSH probe)."""
- _make_project(fake_home, "homelab")
- # First call populates cache.
- result1 = _run(["--json"], env={**os.environ, "HOME": str(fake_home)})
- assert result1.returncode == 0
- cache = fake_home / ".cache" / "cross-agent-comms" / "discovery.json"
- assert cache.exists()
- # Tamper with the cache to a marker only the cache path can produce.
- payload = json.loads(cache.read_text())
- payload["_test_marker"] = True
- cache.write_text(json.dumps(payload))
- # Second call (no --no-cache) should return the tampered payload.
- result2 = _run(["--json"], env={**os.environ, "HOME": str(fake_home)})
- assert result2.returncode == 0
- payload2 = json.loads(result2.stdout)
- assert payload2.get("_test_marker") is True
-
-
-def test_discover_no_cache_flag_bypasses(fake_home):
- """--no-cache ignores even a fresh cache."""
- _make_project(fake_home, "homelab")
- cache_dir = fake_home / ".cache" / "cross-agent-comms"
- cache_dir.mkdir(parents=True)
- cache_dir.joinpath("discovery.json").write_text(json.dumps({
- "_test_marker": True, "local": [], "peers": []
- }))
- result = _run(["--no-cache", "--json"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- # Cache marker should NOT appear in fresh result.
- assert payload.get("_test_marker") is None or payload.get("_test_marker") is False
- assert "homelab" in payload["local"]
-
-
-def test_discover_halt_shows_banner(fake_home):
- halt = fake_home / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("halted")
- _make_project(fake_home, "homelab")
- result = _run(["--no-cache"], env={**os.environ, "HOME": str(fake_home)})
- assert result.returncode == 0 # discover continues to print under HALT
- assert "HALT" in result.stdout
diff --git a/.ai/scripts/tests/test_cross_agent_halt.py b/.ai/scripts/tests/test_cross_agent_halt.py
deleted file mode 100644
index f8bf0b3..0000000
--- a/.ai/scripts/tests/test_cross_agent_halt.py
+++ /dev/null
@@ -1,204 +0,0 @@
-"""Tests for cross-agent-halt and cross-agent-resume (TDD)."""
-
-from __future__ import annotations
-
-import os
-import subprocess
-import textwrap
-from pathlib import Path
-
-import pytest
-
-HALT_SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-halt"
-RESUME_SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-resume"
-
-
-def _run(script: Path, args: list[str], env: dict | None = None) -> subprocess.CompletedProcess:
- return subprocess.run([str(script), *args], capture_output=True, text=True, env=env)
-
-
-@pytest.fixture
-def isolated_env(tmp_path, monkeypatch):
- """Isolated HOME + a fake systemctl that records calls without acting."""
- fake_home = tmp_path / "home"
- fake_home.mkdir()
- fake_bin = tmp_path / "bin"
- fake_bin.mkdir()
- # Fake systemctl: no-op, exit 0.
- fake_systemctl = fake_bin / "systemctl"
- fake_systemctl.write_text("#!/usr/bin/env bash\nexit 0\n")
- fake_systemctl.chmod(0o755)
- # Fake ssh: succeed only for known-good host.
- fake_ssh = fake_bin / "ssh"
- fake_ssh.write_text(textwrap.dedent("""\
- #!/usr/bin/env bash
- # Find the destination arg (skip flags).
- target=""
- for arg in "$@"; do
- case "$arg" in
- -*|*=*) ;;
- *@*|localhost|*.local|*.invalid) target="$arg"; break ;;
- *) target="$arg"; break ;;
- esac
- done
- case "$target" in
- *invalid*|*unreachable*) exit 255 ;;
- *) exit 0 ;;
- esac
- """))
- fake_ssh.chmod(0o755)
-
- monkeypatch.setenv("HOME", str(fake_home))
- # Prepend our fake bin so systemctl + ssh are intercepted, but keep real /bin etc.
- monkeypatch.setenv("PATH", f"{fake_bin}:{os.environ.get('PATH', '')}")
- return fake_home
-
-
-# ---- cross-agent-halt ----
-
-
-def test_halt_help(isolated_env):
- result = _run(HALT_SCRIPT, ["--help"], env={**os.environ, "HOME": str(isolated_env),
- "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert "halt" in result.stdout.lower()
-
-
-def test_halt_creates_halt_file(isolated_env):
- halt_file = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- assert not halt_file.exists()
- result = _run(HALT_SCRIPT, [], env={**os.environ, "HOME": str(isolated_env),
- "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert halt_file.exists()
-
-
-def test_halt_with_reason_writes_body(isolated_env):
- result = _run(HALT_SCRIPT, ["pausing for incident review"],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- halt_file = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- assert halt_file.exists()
- assert "pausing for incident review" in halt_file.read_text()
-
-
-def test_halt_idempotent(isolated_env):
- """Running halt twice doesn't error."""
- halt_file = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- r1 = _run(HALT_SCRIPT, [], env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert r1.returncode == 0
- assert halt_file.exists()
- r2 = _run(HALT_SCRIPT, [], env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert r2.returncode == 0
- assert halt_file.exists()
-
-
-def test_halt_does_not_pkill(isolated_env):
- """Per design: halt does NOT call pkill. Verify by checking no pkill process gets launched."""
- # Replace pkill in PATH with something that fails loudly so we'd see if halt invoked it.
- fake_bin = isolated_env.parent / "bin"
- pkill = fake_bin / "pkill"
- pkill.write_text("#!/usr/bin/env bash\necho 'PKILL CALLED' >&2\nexit 99\n")
- pkill.chmod(0o755)
- result = _run(HALT_SCRIPT, [], env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert "PKILL CALLED" not in result.stderr
-
-
-def test_halt_tailnet_reports_per_peer(isolated_env):
- """--tailnet iterates peers.toml and reports per-peer status."""
- cfg = isolated_env / ".config" / "cross-agent-comms"
- cfg.mkdir(parents=True)
- (cfg / "peers.toml").write_text(textwrap.dedent("""\
- [peers.velox]
- host = "velox"
- ssh_user = "cjennings"
-
- [peers.bogus]
- host = "definitely-unreachable.invalid"
- ssh_user = "cjennings"
- """))
- result = _run(HALT_SCRIPT, ["--tailnet"],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- # Partial halt → exit 1.
- assert result.returncode == 1
- assert "velox" in result.stdout
- assert "bogus" in result.stdout
- # ✓ marker for velox, ✗ for bogus.
- assert "✓" in result.stdout
- assert "✗" in result.stdout
- assert "PARTIAL" in result.stdout or "partial" in result.stdout.lower()
-
-
-def test_halt_tailnet_all_reachable_exits_zero(isolated_env):
- cfg = isolated_env / ".config" / "cross-agent-comms"
- cfg.mkdir(parents=True)
- (cfg / "peers.toml").write_text(textwrap.dedent("""\
- [peers.velox]
- host = "velox"
- ssh_user = "cjennings"
- """))
- result = _run(HALT_SCRIPT, ["--tailnet"],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert "velox" in result.stdout
-
-
-# ---- cross-agent-resume ----
-
-
-def test_resume_help(isolated_env):
- result = _run(RESUME_SCRIPT, ["--help"],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert "resume" in result.stdout.lower()
-
-
-def test_resume_removes_halt_file(isolated_env):
- halt_file = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt_file.parent.mkdir(parents=True)
- halt_file.write_text("halted")
- assert halt_file.exists()
- result = _run(RESUME_SCRIPT, [],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- assert not halt_file.exists()
-
-
-def test_resume_when_no_halt_active_succeeds(isolated_env):
- """No HALT to clear is not an error."""
- result = _run(RESUME_SCRIPT, [],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
-
-
-def test_resume_prints_per_session_instructions(isolated_env):
- """Resume must surface that polling does NOT auto-resume."""
- halt_file = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt_file.parent.mkdir(parents=True)
- halt_file.write_text("halted")
- result = _run(RESUME_SCRIPT, [],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 0
- out = result.stdout.lower()
- assert "polling" in out
- assert "auto" in out or "explicit" in out or "session" in out
-
-
-def test_resume_tailnet_partial_failure_exit_1(isolated_env):
- cfg = isolated_env / ".config" / "cross-agent-comms"
- cfg.mkdir(parents=True)
- (cfg / "peers.toml").write_text(textwrap.dedent("""\
- [peers.velox]
- host = "velox"
-
- [peers.bogus]
- host = "unreachable-host.invalid"
- """))
- halt_file = cfg / "HALT"
- halt_file.write_text("halted")
- result = _run(RESUME_SCRIPT, ["--tailnet"],
- env={**os.environ, "HOME": str(isolated_env), "PATH": os.environ["PATH"]})
- assert result.returncode == 1
- assert "velox" in result.stdout
- assert "bogus" in result.stdout
diff --git a/.ai/scripts/tests/test_cross_agent_recv.py b/.ai/scripts/tests/test_cross_agent_recv.py
deleted file mode 100644
index 27c53a5..0000000
--- a/.ai/scripts/tests/test_cross_agent_recv.py
+++ /dev/null
@@ -1,176 +0,0 @@
-"""Tests for cross-agent-recv."""
-
-from __future__ import annotations
-
-import json
-import os
-import subprocess
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-recv"
-
-
-def _make_message(path: Path, *, conv_id: str = "test-conv", seq: int = 1, msg_type: str = "request",
- proto_version: str = "5", title: str = "Test", requires_tools: str | None = None,
- body: str = "Body.\n") -> Path:
- fm_lines = [
- f"#+TITLE: {title}",
- f"#+CONVERSATION_ID: {conv_id}",
- f"#+MESSAGE_TYPE: {msg_type}",
- f"#+SEQUENCE: {seq}",
- "#+TIMESTAMP: 2026-04-27T05:00:00-05:00",
- f"#+PROTOCOL_VERSION: {proto_version}",
- ]
- if requires_tools:
- fm_lines.append(f"#+REQUIRES_TOOLS: {requires_tools}")
- path.write_text("\n".join(fm_lines) + "\n\n" + body)
- return path
-
-
-def _run(args: list[str], env: dict | None = None) -> subprocess.CompletedProcess:
- return subprocess.run([str(SCRIPT), *args], capture_output=True, text=True, env=env)
-
-
-@pytest.fixture
-def isolated_env(tmp_path, monkeypatch):
- fake_home = tmp_path / "home"
- fake_home.mkdir()
- monkeypatch.setenv("HOME", str(fake_home))
- return fake_home
-
-
-def test_recv_help(isolated_env):
- result = _run(["--help"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0
- assert "Receive and decide" in result.stdout
-
-
-def test_recv_missing_file_rejects(isolated_env, tmp_path):
- result = _run([str(tmp_path / "nope.org")], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 3 # reject
-
-
-def test_recv_malformed_frontmatter_rejects(isolated_env, tmp_path):
- bad = tmp_path / "bad.org"
- bad.write_text("not org-mode at all\n")
- result = _run([str(bad), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 3
- assert "decision: reject" in result.stdout
-
-
-def test_recv_missing_required_field_rejects(isolated_env, tmp_path):
- msg = tmp_path / "msg.org"
- # Missing PROTOCOL_VERSION among others.
- msg.write_text("#+TITLE: x\n#+CONVERSATION_ID: c\n\nBody.\n")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 3
- assert "missing required" in result.stdout
-
-
-def test_recv_protocol_version_mismatch_query(isolated_env, tmp_path):
- msg = _make_message(tmp_path / "msg.org", proto_version="4")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 2 # query
- assert "PROTOCOL_VERSION mismatch" in result.stdout
-
-
-def test_recv_invalid_message_type_rejects(isolated_env, tmp_path):
- msg = _make_message(tmp_path / "msg.org", msg_type="banana")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 3
- assert "invalid MESSAGE_TYPE" in result.stdout
-
-
-def test_recv_missing_signature_rejects(isolated_env, tmp_path):
- """When verify is on, a missing .asc sibling rejects."""
- msg = _make_message(tmp_path / "msg.org")
- # No .asc sidecar.
- result = _run([str(msg)], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 3
- assert "signature file missing" in result.stdout
-
-
-def test_recv_valid_processes(isolated_env, tmp_path):
- """A valid message with --no-verify and no dedup match → process."""
- msg = _make_message(tmp_path / "msg.org")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0 # process
- assert "decision: process" in result.stdout
- assert "sha256:" in result.stdout
-
-
-def test_recv_dedup_against_identical_existing(isolated_env, tmp_path):
- """Same content + same SEQUENCE in same dir → dedup."""
- inbox = tmp_path / "inbox"
- inbox.mkdir()
- first = _make_message(inbox / "20260427T100000Z-from-x-c.org", conv_id="c", seq=5)
- # Second message with same content — name differs (canonical-style would have different timestamp).
- second = _make_message(inbox / "20260427T100100Z-from-x-c.org", conv_id="c", seq=5)
- # Bodies must be byte-identical for hash equality.
- second.write_bytes(first.read_bytes())
- result = _run([str(second), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 1 # dedup
- assert "decision: dedup" in result.stdout
-
-
-def test_recv_collision_with_different_content_processes(isolated_env, tmp_path):
- """Same SEQUENCE + same CONVERSATION_ID but different content → process both."""
- inbox = tmp_path / "inbox"
- inbox.mkdir()
- _make_message(inbox / "20260427T100000Z-from-x-c.org", conv_id="c", seq=5, body="First body.\n")
- second = _make_message(inbox / "20260427T100100Z-from-x-c.org", conv_id="c", seq=5, body="Different body.\n")
- result = _run([str(second), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0 # process
- assert "decision: process" in result.stdout
-
-
-def test_recv_requires_tools_missing_query(isolated_env, tmp_path):
- """REQUIRES_TOOLS naming a definitely-missing binary → query."""
- msg = _make_message(tmp_path / "msg.org", requires_tools="definitely-not-installed-xyzzy-9000")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 2 # query
- assert "required tools unavailable" in result.stdout
-
-
-def test_recv_requires_tools_present_processes(isolated_env, tmp_path):
- """REQUIRES_TOOLS naming a real binary → process."""
- msg = _make_message(tmp_path / "msg.org", requires_tools="ls,cat")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0
- assert "decision: process" in result.stdout
-
-
-def test_recv_json_output(isolated_env, tmp_path):
- msg = _make_message(tmp_path / "msg.org")
- result = _run([str(msg), "--no-verify", "--json"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- assert payload["decision"] == "process"
- assert payload["message_type"] == "request"
- assert payload["conversation_id"] == "test-conv"
-
-
-def test_recv_halt_blocks(isolated_env, tmp_path):
- halt = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("halted\n")
- msg = _make_message(tmp_path / "msg.org")
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 5
- assert "halt active" in result.stderr.lower()
-
-
-def test_recv_halt_leaves_message_in_place(isolated_env, tmp_path):
- """Per spec: under HALT, recv must NOT move/dedup/reject — leave file in place."""
- halt = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("halted\n")
- msg = _make_message(tmp_path / "msg.org")
- pre_content = msg.read_text()
- result = _run([str(msg), "--no-verify"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 5
- # File still exists with same content.
- assert msg.exists()
- assert msg.read_text() == pre_content
diff --git a/.ai/scripts/tests/test_cross_agent_send.py b/.ai/scripts/tests/test_cross_agent_send.py
deleted file mode 100644
index f716e95..0000000
--- a/.ai/scripts/tests/test_cross_agent_send.py
+++ /dev/null
@@ -1,210 +0,0 @@
-"""Tests for cross-agent-send.
-
-Subprocess-based: treat the script as a black-box CLI and assert on its
-exit codes, stdout, and the files it produces.
-"""
-
-from __future__ import annotations
-
-import os
-import subprocess
-import textwrap
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-send"
-
-
-def _make_message(tmp_path: Path, conv_id: str = "test-conv", seq: int = 1, msg_type: str = "request",
- proto_version: str = "5") -> Path:
- msg = tmp_path / "msg.org"
- msg.write_text(textwrap.dedent(f"""\
- #+TITLE: Test message
- #+CONVERSATION_ID: {conv_id}
- #+MESSAGE_TYPE: {msg_type}
- #+SEQUENCE: {seq}
- #+TIMESTAMP: 2026-04-27T05:00:00-05:00
- #+PROTOCOL_VERSION: {proto_version}
-
- Body.
- """))
- return msg
-
-
-def _run(args: list[str], env: dict | None = None, cwd: Path | None = None) -> subprocess.CompletedProcess:
- return subprocess.run(
- [str(SCRIPT), *args],
- capture_output=True,
- text=True,
- env=env,
- cwd=cwd,
- )
-
-
-@pytest.fixture
-def isolated_env(tmp_path, monkeypatch):
- """Redirect HOME so peers.toml, HALT, marker files are scoped to the test."""
- fake_home = tmp_path / "home"
- fake_home.mkdir()
- monkeypatch.setenv("HOME", str(fake_home))
- # Pre-create projects/ so derive_sender_project has somewhere to look.
- (fake_home / "projects" / "homelab").mkdir(parents=True)
- return fake_home
-
-
-def test_send_help(isolated_env):
- """--help works without side effects."""
- result = _run(["--help"], env={**os.environ, "HOME": str(isolated_env)})
- assert result.returncode == 0
- assert "Send a cross-agent message" in result.stdout
-
-
-def test_send_missing_message_file(isolated_env):
- """Nonexistent message file returns general error."""
- import socket
- machine = socket.gethostname().split(".")[0]
- result = _run(
- [f"{machine}.homelab", str(isolated_env / "nonexistent.org")],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 1
- assert "not found" in result.stderr.lower()
-
-
-def test_send_invalid_destination_format(isolated_env, tmp_path):
- """Destination without . returns dest-not-found exit code."""
- msg = _make_message(tmp_path)
- result = _run(
- ["bogus", str(msg)],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 2
- assert "<machine>.<project>" in result.stderr or "destination" in result.stderr.lower()
-
-
-def test_send_dest_not_in_peers(isolated_env, tmp_path):
- """Cross-machine destination with no peers.toml entry exits 2."""
- msg = _make_message(tmp_path)
- result = _run(
- ["unknownmachine.homelab", str(msg)],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 2
- assert "not found in peers" in result.stderr
-
-
-def test_send_frontmatter_missing_required(isolated_env, tmp_path):
- """Message missing required fields exits 4."""
- bad = tmp_path / "bad.org"
- bad.write_text("#+TITLE: nope\n\nBody.\n")
- import socket
- machine = socket.gethostname().split(".")[0]
- result = _run(
- [f"{machine}.homelab", str(bad)],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 4
- assert "missing required fields" in result.stderr
-
-
-def test_send_invalid_message_type(isolated_env, tmp_path):
- """Unknown MESSAGE_TYPE exits 4."""
- msg = _make_message(tmp_path, msg_type="frobnicate")
- import socket
- machine = socket.gethostname().split(".")[0]
- result = _run(
- [f"{machine}.homelab", str(msg)],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 4
- assert "MESSAGE_TYPE" in result.stderr
-
-
-def test_send_halt_blocks(isolated_env, tmp_path):
- """When HALT exists, send refuses with exit 5."""
- halt = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("test halt\n")
- msg = _make_message(tmp_path)
- import socket
- machine = socket.gethostname().split(".")[0]
- result = _run(
- [f"{machine}.homelab", str(msg)],
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 5
- assert "halt active" in result.stderr.lower()
-
-
-def test_send_same_machine_no_sign_delivers(isolated_env, tmp_path):
- """Same-machine delivery with --no-sign produces a canonically named file."""
- msg = _make_message(tmp_path, conv_id="my-conv")
- import socket
- machine = socket.gethostname().split(".")[0]
- # Sender is derived from CWD walking up to ~/projects/<name>/
- cwd = isolated_env / "projects" / "homelab"
- result = _run(
- [f"{machine}.homelab", str(msg), "--no-sign"],
- env={**os.environ, "HOME": str(isolated_env)},
- cwd=cwd,
- )
- assert result.returncode == 0, f"stderr={result.stderr}"
- inbox = isolated_env / "projects" / "homelab" / "inbox" / "from-agents"
- files = list(inbox.glob("*-from-homelab-my-conv.org"))
- assert len(files) == 1
- # No sig file with --no-sign.
- assert not list(inbox.glob("*.asc"))
- # Canonical filename pattern.
- assert files[0].name.startswith("2026") and files[0].name.endswith("-from-homelab-my-conv.org")
-
-
-def test_send_same_machine_signed_writes_asc(isolated_env, tmp_path):
- """Signed delivery writes both .org and .asc."""
- msg = _make_message(tmp_path, conv_id="signed-conv")
- import socket
- machine = socket.gethostname().split(".")[0]
- cwd = isolated_env / "projects" / "homelab"
- # Use the real GPG keyring (not isolating GPG — Craig's existing keys are fine for tests).
- real_env = {**os.environ, "HOME": str(isolated_env), "GNUPGHOME": str(Path.home() / ".gnupg")}
- result = _run(
- [f"{machine}.homelab", str(msg)],
- env=real_env,
- cwd=cwd,
- )
- if result.returncode != 0:
- pytest.skip(f"GPG signing unavailable in this environment: {result.stderr}")
- inbox = isolated_env / "projects" / "homelab" / "inbox" / "from-agents"
- org_files = list(inbox.glob("*-from-homelab-signed-conv.org"))
- asc_files = list(inbox.glob("*-from-homelab-signed-conv.org.asc"))
- assert len(org_files) == 1
- assert len(asc_files) == 1
-
-
-def test_send_filename_ignores_input_basename(isolated_env, tmp_path):
- """User's input filename is ignored; canonical filename is generated."""
- weird = tmp_path / "weird-user-name.org"
- weird.write_text(textwrap.dedent("""\
- #+TITLE: Title
- #+CONVERSATION_ID: ignored-input
- #+MESSAGE_TYPE: request
- #+SEQUENCE: 1
- #+TIMESTAMP: 2026-04-27T05:00:00-05:00
- #+PROTOCOL_VERSION: 5
-
- Body.
- """))
- import socket
- machine = socket.gethostname().split(".")[0]
- cwd = isolated_env / "projects" / "homelab"
- result = _run(
- [f"{machine}.homelab", str(weird), "--no-sign"],
- env={**os.environ, "HOME": str(isolated_env)},
- cwd=cwd,
- )
- assert result.returncode == 0
- inbox = isolated_env / "projects" / "homelab" / "inbox" / "from-agents"
- # No file named after the user's input.
- assert not (inbox / "weird-user-name.org").exists()
- # Canonical naming used.
- assert list(inbox.glob("*-from-homelab-ignored-input.org"))
diff --git a/.ai/scripts/tests/test_cross_agent_status.py b/.ai/scripts/tests/test_cross_agent_status.py
deleted file mode 100644
index bb5b8ba..0000000
--- a/.ai/scripts/tests/test_cross_agent_status.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""Tests for cross-agent-status (TDD: tests written before implementation)."""
-
-from __future__ import annotations
-
-import json
-import os
-import subprocess
-import textwrap
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-status"
-
-
-def _make_msg(path: Path, *, conv_id: str, seq: int, msg_type: str = "request",
- proto_version: str = "5", timestamp: str = "2026-04-27T05:00:00-05:00") -> Path:
- path.parent.mkdir(parents=True, exist_ok=True)
- path.write_text(textwrap.dedent(f"""\
- #+TITLE: T
- #+CONVERSATION_ID: {conv_id}
- #+MESSAGE_TYPE: {msg_type}
- #+SEQUENCE: {seq}
- #+TIMESTAMP: {timestamp}
- #+PROTOCOL_VERSION: {proto_version}
-
- Body.
- """))
- return path
-
-
-def _run(args: list[str], env: dict | None = None) -> subprocess.CompletedProcess:
- return subprocess.run([str(SCRIPT), *args], capture_output=True, text=True, env=env)
-
-
-@pytest.fixture
-def fake_projects(tmp_path, monkeypatch):
- """Create a fake ~/projects/<name>/inbox/from-agents/ tree under tmp_path."""
- home = tmp_path / "home"
- home.mkdir()
- monkeypatch.setenv("HOME", str(home))
- return home
-
-
-def test_status_help(fake_projects):
- result = _run(["--help"], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- assert "snapshot" in result.stdout.lower() or "pending" in result.stdout.lower()
-
-
-def test_status_no_projects_clean_output(fake_projects):
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- # Empty machine prints either header-only table or "no projects" — accept either.
- # No crash, no pending claims.
- assert "pending" in result.stdout.lower() or result.stdout.strip() == ""
-
-
-def test_status_one_pending_shows_up(fake_projects):
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-career-fixup.org", conv_id="fixup", seq=1)
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- assert "homelab" in result.stdout
- assert "1" in result.stdout # pending count
- assert "20260427T100000Z-from-career-fixup.org" in result.stdout
-
-
-def test_status_released_conversation_zero_pending(fake_projects):
- """A conversation with a release message in it counts as 0 pending."""
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-career-done.org", conv_id="done", seq=1)
- _make_msg(inbox / "20260427T100100Z-from-homelab-done.org", conv_id="done", seq=2, msg_type="release")
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- # Check the homelab row shows 0 pending.
- lines = [ln for ln in result.stdout.splitlines() if "homelab" in ln]
- # At least one homelab line should show 0 pending or "—".
- assert any("0" in ln or "—" in ln for ln in lines)
-
-
-def test_status_partial_release(fake_projects):
- """Conversation with release + a later message → that later message counts as pending."""
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-career-x.org", conv_id="x", seq=1,
- timestamp="2026-04-27T05:00:00-05:00")
- _make_msg(inbox / "20260427T100100Z-from-homelab-x.org", conv_id="x", seq=2, msg_type="release",
- timestamp="2026-04-27T05:01:00-05:00")
- # New message AFTER release: starts a fresh thread that's pending.
- _make_msg(inbox / "20260427T200000Z-from-career-x.org", conv_id="x", seq=3,
- timestamp="2026-04-27T15:00:00-05:00")
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- homelab_line = next(ln for ln in result.stdout.splitlines() if "homelab" in ln)
- assert "1" in homelab_line # the post-release message is pending
-
-
-def test_status_multiple_projects(fake_projects):
- inbox_a = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- inbox_b = fake_projects / "projects" / "career" / "inbox" / "from-agents"
- _make_msg(inbox_a / "20260427T100000Z-from-x-a.org", conv_id="a", seq=1)
- _make_msg(inbox_b / "20260427T100100Z-from-x-b.org", conv_id="b", seq=1)
- _make_msg(inbox_b / "20260427T100200Z-from-x-c.org", conv_id="c", seq=1)
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- # career has 2 pending, homelab has 1.
- career_line = next(ln for ln in result.stdout.splitlines() if "career" in ln)
- homelab_line = next(ln for ln in result.stdout.splitlines() if "homelab" in ln)
- assert "2" in career_line
- assert "1" in homelab_line
-
-
-def test_status_json_output(fake_projects):
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-career-test.org", conv_id="test", seq=1)
- result = _run(["--json"], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- payload = json.loads(result.stdout)
- assert "projects" in payload
- assert isinstance(payload["projects"], list)
- homelab = next((p for p in payload["projects"] if p["name"] == "homelab"), None)
- assert homelab is not None
- assert homelab["pending_count"] == 1
-
-
-def test_status_sort_pending_first(fake_projects):
- """Projects with pending messages sort before projects with 0."""
- (fake_projects / "projects" / "alpha" / "inbox" / "from-agents").mkdir(parents=True)
- inbox_zeta = fake_projects / "projects" / "zeta" / "inbox" / "from-agents"
- _make_msg(inbox_zeta / "20260427T100000Z-from-x-z.org", conv_id="z", seq=1)
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0
- lines = result.stdout.splitlines()
- zeta_idx = next(i for i, ln in enumerate(lines) if "zeta" in ln)
- alpha_idx = next(i for i, ln in enumerate(lines) if "alpha" in ln)
- assert zeta_idx < alpha_idx, "pending project should sort before zero-pending project"
-
-
-def test_status_halt_shows_banner(fake_projects):
- halt = fake_projects / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("halted for test")
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-x-x.org", conv_id="x", seq=1)
- result = _run([], env={**os.environ, "HOME": str(fake_projects)})
- assert result.returncode == 0 # status continues to print under HALT
- assert "HALT" in result.stdout
- # Banner should mention the reason.
- assert "halted for test" in result.stdout
-
-
-def test_status_projects_glob_override(fake_projects):
- inbox = fake_projects / "projects" / "homelab" / "inbox" / "from-agents"
- _make_msg(inbox / "20260427T100000Z-from-x-a.org", conv_id="a", seq=1)
- other_inbox = fake_projects / "projects" / "career" / "inbox" / "from-agents"
- _make_msg(other_inbox / "20260427T100100Z-from-x-b.org", conv_id="b", seq=1)
- # Glob limits to homelab only.
- result = _run(
- ["--projects-glob", str(fake_projects / "projects" / "homelab" / "inbox" / "from-agents") + "/"],
- env={**os.environ, "HOME": str(fake_projects)},
- )
- assert result.returncode == 0
- assert "homelab" in result.stdout
- # career not in scope.
- assert "career" not in result.stdout
diff --git a/.ai/scripts/tests/test_cross_agent_watch.py b/.ai/scripts/tests/test_cross_agent_watch.py
deleted file mode 100644
index 417cc19..0000000
--- a/.ai/scripts/tests/test_cross_agent_watch.py
+++ /dev/null
@@ -1,155 +0,0 @@
-"""Tests for cross-agent-watch.
-
-Black-box: spawn the script, drop files into a watched dir, read the log.
-Tests use --no-notify to avoid firing real desktop notifications.
-"""
-
-from __future__ import annotations
-
-import os
-import subprocess
-import time
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parent.parent / "cross-agent-comms" / "cross-agent-watch"
-
-
-def _spawn(watched_dir: Path, log_path: Path, env: dict) -> subprocess.Popen:
- return subprocess.Popen(
- [
- str(SCRIPT),
- "--projects-glob", str(watched_dir) + "/",
- "--log", str(log_path),
- "--no-notify",
- "--quiet",
- ],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.PIPE,
- env=env,
- )
-
-
-def _wait_for_log_lines(log_path: Path, expected: int, timeout: float = 5.0) -> list[str]:
- deadline = time.time() + timeout
- while time.time() < deadline:
- if log_path.exists():
- lines = [ln for ln in log_path.read_text().splitlines() if ln]
- if len(lines) >= expected:
- return lines
- time.sleep(0.1)
- if log_path.exists():
- return [ln for ln in log_path.read_text().splitlines() if ln]
- return []
-
-
-@pytest.fixture
-def isolated_env(tmp_path, monkeypatch):
- fake_home = tmp_path / "home"
- fake_home.mkdir()
- monkeypatch.setenv("HOME", str(fake_home))
- return fake_home
-
-
-def test_watch_help(isolated_env):
- result = subprocess.run(
- [str(SCRIPT), "--help"],
- capture_output=True, text=True,
- env={**os.environ, "HOME": str(isolated_env)},
- )
- assert result.returncode == 0
- assert "Usage:" in result.stdout
-
-
-def test_watch_empty_glob_exits_nonzero(isolated_env):
- """Glob resolving to zero dirs should exit non-zero with a clear message."""
- result = subprocess.run(
- [str(SCRIPT), "--projects-glob", "/nonexistent/path/*/foo/", "--no-notify", "--quiet"],
- capture_output=True, text=True,
- env={**os.environ, "HOME": str(isolated_env)},
- timeout=3,
- )
- assert result.returncode != 0
- assert "0 directories" in result.stderr
-
-
-def test_watch_logs_org_file_create(isolated_env, tmp_path):
- watched = tmp_path / "watched"
- watched.mkdir()
- log = tmp_path / "watch.log"
- proc = _spawn(watched, log, {**os.environ, "HOME": str(isolated_env)})
- try:
- # Give inotifywait a moment to attach.
- time.sleep(0.3)
- (watched / "test-msg.org").write_text("hello")
- lines = _wait_for_log_lines(log, expected=1, timeout=3.0)
- assert len(lines) >= 1
- assert "test-msg.org" in lines[-1]
- finally:
- proc.terminate()
- proc.wait(timeout=2)
-
-
-def test_watch_filters_tmp_files(isolated_env, tmp_path):
- """Files starting with .tmp. must NOT trigger log entries."""
- watched = tmp_path / "watched"
- watched.mkdir()
- log = tmp_path / "watch.log"
- proc = _spawn(watched, log, {**os.environ, "HOME": str(isolated_env)})
- try:
- time.sleep(0.3)
- (watched / ".tmp.staging-file.org").write_text("hello")
- # Wait briefly to confirm nothing logs.
- time.sleep(0.5)
- if log.exists():
- content = log.read_text()
- assert ".tmp.staging-file" not in content
- # Then drop a real file to confirm watcher is alive.
- (watched / "real.org").write_text("real")
- lines = _wait_for_log_lines(log, expected=1, timeout=3.0)
- assert any("real.org" in ln for ln in lines)
- finally:
- proc.terminate()
- proc.wait(timeout=2)
-
-
-def test_watch_filters_asc_sidecars(isolated_env, tmp_path):
- """Only .org events fire; .asc sidecars are silent."""
- watched = tmp_path / "watched"
- watched.mkdir()
- log = tmp_path / "watch.log"
- proc = _spawn(watched, log, {**os.environ, "HOME": str(isolated_env)})
- try:
- time.sleep(0.3)
- (watched / "msg.org.asc").write_text("sig")
- time.sleep(0.5)
- if log.exists():
- assert "msg.org.asc" not in log.read_text()
- # .org event still works.
- (watched / "msg.org").write_text("body")
- lines = _wait_for_log_lines(log, expected=1, timeout=3.0)
- assert any(ln.endswith("msg.org") for ln in lines)
- finally:
- proc.terminate()
- proc.wait(timeout=2)
-
-
-def test_watch_halt_suppresses_but_logs(isolated_env, tmp_path):
- """When HALT is set, watcher logs the event with (suppressed by HALT) marker."""
- halt = isolated_env / ".config" / "cross-agent-comms" / "HALT"
- halt.parent.mkdir(parents=True)
- halt.write_text("halted")
- watched = tmp_path / "watched"
- watched.mkdir()
- log = tmp_path / "watch.log"
- proc = _spawn(watched, log, {**os.environ, "HOME": str(isolated_env)})
- try:
- time.sleep(0.3)
- (watched / "halted-event.org").write_text("body")
- lines = _wait_for_log_lines(log, expected=1, timeout=3.0)
- assert len(lines) >= 1
- assert "suppressed by HALT" in lines[-1]
- finally:
- proc.terminate()
- proc.wait(timeout=2)