@humwick/runner 0.130.4 → 0.130.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/LICENSE +661 -167
  2. package/agent-bin/humwick +2 -2
  3. package/agent-bin/humwick-browser +4 -0
  4. package/hooks/fff-search-redirect/fff-search-redirect.cjs +1 -1
  5. package/hooks/web-tools-redirect/web-tools-redirect.cjs +2 -2
  6. package/package.json +8 -11
  7. package/plugins/browser/skills/playwright-cli/SKILL.md +8 -6
  8. package/plugins/claude/.claude-plugin/plugin.json +3 -3
  9. package/plugins/claude/claude-statusline-probe.cjs +26 -16
  10. package/plugins/claude/hooks/gate-run-guard.provisioned.mjs +47 -17
  11. package/plugins/claude/hooks/gate-run-guard.sh +3 -3
  12. package/plugins/claude/hooks/gate-run-guard.ts +5 -5
  13. package/plugins/claude/hooks/kill-guard.provisioned.mjs +1 -1
  14. package/plugins/claude/hooks/kill-guard.sh +4 -4
  15. package/plugins/claude/hooks/kill-guard.ts +2 -2
  16. package/plugins/claude/hooks/permission-request.sh +1 -1
  17. package/plugins/claude/hooks/post-compact.sh +1 -1
  18. package/plugins/claude/hooks/post-tool-use.sh +3 -3
  19. package/plugins/claude/hooks/pre-compact.sh +2 -2
  20. package/plugins/claude/hooks/read-only-bash-guard.sh +4 -4
  21. package/plugins/claude/hooks/relay-status.sh +32 -32
  22. package/plugins/claude/hooks/session-end.sh +2 -2
  23. package/plugins/claude/hooks/session-start.sh +3 -3
  24. package/plugins/claude/hooks/shell-trust.ts +1 -1
  25. package/plugins/claude/hooks/stop-failure.sh +2 -2
  26. package/plugins/claude/hooks/stop.sh +6 -6
  27. package/plugins/claude/hooks/subagent-skill-policy.cjs +8 -6
  28. package/plugins/claude/hooks/subagent-stop.sh +3 -3
  29. package/plugins/claude/hooks/user-prompt-submit.sh +1 -1
  30. package/plugins/claude/hooks/wait-loop-guard.ts +3 -3
  31. package/plugins/claude/monitors/monitors.json +2 -2
  32. package/plugins/claude/monitors/relay-monitor.provisioned.mjs +96 -62
  33. package/plugins/claude/monitors/relay-monitor.ts +5 -5
  34. package/plugins/claude/skills/label/SKILL.md +3 -3
  35. package/plugins/claude/skills/message/SKILL.md +5 -5
  36. package/plugins/claude/skills/react/SKILL.md +1 -1
  37. package/plugins/claude/skills/read-message/SKILL.md +4 -4
  38. package/plugins/claude/skills/reply/SKILL.md +5 -5
  39. package/plugins/claude/skills/send-claimable/SKILL.md +5 -5
  40. package/plugins/claude/skills/slice-first/SKILL.md +5 -3
  41. package/plugins/claude/skills/slice-first/references/plan-recipe.md +30 -29
  42. package/plugins/claude/skills/status/SKILL.md +3 -3
  43. package/plugins/claude/skills/tags/SKILL.md +5 -5
  44. package/plugins/claude/skills/task/SKILL.md +10 -10
  45. package/plugins/claude-output-style/.claude-plugin/plugin.json +1 -1
  46. package/plugins/claude-output-style/output-styles/{agent-relay.md → humwick.md} +1 -1
  47. package/plugins/codex/skills/guide/SKILL.md +3 -3
  48. package/plugins/codex/skills/label/SKILL.md +3 -3
  49. package/plugins/codex/skills/message/SKILL.md +5 -5
  50. package/plugins/codex/skills/react/SKILL.md +1 -1
  51. package/plugins/codex/skills/read-message/SKILL.md +4 -4
  52. package/plugins/codex/skills/reply/SKILL.md +5 -5
  53. package/plugins/codex/skills/send-claimable/SKILL.md +5 -5
  54. package/plugins/codex/skills/slice-first/SKILL.md +5 -3
  55. package/plugins/codex/skills/slice-first/references/plan-recipe.md +30 -29
  56. package/plugins/codex/skills/status/SKILL.md +3 -3
  57. package/plugins/codex/skills/tags/SKILL.md +5 -5
  58. package/plugins/codex/skills/task/SKILL.md +11 -10
  59. package/src/adapter.ts +95 -92
  60. package/src/adapters/claude-api.ts +8 -11
  61. package/src/adapters/claude-context-command.ts +1 -1
  62. package/src/adapters/claude-credentials.ts +7 -3
  63. package/src/adapters/claude-delivery-lanes.ts +2 -2
  64. package/src/adapters/claude-delivery.ts +16 -16
  65. package/src/adapters/claude-effort.ts +2 -2
  66. package/src/adapters/claude-exit.ts +2 -2
  67. package/src/adapters/claude-headless-mirror.ts +18 -2
  68. package/src/adapters/claude-headless-refusal.ts +3 -3
  69. package/src/adapters/claude-headless.ts +11 -10
  70. package/src/adapters/claude-launch-exit.ts +1 -1
  71. package/src/adapters/claude-monitor-delivery-plan.ts +36 -16
  72. package/src/adapters/claude-permission.ts +5 -5
  73. package/src/adapters/claude-prompt-gates.ts +9 -9
  74. package/src/adapters/claude-prompt-hook.ts +2 -2
  75. package/src/adapters/claude-session-capture.ts +6 -6
  76. package/src/adapters/claude-session-probe.ts +25 -25
  77. package/src/adapters/claude-shutdown.ts +11 -11
  78. package/src/adapters/claude-status-detectors.ts +31 -31
  79. package/src/adapters/claude-subagents.ts +7 -7
  80. package/src/adapters/claude-submit-confirmation.ts +6 -6
  81. package/src/adapters/claude-tmux.ts +43 -43
  82. package/src/adapters/claude-token-usage-capture.ts +5 -5
  83. package/src/adapters/claude-tool-policy.ts +7 -7
  84. package/src/adapters/claude-transcript.ts +24 -24
  85. package/src/adapters/claude.ts +100 -100
  86. package/src/adapters/codex-agent-message-capture.ts +26 -63
  87. package/src/adapters/codex-app-server.ts +1 -1
  88. package/src/adapters/codex-client.ts +9 -9
  89. package/src/adapters/codex-effective-config.ts +1 -1
  90. package/src/adapters/codex-launch-config.ts +5 -5
  91. package/src/adapters/codex-rollout-context.ts +2 -2
  92. package/src/adapters/codex-skill-discovery.ts +1 -1
  93. package/src/adapters/codex-token-usage-capture.ts +16 -16
  94. package/src/adapters/codex-tool-output.ts +4 -4
  95. package/src/adapters/codex-version.ts +3 -3
  96. package/src/adapters/codex.ts +64 -64
  97. package/src/adapters/opencode-api.ts +1 -1
  98. package/src/adapters/opencode-context.ts +20 -22
  99. package/src/adapters/opencode-model-registry.ts +7 -7
  100. package/src/adapters/opencode-provider.ts +8 -8
  101. package/src/adapters/opencode-provisioning.ts +30 -0
  102. package/src/adapters/opencode-server-retry.ts +1 -1
  103. package/src/adapters/opencode-soft-steer.ts +5 -5
  104. package/src/adapters/opencode-spawn.ts +18 -14
  105. package/src/adapters/opencode-token-usage-capture.ts +12 -12
  106. package/src/adapters/opencode-tool-events.ts +15 -15
  107. package/src/adapters/opencode.ts +232 -232
  108. package/src/adapters/project-shell.ts +11 -11
  109. package/src/adapters/service-access.ts +6 -6
  110. package/src/adapters/tmux-offload.ts +9 -9
  111. package/src/adapters/tool-summary.ts +5 -5
  112. package/src/agent-redact.ts +1 -1
  113. package/src/agent-runner/commands/dispatch.ts +10 -10
  114. package/src/agent-runner/commands/lifecycle.ts +2 -2
  115. package/src/agent-runner/commands/prompt.ts +19 -19
  116. package/src/agent-runner/credentials.ts +5 -5
  117. package/src/agent-runner/inbox.ts +1 -1
  118. package/src/agent-runner/lifecycle-milestones.ts +3 -3
  119. package/src/agent-runner/lifecycle-phase.ts +2 -2
  120. package/src/agent-runner/liveness-exchange.ts +4 -10
  121. package/src/agent-runner/registration.ts +8 -8
  122. package/src/agent-runner/runner-context.ts +9 -14
  123. package/src/agent-runner/session-mirror.ts +12 -12
  124. package/src/agent-runner/task-claims.ts +2 -2
  125. package/src/agent-runner/token-usage-coverage.ts +1 -1
  126. package/src/agent-runner/turn-report.ts +12 -12
  127. package/src/api-budget-accounting.ts +3 -3
  128. package/src/area-memory.ts +6 -6
  129. package/src/artifact-path-materialize.ts +1 -1
  130. package/src/async-guard.ts +5 -5
  131. package/src/attachment-cache.ts +17 -22
  132. package/src/background-script-reconcile.ts +6 -6
  133. package/src/bounded-log.ts +1 -1
  134. package/src/busy-reconciler.ts +22 -22
  135. package/src/claim-tracker.ts +3 -3
  136. package/src/claude-settings.ts +8 -8
  137. package/src/claude-system-prompt.ts +1 -1
  138. package/src/claude-workspace-trust.ts +1 -1
  139. package/src/config.ts +62 -61
  140. package/src/context-boundary.ts +5 -5
  141. package/src/context-command.ts +3 -3
  142. package/src/control-server.ts +32 -32
  143. package/src/delivery-result.ts +2 -2
  144. package/src/effort-command.ts +2 -2
  145. package/src/empty-turn.ts +22 -14
  146. package/src/free-port.ts +1 -1
  147. package/src/gate-run-config.ts +3 -3
  148. package/src/host-asset-plan.ts +24 -17
  149. package/src/host-claude-config-worker.ts +2 -2
  150. package/src/host-sources.ts +2 -2
  151. package/src/index.ts +16 -16
  152. package/src/launch-assembly.ts +94 -96
  153. package/src/liveness.ts +15 -15
  154. package/src/logger.ts +3 -3
  155. package/src/mcp-outbox.ts +3 -3
  156. package/src/mcp-preflight.ts +2 -2
  157. package/src/mcp-source-selection.ts +2 -2
  158. package/src/mcp-tool-deferral.ts +1 -1
  159. package/src/mcp-vault-env.ts +2 -2
  160. package/src/message-body-config/config.ts +4 -4
  161. package/src/mid-turn-delivery.ts +2 -2
  162. package/src/native-memory-lever.ts +8 -8
  163. package/src/outbox.ts +15 -15
  164. package/src/pending-permission-store.ts +1 -1
  165. package/src/profile-home.ts +19 -19
  166. package/src/profile-projection.ts +26 -24
  167. package/src/project-instructions.ts +5 -5
  168. package/src/provider-auth-warning.ts +17 -0
  169. package/src/provider-double.ts +1 -1
  170. package/src/provider-hold.ts +3 -3
  171. package/src/provider-home-marker.ts +1 -1
  172. package/src/provider-home-tombstone.ts +1 -1
  173. package/src/provider-input-queue.ts +2 -2
  174. package/src/provider-integration.ts +15 -13
  175. package/src/provider-setup.ts +15 -3
  176. package/src/providers.ts +1 -1
  177. package/src/provisioning.ts +37 -40
  178. package/src/question-decision.ts +2 -2
  179. package/src/quota.ts +0 -6
  180. package/src/rate-limit.ts +24 -13
  181. package/src/refused-prompt-store.ts +2 -2
  182. package/src/relay-injection-events.ts +2 -2
  183. package/src/relay-instructions.ts +5 -5
  184. package/src/relay-mcp-proxy.long-turn-e2e.ts +13 -13
  185. package/src/relay-mcp-proxy.ts +57 -58
  186. package/src/relay-mcp.ts +55 -69
  187. package/src/reply-obligation-cache.ts +9 -9
  188. package/src/response-capture-report.ts +9 -9
  189. package/src/response-routing.ts +1 -1
  190. package/src/runner-core.ts +209 -222
  191. package/src/runner-exit.ts +1 -1
  192. package/src/runner-helpers.ts +10 -10
  193. package/src/runner-insights.ts +4 -2
  194. package/src/runner-mcp-proxy.ts +3 -3
  195. package/src/runner-spawn-config.ts +3 -3
  196. package/src/runtime-token-file.ts +1 -1
  197. package/src/runtime-token-remint.ts +1 -1
  198. package/src/service-access.ts +2 -2
  199. package/src/session-destroy.ts +1 -1
  200. package/src/session-insights.ts +1 -1
  201. package/src/session-scratch.ts +24 -37
  202. package/src/spawn-input.ts +6 -6
  203. package/src/startup-config-fetch.ts +4 -4
  204. package/src/subreaper.ts +3 -5
  205. package/src/test-run-dedup.ts +13 -13
  206. package/src/transcript-context.ts +2 -2
  207. package/src/transport-errors.ts +1 -1
  208. package/src/turn-opener.ts +1 -1
  209. package/src/turn-reconcile-event.ts +2 -2
  210. package/src/vault-proxy-hop.ts +2 -2
  211. package/src/web-tools.ts +2 -2
  212. package/agent-bin/agent-relay-browser +0 -10
  213. package/plugins/claude/skills/disconnect/SKILL.md +0 -16
  214. package/plugins/claude/skills/pair/SKILL.md +0 -30
  215. package/plugins/codex/skills/disconnect/SKILL.md +0 -15
  216. package/plugins/codex/skills/pair/SKILL.md +0 -29
  217. package/src/adapters/provider-quota-harvest.ts +0 -76
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
3
  # POST a JSON body over stdin. A curl argv argument is capped by the kernel (~128 KiB), and a
4
- # prompt or assistant message can exceed it; curl then never starts and the report is lost (#2664).
4
+ # prompt or assistant message can exceed it; curl then never starts and the report is lost.
5
5
  relay_post_json() {
6
6
  local port="$1" path="$2" max_time="${3:-}"
7
7
  curl -fsS ${max_time:+--max-time "$max_time"} -X POST "http://127.0.0.1:${port}${path}" \
@@ -21,11 +21,11 @@ relay_post_status() {
21
21
  # responsible for producing valid JSON (see relay_background_task_metadata). Empty/unset
22
22
  # omits the field entirely so ordinary status posts are unaffected.
23
23
  local metadata_json="${9:-}"
24
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
24
+ local port="${HUMWICK_RUNNER_PORT:-}"
25
25
  [ -z "$port" ] && return 0
26
26
  [ -z "$status" ] && return 0
27
27
  local body="{\"status\":\"$(relay_json_escape "$status")\""
28
- [ -n "${AGENT_RELAY_PROVIDER_SESSION_ID:-}" ] && body="${body},\"providerSessionId\":\"$(relay_json_escape "$AGENT_RELAY_PROVIDER_SESSION_ID")\""
28
+ [ -n "${HUMWICK_PROVIDER_SESSION_ID:-}" ] && body="${body},\"providerSessionId\":\"$(relay_json_escape "${HUMWICK_PROVIDER_SESSION_ID-}")\""
29
29
  [ -n "$reason" ] && body="${body},\"reason\":\"$(relay_json_escape "$reason")\""
30
30
  [ -n "$clear_kind" ] && body="${body},\"clear\":[\"$(relay_json_escape "$clear_kind")\"]"
31
31
  [ -n "$timeline_status" ] && body="${body},\"timeline\":{\"status\":\"$(relay_json_escape "$timeline_status")\"}"
@@ -42,7 +42,7 @@ relay_post_status_clearing_subagents() {
42
42
  relay_post_status "$1" "${2:-}" "${3:-}" "${4:-}" "${5:-}" "${6:-}" subagent
43
43
  }
44
44
 
45
- # #502/#539: count user background shells still running at turn end.
45
+ # count user background shells still running at turn end.
46
46
  # Claude's Stop payload carries a `background_tasks` array (CC v2.1.157+) listing
47
47
  # shells launched with run_in_background that have not yet finished. It can also
48
48
  # include the long-lived Humwick monitor; that monitor is notification
@@ -56,9 +56,9 @@ relay_background_task_count() {
56
56
  n="$(printf '%s' "$input" | jq -r '
57
57
  (.background_tasks // [])
58
58
  | map(select(
59
- (.name // "") != "agent-relay-runner-monitor"
59
+ ((.name // "") | test("^(humwick|agent-relay)-runner-monitor$") | not)
60
60
  and ((.command // "") | contains("relay-monitor.ts") | not)
61
- and ((.command // "") | contains("agent-relay-runner-monitor") | not)
61
+ and ((.command // "") | test("(humwick|agent-relay)-runner-monitor") | not)
62
62
  ))
63
63
  | length
64
64
  ' 2>/dev/null)"
@@ -69,7 +69,7 @@ relay_background_task_count() {
69
69
  local compact
70
70
  compact="$(printf '%s' "$input" | tr -d '[:space:]')"
71
71
  if printf '%s' "$compact" | grep -q '"background_tasks":\[{'; then
72
- if printf '%s' "$compact" | grep -qE '("name":"agent-relay-runner-monitor"|relay-monitor\.ts)' \
72
+ if printf '%s' "$compact" | grep -qE '("name":"(humwick|agent-relay)-runner-monitor"|relay-monitor\.ts)' \
73
73
  && ! printf '%s' "$compact" | grep -q '},{'; then
74
74
  printf '0'
75
75
  return 0
@@ -80,7 +80,7 @@ relay_background_task_count() {
80
80
  fi
81
81
  }
82
82
 
83
- # #2034 (#2031 L3): cap on the per-task detail list — bounds task count and per-command
83
+ # cap on the per-task detail list — bounds task count and per-command
84
84
  # length so a pathological Stop payload (a runaway number of concurrent background shells,
85
85
  # or an absurdly long command string) can never bloat the persisted work record.
86
86
  # relay_background_task_count above (the busy/label signal) stays uncapped; only this
@@ -88,7 +88,7 @@ relay_background_task_count() {
88
88
  RELAY_BACKGROUND_TASK_LIST_MAX=20
89
89
  RELAY_BACKGROUND_TASK_COMMAND_MAX=200
90
90
 
91
- # #2034 (#2031 L3): shape Claude's Stop-payload background_tasks[] into the compact
91
+ # shape Claude's Stop-payload background_tasks[] into the compact
92
92
  # {id, command} detail list the runner keeps as the background-script work record's
93
93
  # `metadata.backgroundTasks` — the per-task identity a watchdog can name directly instead
94
94
  # of just a count. The runner (not this hook) stamps startedAt: each hook invocation is a
@@ -105,9 +105,9 @@ relay_background_task_list() {
105
105
  --argjson cmdmax "$RELAY_BACKGROUND_TASK_COMMAND_MAX" '
106
106
  (.background_tasks // [])
107
107
  | map(select(
108
- (.name // "") != "agent-relay-runner-monitor"
108
+ ((.name // "") | test("^(humwick|agent-relay)-runner-monitor$") | not)
109
109
  and ((.command // "") | contains("relay-monitor.ts") | not)
110
- and ((.command // "") | contains("agent-relay-runner-monitor") | not)
110
+ and ((.command // "") | test("(humwick|agent-relay)-runner-monitor") | not)
111
111
  ))
112
112
  | map({
113
113
  id: ((.id // "") | tostring),
@@ -120,7 +120,7 @@ relay_background_task_list() {
120
120
 
121
121
  # Wrap a capped task list into the `metadata` object relay_post_status expects, or print
122
122
  # nothing when there is nothing to report (no task list, empty list, or jq-less host) so an
123
- # ordinary background-script status post is byte-for-byte what it was before #2034.
123
+ # ordinary background-script status post is byte-for-byte what it was before.
124
124
  relay_background_task_metadata() {
125
125
  local list_json="${1:-}"
126
126
  case "$list_json" in
@@ -129,14 +129,14 @@ relay_background_task_metadata() {
129
129
  esac
130
130
  }
131
131
 
132
- # #502: end the provider turn (idle) clearing any stale subagent work — the
133
- # critical path (#199) — then report the live background-script snapshot so an
132
+ # end the provider turn (idle) clearing any stale subagent work — the
133
+ # critical path — then report the live background-script snapshot so an
134
134
  # agent whose turn ended while a `run_in_background` shell keeps running stays
135
135
  # busy instead of falsely reading idle. A single full-snapshot post per turn-end:
136
136
  # >0 → busy(background-script); 0 → idle(background-script) which clears any prior.
137
137
  relay_post_turn_end_status() {
138
138
  local bg_count="${1:-0}"
139
- # #2034: the capped {id, command} detail list (see relay_background_task_list) — only
139
+ # the capped {id, command} detail list (see relay_background_task_list) — only
140
140
  # relevant on the busy branch; a bg_count of 0 always resolves to idle regardless.
141
141
  local bg_tasks_json="${2:-[]}"
142
142
  local bg_metadata
@@ -149,7 +149,7 @@ relay_post_turn_end_status() {
149
149
  esac
150
150
  }
151
151
 
152
- # Report a provider usage/rate-limit hold to the runner (#286). The runner turns
152
+ # Report a provider usage/rate-limit hold to the runner. The runner turns
153
153
  # this into a `providerState: blocked` (reason rate_limit), posts a chat notice,
154
154
  # and auto-resumes the agent once the window resets. reset_time (unix seconds,
155
155
  # only "if available" per CC StopFailure docs) drives the resume; the runner falls
@@ -158,7 +158,7 @@ relay_post_rate_limit() {
158
158
  local error_type="${1:-}"
159
159
  local reset_time="${2:-}"
160
160
  local error_message="${3:-}"
161
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
161
+ local port="${HUMWICK_RUNNER_PORT:-}"
162
162
  [ -z "$port" ] && return 0
163
163
  local body="{\"errorType\":\"$(relay_json_escape "$error_type")\""
164
164
  case "$reset_time" in ''|*[!0-9]*) ;; *) body="${body},\"resetTime\":${reset_time}" ;; esac
@@ -179,7 +179,7 @@ relay_post_session_turn() {
179
179
  local transcript_path="${1:-}"
180
180
  local last_assistant_message="${2:-}"
181
181
  local prompt_id="${3:-}"
182
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
182
+ local port="${HUMWICK_RUNNER_PORT:-}"
183
183
  [ -z "$port" ] && return 0
184
184
  # transcript_path is the primary capture source, but the Stop payload can omit it
185
185
  # (known CC edge case). last_assistant_message is the fallback for exactly that —
@@ -191,7 +191,7 @@ relay_post_session_turn() {
191
191
  [ "$body" != "{" ] && body="${body},"
192
192
  body="${body}\"lastAssistantMessage\":${last_assistant_message}"
193
193
  fi
194
- # prompt_id (#1086): Claude's native turn identifier — the stable id the runner
194
+ # prompt_id: Claude's native turn identifier — the stable id the runner
195
195
  # uses instead of a minted random UUID, and the deterministic key it slices the
196
196
  # transcript by for full-mode enrichment.
197
197
  if [ -n "$prompt_id" ]; then
@@ -202,11 +202,11 @@ relay_post_session_turn() {
202
202
  printf '%s' "$body" | relay_post_json "$port" /session-turn >/dev/null 2>&1 || true
203
203
  }
204
204
 
205
- # Forward a hook's raw stdin JSON unchanged, stamped with when the hook ran (#2664). No jq: a
205
+ # Forward a hook's raw stdin JSON unchanged, stamped with when the hook ran. No jq: a
206
206
  # missing jq must not silence the prompt hook the runner confirms submits by.
207
207
  relay_forward_hook_payload() {
208
208
  local path="${1:-}" payload="${2:-}" fired_at="${3:-}"
209
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
209
+ local port="${HUMWICK_RUNNER_PORT:-}"
210
210
  [ -z "$port" ] && return 0
211
211
  case "$fired_at" in ''|*[!0-9]*) fired_at="" ;; esac
212
212
  printf '%s' "$payload" | relay_post_json "$port" "${path}${fired_at:+?firedAt=${fired_at}}" 3 >/dev/null 2>&1 || true
@@ -223,13 +223,13 @@ relay_post_user_prompt() {
223
223
  }
224
224
 
225
225
  relay_post_session_boundary() {
226
- # Pre-destroy seam (#183): tell the runner a context reset or termination is imminent
227
- # (compact/clear/logout/…) so it can run end-of-session work — the #184 context-gathering
226
+ # Pre-destroy seam: tell the runner a context reset or termination is imminent
227
+ # (compact/clear/logout/…) so it can run end-of-session work — the context-gathering
228
228
  # ratio capture — from the full transcript before the invasive op. Fire-and-forget; the
229
229
  # transcript path is optional (the runner falls back to the last path it saw).
230
230
  local transcript_path="${1:-}"
231
231
  local reason="${2:-}"
232
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
232
+ local port="${HUMWICK_RUNNER_PORT:-}"
233
233
  [ -z "$port" ] && return 0
234
234
  local body="{"
235
235
  [ -n "$transcript_path" ] && body="${body}\"transcriptPath\":\"$(relay_json_escape "$transcript_path")\""
@@ -241,14 +241,14 @@ relay_post_session_boundary() {
241
241
  printf '%s' "$body" | relay_post_json "$port" /session-boundary 3 >/dev/null 2>&1 || true
242
242
  }
243
243
 
244
- # --- Hook FATAL surfacing (#198) -------------------------------------------
244
+ # --- Hook FATAL surfacing -------------------------------------------
245
245
  # A hook that dies unexpectedly must never be silent. relay_install_hook_guard
246
246
  # arms an ERR trap that reports the failure FATAL to the runner control port,
247
247
  # which logs it to the dashboard-surfaced per-agent log. Best-effort and bounded
248
248
  # (--max-time 2) so the report itself can never blow the hook's timeout budget.
249
249
  relay_hook_fatal_report() {
250
250
  local hook="${1:-unknown}" detail="${2:-}"
251
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
251
+ local port="${HUMWICK_RUNNER_PORT:-}"
252
252
  [ -z "$port" ] && return 0
253
253
  local body="{\"hook\":\"$(relay_json_escape "$hook")\",\"error\":\"$(relay_json_escape "$detail")\"}"
254
254
  printf '%s' "$body" | relay_post_json "$port" /hook-fatal 2 >/dev/null 2>&1 || true
@@ -258,7 +258,7 @@ relay_install_hook_guard() {
258
258
  RELAY_HOOK_NAME="${1:-unknown}"
259
259
  # The pipe adapter owns native turn boundaries and final-result reporting.
260
260
  # Permission and safety hooks still run; TUI lifecycle hooks must not compete.
261
- if [ "${AGENT_RELAY_CLAUDE_TRANSPORT:-}" = "stream-json" ]; then
261
+ if [ "${HUMWICK_CLAUDE_TRANSPORT:-}" = "stream-json" ]; then
262
262
  case "$RELAY_HOOK_NAME" in
263
263
  user-prompt-submit|stop|stop-failure|session-end|pre-compact|post-compact|subagent-start|subagent-stop) exit 0 ;;
264
264
  esac
@@ -271,12 +271,12 @@ relay_install_hook_guard() {
271
271
  }
272
272
 
273
273
  relay_pending_reply_stop_decision() {
274
- local port="${AGENT_RELAY_RUNNER_PORT:-}"
274
+ local port="${HUMWICK_RUNNER_PORT:-}"
275
275
  [ -z "$port" ] && return 0
276
276
  local response
277
277
  # --max-time guards the Claude Stop hook's 5s budget: a slow runner/server (e.g. an
278
278
  # un-indexed obligation query) must never block past the timeout, or Claude SIGKILLs
279
- # the hook before it clears the turn -> stuck "busy" (#199). On timeout: no block.
279
+ # the hook before it clears the turn -> stuck "busy". On timeout: no block.
280
280
  response="$(curl -fsS --max-time 2 "http://127.0.0.1:${port}/reply-obligations/claude-stop" 2>/dev/null || true)"
281
281
  case "$response" in
282
282
  *'"decision":"block"'*|*'"decision": "block"'*) ;;
@@ -337,10 +337,10 @@ relay_json_escape() {
337
337
  # an isolated workspace whose branch has committed work not yet integrated into
338
338
  # base. Prints nothing otherwise — so plain chat, shared-mode, and no-change
339
339
  # sessions never pay context/token cost. Reads the workspace from
340
- # AGENT_RELAY_WORKSPACE_JSON (set by the orchestrator at spawn) and does a local,
340
+ # HUMWICK_WORKSPACE_JSON (set by the orchestrator at spawn) and does a local,
341
341
  # network-free git count. Always returns 0 (never aborts its caller).
342
342
  relay_review_reminder_text() {
343
- local ws="${AGENT_RELAY_WORKSPACE_JSON:-}"
343
+ local ws="${HUMWICK_WORKSPACE_JSON:-}"
344
344
  [ -z "$ws" ] && return 0
345
345
  local mode worktree base id branch ahead
346
346
  mode="$(relay_json_string_field mode "$ws")"
@@ -356,7 +356,7 @@ relay_review_reminder_text() {
356
356
  ahead="$(git -C "$worktree" rev-list --count "${base}..HEAD" 2>/dev/null || echo 0)"
357
357
  case "$ahead" in ''|*[!0-9]*) ahead=0 ;; esac
358
358
  [ "$ahead" -gt 0 ] || return 0
359
- printf '[agent-relay] You have %s committed change(s) on `%s` that are not yet integrated into base. If your task is complete, request review so Humwick can auto-land it: POST /api/workspaces/%s/actions with {"action":"request-review"}. If you are still working, ignore this — it only appears while there is unmerged committed work.' \
359
+ printf '[humwick] You have %s committed change(s) on `%s` that are not yet integrated into base. If your task is complete, request review so Humwick can auto-land it: POST /api/workspaces/%s/actions with {"action":"request-review"}. If you are still working, ignore this — it only appears while there is unmerged committed work.' \
360
360
  "$ahead" "${branch:-this branch}" "$id"
361
361
  return 0
362
362
  }
@@ -11,7 +11,7 @@ case "$reason" in
11
11
  clear)
12
12
  relay_post_timeline_status idle provider-turn subagent clearing-context
13
13
  # /clear wipes the context — the most common work boundary for a long-lived agent.
14
- # Capture this segment's Insights (#183/#184) before it's gone.
14
+ # Capture this segment's Insights before it's gone.
15
15
  relay_post_session_boundary "$transcript_path" clear
16
16
  ;;
17
17
  resume)
@@ -19,7 +19,7 @@ case "$reason" in
19
19
  ;;
20
20
  logout|prompt_input_exit|bypass_permissions_disabled|other|*)
21
21
  relay_post_status_clearing_subagents offline
22
- # Real session termination: capture end-of-session Insights (#183/#184). Order after the
22
+ # Real session termination: capture end-of-session Insights. Order after the
23
23
  # status post is arbitrary — the runner reads the transcript file regardless.
24
24
  relay_post_session_boundary "$transcript_path" "$reason"
25
25
  ;;
@@ -2,7 +2,7 @@
2
2
  set -euo pipefail
3
3
  source "${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/hooks/relay-status.sh"
4
4
  relay_install_hook_guard session-start
5
- # #2664 — a stamped check-in proves the hook path works before the first prompt is submitted.
5
+ # a stamped check-in proves the hook path works before the first prompt is submitted.
6
6
  relay_forward_hook_payload /hook-check "{}" "$(relay_now_ms)"
7
7
 
8
8
  payload="$(cat || true)"
@@ -13,8 +13,8 @@ case "$source_kind" in
13
13
  clear)
14
14
  # A queued /clear can commit after the runner's confirmation timed out. Restore
15
15
  # its continuation in THIS fresh context, even if the backstop hit the old one.
16
- if [ -n "${AGENT_RELAY_RUNNER_PORT:-}" ]; then
17
- continuation="$(printf '{"source":"clear","providerSessionId":"%s"}' "$(relay_json_escape "${AGENT_RELAY_PROVIDER_SESSION_ID:-}")" | relay_post_json "$AGENT_RELAY_RUNNER_PORT" /session-start 3 || true)"
16
+ if [ -n "${HUMWICK_RUNNER_PORT:-}" ]; then
17
+ continuation="$(printf '{"source":"clear","providerSessionId":"%s"}' "$(relay_json_escape "${HUMWICK_PROVIDER_SESSION_ID:-}")" | relay_post_json "${HUMWICK_RUNNER_PORT-}" /session-start 3 || true)"
18
18
  fi
19
19
  relay_post_timeline_status idle provider-turn subagent context-cleared
20
20
  ;;
@@ -1,4 +1,4 @@
1
- // Shared "is this plain simple commands?" pre-filter for the PreToolUse guards (#2834, #2993).
1
+ // Shared "is this plain simple commands?" pre-filter for the PreToolUse guards.
2
2
  // Heredocs, comments, functions, control-flow keywords, continuations, substitutions and
3
3
  // per-line unbalanced quotes (a string spanning lines) all mean "unsure": the caller allows.
4
4
  // `do`/`done` are deliberately not keywords here: they never appear without a header keyword
@@ -13,11 +13,11 @@ error_message="$(relay_json_string_field error_message "$payload")"
13
13
  [ -z "$error_message" ] && error_message="$(relay_json_string_field error_details "$payload")"
14
14
  [ -z "$error_message" ] && error_message="$(relay_json_string_field last_assistant_message "$payload")"
15
15
 
16
- # #286: a usage/rate-limit stall is transient and time-bounded — hold the agent
16
+ # a usage/rate-limit stall is transient and time-bounded — hold the agent
17
17
  # (providerState blocked) and auto-resume at reset, instead of silently going idle.
18
18
  # The disambiguator for billing_error is reset_time: a subscription rolling-window
19
19
  # limit carries one (and is auto-resumable); true credit exhaustion does not (fatal).
20
- # #3577: a refused proxy credential (ERR_PROXY_TUNNEL) also posts here; the runner classifies it.
20
+ # a refused proxy credential (ERR_PROXY_TUNNEL) also posts here; the runner classifies it.
21
21
  case "$error" in
22
22
  rate_limit|overloaded|server_error|api_error)
23
23
  relay_post_rate_limit "$error" "$reset_time" "$error_message"
@@ -3,15 +3,15 @@ set -euo pipefail
3
3
  source "${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/hooks/relay-status.sh"
4
4
  relay_install_hook_guard stop
5
5
 
6
- # Clearing the turn's busy state is the critical path (#199). Register it on EXIT
6
+ # Clearing the turn's busy state is the critical path. Register it on EXIT
7
7
  # so it runs even if a side-call below fails or times out under `set -e`. The one
8
8
  # exception is the reply-obligation block path, which deliberately keeps the agent
9
9
  # busy to answer — it opts out via the flag before exiting.
10
10
  _relay_clear_idle_on_exit=1
11
11
  # bg_count/bg_tasks_json are read from the payload below and consumed by the trap at exit
12
- # time (#502): the turn-end status carries the live background-script snapshot so an agent
12
+ # time: the turn-end status carries the live background-script snapshot so an agent
13
13
  # whose turn ended while a run_in_background shell keeps running stays busy instead of
14
- # falsely reading idle. bg_tasks_json (#2034) is the per-task {id, command} detail behind
14
+ # falsely reading idle. bg_tasks_json is the per-task {id, command} detail behind
15
15
  # that snapshot — the ledger the runner enriches with startedAt and a watchdog can read.
16
16
  bg_count=0
17
17
  bg_tasks_json="[]"
@@ -22,11 +22,11 @@ stop_hook_active="$(relay_json_bool_field stop_hook_active "$payload")"
22
22
  bg_count="$(relay_background_task_count "$payload")"
23
23
  bg_tasks_json="$(relay_background_task_list "$payload")"
24
24
 
25
- # Session-mirror capture is orthogonal to reply-obligation gating (#332): a recursive Stop
25
+ # Session-mirror capture is orthogonal to reply-obligation gating: a recursive Stop
26
26
  # (stop_hook_active=true) must NOT suppress capturing this turn's response, or the live mirror
27
27
  # silently drops frames. Always post the turn; only the reply-obligation decision is gated below.
28
28
  last_assistant_msg="$(echo "$payload" | jq -c '.last_assistant_message // empty' 2>/dev/null || true)"
29
- # prompt_id (#1086): Claude's own native turn identifier, correlating this Stop with
29
+ # prompt_id: Claude's own native turn identifier, correlating this Stop with
30
30
  # the same UUID stamped on every transcript entry of the turn (and the id the
31
31
  # UserPromptSubmit hook reported at turn start) — the stable replacement for a
32
32
  # runner-minted random UUID.
@@ -35,7 +35,7 @@ relay_post_session_turn "$(relay_json_string_field transcript_path "$payload")"
35
35
 
36
36
  if [ "$stop_hook_active" != "true" ]; then
37
37
  # `|| true`: under `set -e`, a non-zero from the obligation check must never abort
38
- # the hook before the idle-clear — clearing the turn is the critical path (#199).
38
+ # the hook before the idle-clear — clearing the turn is the critical path.
39
39
  stop_decision="$(relay_pending_reply_stop_decision || true)"
40
40
  if [ -n "$stop_decision" ]; then
41
41
  _relay_clear_idle_on_exit=0
@@ -125,8 +125,10 @@ exports.skillDenial = async function skillDenial(payload, name) {
125
125
  }
126
126
  for (const plugin of plugins) {
127
127
  const manifest = json(path.join(plugin, '.claude-plugin/plugin.json'));
128
- if (typeof manifest.name !== 'string') throw new Error(`Cannot establish plugin namespace in ${plugin}`);
129
- const prefix = `${manifest.name}:`;
128
+ // Claude infers a manifestless plugin's namespace from its directory in either generation.
129
+ const namespace = manifest.name ?? path.basename(plugin);
130
+ if (typeof namespace !== 'string') throw new Error(`Cannot establish plugin namespace in ${plugin}`);
131
+ const prefix = `${namespace}:`;
130
132
  inspect(path.join(plugin, 'skills'), false, prefix);
131
133
  if (!stat(path.join(plugin, 'skills')) && manifest.skills === undefined) inspect(path.join(plugin, 'SKILL.md'), false, prefix);
132
134
  if (manifest.commands === undefined) inspect(path.join(plugin, 'commands'), true, prefix);
@@ -145,7 +147,7 @@ exports.skillDenial = async function skillDenial(payload, name) {
145
147
  if (typeof definition.content === 'string') inspectText(definition.content, `${plugin}:${command}`, command, prefix, definition.model);
146
148
  }
147
149
  }
148
- // #3706: the role-provisioned copy in the managed home and its identical repo source are one skill; differing same-name skills stay ambiguous.
150
+ // the role-provisioned copy in the managed home and its identical repo source are one skill; differing same-name skills stay ambiguous.
149
151
  const sourced = new Set([...candidates.values()].filter((entry) => !entry.managed).map((entry) => entry.digest));
150
152
  for (const [key, entry] of candidates) if (entry.managed && sourced.has(entry.digest)) candidates.delete(key);
151
153
  if (candidates.size !== 1) return `skill ${name} ${candidates.size ? 'resolves ambiguously' : 'cannot be resolved'}; refusing unverified execution`;
@@ -154,7 +156,7 @@ exports.skillDenial = async function skillDenial(payload, name) {
154
156
  if (typeof skill.context === 'string' && skill.context.trim() === 'fork' && (typeof skill.model !== 'string' || !skill.model.trim() || skill.model.trim() === 'inherit')) return `fork skill ${name} requires an explicit model under capped profiles`;
155
157
  };
156
158
 
157
- // #3470: standalone CJS config adapters; this file is shipped beside subagent-guard.cjs.
158
- function skillSources() { return JSON.parse(process.env.AGENT_RELAY_CLAUDE_SKILL_SOURCES || '{}'); }
159
- function harnessSubagentsDisabled() { return process.env.AGENT_RELAY_HARNESS_SUBAGENTS === '0'; }
159
+ // standalone CJS config adapters; this file is shipped beside subagent-guard.cjs.
160
+ function skillSources() { return JSON.parse((process.env.HUMWICK_CLAUDE_SKILL_SOURCES) || '{}'); }
161
+ function harnessSubagentsDisabled() { return (process.env.HUMWICK_HARNESS_SUBAGENTS) === '0'; }
160
162
  exports.harnessSubagentsDisabled = harnessSubagentsDisabled;
@@ -10,10 +10,10 @@ payload="$(cat || true)"
10
10
  agent_id="$(relay_json_string_field agent_id "$payload")"
11
11
  agent_type="$(relay_json_string_field agent_type "$payload")"
12
12
 
13
- if [ -n "${AGENT_RELAY_RUNNER_PORT:-}" ] && [ -n "$(relay_json_string_field agent_transcript_path "$payload")" ]; then
14
- printf '%s' "$payload" | relay_post_json "$AGENT_RELAY_RUNNER_PORT" /subagent-usage 4 >/dev/null
13
+ if [ -n "${HUMWICK_RUNNER_PORT:-}" ] && [ -n "$(relay_json_string_field agent_transcript_path "$payload")" ]; then
14
+ printf '%s' "$payload" | relay_post_json "${HUMWICK_RUNNER_PORT-}" /subagent-usage 4 >/dev/null
15
15
  fi
16
16
 
17
- if [ "${AGENT_RELAY_CLAUDE_TRANSPORT:-}" != "stream-json" ]; then
17
+ if [ "${HUMWICK_CLAUDE_TRANSPORT:-}" != "stream-json" ]; then
18
18
  relay_post_status idle subagent "${agent_id:-subagent}" "$agent_type" "$agent_type"
19
19
  fi
@@ -4,7 +4,7 @@ source "${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/
4
4
  relay_install_hook_guard user-prompt-submit
5
5
  fired_at="$(relay_now_ms)"
6
6
  payload="$(cat || true)"
7
- # prompt_id (#1086): Claude's own native turn identifier for the prompt starting
7
+ # prompt_id: Claude's own native turn identifier for the prompt starting
8
8
  # now — the same UUID the Stop hook reports and the transcript stamps on every
9
9
  # entry of this turn. Passed as the busy report's `id` so the runner adopts it as
10
10
  # currentTurnId instead of minting a random UUID (runner-core.ts setProviderStatus).
@@ -1,5 +1,5 @@
1
- // #2993: a FOREGROUND wait (bare long `sleep`, or an until/while loop that only sleeps between checks) holds the
2
- // turn; the wait belongs in one detached relay_run. STRICT ALLOWLIST: the command must be exactly
1
+ // a FOREGROUND wait (bare long `sleep`, or an until/while loop that only sleeps between checks) holds the
2
+ // turn; the wait belongs in one detached humwick_run. STRICT ALLOWLIST: the command must be exactly
3
3
  // setup* ( sleep D | (until|while) CHECK; do (sleep D | echo|printf|date|true)+; done ) rest*
4
4
  // Anything else (loops doing work, `for`, nesting, `$(...)`, background `&`, unknown durations) is not matched,
5
5
  // so every parse doubt fails open to "allow".
@@ -110,7 +110,7 @@ export function waitLoopDenial(command: string): string | null {
110
110
  for (let depth = 0; depth <= MAX_UNWRAP_DEPTH && candidate !== undefined; depth += 1) {
111
111
  candidate = candidate.replace(TIMEOUT_PREFIX, ""); // `timeout 600 <cmd>` is transparent
112
112
  if (isForegroundWait(lexCommandLine(candidate))) {
113
- return "Do not hold the turn on a foreground wait. Run it with the relay_run MCP tool (detach: true, waitMs: 0) as ONE poll loop with a deadline "
113
+ return "Do not hold the turn on a foreground wait. Run it with the humwick_run MCP tool (detach: true, waitMs: 0) as ONE poll loop with a deadline "
114
114
  + "(e.g. `end=$((SECONDS+1800)); until <check>; do [ $SECONDS -ge $end ] && exit 1; sleep 30; done`), then end your turn with no text; "
115
115
  + `Relay wakes you once when it finishes. Command: ${command}`;
116
116
  }
@@ -1,7 +1,7 @@
1
1
  [
2
2
  {
3
- "name": "agent-relay-runner-monitor",
3
+ "name": "humwick-runner-monitor",
4
4
  "command": "bun run \"${CLAUDE_PLUGIN_ROOT}/monitors/relay-monitor.ts\"",
5
- "description": "Agent Relay runner message delivery pipe"
5
+ "description": "Humwick runner message delivery pipe"
6
6
  }
7
7
  ]