docs: gap-review round 2 — fix hook-wiring self-contradiction

- HIGH: settings.json example wired PermissionRequest to a bare curl that drops
  the env-only $TMUX_PANE; route all hooks through trailboss-emit.sh (which
  injects $TMUX_PANE) and note SessionStart is not special
- MEDIUM: remove the stray trailboss-register.sh (contradicted "registry
  self-heals on every emit"); single emitter script
- LOW: add struck-through SubagentStop row to plan detection table; clarify
  disler's store is append-only (not "read-only")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-05-25 15:21:23 -04:00
parent 675c1e531d
commit 4e1b8a9cf2
3 changed files with 14 additions and 9 deletions

View file

@ -125,6 +125,7 @@ stuck conditions: a session waiting at a permission prompt is mid-turn and does
| `SessionStart` | Register the session; re-assert `session_id → pane`. | Confirmed firing (probe) |
| `SessionEnd` | Retire the session. | Exists; firing not yet probed |
| ~~`Notification`~~ | Dropped — `Stop` + `PermissionRequest` cover every stuck case; the dead-letter queue just fills and drains. | Not used |
| ~~`SubagentStop`~~ | Ignored — a subagent finishing is not a human-input point. | Not used |
Both `Stop` and `PermissionRequest` enqueue a plain stuck item with no priority difference.

View file

@ -9,24 +9,28 @@ Code's hook surface evolves and some semantics are undocumented.
## 1. DETECT — which hook says a session is blocked
Hooks live in `~/.claude/settings.json` (user-global) or `.claude/settings.json` (per-project).
Each `command` hook receives the **event JSON on stdin**, so a one-liner that pipes stdin to
the collector is enough:
Each `command` hook receives the **event JSON on stdin**. **Every** hook routes through the same
`trailboss-emit.sh` — a thin wrapper that forwards stdin *and* injects `$TMUX_PANE` from the
environment (the pane is not in the payload; see §2). A bare `curl` of stdin alone is **not**
enough, because it would drop the env-only pane mapping. `SessionStart` is **not** special — it
uses the same emitter; the registry self-heals on every event:
```json
{
"hooks": {
"PermissionRequest": [
{ "hooks": [ { "type": "command",
"command": "curl -s -X POST http://localhost:4000/event --data-binary @-" } ] }
],
"PermissionRequest": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-emit.sh" } ] } ],
"Stop": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-emit.sh" } ] } ],
"UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-emit.sh" } ] } ],
"SessionStart": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-register.sh" } ] } ],
"SessionStart": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-emit.sh" } ] } ],
"SessionEnd": [ { "hooks": [ { "type": "command", "command": "~/.claude/trailboss-emit.sh" } ] } ]
}
}
```
`trailboss-emit.sh` is essentially:
`curl -s -X POST http://localhost:4000/event --data-binary @- -H "X-Tmux-Pane: $TMUX_PANE"`
(or it merges `$TMUX_PANE` into the JSON body before POSTing).
Events relevant to "needs a human":
| Event | Meaning for the queue | Confidence |

View file

@ -15,8 +15,8 @@ layer** Trail Boss needs: hooks → collector → live UI, keyed by `session_id`
**How Trail Boss differs:** it is *observability*, not *action*. It shows *that* a session is
waiting; Trail Boss adds the missing half — surfacing the blocked session and **navigating the
operator to the live pane** to act on it (it never injects input; see "Navigator, not relay" in
the plan). Its collector is a strong starting point to fork; Trail Boss extends the read-only
event store with a self-healing session→pane registry and a tmux navigation layer. It reuses the
the plan). Its collector is a strong starting point to fork; Trail Boss extends disler's
append-only event store with a self-healing session→pane registry and a tmux navigation layer. It reuses the
SQLite event store, not the WebSocket/browser-UI layer (presentation is tmux, not a web app).
### [`langchain-ai/agent-inbox`](https://github.com/langchain-ai/agent-inbox)