docs: scrub gemini_cli references from 12 docs (provider count 8->7)

Cleaned: docs/guide_ai_client.md, docs/guide_architecture.md,
docs/guide_models.md, docs/guide_simulations.md,
docs/guide_context_aggregation.md, docs/guide_tools.md, docs/Readme.md,
conductor/tech-stack.md, conductor/product.md,
conductor/product-guidelines.md, conductor/workflow.md,
conductor/code_styleguides/error_handling.md.

Provider list citations updated to 7 (gemini, anthropic, deepseek,
minimax, qwen, grok, llama). guide_meta_boundary.md intentionally
retained (its gemini_cli references are the meta-tooling
GEMINI_CLI_HOOK_CONTEXT env var, NOT the provider; per spec GAP-A12).
This commit is contained in:
ed
2026-07-05 20:16:53 -04:00
parent be93c262e0
commit bd1d966c12
12 changed files with 1242 additions and 1242 deletions
+58 -58
View File
@@ -29,13 +29,13 @@ Defined in `tests/conftest.py`, this session-scoped fixture manages the lifecycl
```python
@pytest.fixture(scope="session")
def live_gui(request) -> Generator["_LiveGuiHandle", None, None]:
process = subprocess.Popen(
["uv", "run", "python", "-u", gui_script, "--enable-test-hooks"],
stdout=log_file, stderr=log_file, text=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
)
# ... (readiness polling + xdist coordination) ...
yield _LiveGuiHandle(process, gui_script, workspace=temp_workspace)
process = subprocess.Popen(
["uv", "run", "python", "-u", gui_script, "--enable-test-hooks"],
stdout=log_file, stderr=log_file, text=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
)
# ... (readiness polling + xdist coordination) ...
yield _LiveGuiHandle(process, gui_script, workspace=temp_workspace)
```
- **`-u` flag**: Disables output buffering for real-time log capture.
@@ -45,13 +45,13 @@ def live_gui(request) -> Generator["_LiveGuiHandle", None, None]:
**Readiness polling:**
```python
max_retries = 15 # seconds
max_retries = 15 # seconds
while time.time() - start_time < max_retries:
response = requests.get("http://127.0.0.1:8999/status", timeout=0.5)
if response.status_code == 200:
ready = True; break
if process.poll() is not None: break # Process died early
time.sleep(0.5)
response = requests.get("http://127.0.0.1:8999/status", timeout=0.5)
if response.status_code == 200:
ready = True; break
if process.poll() is not None: break # Process died early
time.sleep(0.5)
```
Polls `GET /status` every 500ms for up to 15 seconds. Checks `process.poll()` each iteration to detect early crashes (avoids waiting the full timeout if the GUI exits). Pre-check: tests if port 8999 is already occupied.
@@ -62,11 +62,11 @@ Polls `GET /status` every 500ms for up to 15 seconds. Checks `process.poll()` ea
```python
finally:
client = ApiHookClient()
client.reset_session() # Clean GUI state before killing
time.sleep(0.5)
kill_process_tree(process.pid)
log_file.close()
client = ApiHookClient()
client.reset_session() # Clean GUI state before killing
time.sleep(0.5)
kill_process_tree(process.pid)
log_file.close()
```
Sends `reset_session()` via `ApiHookClient` before killing to prevent stale state files.
@@ -91,9 +91,9 @@ Sends `reset_session()` via `ApiHookClient` before killing to prevent stale stat
```python
@pytest.fixture(autouse=True)
def reset_ai_client() -> Generator[None, None, None]:
ai_client.reset_session()
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
yield
ai_client.reset_session()
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
yield
```
Runs automatically before every test. Resets the `ai_client` module state and defaults to a safe model, preventing state pollution between tests.
@@ -103,9 +103,9 @@ Runs automatically before every test. Resets the `ai_client` module state and de
```python
@pytest.fixture(autouse=True)
def isolate_workspace(tmp_path_factory, monkeypatch) -> Generator[None, None, None]:
# Redirects the path resolution layer to a temp directory
# Prevents tests from writing to the user's actual project
...
# Redirects the path resolution layer to a temp directory
# Prevents tests from writing to the user's actual project
...
```
This autouse fixture ensures every test runs against an isolated `tmp_path` workspace. It `monkeypatch`-es `src.paths` so that any code path resolving a project directory (e.g., `manual_slop.toml` lookup, conductor directory resolution, log directory) is redirected to a fresh temp directory per test. Without this, tests could mutate the user's actual `manual_slop.toml` or conductor tracks directory.
@@ -117,8 +117,8 @@ This is the primary mechanism for satisfying the **Artifact Isolation** rule in
```python
@pytest.fixture(autouse=True)
def reset_paths() -> Generator[None, None, None]:
# Forces `src/paths.py` to re-resolve from environment / config on next access
...
# Forces `src/paths.py` to re-resolve from environment / config on next access
...
```
Pairs with `isolate_workspace` to fully reset the path subsystem. After a test that creates a project config, the next test gets a clean slate.
@@ -147,11 +147,11 @@ Structured diagnostic logging for test telemetry:
```python
class VerificationLogger:
def __init__(self, test_name: str, script_name: str):
self.logs_dir = Path(f"logs/test/{datetime.now().strftime('%Y%m%d_%H%M%S')}")
def __init__(self, test_name: str, script_name: str):
self.logs_dir = Path(f"logs/test/{datetime.now().strftime('%Y%m%d_%H%M%S')}")
def log_state(self, field: str, before: Any, after: Any, delta: Any = None)
def finalize(self, description: str, status: str, result_msg: str)
def log_state(self, field: str, before: Any, after: Any, delta: Any = None)
def finalize(self, description: str, status: str, result_msg: str)
```
Output format: fixed-width column table (`Field | Before | After | Delta`) written to `logs/test/<timestamp>/<script_name>.txt`. Dual output: file + tagged stdout lines for CI visibility.
@@ -191,12 +191,12 @@ Enters an epic description and triggers planning. The GUI invokes the LLM (which
```python
for _ in range(60):
status = client.get_mma_status()
if status.get('pending_mma_spawn_approval'): client.click('btn_approve_spawn')
elif status.get('pending_mma_step_approval'): client.click('btn_approve_mma_step')
elif status.get('pending_tool_approval'): client.click('btn_approve_tool')
if status.get('proposed_tracks') and len(status['proposed_tracks']) > 0: break
time.sleep(1)
status = client.get_mma_status()
if status.get('pending_mma_spawn_approval'): client.click('btn_approve_spawn')
elif status.get('pending_mma_step_approval'): client.click('btn_approve_mma_step')
elif status.get('pending_tool_approval'): client.click('btn_approve_tool')
if status.get('proposed_tracks') and len(status['proposed_tracks']) > 0: break
time.sleep(1)
```
The **approval automation** is a critical pattern repeated in every polling loop. The MMA engine has three approval gates:
@@ -235,9 +235,9 @@ Polls until `mma_status == 'running'` or `'done'`. Continues auto-approving all
```python
streams = status.get('mma_streams', {})
if any("Tier 3" in k for k in streams.keys()):
tier3_key = [k for k in streams.keys() if "Tier 3" in k][0]
if "SUCCESS: Mock Tier 3 worker" in streams[tier3_key]:
streams_found = True
tier3_key = [k for k in streams.keys() if "Tier 3" in k][0]
if "SUCCESS: Mock Tier 3 worker" in streams[tier3_key]:
streams_found = True
```
Verifies that `mma_streams` contains a key with "Tier 3" and the value contains the exact mock output string.
@@ -262,16 +262,16 @@ A fake Gemini CLI executable that replaces the real `gemini` binary during integ
**Input mechanism:**
```python
prompt = sys.stdin.read() # Primary: prompt via stdin
sys.argv # Secondary: management command detection
os.environ.get('GEMINI_CLI_HOOK_CONTEXT') # Tertiary: environment variable
prompt = sys.stdin.read() # Primary: prompt via stdin
sys.argv # Secondary: management command detection
os.environ.get('GEMINI_CLI_HOOK_CONTEXT') # Tertiary: environment variable
```
**Management command bypass:**
```python
if len(sys.argv) > 1 and sys.argv[1] in ["mcp", "extensions", "skills", "hooks"]:
return # Silent exit
return # Silent exit
```
**Response routing** — keyword matching on stdin content:
@@ -390,22 +390,22 @@ The headless service uses the **Remote Confirmation Protocol** for HITL: when an
```python
class ASTParser:
def __init__(self, language: str = "python"):
self.language = tree_sitter.Language(tree_sitter_python.language())
self.parser = tree_sitter.Parser(self.language)
def __init__(self, language: str = "python"):
self.language = tree_sitter.Language(tree_sitter_python.language())
self.parser = tree_sitter.Parser(self.language)
def parse(self, code: str) -> tree_sitter.Tree
def get_skeleton(self, code: str, path: str = "") -> str
def get_curated_view(self, code: str, path: str = "") -> str
def get_targeted_view(self, code: str, symbols: List[str], path: str = "") -> str
def parse(self, code: str) -> tree_sitter.Tree
def get_skeleton(self, code: str, path: str = "") -> str
def get_curated_view(self, code: str, path: str = "") -> str
def get_targeted_view(self, code: str, symbols: List[str], path: str = "") -> str
```
**`get_skeleton` algorithm:**
1. Parse code to tree-sitter AST.
2. Walk all `function_definition` nodes.
3. For each body (`block` node):
- If first non-comment child is a docstring: preserve docstring, replace rest with `...`.
- Otherwise: replace entire body with `...`.
- If first non-comment child is a docstring: preserve docstring, replace rest with `...`.
- Otherwise: replace entire body with `...`.
4. Apply edits in reverse byte order (maintains valid offsets).
**`get_curated_view` algorithm:**
@@ -428,10 +428,10 @@ Token-efficient structural descriptions without AI calls:
```python
_SUMMARISERS: dict[str, Callable] = {
".py": _summarise_python, # imports, classes, methods, functions, constants
".toml": _summarise_toml, # table keys + array lengths
".md": _summarise_markdown, # h1-h3 headings
".ini": _summarise_generic, # line count + preview
".py": _summarise_python, # imports, classes, methods, functions, constants
".toml": _summarise_toml, # table keys + array lengths
".md": _summarise_markdown, # h1-h3 headings
".ini": _summarise_generic, # line count + preview
}
```
@@ -455,8 +455,8 @@ functions: summarise_file, build_summary_markdown
```python
class CodeOutliner:
def __init__(self) -> None: ...
def outline(self, code: str) -> str: ...
def __init__(self) -> None: ...
def outline(self, code: str) -> str: ...
def get_outline(path: Path, code: str) -> str: ...
```