aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests/test_cross_project_broadcast.py
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-09 17:16:08 -0500
committerCraig Jennings <c@cjennings.net>2026-06-09 17:16:08 -0500
commitc91bd0b1e8183814f248b0751d88a8e422a905e8 (patch)
treef70abe516c47162f8e6538c2d9fa639aa9349d13 /.ai/scripts/tests/test_cross_project_broadcast.py
parent1f0900281b8262539137bc1aff3f01cc05745139 (diff)
downloadrulesets-c91bd0b1e8183814f248b0751d88a8e422a905e8.tar.gz
rulesets-c91bd0b1e8183814f248b0751d88a8e422a905e8.zip
feat(workflows): generalize broadcast into announcement + situational modes
cross-project-broadcast handled tooling and rule announcements but had no shape for the situational case: a life or work event I want every project's agent to know, said once so none is missing context when I next talk to them. I renamed it to broadcast (helper and test alongside) and split it into two modes over the same fan-out plumbing. Announcement keeps the rigid capability template. Situational carries a general-not-comprehensive summary plus a fixed receiving-agent contract: record it in notes.org, hold it time-boxed or standing, apply on the project's own judgment, ask follow-ups at startup. The broadcasting agent does no per-project relevance analysis. Each receiving agent decides what the event means for its own work.
Diffstat (limited to '.ai/scripts/tests/test_cross_project_broadcast.py')
-rw-r--r--.ai/scripts/tests/test_cross_project_broadcast.py116
1 files changed, 0 insertions, 116 deletions
diff --git a/.ai/scripts/tests/test_cross_project_broadcast.py b/.ai/scripts/tests/test_cross_project_broadcast.py
deleted file mode 100644
index 5919fbf..0000000
--- a/.ai/scripts/tests/test_cross_project_broadcast.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""Tests for cross-project-broadcast.py: project fingerprinting + discovery.
-
-Plain python3 script. The pure-ish helpers are driven against tmp project
-trees; discovery is exercised with SEARCH_ROOTS monkeypatched to the tree, and
-the cwd-based helpers with monkeypatch.chdir.
-"""
-from __future__ import annotations
-
-import importlib.util
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parents[1] / "cross-project-broadcast.py"
-
-
-@pytest.fixture(scope="module")
-def bcast():
- spec = importlib.util.spec_from_file_location("cross_project_broadcast", SCRIPT)
- assert spec and spec.loader
- module = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(module)
- return module
-
-
-def _make_project(root: Path, name: str, with_inbox: bool = True,
- with_protocols: bool = True) -> Path:
- p = root / name
- (p / ".ai").mkdir(parents=True)
- if with_protocols:
- (p / ".ai" / "protocols.org").write_text("#+TITLE: protocols\n")
- if with_inbox:
- (p / "inbox").mkdir()
- return p
-
-
-# --- is_broadcastable ---
-
-def test_is_broadcastable_true_with_protocols_and_inbox(bcast, tmp_path):
- assert bcast.is_broadcastable(_make_project(tmp_path, "proj")) is True
-
-
-def test_is_broadcastable_false_without_inbox(bcast, tmp_path):
- p = _make_project(tmp_path, "proj", with_inbox=False)
- assert bcast.is_broadcastable(p) is False
-
-
-def test_is_broadcastable_false_without_protocols(bcast, tmp_path):
- p = _make_project(tmp_path, "proj", with_protocols=False)
- assert bcast.is_broadcastable(p) is False
-
-
-def test_is_broadcastable_false_on_plain_dir(bcast, tmp_path):
- assert bcast.is_broadcastable(tmp_path) is False
-
-
-# --- discover (SEARCH_ROOTS monkeypatched onto the tmp tree) ---
-
-def test_discover_finds_broadcastable_subprojects(bcast, tmp_path, monkeypatch):
- root = tmp_path / "code"
- root.mkdir()
- _make_project(root, "alpha")
- _make_project(root, "beta")
- _make_project(root, "no-inbox", with_inbox=False) # not broadcastable
- monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root])
- assert [p.name for p in bcast.discover()] == ["alpha", "beta"]
-
-
-def test_discover_handles_root_that_is_itself_a_project(bcast, tmp_path, monkeypatch):
- root = _make_project(tmp_path, ".emacs.d")
- monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root])
- assert [p.name for p in bcast.discover()] == [".emacs.d"]
-
-
-def test_discover_dedups_by_basename_across_roots(bcast, tmp_path, monkeypatch):
- root1 = tmp_path / "code"
- root1.mkdir()
- root2 = tmp_path / "projects"
- root2.mkdir()
- _make_project(root1, "dup")
- _make_project(root2, "dup")
- monkeypatch.setattr(bcast, "SEARCH_ROOTS", [root1, root2])
- assert [p.name for p in bcast.discover()] == ["dup"]
-
-
-def test_discover_skips_missing_roots(bcast, tmp_path, monkeypatch):
- monkeypatch.setattr(bcast, "SEARCH_ROOTS", [tmp_path / "does-not-exist"])
- assert bcast.discover() == []
-
-
-# --- sender_project / inbox_send_path (cwd-based) ---
-
-def test_sender_project_returns_basename_inside_an_ai_project(bcast, tmp_path, monkeypatch):
- p = _make_project(tmp_path, "myproj")
- monkeypatch.chdir(p)
- assert bcast.sender_project() == "myproj"
-
-
-def test_sender_project_none_outside_an_ai_project(bcast, tmp_path, monkeypatch):
- monkeypatch.chdir(tmp_path)
- assert bcast.sender_project() is None
-
-
-def test_inbox_send_path_found_in_project(bcast, tmp_path, monkeypatch):
- p = _make_project(tmp_path, "myproj")
- (p / ".ai" / "scripts").mkdir()
- helper = p / ".ai" / "scripts" / "inbox-send.py"
- helper.write_text("# stub\n")
- monkeypatch.chdir(p)
- assert bcast.inbox_send_path() == helper
-
-
-def test_inbox_send_path_raises_when_missing(bcast, tmp_path, monkeypatch):
- monkeypatch.chdir(tmp_path)
- with pytest.raises(SystemExit):
- bcast.inbox_send_path()