Context
Nothing reaches a human who is not at the machine running a loop lane. Local toast, terminal bell, and OSC 9 do not survive a closed laptop or dead process; GitHub telemetry is explicitly disqualified as an escalation channel; the severity fan-out in plugins/autonomy/reference/runner/escalation.md is unbuilt design. Source analysis (item 1, Tier 1): https://github.com/melodic-software/knowledge-corpus/blob/main/sources/webinars/getting-started-with-loops/analysis/action-items.md.
Premise verification (2026-07-26, against current official Claude Code docs): the claim in plugins/autonomy/hooks/lane-notify.sh that "there is no remote/Slack/push transport here (none exists as a marketplace primitive yet)" is STALE — both clauses:
PushNotification built-in tool: desktop notification + phone push when Remote Control connected; permission column "No" so an autonomous lane can fire it unprompted. Model-discretionary ("Claude decides when to push", no per-event configuration) — good human-attention signal, unreliable as a machine-triggered webhook. Phone reach requires claude.ai OAuth (not API key), no Bedrock/Agent-Platform/Foundry, mobile app + toggles. (https://code.claude.com/docs/en/tools-reference, https://code.claude.com/docs/en/remote-control)
- Hooks support
type: "http" handlers — "shell commands, HTTP endpoints, or LLM prompts"; POSTs the hook's JSON input with Content-Type: application/json, headers with env-var interpolation. Deterministic — fires on matched lifecycle events with no model judgment. Best fit: PostToolUse matched on Write/Edit → http handler on the escalation surface. (https://code.claude.com/docs/en/hooks)
- Official marketplace:
slack MCP plugin (outbound send from a local session), Telegram/Discord/iMessage channel plugins (inbound-first; reply needs an inbound chat_id; unprompted outbound undocumented). (https://code.claude.com/docs/en/discover-plugins, https://code.claude.com/docs/en/channels)
- Cloud Routines: no documented completion/failure notification; a routine notifies only if its own prompt posts somewhere. Poor fit as transport.
Defensible residue: no primitive's specific job is "fire a webhook when a lane writes an escalation" — but the composition is a few lines of settings JSON using documented first-party mechanisms, not a workaround.
Proposed work
- Scope to the escalation event, not the cycle: consuming-repo-configured webhook fired on escalation write (deterministic hook path), optionally paired with
PushNotification as the human-attention layer
- Design the seam so the destination (generic webhook / Slack via the official plugin / push) is consuming-repo config, not hardcoded
- Correct the stale claim in
plugins/autonomy/hooks/lane-notify.sh as part of the change
- Caution from verification: a
FileChanged hook event exists but firing on Claude-written files is UNVERIFIED — prefer the PostToolUse path
Acceptance criteria
References
Context
Nothing reaches a human who is not at the machine running a loop lane. Local toast, terminal bell, and OSC 9 do not survive a closed laptop or dead process; GitHub telemetry is explicitly disqualified as an escalation channel; the severity fan-out in
plugins/autonomy/reference/runner/escalation.mdis unbuilt design. Source analysis (item 1, Tier 1): https://github.com/melodic-software/knowledge-corpus/blob/main/sources/webinars/getting-started-with-loops/analysis/action-items.md.Premise verification (2026-07-26, against current official Claude Code docs): the claim in
plugins/autonomy/hooks/lane-notify.shthat "there is no remote/Slack/push transport here (none exists as a marketplace primitive yet)" is STALE — both clauses:PushNotificationbuilt-in tool: desktop notification + phone push when Remote Control connected; permission column "No" so an autonomous lane can fire it unprompted. Model-discretionary ("Claude decides when to push", no per-event configuration) — good human-attention signal, unreliable as a machine-triggered webhook. Phone reach requires claude.ai OAuth (not API key), no Bedrock/Agent-Platform/Foundry, mobile app + toggles. (https://code.claude.com/docs/en/tools-reference, https://code.claude.com/docs/en/remote-control)type: "http"handlers — "shell commands, HTTP endpoints, or LLM prompts"; POSTs the hook's JSON input withContent-Type: application/json, headers with env-var interpolation. Deterministic — fires on matched lifecycle events with no model judgment. Best fit:PostToolUsematched onWrite/Edit→ http handler on the escalation surface. (https://code.claude.com/docs/en/hooks)slackMCP plugin (outbound send from a local session), Telegram/Discord/iMessage channel plugins (inbound-first;replyneeds an inboundchat_id; unprompted outbound undocumented). (https://code.claude.com/docs/en/discover-plugins, https://code.claude.com/docs/en/channels)Defensible residue: no primitive's specific job is "fire a webhook when a lane writes an escalation" — but the composition is a few lines of settings JSON using documented first-party mechanisms, not a workaround.
Proposed work
PushNotificationas the human-attention layerplugins/autonomy/hooks/lane-notify.shas part of the changeFileChangedhook event exists but firing on Claude-written files is UNVERIFIED — prefer thePostToolUsepathAcceptance criteria
lane-notify.sh's stale no-transport claim is correctedReferences
plugins/autonomy/hooks/lane-notify.sh,plugins/autonomy/reference/runner/escalation.md