fix(issue-36): create_session hands the agent a brief path, not the task; a prompt file that cannot be written is removed

Review of f26952c (codex, job cc849cbf):

- P2: create_session registered the task by file but then pasted the whole
  task into the onboarding text, which send_keys_safe hands to `herdr agent
  prompt` as one argv string. A 130,500-byte --submit-job was registered
  intact and never reached the agent (execve E2BIG). The task now goes into
  <jobs>/<id>/brief.md, as the delegate-job wrapper does, and the injected
  text names that path. The publish command and its dispatch token (#23) are
  unchanged. The other send_keys_safe callers (the wrapper's short pointer,
  stop_session's exit key) carry no task text.
- P3: delegate_job_safe's write-failure branch left the partial prompt file
  behind and logged to stdout, which callers capture. It now removes the file
  and logs to stderr.

S8 (real create_session.sh, 100 and 130,500 bytes, strace when present) and
S9 (the real function, RLIMIT_FSIZE write failure) carry the reviewer's
reproductions over; all three fail on f26952c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-09-24 07:02:20 +00:00
1 parent f26952ccc3
commit 59be1c8920
3 files changed
+82 -2

No files matched your search

+66
View File
@@ -537,3 +537,69 @@ def test_s7b_shell_loop_ends_nonzero_when_a_job_cannot_be_registered(tmp_path, r
assert f"{refuse} registration refused" in res.stderr
assert "delegate_job_safe failed (exit 2)" in res.stderr
assert "100% PASS" not in out
# ---------------------------------------------------------------------------
# S8 - create_session's onboarding / --submit-job: the task reaches the agent
# through a brief in the job directory, never inside the injected text
# (herdr `agent prompt` takes that text as one argv string). Real
# create_session.sh, registry and send_keys_safe; herdr and the agent CLIs are
# the conftest executables. From the review of job cc849cbf (codex).
# ---------------------------------------------------------------------------
@pytest.mark.parametrize("size", [100, 130_500]) # the second is under the cap on its own
def test_s8_create_session_task_reaches_the_pane_through_a_brief(mam_sandbox, mock_herdr, mock_agents,
monkeypatch, size):
import shutil
monkeypatch.setenv("MAM_ONBOARD_ACK_S", "1")
monkeypatch.setenv("SKS_DELIVERY_GRACE_S", "0")
script = mam_sandbox / ".agents/skills/multi-agent-mux-create/scripts/create_session.sh"
prompt = "q" * size
cmd = ["bash", str(script), "--workspace", str(mam_sandbox), "--agent", "claude",
"--role", "Creator", "--session", "review36-creator-claude", "--submit-job", prompt]
trace = mam_sandbox / "exec.trace"
strace = shutil.which("strace")
if strace: # the kernel's own verdict on every exec, when available
cmd = [strace, "-f", "-s", "100", "-e", "trace=execve", "-o", str(trace)] + cmd
result = subprocess.run(cmd, cwd=mam_sandbox, capture_output=True, text=True, timeout=150)
out = result.stdout + result.stderr
records = [json.loads(p.read_text()) for p in (mam_sandbox / ".mam/jobs").glob("*.json")]
assert [r for r in records if r.get("prompt") == prompt], out
jid = next(r["job_id"] for r in records if r.get("prompt") == prompt)
brief = mam_sandbox / ".mam/jobs" / jid / "brief.md"
assert brief.read_text() == prompt
calls = [str(c) for c in json.loads(mock_herdr.read_text())["calls"]]
injected = [c for c in calls if "agent" in c and "prompt" in c and jid in c]
assert injected, f"rc={result.returncode}; no onboarding text reached herdr\n{out[-3000:]}"
text = injected[0]
assert str(brief) in text and prompt not in text
# the #23 ack contract is unchanged: the publish command names this dispatch
assert "--expect-dispatch-token" in text and "--event started" in text
if strace:
assert not [line for line in trace.read_text().splitlines() if "E2BIG" in line]
# ---------------------------------------------------------------------------
# S9 - the shell loop's delegate_job_safe: a prompt file that cannot be written
# is removed, and the cause reaches stderr (callers capture stdout). The real
# function is taken from run_loop.sh; the write fails for real (RLIMIT_FSIZE).
# From the review of job cc849cbf (codex).
# ---------------------------------------------------------------------------
def test_s9_shell_loop_removes_a_partial_prompt_file_and_says_why(tmp_path):
source = (SKILLS / "multi-agent-mux-loop/scripts/run_loop.sh").read_text()
function = source[source.index("delegate_job_safe() {"):source.index("\nlog_info() {")]
(tmp_path / "input.md").write_text("x" * 2000)
harness = tmp_path / "run.sh"
harness.write_text('set -euo pipefail\nREPO_ROOT="$PWD"\nMAM_REAL_ROOT="$PWD"\n'
'log_error() { printf "%s\\n" "$1"; }\n' + function +
'\ntrap "" XFSZ\nulimit -f 1\n'
'output=$(delegate_job_safe submit --prompt "$(cat input.md)")\n')
result = subprocess.run(["bash", str(harness)], cwd=tmp_path, capture_output=True, text=True, timeout=60)
assert result.returncode != 0
assert "File too large" in result.stderr
leftovers = list((tmp_path / ".mam").glob("prompt-shloop-*"))
assert not leftovers, [(p.name, p.stat().st_size) for p in leftovers]
assert "delegate_job_safe: cannot write the prompt file" in result.stderr