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
+66 -66
View File
@@ -11,9 +11,9 @@ The AI's ability to interact with the filesystem is mediated by a three-layer se
### Global State
```python
_allowed_paths: set[Path] = set() # Explicit file allowlist (resolved absolutes)
_base_dirs: set[Path] = set() # Directory roots for containment checks
_primary_base_dir: Path | None = None # Used for resolving relative paths
_allowed_paths: set[Path] = set() # Explicit file allowlist (resolved absolutes)
_base_dirs: set[Path] = set() # Directory roots for containment checks
_primary_base_dir: Path | None = None # Used for resolving relative paths
perf_monitor_callback: Optional[Callable[[], dict[str, Any]]] = None
```
@@ -61,7 +61,7 @@ The `dispatch` function (`mcp_client.py:1322`) is a flat if/elif chain mapping 4
| Tool | Parameters | Description |
|---|---|---|
| `read_file` | `path` | UTF-8 file content extraction |
| `list_directory` | `path` | Compact table: `[file/dir] name size`. Applies blacklist filter to entries. |
| `list_directory` | `path` | Compact table: `[file/dir] name size`. Applies blacklist filter to entries. |
| `search_files` | `path`, `pattern` | Glob pattern matching within an allowed directory. Applies blacklist filter. |
| `get_file_slice` | `path`, `start_line`, `end_line` | Returns specific line range (1-based, inclusive) |
| `set_file_slice` | `path`, `start_line`, `end_line`, `new_content` | Replaces a line range with new content (surgical edit) |
@@ -166,28 +166,28 @@ See [guide_beads.md](guide_beads.md) (placeholder; written in Task 10) for the f
**AST-based read tools** follow this pattern:
```python
def py_get_skeleton(path: str) -> str:
p, err = _resolve_and_check(path)
if err: return err
if not p.exists(): return f"ERROR: file not found: {path}"
if not p.is_file() or p.suffix != ".py": return f"ERROR: not a python file: {path}"
from file_cache import ASTParser
code = p.read_text(encoding="utf-8")
parser = ASTParser("python")
return parser.get_skeleton(code)
p, err = _resolve_and_check(path)
if err: return err
if not p.exists(): return f"ERROR: file not found: {path}"
if not p.is_file() or p.suffix != ".py": return f"ERROR: not a python file: {path}"
from file_cache import ASTParser
code = p.read_text(encoding="utf-8")
parser = ASTParser("python")
return parser.get_skeleton(code)
```
**AST-based write tools** use stdlib `ast` (not tree-sitter) to locate symbols, then delegate to `set_file_slice`:
```python
def py_update_definition(path: str, name: str, new_content: str) -> str:
p, err = _resolve_and_check(path)
if err: return err
code = p.read_text(encoding="utf-8").lstrip(chr(0xFEFF)) # Strip BOM
tree = ast.parse(code)
node = _get_symbol_node(tree, name) # Walks AST for matching node
if not node: return f"ERROR: could not find definition '{name}'"
start = getattr(node, "lineno")
end = getattr(node, "end_lineno")
return set_file_slice(path, start, end, new_content)
p, err = _resolve_and_check(path)
if err: return err
code = p.read_text(encoding="utf-8").lstrip(chr(0xFEFF)) # Strip BOM
tree = ast.parse(code)
node = _get_symbol_node(tree, name) # Walks AST for matching node
if not node: return f"ERROR: could not find definition '{name}'"
start = getattr(node, "lineno")
end = getattr(node, "end_lineno")
return set_file_slice(path, start, end, new_content)
```
The `_get_symbol_node` helper supports dot notation (`ClassName.method_name`) by first finding the class, then searching its body for the method.
@@ -200,19 +200,19 @@ Tools can be executed concurrently via `async_dispatch`:
```python
async def async_dispatch(tool_name: str, tool_input: dict[str, Any]) -> str:
"""Dispatch an MCP tool call asynchronously."""
return await asyncio.to_thread(dispatch, tool_name, tool_input)
"""Dispatch an MCP tool call asynchronously."""
return await asyncio.to_thread(dispatch, tool_name, tool_input)
```
In `ai_client.py`, multiple tool calls within a single AI turn are executed in parallel:
```python
async def _execute_tool_calls_concurrently(calls, base_dir, ...):
tasks = []
for fc in calls:
tasks.append(_execute_single_tool_call_async(name, args, ...))
results = await asyncio.gather(*tasks)
return results
tasks = []
for fc in calls:
tasks.append(_execute_single_tool_call_async(name, args, ...))
results = await asyncio.gather(*tasks)
return results
```
This significantly reduces latency when the AI makes multiple independent file reads in a single turn.
@@ -229,16 +229,16 @@ Manual Slop exposes a REST-based IPC interface on `127.0.0.1:8999` using Python'
```python
class HookServerInstance(ThreadingHTTPServer):
app: Any # Reference to main App instance
app: Any # Reference to main App instance
class HookHandler(BaseHTTPRequestHandler):
# Accesses self.server.app for all state
# Accesses self.server.app for all state
class HookServer:
app: Any
port: int = 8999
server: HookServerInstance | None
thread: threading.Thread | None
app: Any
port: int = 8999
server: HookServerInstance | None
thread: threading.Thread | None
```
**Start conditions**: Only starts if `app.test_hooks_enabled == True` OR current provider is `'gemini_cli'`. Otherwise `start()` silently returns.
@@ -274,20 +274,20 @@ This ensures all state reads happen on the GUI main thread during `_process_pend
```python
{
"mma_status": str, # "idle" | "planning" | "executing" | "done"
"ai_status": str, # "idle" | "sending..." | etc.
"active_tier": str | None,
"active_track": str, # Track ID or raw value
"active_tickets": list, # Serialized ticket dicts
"mma_step_mode": bool,
"pending_tool_approval": bool, # _pending_ask_dialog
"pending_mma_step_approval": bool, # _pending_mma_approval is not None
"pending_mma_spawn_approval": bool, # _pending_mma_spawn is not None
"pending_approval": bool, # Backward compat: step OR tool
"pending_spawn": bool, # Alias for spawn approval
"tracks": list,
"proposed_tracks": list,
"mma_streams": dict, # {stream_id: output_text}
"mma_status": str, # "idle" | "planning" | "executing" | "done"
"ai_status": str, # "idle" | "sending..." | etc.
"active_tier": str | None,
"active_track": str, # Track ID or raw value
"active_tickets": list, # Serialized ticket dicts
"mma_step_mode": bool,
"pending_tool_approval": bool, # _pending_ask_dialog
"pending_mma_step_approval": bool, # _pending_mma_approval is not None
"pending_mma_spawn_approval": bool, # _pending_mma_spawn is not None
"pending_approval": bool, # Backward compat: step OR tool
"pending_spawn": bool, # Alias for spawn approval
"tracks": list,
"proposed_tracks": list,
"mma_streams": dict, # {stream_id: output_text}
}
```
@@ -295,9 +295,9 @@ This ensures all state reads happen on the GUI main thread during `_process_pend
```python
{
"thinking": bool, # ai_status in ["sending...", "running powershell..."]
"live": bool, # ai_status in ["running powershell...", "fetching url...", ...]
"prior": bool, # app.is_viewing_prior_session
"thinking": bool, # ai_status in ["sending...", "running powershell..."]
"live": bool, # ai_status in ["running powershell...", "fetching url...", ...]
"prior": bool, # app.is_viewing_prior_session
}
```
@@ -340,7 +340,7 @@ The counterpart `/api/ask/respond`:
```python
class ApiHookClient:
def __init__(self, base_url="http://127.0.0.1:8999", max_retries=5, retry_delay=0.2)
def __init__(self, base_url="http://127.0.0.1:8999", max_retries=5, retry_delay=0.2)
```
### Connection Methods
@@ -400,21 +400,21 @@ Tool calls are executed concurrently within a single AI turn using `asyncio.gath
```python
async def async_dispatch(tool_name: str, tool_input: dict[str, Any]) -> str:
"""
Dispatch an MCP tool call by name asynchronously.
Returns the result as a string.
"""
# Run blocking I/O bound tools in a thread to allow parallel execution
return await asyncio.to_thread(dispatch, tool_name, tool_input)
"""
Dispatch an MCP tool call by name asynchronously.
Returns the result as a string.
"""
# Run blocking I/O bound tools in a thread to allow parallel execution
return await asyncio.to_thread(dispatch, tool_name, tool_input)
```
All tools are wrapped in `asyncio.to_thread()` to prevent blocking the event loop. This enables `ai_client.py` to execute multiple tools via `asyncio.gather()`:
```python
results = await asyncio.gather(
async_dispatch("read_file", {"path": "src/module_a.py"}),
async_dispatch("read_file", {"path": "src/module_b.py"}),
async_dispatch("get_file_summary", {"path": "src/module_c.py"}),
async_dispatch("read_file", {"path": "src/module_a.py"}),
async_dispatch("read_file", {"path": "src/module_b.py"}),
async_dispatch("get_file_summary", {"path": "src/module_c.py"}),
)
```
@@ -453,13 +453,13 @@ Summary:
```
logs/sessions/<session_id>/
comms.log # JSON-L: every API interaction (direction, kind, payload)
toolcalls.log # Markdown: sequential tool invocation records
apihooks.log # API hook invocations
clicalls.log # JSON-L: CLI subprocess details (command, stdin, stdout, stderr, latency)
comms.log # JSON-L: every API interaction (direction, kind, payload)
toolcalls.log # Markdown: sequential tool invocation records
apihooks.log # API hook invocations
clicalls.log # JSON-L: CLI subprocess details (command, stdin, stdout, stderr, latency)
scripts/generated/
<ts>_<seq:04d>.ps1 # Each AI-generated PowerShell script, preserved in order
<ts>_<seq:04d>.ps1 # Each AI-generated PowerShell script, preserved in order
```
### Logging Functions