Files
multi-agent-mux/.agents/reports/reviewer-agy-01/report-db46a0da.md
T
GodopuandClaude Fable 5.1 c3e6a7e96d release(v4.7.3): bump framework and eight skills to 4.7.3 in lockstep; archive PR #37 merge-side reviews
Issue #36: delegated prompts travel by file, a delegation that fails ends
the loop with rc 1. VERSIONS.md carries the entry; the merge-side reports
(round 1 @59be1c8 and round 2 @708262a with identity sidecars, base
59be1c8 -> head 708262a, evidence review-tree) are archived under
.agents/reports/<session>/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-09-24 18:10:28 +09:00

136 lines
9.7 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.
# Pre-Merge Independent Review Report: PR #37 (`fix/issue-36`)
- **Job ID**: `db46a0da`
- **Target Agent**: `agy` (Session: `herdr:reviewer-agy-01`)
- **Role**: Reviewer
- **Target Worktree Context**:
- **Loop ID**: `loop-20260924T080014Z-2b3df0`
- **Base Commit**: `1debc7d92444385b9200e821efa0ff0f6d82023e` (v4.7.2)
- **Head Commit**: `59be1c89209a232059aec0c5aeecc2329929cb49` (6 commits: +765 / −30)
- **Tree SHA**: `a009c9062d9818f343ac57e6c72cda932887fab7`
- **Verification Path**: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20260924T080014Z-2b3df0/1`
---
## 1. Executive Summary
PR #37 resolves Issue #36 ("위임 프롬프트를 argv 가 아닌 파일로 전달하고, 위임 실패를 종료 코드 1 로 보고", Closes #36) across 6 commits and 11 files (+765 / −30):
- `59be1c8` fix(issue-36): create_session hands the agent a brief path, not the task; a prompt file that cannot be written is removed
- `f26952c fix(issue-36): the legacy shell loop and lib.sh's submit helpers pass prompts by file
- `14d11bf` fix(issue-36): a job that cannot be registered after a rebuttal ends the loop with rc 1
- `f5cadd9` test(issue-36): prompts over the argv cap go through the real wrapper, registry and loop; a failed delegation ends the loop with rc 1 and no traceback
- `c77806b` fix(issue-36): the loop passes every delegated prompt as a file; a wrapper that cannot start is a failed submit, on the first try and on the retry
- `68a5d31` fix(issue-36): registry and wrapper accept --prompt-file; the wrapper hands the same path on
The core architecture correctly eliminates the 131,072-byte `MAX_ARG_STRLEN` barrier on Linux by passing prompts via temporary files (`--prompt-file`) across the Python loop runner, delegate-job wrapper, `registry.py`, `lib.sh`, and `create_session.sh`. All legacy CLI contracts and `--prompt` backward compatibility remain intact.
However, during execution in the verification environment on macOS, test `test_s9_shell_loop_removes_a_partial_prompt_file_and_says_why` in `tests/test_issue36_prompt_transport.py` **failed** with an `AssertionError` at line 602 (`assert "File too large" in result.stderr`). This is a platform-dependent test expectation: GNU bash / glibc on Linux prints `write error: File too large` when `ulimit -f` is exceeded, whereas macOS `/bin/bash` (3.2.57) does not emit that string. Because the test suite must pass cleanly across supported platforms (macOS/Linux), a verdict of `NOT PASS` is issued.
---
## 2. Blocking Defect Details
### [Defect 1] Platform-Specific Assertion Failure on macOS in `test_s9`
- **File & Line**: `tests/test_issue36_prompt_transport.py:602`
- **Code**:
```python
598: harness.write_text('set -euo pipefail\nREPO_ROOT="$PWD"\nMAM_REAL_ROOT="$PWD"\n'
599: 'log_error() { printf "%s\\n" "$1"; }\n' + function +
600: '\ntrap "" XFSZ\nulimit -f 1\n'
601: 'output=$(delegate_job_safe submit --prompt "$(cat input.md)")\n')
602: result = subprocess.run(["bash", str(harness)], cwd=tmp_path, capture_output=True, text=True, timeout=60)
603: assert result.returncode != 0
604: assert "File too large" in result.stderr
605: leftovers = list((tmp_path / ".mam").glob("prompt-shloop-*"))
606: assert not leftovers, [(p.name, p.stat().st_size) for p in leftovers]
607: assert "delegate_job_safe: cannot write the prompt file" in result.stderr
```
- **Error Trace**:
```
FAILED tests/test_issue36_prompt_transport.py::test_s9_shell_loop_removes_a_partial_prompt_file_and_says_why
AssertionError: assert 'File too large' in 'xxxx...xxxxdelegate_job_safe: cannot write the prompt file under /private/tmp/.../.mam\n'
```
- **Root Cause**:
When `ulimit -f 1` is exceeded during `printf '%s' "$2" > "$prompt_file"`:
* On Linux (GNU bash 5.x / glibc), the shell writes `bash: line X: printf: write error: File too large` to stderr.
* On macOS (Darwin / bash 3.2.57), the redirection write fails and `printf` exits non-zero without printing the exact literal `"File too large"`.
* The actual implementation behavior is completely correct on macOS: `result.returncode != 0` (Line 603 passes), partial files are cleaned up (`assert not leftovers` Line 606 passes), and MAM's error message `delegate_job_safe: cannot write the prompt file` is printed to stderr (Line 607 passes).
* Line 604 strictly demands `"File too large"` unconditionally, causing the test to fail on macOS.
- **Remediation**:
Guard the assertion with `sys.platform == "linux"`, or allow MAM's error string to satisfy the failure check:
```python
if sys.platform == "linux":
assert "File too large" in result.stderr
```
or
```python
assert ("File too large" in result.stderr or "cannot write the prompt file" in result.stderr)
```
---
## 3. Detailed Verification of Other Checklist Items
### (1) Completeness of Prompt Transport Pathways
- **No Residual Raw `--prompt` Exec Invocations**:
- `lib_py/loop/runner.py`: `_run_cmd` creates a temporary file under `self.mam_dir` (`prompt-{loop_id}-*.md`) and invokes the wrapper with `--prompt-file <path>`. The temporary file is safely cleaned up in a `finally:` block.
- `lib_py/delegation/registry.py`: Supports mutually exclusive `--prompt` and `--prompt-file` in both `register` and `update` commands. Evaluated via `_prompt_from_args()` during CLI parsing before writing to registry JSON.
- `lib_py/delegation/cli.py`: Supports `--prompt-file`, forwarding to `registry.py`.
- `lib.sh`: `delegate_submit_job()` and `_delegate_submit_job_legacy()` both utilize `_delegate_prompt_file` and clean up via `rm -f "$prompt_file"`.
- `multi-agent-mux-delegate-job`: Iteration brief provisions write to `$job_dir/prompt.md` and invoke `registry.py update --prompt-file "$job_dir/prompt.md"`.
- `run_loop.sh`: `delegate_job_safe` intercepts `--prompt` and converts it into `--prompt-file "$prompt_file"`, unlinking it upon return.
- `create_session.sh`: Injected pane text no longer includes the full prompt text; instead, writes `$SUBMIT_JOB_PROMPT` to `$task_brief` (`.mam/jobs/<id>/brief.md`) and passes: `Task: read the complete task in $task_brief and follow it.`.
- Relative paths passed to `--prompt-file` in `cmd_submit` are converted to absolute paths against caller `pwd` before changing directory to `WORKDIR` (`multi-agent-mux-delegate-job:384`), preventing directory-shift bugs.
### (2) Error and Failure Handling
- **`OSError` Handling on Wrapper Execution**:
- In `runner.py`:
```python
except OSError as e:
msg = (f"cannot start the wrapper: {e} "
f"(prompt {len(p_text.encode('utf-8'))} bytes, wrapper {wrapper_script})")
return subprocess.CompletedProcess(cmd, 126, "", msg)
```
Wraps execution failure cleanly as returncode 126. The loop logs the failure and aborts with rc 1 without tracebacks (`test_s3b`, `test_s4`).
- **Fail-Closed Unregistered / Failed Jobs**:
- Re-adjudication failure (`if not adj_jid:`): terminates with error and rc 1.
- Arbitration failure (`if not arb_jid:`): terminates with error and rc 1.
- Compliance failure (`if not comp_jid or not self.wait_for_job(comp_jid):`): terminates with error and rc 1.
- Changing compliance failure from continue to `return 1` is an intentional, sound hardening: if the compliance job fails or times out after an overruled rebuttal, the Creator did not implement the required changes; proceeding to review un-updated code would be erroneous.
### (3) Evidence vs. Delivery Sizing (`MAM_DIFF_MAX_BYTES` / `MAM_DIFF_MAX_LINES`)
- In `diff_collect.sh`: Comments clarify that `MAM_DIFF_MAX_BYTES` (default 200,000) and `MAM_DIFF_MAX_LINES` (default 4000) bound the evidence shown to reviewers, while delivery itself is unbound due to `--prompt-file`.
- `test_s5_a_diff_in_the_former_blind_spot_is_delivered_whole` confirms a 150,000-byte diff (between 131,072 and 200,000 bytes) is not truncated and delivered intact.
### (4) `create_session.sh` Onboarding & Brief Alignment
- Task text is written to `.mam/jobs/<id>/brief.md`.
- Injected instruction provides the absolute path to `brief.md`.
- Handshake protocol (`delegate_publish_cmd`, `--event started`, token verification) remains 100% compliant with Issue #23. Verified by `test_issue23_24_startup_path.py` (19/19 tests passed).
### (5) Existing Test Contracts & Backwards Compatibility
- `test_issue5_phase1_delegation.py`: **66 / 66 passed**.
- `test_version_consistency.py`: **3 / 3 passed**.
- `test_loop_cli.py`: **9 / 9 passed**.
- `test_issue14_delivery_ack.py`: **12 / 12 passed**.
- `test_issue21_phase2_loop_a.py`: **29 / 29 passed**.
- Existing `--prompt` syntax remains fully supported for backward compatibility across all CLIs.
---
## 4. Test Execution Summary
| Test Suite | Result | Duration | Notes |
| :--- | :--- | :--- | :--- |
| `tests/test_issue36_prompt_transport.py` | **20 PASS, 1 FAIL, 1 SKIP** | 39.9s | `test_s9` failed on line 602 (`File too large` assertion on macOS); `test_s1b` skipped (`linux_only`) |
| `tests/test_issue5_phase1_delegation.py` | **66 / 66 PASS** | 12.1s | Registry CLI, backward compatibility with `--prompt` |
| `tests/test_issue23_24_startup_path.py` (S7/S8) | **19 / 19 PASS** | 63.1s | `create_session.sh` brief task injection & handshake |
| `tests/test_loop_cli.py` | **9 / 9 PASS** | 39.2s | Loop CLI regressions |
| `tests/test_issue14_delivery_ack.py` | **12 / 12 PASS** | 98.2s | Delivery acknowledgement contracts |
| `tests/test_issue21_phase2_loop_a.py` | **29 / 29 PASS** | 155.3s | Isolated worktree loop review regressions |
| `tests/test_version_consistency.py` | **3 / 3 PASS** | 0.3s | Version consistency checks |
| `git diff 1debc7d...HEAD --check` | **0 errors** | 0.05s | Clean formatting and no whitespace errors |
---
[VERDICT: NOT PASS]