A read-write open checkpointed the WAL and deleted -wal/-shm on close; a
plain mode=ro open created missing ones and left them. _ro_connect uses the
sidecars only when both exist (a live writer keeps them) and reads the file
as immutable otherwise. verify_artifact, _has_session, discover,
_descendants and residual_artifacts (db_rows_naming takes a connect) use it;
the purge's own writes are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An adapter can now name its placeholder as a pattern the box's first line
matches in full (input_placeholder_pattern); input_placeholder stays the
literal lib.sh greps for. opencode: `Ask anything… "<example>"`, the closing
quote optional because a box under ~65 columns cuts the example. Fixtures:
the 140-column herdr capture and a 60-column one with the cut example.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Review 614b6263 (codex, P2): `opencode session delete` removes the child
sessions with their parent, but their 1.x rows stayed and the parent's
residual was empty. The child sessions (session_v2 and a 1.x session
table, any depth) are taken before the delete; the 1.x tables (message,
part, todo, session_share, session) are cleaned for all of them, and the
residual also reports a child still on record (a failed delete).
- The in-use check counted any process holding the shared opencode.db; the
per-user 2.x background service (`serve --service`) holds it for every
session, so every opencode purge was refused while it ran (it does on
this Mac). It no longer counts; any other holder and a command line
naming the session still do.
- The data dir follows the caller's XDG_DATA_HOME when ctx is the caller's
own home (else <home>/.local/share), for debug paths, the fallback and the
residual scan (review 614b6263 / f4cedbae N4).
- resident_children = ('opencode',): the --standalone server stays the TUI's
idle child; what runs under it still counts (review 1abe0a90).
- Tests: child sessions on a migrated database, a failed delete, the service
holder, XDG, resident children, drift C pinning the parent over a newer
child session (review f4cedbae N2), and the real-binary test no longer
depends on PATH (N1).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
Measured on opencode 2.0.32 (macOS):
- the TUI rejects --agent ("Unrecognized flag"), so create and resume could
not start opencode at all; the default agent is build. MAM now spawns
`opencode --auto --standalone` (resume adds --session <id>): the server
runs as the TUI's child and ends with it, and the per-user background
service is neither used nor started;
- sessions live in session_v2 (a fresh 2.x database has no `session` table;
a migrated one keeps the 1.x tables but no longer writes them). discover,
verify_artifact, reconcile drift C and status read session_v2, and
discover / drift C skip child (subagent) sessions;
- `db path` is gone (it prints the help and exits 0): the db comes from
the `db` line of `opencode debug paths`, else the default path;
- `opencode session delete` removes a session with its child sessions from
the 2.x tables (and leaves the 1.x ones): purge runs it with --standalone
for a session in session_v2, still deletes the 1.x message/part/session
rows, and residual also reports a session_v2 row left by a failed delete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
Their purge is unchanged; what it leaves is now reported: codex names and
thread rows (state_*, thread_history_*; logs_* is not scanned), grok
memory-v2 observations, opencode event/todo rows. db_rows_naming opens the
DB read-only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib_py/stall_watch.py runs beside the wrapper's subscriber for a local herdr
job (started after delivery, stopped when the subscriber ends; MAM_STALL_WATCH=0
turns it off). It follows `herdr agent wait` transitions and publishes only
`progress` events through one publisher; it has no path that closes a job.
- blocked: `stalled:blocked <detection line>` once per episode, never answered.
- idle for MAM_STALL_IDLE_S (600) with no background descendants of the agent
pid (pane process-info + /proc; adapter resident_children and the heartbeat
timer excluded) and an empty input box: `stalled:idle` and one nudge.
- input box judged from adapter facts measured on herdr 0.9.1 (codex '›',
grok frame '│', opencode '┃' block + stop pattern); the whole-pane fallback
is gone. No facts: withheld + `stall_watch:input_check_unavailable` once;
never empty for 3 x S: `stall_watch:input_never_empty` once.
- herdr failures are not "no event": warning + `stall_watch:herdr_unavailable:
<code>` (or agent_not_found), backoff, rc 2 after MAM_STALL_HERDR_FAIL_S
(120); the wrapper prints the watcher's last lines.
- remote and human jobs are skipped with one log line.
- agent_status_reliable is an adapter field; false turns idle judgement off.
- the loop runner relays stalled:/stall_watch: notices once each.
- scoped_env drops a pane-inherited workspace scope for name lookups (#34 rule).
The module sits at the top of lib_py: delegation and loop may not import the
agent adapters (their sibling-import rules). Idle pane captures of the five
CLIs are fixtures; the mock herdr answers process-info in the real shape.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>