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, base59be1c8-> head708262a, 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
9.7 KiB
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
- Loop ID:
1. Executive Summary
PR #37 resolves Issue #36 ("위임 프롬프트를 argv 가 아닌 파일로 전달하고, 위임 실패를 종료 코드 1 로 보고", Closes #36) across 6 commits and 11 files (+765 / −30):
59be1c8fix(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
14d11bffix(issue-36): a job that cannot be registered after a rebuttal ends the loop with rc 1f5cadd9test(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 tracebackc77806bfix(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 retry68a5d31fix(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:
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 1is exceeded duringprintf '%s' "$2" > "$prompt_file":- On Linux (GNU bash 5.x / glibc), the shell writes
bash: line X: printf: write error: File too largeto stderr. - On macOS (Darwin / bash 3.2.57), the redirection write fails and
printfexits 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 leftoversLine 606 passes), and MAM's error messagedelegate_job_safe: cannot write the prompt fileis printed to stderr (Line 607 passes). - Line 604 strictly demands
"File too large"unconditionally, causing the test to fail on macOS.
- On Linux (GNU bash 5.x / glibc), the shell writes
- Remediation:
Guard the assertion with
sys.platform == "linux", or allow MAM's error string to satisfy the failure check:orif sys.platform == "linux": assert "File too large" in result.stderrassert ("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
--promptExec Invocations:lib_py/loop/runner.py:_run_cmdcreates a temporary file underself.mam_dir(prompt-{loop_id}-*.md) and invokes the wrapper with--prompt-file <path>. The temporary file is safely cleaned up in afinally:block.lib_py/delegation/registry.py: Supports mutually exclusive--promptand--prompt-filein bothregisterandupdatecommands. Evaluated via_prompt_from_args()during CLI parsing before writing to registry JSON.lib_py/delegation/cli.py: Supports--prompt-file, forwarding toregistry.py.lib.sh:delegate_submit_job()and_delegate_submit_job_legacy()both utilize_delegate_prompt_fileand clean up viarm -f "$prompt_file".multi-agent-mux-delegate-job: Iteration brief provisions write to$job_dir/prompt.mdand invokeregistry.py update --prompt-file "$job_dir/prompt.md".run_loop.sh:delegate_job_safeintercepts--promptand 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_PROMPTto$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-fileincmd_submitare converted to absolute paths against callerpwdbefore changing directory toWORKDIR(multi-agent-mux-delegate-job:384), preventing directory-shift bugs.
(2) Error and Failure Handling
OSErrorHandling on Wrapper Execution:- In
runner.py:Wraps execution failure cleanly as returncode 126. The loop logs the failure and aborts with rc 1 without tracebacks (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)test_s3b,test_s4).
- In
- 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 1is 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.
- Re-adjudication failure (
(3) Evidence vs. Delivery Sizing (MAM_DIFF_MAX_BYTES / MAM_DIFF_MAX_LINES)
- In
diff_collect.sh: Comments clarify thatMAM_DIFF_MAX_BYTES(default 200,000) andMAM_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_wholeconfirms 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 bytest_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
--promptsyntax 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]