tenseleyflow/loader / 886dfe1

Browse files

Document and lock the Agent facade boundary

Authored by espadonne
SHA
886dfe11cd9a0744d016432aff17781ef3c9673f
Parents
0165b57
Tree
7b8c473

2 changed files

StatusFile+-
M src/loader/agent/loop.py 12 2
M tests/test_compat_boundaries.py 22 0
src/loader/agent/loop.pymodified
@@ -1,4 +1,14 @@
1
-"""The main agent loop."""
1
+"""Public Loader agent facade.
2
+
3
+The long-term shell boundary is now intentional:
4
+
5
+- `Agent` owns public construction, workspace/config bootstrap, and compatibility
6
+  properties used by the CLI, UI, and tests.
7
+- `Agent` delegates prompt/session lifecycle plus runtime entrypoints to
8
+  `loader.runtime.public_shell`.
9
+- `Agent` does not directly own turn orchestration, workflow routing, completion
10
+  policy, or explore runtime behavior.
11
+"""
212
 
313
 from collections.abc import AsyncIterator, Awaitable, Callable
414
 from dataclasses import dataclass
@@ -91,7 +101,7 @@ class AgentConfig:
91101
 
92102
 
93103
 class Agent:
94
-    """The main agent that orchestrates the LLM and tools."""
104
+    """Thin public facade over the runtime-owned shell and launcher."""
95105
 
96106
     def __init__(
97107
         self,
tests/test_compat_boundaries.pymodified
@@ -28,3 +28,25 @@ def test_runtime_code_does_not_import_agent_compatibility_modules() -> None:
2828
             violations.append(str(relative_path))
2929
 
3030
     assert violations == []
31
+
32
+
33
+def test_agent_loop_stays_off_runtime_controller_modules() -> None:
34
+    repo_root = Path(__file__).resolve().parents[1]
35
+    loop_path = repo_root / "src" / "loader" / "agent" / "loop.py"
36
+    text = loop_path.read_text()
37
+    forbidden_runtime_modules = (
38
+        "runtime.conversation",
39
+        "runtime.explore",
40
+        "runtime.launcher",
41
+        "runtime.turn_completion",
42
+        "runtime.turn_iteration",
43
+        "runtime.turn_loop",
44
+        "runtime.turn_preparation",
45
+        "runtime.workflow_lanes",
46
+        "runtime.workflow_recovery",
47
+        "runtime.response_routing",
48
+        "runtime.tool_batches",
49
+    )
50
+
51
+    for module_name in forbidden_runtime_modules:
52
+        assert module_name not in text