Commit Graph
3 Commits
Author SHA1 Message Date
GodopuandClaude Fable 5.1 e9efabf74b feat(issue-50): the delegate-job wrapper waits by the registry before it injects (C)
Reproduction first (herdr 0.9.3, a real claude, one-off server, job
51ccd800): after a job that left a background subagent running
(`← 1 agent` on screen for 5 min), herdr reported `working` only while
the job ran and `idle` ~10 s after `completed`; a second submit with a
20 s idle wait was injected, not cancelled. The 2026-10-04 observation
(0.9.1, 10+ min of `working`) does not reproduce on 0.9.3, so the herdr
idle wait stays and the registry wait runs before it (plan §4.3 (나)).

- lib_py/delegation/wrapper.py: `open-jobs` (diagnostic) and
  `wait-open-jobs`. An open job of the session is live when the #18
  contract says so: `running` with an event in events.log within
  idle_timeout_sec; `pending` with a dispatch signal (dispatch_wait_at,
  else created_at) within ack_timeout_sec. A dead record is reported
  (`stale open job <id> ignored (...)`) and never waited for. The waiter
  signals every 10 s by merging dispatch_wait_at into its own pending
  record through the registry's transition boundary (status untouched, no
  event), so later waiters see it alive; a waiter whose wrapper is gone
  stops and its signal goes stale (Creator's challenge, job bf8863e1).
  Release is FIFO by (created_at, job_id): `clear` when no live running
  job remains and this job is the earliest live pending one; `busy <ids>`
  at the bound min(MAM_DISPATCH_WAIT_S, remaining wall clock).
- the wrapper: _registry_wait after the preflight in both dispatch paths;
  `busy` closes the job as cancelled/session_busy (phase registry_wait),
  exit 5 - the existing contract.
- tests/test_issue50_dispatch.py: the open-job table (status x age x
  signal x spelling), FIFO and the tie, the signal as a registry merge,
  the bound, a dead wrapper, finalize-end's new phase, both call sites.
- tests/test_issue50_dispatch_herdr.py: a real herdr 0.9.3 server per
  test (short mkdtemp HOME, fake claude the server reports idle, the real
  publish path over the suite's broker): C1 wait-then-run, C2 the bound,
  C3 a dead running record, C4 the loop runner's first job behind an
  onboarding, C5 a session without a row, C7 two waiters in FIFO order
  with no cancellation, C8 a killed waiter skipped once stale; and three
  concurrent `create --onboard` / `worktree_prepare.sh --onboard` in one
  server (one server process survives the shims' concurrent bootstrap,
  so no bootstrap lock is needed).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 15:39:21 +00:00
GodopuandClaude Fable 5.1 c29c5b2142 feat(issue-50): create --onboard waits for the onboarding job to end (A)
The handshake only said the agent saw the prompt (#23). create_session.sh
now waits, after `started`, for the onboarding job to reach a terminal
status and makes that its own result, so the orchestrator learns it from
create's exit (MULTI_AGENT_RULES §6) instead of guessing from herdr's
agent_status:

- lib_py/delegation/wrapper.py: `wait-terminal` (completed|error|cancelled,
  `timeout` after --timeout, `missing` when the record is gone; stops with
  its caller via --watch-pid) and `onboard-exit` (completed 0, error or
  cancelled 44, timeout or missing 45). bash branches on the printed answer.
- lib.sh: delegate_wait_terminal / delegate_onboard_exit, thin calls.
- create_session.sh: `onboarding completed: job <id> (<n>s)` on stdout, or
  `last_visible_status: onboarding-<status>` on the row, the reason on stderr
  and `exit 44` / `exit 45` after `trap - EXIT` - the session is kept, as for
  a missing handshake. The "no started" path (error, exit 0 before) now ends
  with 44. MAM_ONBOARD_WAIT_S (default 600, floor 1) bounds the wait.
- worktree_prepare.sh: 44/45 pass through with "session and worktree kept".
- create SKILL.md exit table (44, 45) and the knob; the #42 inventory follows.
- tests/conftest.py: --onboard is the default, so ~60 sandbox create tests
  reach the new wait. The mock herdr now acts as the agent for create's
  onboarding prompt - it runs the publish commands the prompt names through
  the real publish_event.py - and MAM_ONBOARD_WAIT_S=3 caps a test that turns
  that off (MAM_MOCK_ONBOARD_HANDSHAKE=0 -> 44, `started` -> 45). The
  delegate-job wrapper's prompt has another shape and is never answered.
- tests/test_issue50_onboard.py: the decision tables, create in the sandbox
  (0 / 44 / 45, session kept, row note, trap window), the knob's integer
  rule, worktree_prepare's pass-through.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 15:39:21 +00:00
GodopuandClaude Fable 5.1 40293841e7 test(issue-55): tests no longer write into the user's real agent homes
An agent pane inherits HOME_DIR, CLAUDE_PROJECT_DIR and LOCAL_BIN from
lib.sh's exports (and the adapters read CODEX_HOME). DiscoveryContext
prefers CLAUDE_PROJECT_DIR over the home_dir a test passes and every
adapter path reads HOME_DIR before HOME, so a suite run by an agent
wrote fake conversation folders into the user's real ~/.claude/projects
(test_adapter_discover, 40 folders on 2026-10-10).

- conftest._isolate_agent_homes (autouse): drops the four pane variables
  for every test, so HOME - which the suite's tests set for an isolated
  home - governs, as in a plain shell. Dropped rather than pointed into
  tmp_path: a fixture-set HOME_DIR would shadow the 11 adapter-contract
  tests that set HOME alone, the same way the pane's value did.
- conftest.agent_home_leak_guard (session autouse) + tests/_agent_home_guard.py:
  snapshots the entry names of the real claude/agy/codex/grok/opencode/
  hermes conversation directories (as the ambient environment names them,
  recorded in pytest_configure) and fails on new ones; read-only. A claude
  folder whose name decodes (against the file system) to a real directory
  outside the temp roots is an operating agent's and is not counted.
- tests/test_issue55_agent_homes.py: the dropped-variable list is pinned
  against the env reads of lib_py/agents, lib_py/paths.py and lib.sh;
  guard unit tests; the issue's reproduction as a subprocess regression
  (on base 42e5173 it leaves <dir>/-…-test-adapter-discover0-ws/u-c1.jsonl).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 14:29:36 +00:00