remote.py closes a job whose end it could not see with
`error --detail "deadline_timeout (remote runner)"`; the sub-job table
matched the reason exactly and filed it as a plain failure, losing the
unconfirmed count and the late-write warning (merge review, codex R2).
The kind is the first word of the reason now. Test T14 replays the
remote runner's close through the real registry and producer; it fails
without the fix.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
- registry.get_feedback only returned the detail of the last completed or
error event, so a sub-job the wrapper cancelled before injection
(target_not_found, session_busy) reached the review table as a bare
`cancelled` and its reason was lost (merge review, grok N1). get_feedback
takes the event kinds to read (default unchanged); the table asks for
cancelled too and shows NOT-DISPATCHED with the reason. Test T13, both
reasons, fails without the fix.
- the [귀속되지 않은 열린 잡] line listed jobs registered without
--parent-job but gave the reviewer no rule for them - the one case the
table cannot show (claude K1). A rule sentence follows the line whenever
such a job exists; without one the prompt is unchanged. T6 pins it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
- mam_herdr: for name lookups (agent / has-session / kill-session) a
HERDR_WORKSPACE_ID that is the caller pane's own workspace (it matches
the HERDR_PANE_ID prefix) is dropped. Live agent names are unique per
server (herdr --skill), so this cannot address a same-named agent of
another workspace; an id the caller chose, or one set outside a pane,
still scopes (H-18/H-21/H-23). The generated shim is unchanged (S11).
- wrapper: a preflight that cannot see the target closes the job
cancelled with detail target_not_found instead of session_busy; the
loop's sub-job table counts it as NOT-DISPATCHED.
- tests: T10-T12 with the measured pane env (same-server socket, caller
w6, target w2); T8 follows the sub-job-armed guard.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
round_roots was replaced by the correction job, so an implementation
job's open or failed sub-job vanished from the next review and the loop
could pass (planner-reviewer-codex-01, P2). The run's creator jobs now
accumulate; each wait still covers only the new job's tree, so the wait
cap is not paid again per round. T9 covers open / error / completed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- wait_for_job_tree at the execution, correction and compliance waits;
bounded by MAM_CHILD_WAIT_S (3900) and MAM_JOB_TREE_MAX (50)
- [하위 위임 잡] table: OPEN / CLOSED-UNCONFIRMED (deadline_timeout,
agent_blocked, or error with no reason) / NOT-DISPATCHED / error /
completed, plus unattributed open jobs; omitted when there are none so
option-less prompts stay byte-identical
- --wait-open-jobs also waits for unattributed open jobs
- stale-review guard without --worktree/--base: head + tree (control
plane excluded) before review, re-checked after verdicts and before
promotion; off with a warning when the source cannot be fingerprinted
- tests/test_issue34_job_tree.py: real wrapper registrations, real
publish_event / deadline close, real loop process
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>