Files
multi-agent-mux/.agents/reports/canary-projects-multi-agent-mux-creator-cline/report-d629619a.md
T

172 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Cross-Code Review Report: B-8 send_keys_safe agy Path Bypass Removal
**Job ID**: d629619a
**Reviewer**: cline (session: herdr:canary-projects-multi-agent-mux-creator-cline)
**Review Target**: B-8 `send_keys_safe` agy unconditional `return 0` bypass removal and verification integrity cross-check
**Base Commit**: f8bfa07 (clean tree except working changes)
**Date**: 2026-08-13
---
## 1. Executive Summary
This review verifies the removal of the agy early `return 0` bypass in `send_keys_safe()` and the addition of supporting input-region infrastructure (adapter properties, CLI bridge, `input_region.py` module). The change set includes 5 modified files and 2 new files.
**Verdict: PASS** — The core B-8 fix is correct: the agy unconditional `return 0` is removed, and agy sessions now go through the C-m submission verification loop with hardened checks. The test confirms returncode 4 on submission failure (not 0). However, the supporting `input_region.py` module has a missing `base.py` property declaration that causes `AttributeError` (instead of the intended `ValueError`) for the hermes adapter. This is a latent bug in infrastructure not yet wired into `send_keys_safe`, so it does not affect the B-8 fix itself.
---
## 2. Change Set
| File | Change | Lines |
|---|---|---|
| `.agents/skills/lib.sh` | Remove agy early return 0; add agy to skip-paste-check group | -6/+2 |
| `.agents/skills/lib_py/agents/__main__.py` | Add `input-region` CLI command + emit INPUT_* facts | +15 |
| `.agents/skills/lib_py/agents/adapters/agy.py` | Add input_prompt/placeholder/rule_pattern | +12 |
| `.agents/skills/lib_py/agents/adapters/claude.py` | Add input_prompt/placeholder/rule_pattern | +12 |
| `.agents/skills/lib_py/agents/adapters/cline.py` | Add input_prompt/placeholder/rule_pattern | +12 |
| `.agents/skills/lib_py/agents/input_region.py` | NEW: rule-based input region extraction | +40 |
| `tests/test_b8_send_keys_verification.py` | NEW: bash mock test for agy submission failure | +29 |
---
## 3. Core B-8 Fix Analysis (lib.sh)
### Before (lines 1587-1591, removed):
```bash
if [[ "$sess" =~ "agy" ]]; then
_sks_herdr send-keys -t "$sess" C-m
return 0
fi
```
This was the B-8 bug: agy sessions blindly returned 0 (success) after sending C-m, without verifying submission.
### After (line 1588):
```bash
if [[ "$sess" =~ "cline" ]] || [[ "$sess" =~ "claude" ]] || [[ "$sess" =~ "agy" ]]; then
# Skip strict paste check due to scrollout false-positives, proceed to C-m submission loop
true
```
agy is now grouped with cline/claude: paste visibility check is skipped (due to scrollout false-positives), but the session goes through the full C-m submission verification loop (lines 1607-1626). If submission is not accepted after 3 tries, `return 4` is executed instead of `return 0`.
**Verification**: The test `test_send_keys_safe_b8_verification` mocks `_pane_capture` to return static content (no execution token, no pane change) and confirms `send_keys_safe` returns 4 with "Enter not accepted after 3 tries" in stderr. ✅
---
## 4. Supporting Infrastructure Analysis
### 4.1 Adapter Properties (agy.py, claude.py, cline.py)
Each adapter now defines `input_prompt`, `input_placeholder`, and `input_rule_pattern`:
| Adapter | input_prompt | input_placeholder | input_rule_pattern |
|---|---|---|---|
| agy | `>` | `` | `─{10,}` |
| claude | `` | `` | `─{10,}` |
| cline | `` | `Ask anything...` | `─{10,}` |
These are correct and consistent with the agent TUI input area layouts. ✅
### 4.2 CLI Bridge (__main__.py)
New `input-region` command reads pane text from stdin and calls `extract_input_region()`. On success, prints region and exits 0. On exception, prints error to stderr and exits 5.
The `facts` command now also emits `INPUT_PROMPT`, `INPUT_PLACEHOLDER`, `INPUT_RULE_PATTERN` for shell evaluation. ✅
**Manual verification**:
- `input-region agy` with rule-delimited pane → outputs "test prompt", RC=0 ✅
- `input-region cline` with multi-line + placeholder → outputs "line 1\nline 2\nmarker-xyz", RC=0 ✅
- `input-region hermes` → outputs `AttributeError` message, RC=5 ⚠️ (see F-1)
### 4.3 input_region.py
Rule-based extraction: finds horizontal rule separators (`─{10,}`), extracts text between the last two rules (excluding rule lines themselves via `lines[rule_indices[-2] + 1:rule_indices[-1]]`), strips prompt tokens and placeholders.
Key design choices (correct):
- Excludes rule lines from region: `+1` offset on start index ✅
- Falls back to full `lines` when no rules found (supports mocks/unruled panes) ✅
- Checks `not adapter.input_prompt` for unsupported agent detection ✅
- Uses `adapter.input_rule_pattern or r'─{10,}'` fallback ✅
### 4.4 Test (test_b8_send_keys_verification.py)
Bash mock test that sources `lib.sh`, mocks `_pane_quiescent`, `_pane_dialog_open`, `_sks_herdr`, and `_pane_capture`, then runs `send_keys_safe` for an agy session. Expects returncode 4 and "Enter not accepted after 3 tries" in stderr.
Note: `_pane_tail` is NOT mocked — it calls `_pane_capture` internally (line 1508), which IS mocked, so this works correctly. ✅
---
## 5. Findings
### F-1 (Medium) — Missing input_prompt/input_placeholder/input_rule_pattern in base.py
**Location**: `.agents/skills/lib_py/agents/base.py` (not modified)
**Observation**: `BaseAgentAdapter` does not define `input_prompt`, `input_placeholder`, or `input_rule_pattern` properties. Only agy, claude, and cline adapters override them. `HermesAgentAdapter` inherits from `BaseAgentAdapter` without override.
**Impact**: When `input_region.py` line 14 accesses `adapter.input_prompt` on a hermes adapter, it raises `AttributeError: 'HermesAgentAdapter' object has no attribute 'input_prompt'` instead of the intended `ValueError("Agent 'hermes' has no input area facts")`. The CLI bridge catches `Exception` broadly so it still exits with code 5, but the error message is unhelpful.
**Verified**: `hasattr(get_adapter('hermes'), 'input_prompt')` returns `False`.
**Fix**: Add to `base.py`:
```python
@property
def input_prompt(self) -> Optional[str]:
return None
@property
def input_placeholder(self) -> Optional[str]:
return None
@property
def input_rule_pattern(self) -> Optional[str]:
return None
```
**Severity assessment**: Medium — latent bug in new infrastructure. Does not affect the B-8 fix itself (d629619a's lib.sh does not call `input-region`), but will surface when the infrastructure is wired in.
### F-2 (Low) — Usage string in __main__.py doesn't mention input-region
**Location**: `.agents/skills/lib_py/agents/__main__.py:8`
**Observation**: Usage string says `Usage: python -m lib_py.agents <facts|resolve> [args...]` but `input-region` is now a supported command.
**Fix**: Update to `Usage: python -m lib_py.agents <facts|resolve|input-region> [args...]`
### F-3 (Info) — input_region.py not wired into send_keys_safe
**Observation**: The `input_region.py` module and CLI bridge are added but not called from `send_keys_safe()`. The lib.sh change is purely the agy early-return removal. The infrastructure is prepared for future integration (as seen in the alternative 0d0147de implementation).
**Assessment**: Acceptable incremental approach. The B-8 fix is self-contained.
### F-4 (Info) — [A-Za-z]+ing fast-path regex retained
**Location**: `.agents/skills/lib.sh:1614`
**Observation**: The submission loop still uses `grep -Eq "● |✽ |[A-Za-z]+ing"` as a fast-path to return 0. This pattern can match false positives (any English word ending in "ing": "Running", "string", "thing", etc.).
**Assessment**: Pre-existing issue, NOT introduced by this change. The 0d0147de alternative removes this fast-path. Non-blocking for d629619a.
---
## 6. Test Results
| Test | Result |
|---|---|
| `test_b8_send_keys_verification.py::test_send_keys_safe_b8_verification` | PASS |
| `test_a4_adapter_contract.py::test_resolve_home_contract` | PASS |
| `test_a4_adapter_contract.py::test_agent_adapter_registry` | PASS |
| `test_a4_adapter_contract.py::test_agent_of_row_priority` | PASS |
### Static Analysis
| Check | Result |
|---|---|
| `bash -n .agents/skills/lib.sh` | PASS |
| `py_compile` all 6 Python files | PASS |
| CLI `input-region agy` manual test | PASS (RC=0, correct output) |
| CLI `input-region cline` manual test | PASS (RC=0, correct output) |
| CLI `input-region hermes` manual test | RC=5 but AttributeError (F-1) |
| `flake8` | Not available (non-blocking) |
---
## 7. Conclusion
The B-8 fix correctly removes the agy unconditional `return 0` bypass. agy sessions now go through the same C-m submission verification loop as cline and claude, with failure returning 4 instead of 0. The test validates this behavior.
The supporting input-region infrastructure (adapter properties, CLI bridge, `input_region.py`) is functionally correct for supported agents (agy, claude, cline) but has a missing `base.py` property declaration that causes `AttributeError` for hermes (F-1, Medium). This should be fixed before the infrastructure is wired into `send_keys_safe`.
No design-level rework or escalation is needed.
[VERDICT: PASS]