Commit Graph
14 Commits
Author SHA1 Message Date
GodopuandClaude Opus 5.5 a907cc5294 chore(stop,resume): drop what Issue #63 left unused (Issue #63)
- workspace_uuid.py: the unused sys import.
- stop_session.sh: the orphan CAPTURE_ID and the blank padding that kept
  later line numbers; the inventory pins follow the move instead.
- lib.sh: capture_conversation_id, which nothing calls any more.
- resume SKILL.md: the flow names the session-id decision (session_ids.py),
  not resolve_session_id.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:53:10 +00:00
GodopuandClaude Opus 5.5 84af709bb3 test(issue42): follow the SKILL.md and reconcile.sh line moves of the Issue #40 change
The skill-block inventory recorded line numbers that the auto-pin change moved:
one create block, two monitor blocks, and the reconcile.sh evidence for the
drift A example (601 -> 593) and the status --json example (1084, past the new
end of the file -> 816).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-21 02:11:14 +09:00
GodopuandClaude Opus 5.5 57830cf00a docs(stop): the workflow and the state diagram say a purge removes the row (Issue #31)
SKILL.md lines 52 and 83 still said a purge leaves a `terminated` row. The
two blocks' inventory shas move with them (#42), and so does the
passthrough line of stop's heredoc SystemExit(1) (310 -> 327, after the
process gate). Line counts are unchanged, so no other block moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:00:40 +00:00
GodopuandClaude Opus 5.5 21f0c12b9e fix(issue-50): the monitor labels a row with the server that answered
A `default` scan runs without -L, so the shim answers it from the inherited
HERDR_SESSION_NAME; a create's reconcile --once labelled that server's panes
`default`, and since create adopts only a row of its own server (1e25cf2f
F2), parallel creates in one folder were refused (test_tier4_e2e scenario 4).
The skill-blocks data follows create_session.sh's SystemExit line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-12 10:37:50 +09:00
GodopuandClaude Fable 5.1 7844ae2c5f fix(create): one pane claim at a time per herdr server; a create keeps the pane the monitor registered for it
Three `create --onboard` at once into one folder (the control root, so no
control-plane prefix reaches the pane and the shim reuses an idle pane):
the shim's new-session chooses a pane - an idle one in a workspace on the
same cwd, a split, a fresh workspace's root pane - and then claims it with
`agent start`; two shims could choose the pane one of them had just made,
and the later start failed with agent_pane_busy (one create in three).

mam_herdr now runs every new-session call holding one lock per server: a
flock on fd 9, opened for the block and taken by lib_py.pane_lock, which
also bounds the wait (MAM_PANE_CLAIM_WAIT_S, default 120). It is released
with the block or with the process, however it ends. The shim heredoc is
unchanged (S11). Other servers' creates are not held.

Serialising the claims exposed a second race: a create's end-of-run
`reconcile.sh --once` adopted the pane of another create that had not yet
written its row, and that create refused its own name as already running
(exit 4). Such a row - registered by the monitor, no job, for a pane
created after this create began - is now replaced, not refused.

Tests: real herdr - shim-level and create-level three-way races into one
folder (the real herdr's pane-creating replies held back so the window is
hit on every run; both fail on the base with the orchestrator's error),
the different-folder test kept; pane_lock unit tests (per-server file,
timeout, kill -9 holder, handover, knob); the adoption rule and its three
refusals; shim contract h26 (held lock: no pane calls). The herdr box gets
a ~/.zshrc: without it every first `agent start` typed into zsh's first-run
menu and timed out at 30 s.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-11 06:05:52 +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 Opus 5.5 c5cebe6c32 fix(issue-17): review R1 - the finalizer ends with its wrapper
finalize-end ran the disk grace and the broker re-observation as a child
of the wrapper; TERM to the wrapper left it running, and at the deadline it
still closed the job and published the error (codex R1, reproduced with the
real registry). The bash loops it replaced ended with the wrapper.

The wrapper now passes its own pid (--watch-pid "$$", as for the stall
watcher). finalize-end checks it every 0.2 s through both waits and before
the close and the event, and leaves without either once it is gone.
A comparison test sends TERM to the old and the new wrapper inside each
grace: both exit at once, leave no process behind and make no call.

Also: no blank line at the end of the old-decisions fixture, and the #42
inventory follows main() one line down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:02:26 +00:00
GodopuandClaude Opus 5.5 6947d3c785 test(issue-17): item 4 - the #42 inventory follows runner.py's shorter header
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 05:36:48 +00:00
GodopuandClaude Opus 5.5 3b3ce307df test(issue-17): item 4 - the #42 inventory points at main() where it now is
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 05:36:23 +00:00
GodopuandClaude Opus 5.5 63d9c205ff refactor(issue-17): item 4 - the delegate-job wrapper's decisions move to Python
The wrapper keeps spawn / wait / kill, key injection and the herdr
diagnostic probe; what it decided in bash is now lib_py/delegation/wrapper.py,
reached through one `_decide` helper:

- finalize_unfinished: the clock choice, the disk grace and broker
  re-observation, the close request / label, the close and the event
  (finalize-begin / finalize-end; bash runs only the busy probe between them)
- start_stall_watch: whether to watch (MAM_STALL_WATCH, remote, human)
- _map_sub_rc, _rc_for (+ MAM_DELEGATE_FAIL_CLOSED), the subscriber
  early-exit check and cmd_wait's rc normalisation
- mam_int / mam_int_knob run lib_py/ints.py, which is also the runner's
  _positive_int: one implementation of the Issue #26 rule

No behaviour change: tests/test_issue17_item4_decisions.py runs the old
bash functions (copied verbatim from 7209750) and the new wrapper on the
same inputs and compares output, FINAL_JOB_STATUS and the registry /
publish calls. Three static tests that pinned the old bash literals now
pin the Python entry points instead.

Refs #17

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 04:59:58 +00:00
GodopuandClaude Opus 5.5 feceddf49f docs(issue-45): isolation and resume notes; block inventory line shifts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:49 +00:00
GodopuandClaude Opus 5.5 17eba0904e docs(issue-42): review - attach names the herdr server, --dry-run is not "write nothing", a deleted block stays deleted
Merge-workspace review of PR #46 (codex R1-R3 and C1, claude O1 and O4).

- R1: resume never attaches, and the server it exports does not reach the
  calling shell; the native herdr binary does not route on environment
  variables. The attach advice and the Verification block now name the
  server: `herdr --session <server> agent attach <name>`, with <server> the
  row's herdr_session.
- R2: --dry-run in resume and create skips the spawn and the registry
  update, but the checks before it still run and on macOS remove the
  quarantine attribute from the agent binary. The option rows say so.
- R3: test_no_deleted_body_came_back compares every current block with the
  deleted bodies by exact sha and by a whitespace-insensitive fingerprint
  (stored as base_fingerprint), independently of the inventory, so a
  deleted block cannot return by being listed again under class c.
  Replaying the review's probe (the deleted resume Workflow re-added and
  inventoried as c) fails the new test and passes the old one.
- C1 / O1: the base create call block at 263-266 (class c) folded into the
  Workflow call is recorded under "superseded"; the 37 base blocks are all
  accounted for.
- O4: create exit 42 also covers MAM_KILL_ON_READY_TIMEOUT=1; stop's no-op
  exit 0 does not apply with --purge-conversation.
- The inventory's positions and shas are regenerated for the edited blocks;
  every classification is unchanged.

No product code changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-04 08:06:32 +09:00
GodopuandClaude Opus 5.5 e6a46cd7c4 fix(issue-42): review R1 - stop's exit 1 also comes after the stop
The registry update after the kill chain raises SystemExit(1) when the row
disappeared during the run (stop_session.sh:310), so "exit 1 changed nothing"
was false on that path. The stop table now says so, the code is declared as a
passthrough, and the test requires every integer SystemExit in an entry
script's heredocs to be declared - the check that would have caught it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:56:36 +00:00
GodopuandClaude Opus 5.5 7670b41afd docs(issue-42): stages 1-2 - SKILL.md code-block inventory as test data; remove blocks the scripts already do
Stage 1: tests/data/skill_code_blocks.json lists all 37 fenced blocks of the
eight SKILL.md files at base 45d1621 (indented fences count), classed (a)
duplicate of a script, (b) procedure no script offers, (c) example/call/
diagram, with script file:line evidence and recorded mismatches.
tests/test_issue42_skill_blocks.py fails when a block changes without the
inventory, an (a) block comes back, a removed block's entry call is missing,
an exit-code table drifts from the script, or evidence points nowhere.

Stage 2: the five (a) blocks are gone - resume Workflow, stop pre-flight,
create pre-flight / Workflow / manual YAML append - replaced by the
entry-point call with option and exit-code tables. Each exit table has a
catch-all row: under set -e a failing sub-step's code passes through.
create's exit 4 is real (the YAML write raises SystemExit(4) for a duplicate
running row) and is listed as such. Doc-to-script mismatches are fixed in the
doc (resume Case 3 / no attach, stop --purge-conversation --yes, status
--json keys, create cmd_full and the nonexistent yaml-edit script). No
behaviour change, no version bump.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:42:08 +00:00