@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
package/agent-bin/humwick CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/bin/sh
2
- # Humwick #3470: `humwick browser` from the release this agent's runner belongs to, never an older
2
+ # Humwick: `humwick browser` from the release this agent's runner belongs to, never an older
3
3
  # install a login shell puts first on PATH. Checkout: <root>/runner/agent-bin -> <root>/src;
4
4
  # npm: node_modules/@humwick/runner/agent-bin -> node_modules/@humwick/server/src.
5
5
  here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) || exit 1
6
6
  for cli in "$here/../../src/index.ts" "$here/../../server/src/index.ts"; do
7
- if [ -f "$cli" ]; then exec "${AGENT_RELAY_BUN_BIN:-bun}" run --no-env-file "$cli" "$@"; fi
7
+ if [ -f "$cli" ]; then exec "${HUMWICK_BUN_BIN:-bun}" run --no-env-file "$cli" "$@"; fi
8
8
  done
9
9
  echo "humwick: no CLI next to $here" >&2
10
10
  exit 127
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # use the runner's adjacent CLI shim and its shared interpreter compatibility.
3
+ here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) || exit 1
4
+ exec "$here/humwick" browser "$@"
@@ -110,7 +110,7 @@ function classifyStandaloneSearch(command, cwd, root, words = candidateWords(com
110
110
  return patterns > 1 ? "mcp__fff__multi_grep" : "mcp__fff__grep";
111
111
  }
112
112
 
113
- function fffBinary(env) { return env.AGENT_RELAY_FFF_MCP_BINARY; }
113
+ function fffBinary(env) { return env.HUMWICK_FFF_MCP_BINARY; }
114
114
 
115
115
  function decide(payload, env = process.env, runGit = spawnSync) {
116
116
  try {
@@ -23,12 +23,12 @@ const REDIRECTS = {
23
23
  const MAX_REMEMBERED = 100;
24
24
 
25
25
  function enabledTools(env) {
26
- return new Set(String(env.AGENT_RELAY_WEB_TOOLS || "").split(",").map((part) => part.trim()).filter(Boolean));
26
+ return new Set(String(env.HUMWICK_WEB_TOOLS ?? "").split(",").map((part) => part.trim()).filter(Boolean));
27
27
  }
28
28
 
29
29
  function stateFile(env, sessionId) {
30
30
  const safe = typeof sessionId !== "string" ? "" : sessionId.replace(/[^A-Za-z0-9_-]/g, "").slice(0, 80);
31
- return safe ? join(env.AGENT_RELAY_SCRATCH_DIR || tmpdir(), `web-tools-redirect-${safe}.json`) : null;
31
+ return safe ? join((env.HUMWICK_SCRATCH_DIR) || tmpdir(), `web-tools-redirect-${safe}.json`) : null;
32
32
  }
33
33
 
34
34
  function decide(payload, env = process.env) {
package/package.json CHANGED
@@ -1,12 +1,9 @@
1
1
  {
2
2
  "name": "@humwick/runner",
3
- "version": "0.130.4",
3
+ "version": "0.130.6",
4
4
  "description": "Unified provider lifecycle runner for Humwick",
5
5
  "type": "module",
6
6
  "bin": {
7
- "claude-relay": "src/bin/claude.ts",
8
- "codex-relay": "src/bin/codex.ts",
9
- "opencode-relay": "src/bin/opencode.ts",
10
7
  "claude-humwick": "src/bin/claude.ts",
11
8
  "codex-humwick": "src/bin/codex.ts",
12
9
  "opencode-humwick": "src/bin/opencode.ts"
@@ -21,18 +18,18 @@
21
18
  "!hooks/**/*.test.ts",
22
19
  "LICENSE"
23
20
  ],
24
- "license": "PolyForm-Shield-1.0.0",
25
- "author": "Edin Mujkanovic <edin@exelerus.com>",
21
+ "license": "AGPL-3.0-only",
22
+ "author": "Humwick contributors",
26
23
  "repository": {
27
24
  "type": "git",
28
- "url": "git+https://github.com/edimuj/agent-relay.git",
25
+ "url": "git+https://github.com/humwick/humwick.git",
29
26
  "directory": "runner"
30
27
  },
31
28
  "dependencies": {
32
- "@humwick/offload": "0.130.4",
33
- "@humwick/providers": "0.104.10",
34
- "@humwick/sdk": "0.2.139",
35
- "callmux": "0.25.0",
29
+ "@humwick/offload": "0.130.6",
30
+ "@humwick/providers": "0.104.12",
31
+ "@humwick/sdk": "0.2.141",
32
+ "callmux": "0.27.0",
36
33
  "unbash": "6.0.0"
37
34
  },
38
35
  "devDependencies": {
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: playwright-cli
3
3
  description: Drive Relay browsers; live dashboard.
4
- allowed-tools: Bash(agent-relay-browser:*) Bash(playwright-cli:*)
4
+ allowed-tools: Bash(humwick-browser:*) Bash(playwright-cli:*)
5
5
  ---
6
6
 
7
7
  # Browser sessions with playwright-cli
@@ -13,14 +13,14 @@ Never install a browser or run `playwright-cli open`.
13
13
  ## Start, attach, stop
14
14
 
15
15
  ```bash
16
- agent-relay-browser start --json # prints sessionId, cdpUrl, viewUrl
16
+ humwick-browser start --json # prints sessionId, cdpUrl, viewUrl
17
17
  playwright-cli attach --cdp=<cdpUrl> --session=relay
18
18
  playwright-cli -s=relay goto http://localhost:3000
19
19
  # ... work ...
20
- agent-relay-browser stop # ends the session and deletes its profile
20
+ humwick-browser stop # ends the session and deletes its profile
21
21
  ```
22
22
 
23
- - One session per agent. `agent-relay-browser status` shows yours.
23
+ - One session per agent. `humwick-browser status` shows yours.
24
24
  - Send `viewUrl` to the operator when they should watch ("look at this").
25
25
  - The profile is fresh each session: no logins or cookies carry over.
26
26
 
@@ -37,13 +37,15 @@ playwright-cli -s=relay hover e4; playwright-cli -s=relay upload ./file.pdf
37
37
  playwright-cli -s=relay go-back; playwright-cli -s=relay reload
38
38
  playwright-cli -s=relay eval "document.title"
39
39
  playwright-cli -s=relay eval "el => el.getAttribute('data-testid')" e5
40
- playwright-cli -s=relay screenshot --filename=page.png
40
+ playwright-cli -s=relay screenshot --filename="$TMPDIR/page.png"
41
41
  playwright-cli -s=relay tab-list; playwright-cli -s=relay tab-new http://localhost:3000/b
42
42
  playwright-cli -s=relay console; playwright-cli -s=relay requests
43
43
  playwright-cli -s=relay resize 1280 800
44
44
  ```
45
45
 
46
- Snapshots go to `.playwright-cli/` in the working directory; read only what you need.
46
+ Snapshots go to `.playwright-cli/` in the working directory (locally git-ignored by Relay).
47
+ Write screenshots, traces, downloads and other scratch output under `$TMPDIR`;
48
+ read only what you need.
47
49
  Refs change after the page changes: take a new snapshot before acting on old refs.
48
50
 
49
51
  ## More
@@ -1,8 +1,8 @@
1
1
  {
2
- "name": "agent-relay-runner",
2
+ "name": "humwick-runner",
3
3
  "description": "Thin Humwick runner bridge for Claude Code",
4
- "version": "0.130.4",
5
- "agentRelayContracts": {
4
+ "version": "0.130.6",
5
+ "humwickContracts": {
6
6
  "providerPluginProtocol": 1
7
7
  }
8
8
  }
@@ -5,24 +5,33 @@ const { mkdirSync, renameSync, writeFileSync } = require("node:fs");
5
5
  const { tmpdir } = require("node:os");
6
6
  const { basename, dirname, join } = require("node:path");
7
7
 
8
- let input = "";
9
- process.stdin.setEncoding("utf8");
10
- process.stdin.on("data", (chunk) => { input += chunk; });
11
- process.stdin.on("end", () => {
12
- const metrics = parseClaudeStatusLineInput(input);
13
- if (metrics) writeState(metrics);
14
- process.stdout.write(`${standaloneOutput(metrics)}\n`);
15
- });
8
+ if (require.main === module) {
9
+ let input = "";
10
+ process.stdin.setEncoding("utf8");
11
+ process.stdin.on("data", (chunk) => { input += chunk; });
12
+ process.stdin.on("end", () => {
13
+ process.stdout.write(`${runStatuslineProbe(input).output}\n`);
14
+ });
15
+ }
16
+
17
+ function runStatuslineProbe(raw, options) {
18
+ const opts = options || {};
19
+ const metrics = parseClaudeStatusLineInput(raw, opts.now === undefined ? Date.now() : opts.now, opts.agentId);
20
+ if (metrics) writeState(metrics, opts.stateDir || statuslineStateDir());
21
+ return { metrics, output: standaloneOutput(metrics) };
22
+ }
16
23
 
17
24
  function statuslineAgentId() {
18
- return stringValue(process.env.AGENT_RELAY_AGENT_ID) || stringValue(process.env.AGENT_RELAY_ID);
25
+ return stringValue(process.env.HUMWICK_AGENT_ID)
26
+ || stringValue(process.env.HUMWICK_ID);
19
27
  }
20
28
 
21
29
  function statuslineStateDir() {
22
- return process.env.AGENT_RELAY_CONTEXT_STATE_DIR || process.env.AGENT_RELAY_HOST_TMPDIR || tmpdir();
30
+ return (process.env.HUMWICK_CONTEXT_STATE_DIR)
31
+ || (process.env.HUMWICK_HOST_TMPDIR) || tmpdir();
23
32
  }
24
33
 
25
- function parseClaudeStatusLineInput(raw) {
34
+ function parseClaudeStatusLineInput(raw, timestamp, agentId) {
26
35
  let data;
27
36
  try {
28
37
  data = JSON.parse(raw);
@@ -31,7 +40,6 @@ function parseClaudeStatusLineInput(raw) {
31
40
  }
32
41
  if (!isRecord(data) || !isRecord(data.context_window)) return null;
33
42
  const context = data.context_window;
34
- const timestamp = Date.now();
35
43
  const contextPercent = numberValue(context.used_percentage);
36
44
  const tokensMax = numberValue(context.context_window_size);
37
45
  const usage = isRecord(context.current_usage) ? context.current_usage : undefined;
@@ -50,7 +58,7 @@ function parseClaudeStatusLineInput(raw) {
50
58
  const resolvedEffort = effort || stringValue(process.env.CLAUDE_EFFORT) || stringValue(process.env.CLAUDE_CODE_EFFORT_LEVEL);
51
59
 
52
60
  const metrics = {
53
- agentId: statuslineAgentId() || stringValue(data.session_id) || "unknown",
61
+ agentId: agentId || statuslineAgentId() || stringValue(data.session_id) || "unknown",
54
62
  contextPercent: contextPercent !== undefined ? contextPercent : ((tokensUsed || 0) / (tokensMax || 1)) * 100,
55
63
  source: "statusline",
56
64
  confidence: "exact",
@@ -69,9 +77,8 @@ function parseClaudeStatusLineInput(raw) {
69
77
  return metrics;
70
78
  }
71
79
 
72
- function writeState(metrics) {
73
- // The runner reads this from the host temp root, not this agent's private TMPDIR (#3084).
74
- const dir = statuslineStateDir();
80
+ function writeState(metrics, dir) {
81
+ // The runner reads this from the host temp root, not this agent's private TMPDIR.
75
82
  const file = join(dir, `agent-relay-context-${safeStateId(metrics.agentId)}.json`);
76
83
  mkdirSync(dirname(file), { recursive: true });
77
84
  const tmp = `${file}.${process.pid}.tmp`;
@@ -79,6 +86,7 @@ function writeState(metrics) {
79
86
  renameSync(tmp, file);
80
87
  }
81
88
 
89
+
82
90
  function quotaWindowsFromRateLimits(rateLimits) {
83
91
  const windows = [];
84
92
  for (const name of ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"]) {
@@ -142,3 +150,5 @@ function secondsUntil(epochSeconds, nowMs) {
142
150
  function epochSecondsToMs(epochSeconds) {
143
151
  return epochSeconds === undefined ? undefined : epochSeconds * 1000;
144
152
  }
153
+
154
+ module.exports = { runStatuslineProbe };
@@ -260,19 +260,27 @@ function classifyGateRun(command, commands = {}) {
260
260
  return null;
261
261
  }
262
262
 
263
- // sdk/src/types/host.ts
264
- var HOST_GATE_KINDS = ["land", "iterate", "validation"];
265
-
266
- // sdk/src/land-gates.ts
267
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "path";
268
-
269
- // sdk/src/types/guards.ts
270
- function isRecord(value) {
271
- return typeof value === "object" && value !== null && !Array.isArray(value);
263
+ // sdk/src/project-config.ts
264
+ var PROJECT_CONFIG_DIR = ".humwick";
265
+ var LEGACY_PROJECT_CONFIG_DIR = ".agent-relay";
266
+ var warnedProjects = new Set;
267
+ function selectProjectConfigDir(project, canonical, legacy) {
268
+ if (project && legacy && !warnedProjects.has(project)) {
269
+ warnedProjects.add(project);
270
+ console.warn(`[project-config] ${project}: ${canonical ? `${PROJECT_CONFIG_DIR}/ wins over deprecated ${LEGACY_PROJECT_CONFIG_DIR}/` : `reading deprecated ${LEGACY_PROJECT_CONFIG_DIR}/`}; migrate with humwick project migrate-config in that checkout`);
271
+ }
272
+ return canonical || !legacy ? PROJECT_CONFIG_DIR : LEGACY_PROJECT_CONFIG_DIR;
273
+ }
274
+ function isProjectConfigPath(path) {
275
+ return [PROJECT_CONFIG_DIR, LEGACY_PROJECT_CONFIG_DIR].some((dir) => path === dir || path.startsWith(`${dir}/`));
276
+ }
277
+ function projectConfigPathIn(path, directory) {
278
+ return isProjectConfigPath(path) ? directory + path.slice(path.indexOf("/") < 0 ? path.length : path.indexOf("/")) : path;
272
279
  }
273
280
 
274
- // sdk/src/types/land-gates.ts
275
- var LAND_GATE_SCOPES = ["full", "partial"];
281
+ // sdk/src/repo-config-file.ts
282
+ import { dirname, resolve as resolve2 } from "path";
283
+ import { readFileSync, existsSync, mkdirSync, appendFileSync } from "fs";
276
284
 
277
285
  // sdk/src/validation-core.ts
278
286
  import { isAbsolute, relative, resolve } from "path";
@@ -321,9 +329,12 @@ function assertNoControlBytes(text, field) {
321
329
  throw new ValidationError(`${field} must not contain control bytes (only newline and tab are allowed)`);
322
330
  }
323
331
 
332
+ // sdk/src/types/guards.ts
333
+ function isRecord(value) {
334
+ return typeof value === "object" && value !== null && !Array.isArray(value);
335
+ }
336
+
324
337
  // sdk/src/repo-config-file.ts
325
- import { dirname, resolve as resolve2 } from "path";
326
- import { readFileSync } from "fs";
327
338
  function absent(err) {
328
339
  const code = err.code;
329
340
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -347,7 +358,7 @@ function findRepoConfigFile(startDir, file, clean) {
347
358
  for (const dir of ancestors(startDir)) {
348
359
  let raw;
349
360
  try {
350
- raw = readFileSync(resolve2(dir, file), "utf8");
361
+ raw = readFileSync(resolve2(dir, resolveRepoConfigPath(dir, file)), "utf8");
351
362
  } catch (err) {
352
363
  raw = absent(err);
353
364
  }
@@ -356,9 +367,28 @@ function findRepoConfigFile(startDir, file, clean) {
356
367
  }
357
368
  return null;
358
369
  }
370
+ function resolveRepoConfigPath(root, file) {
371
+ if (!isProjectConfigPath(file))
372
+ return file;
373
+ const canonical = existsSync(resolve2(root, PROJECT_CONFIG_DIR));
374
+ const legacy = existsSync(resolve2(root, LEGACY_PROJECT_CONFIG_DIR));
375
+ const actual = projectConfigPathIn(file, selectProjectConfigDir(undefined, canonical, legacy));
376
+ if (existsSync(resolve2(root, actual)))
377
+ selectProjectConfigDir(resolve2(root), canonical, legacy);
378
+ return actual;
379
+ }
380
+
381
+ // sdk/src/types/host.ts
382
+ var HOST_GATE_KINDS = ["land", "iterate", "validation"];
383
+
384
+ // sdk/src/land-gates.ts
385
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "path";
386
+
387
+ // sdk/src/types/land-gates.ts
388
+ var LAND_GATE_SCOPES = ["full", "partial"];
359
389
 
360
390
  // sdk/src/land-gates.ts
361
- var LAND_GATES_FILE = ".agent-relay/land-gates.json";
391
+ var LAND_GATES_FILE = ".humwick/land-gates.json";
362
392
  var DEFAULT_LAND_GATE_TIMEOUT_MS = 5 * 60 * 1000;
363
393
  var LAND_GATE_TIMEOUT_MARGIN_MS = 5 * 60 * 1000;
364
394
  function cleanLandGate(value, index, worktreePath) {
@@ -681,7 +711,7 @@ function waitLoopDenial(command) {
681
711
  for (let depth = 0;depth <= MAX_UNWRAP_DEPTH && candidate !== undefined; depth += 1) {
682
712
  candidate = candidate.replace(TIMEOUT_PREFIX, "");
683
713
  if (isForegroundWait(lexCommandLine(candidate))) {
684
- 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 " + "(e.g. `end=$((SECONDS+1800)); until <check>; do [ $SECONDS -ge $end ] && exit 1; sleep 30; done`), then end your turn with no text; " + `Relay wakes you once when it finishes. Command: ${command}`;
714
+ 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 " + "(e.g. `end=$((SECONDS+1800)); until <check>; do [ $SECONDS -ge $end ] && exit 1; sleep 30; done`), then end your turn with no text; " + `Relay wakes you once when it finishes. Command: ${command}`;
685
715
  }
686
716
  candidate = executingShellScript(candidate) ?? unwrapGroupCommand(candidate);
687
717
  }
@@ -922,7 +952,7 @@ function gateDenial(command, flat, cwd) {
922
952
  return null;
923
953
  if (leavesProject(normalized, cwd))
924
954
  return null;
925
- return `This is a project gate: run it with the relay_run MCP tool (waitMs: 0), then end your turn; Relay wakes you once when it finishes. Command: ${command}`;
955
+ return `This is a project gate: run it with the humwick_run MCP tool (waitMs: 0), then end your turn; Relay wakes you once when it finishes. Command: ${command}`;
926
956
  }
927
957
  function decide(payload) {
928
958
  const input = payload;
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env bash
2
- # PreToolUse guard (#2834): steers project gate commands run via Bash/Monitor to relay_run.
2
+ # PreToolUse guard: steers project gate commands run via Bash/Monitor to humwick_run.
3
3
  # FAIL-OPEN: the decision lives in gate-run-guard.ts (shared SDK gate classifier); every
4
4
  # precondition miss here (not relay-managed, read-only, no bun) exits 0 with no output.
5
- [ -n "${AGENT_RELAY_RUNNER_PORT:-}" ] || exit 0
6
- [ "${AGENT_RELAY_APPROVAL:-}" != "read-only" ] || exit 0
5
+ [ -n "${HUMWICK_RUNNER_PORT:-}" ] || exit 0
6
+ [ "${HUMWICK_APPROVAL:-}" != "read-only" ] || exit 0
7
7
  command -v bun >/dev/null 2>&1 || exit 0
8
8
  HOOK_DIR="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/hooks"
9
9
  exec bun "${HOOK_DIR}/gate-run-guard.ts" 2>/dev/null || exit 0
@@ -1,6 +1,6 @@
1
- // PreToolUse guard (#2834): a Bash/Monitor call that runs one of THIS project's own gates
1
+ // PreToolUse guard: a Bash/Monitor call that runs one of THIS project's own gates
2
2
  // (`iterate`, `delivery`, `gates[].command` in the session repo's land-gates.json) is denied with
3
- // a steer to `relay_run`. FAIL-OPEN: any doubt or error prints nothing and exits 0. Bundled to a
3
+ // a steer to `humwick_run`. FAIL-OPEN: any doubt or error prints nothing and exits 0. Bundled to a
4
4
  // dependency-free .mjs for provisioned copies (scripts/build-claude-monitor.ts).
5
5
  import { resolve } from "node:path";
6
6
  import { classifyGateRun, lexCommandLine, unwrapGroupCommand, unwrapShellCommand } from "@humwick/sdk/gate-run-classify";
@@ -185,7 +185,7 @@ function dropShellOptionOperands(command: string): string {
185
185
  return command.slice(0, regionStart) + kept + rest;
186
186
  }
187
187
 
188
- // #2843 fail-opens, hook only: the shared classifier is unchanged (heavy-lease callers keep
188
+ // fail-opens, hook only: the shared classifier is unchanged (heavy-lease callers keep
189
189
  // its conservative join/short-circuit behavior). Each layer is checked, so wrapped forms
190
190
  // (`bash -lc 'false && gate'`, `bash -lc 'env --help gate'`) fail open through the wrapper.
191
191
  function failOpenForContrivedForm(flat: string): boolean {
@@ -212,7 +212,7 @@ function gateDenial(command: string, flat: string, cwd: string): string | null {
212
212
  const category = classifyGateRun(normalized, commands);
213
213
  if (!category || category === "heuristic") return null;
214
214
  if (leavesProject(normalized, cwd)) return null;
215
- return `This is a project gate: run it with the relay_run MCP tool (waitMs: 0), then end your turn; Relay wakes you once when it finishes. Command: ${command}`;
215
+ return `This is a project gate: run it with the humwick_run MCP tool (waitMs: 0), then end your turn; Relay wakes you once when it finishes. Command: ${command}`;
216
216
  }
217
217
 
218
218
  function decide(payload: unknown): string | null {
@@ -223,7 +223,7 @@ function decide(payload: unknown): string | null {
223
223
  const cwd = typeof input.cwd === "string" && input.cwd ? input.cwd : process.cwd();
224
224
  const flat = trustedFlatCommand(command);
225
225
  const gate = flat === null ? null : gateDenial(command, flat, cwd);
226
- // A harness-backgrounded Bash already returns the turn, so only foreground waits are redirected (#2993).
226
+ // A harness-backgrounded Bash already returns the turn, so only foreground waits are redirected.
227
227
  return gate ?? (input.tool_input?.run_in_background === true ? null : waitLoopDenial(command));
228
228
  }
229
229
 
@@ -6739,7 +6739,7 @@ var DYNAMIC = new Set(["eval", "source", ".", "trap", "python", "python2", "pyth
6739
6739
  var PLAIN_READERS = new Set(["cat", "tee", "head", "tail", "wc", "tr", "cut", "nl", "rev", "tac", "fold", "base64", "od", "md5sum", "sha256sum", "grep", "egrep", "fgrep", "jq", "echo", "printf", "true"]);
6740
6740
  var GIT_BODY_COMMANDS = new Set(["commit", "tag", "notes"]);
6741
6741
  var GH_BODY_COMMANDS = new Set(["issue create", "issue comment", "issue edit", "pr create", "pr comment", "pr edit", "pr review", "release create", "release edit", "gist create"]);
6742
- var RELAY_BODY_COMMANDS = new Set(["message", "/message", "reply", "/reply", "pair", "/pair"]);
6742
+ var RELAY_BODY_COMMANDS = new Set(["message", "/message", "reply", "/reply"]);
6743
6743
  var STDIN_PATHS = new Set(["/dev/stdin", "/dev/fd/0", "/proc/self/fd/0"]);
6744
6744
  var REDEFINERS = new Set(["alias", "shopt", "enable", "hash"]);
6745
6745
  var ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/;
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # Shared "fleet fratricide" kill-pattern guard (issue #753).
2
+ # Shared "fleet fratricide" kill-pattern guard.
3
3
  #
4
4
  # Every managed agent's runner runs as
5
5
  # bun run .../agent-relay-runner/src/index.ts <provider> ... (scoped install: .../@humwick/runner/...)
@@ -13,7 +13,7 @@
13
13
  # kill "$SERVER_PID") and pkill -f on a token that is unique to the caller's own
14
14
  # throwaway server (its exact test port, or "$PWD/public").
15
15
  #
16
- # Layers (#3117): when neither the segment matcher below nor a raw kill-verb +
16
+ # Layers: when neither the segment matcher below nor a raw kill-verb +
17
17
  # fleet-token check fires, the command passes without starting a process.
18
18
  # Otherwise kill-guard.ts parses it and answers block (an executed broad kill, e.g.
19
19
  # behind sudo or bash -c), static (no dynamic execution, so a kill word in an
@@ -29,7 +29,7 @@
29
29
  # the command is a dangerous broad kill, and exits 1 (silent) when it is safe.
30
30
  # This lets non-bash callers reuse the SAME matcher as a subprocess.
31
31
  #
32
- # TODO(#753 follow-up): wire the Codex runner/exec layer to invoke this guard.
32
+ # TODO: wire the Codex runner/exec layer to invoke this guard.
33
33
  # Codex managed agents have no Claude PreToolUse hook, so the same broad pkill can
34
34
  # still fratricide the fleet from a Codex session until that wiring lands. The
35
35
  # matcher is intentionally factored here so the Codex side can call it directly
@@ -41,7 +41,7 @@ shopt -s extglob
41
41
  case "${BASH_SOURCE[0]}" in */*) KILL_GUARD_PARSER="${BASH_SOURCE[0]%/*}/kill-guard.ts" ;; *) KILL_GUARD_PARSER=kill-guard.ts ;; esac
42
42
 
43
43
  # Guidance returned on a block — tells the caller how to clean up safely instead.
44
- FRATRICIDE_KILL_GUIDANCE='Blocked a broad process-kill (#753 fleet-fratricide guard): this pattern would match sibling agents'\'' runners, because every managed agent runs "bun run .../agent-relay-runner/src/index.ts". Kill only a PID you own — capture it when you spawn the server (SERVER_PID=$!; kill "$SERVER_PID") — or pkill -f a token that is unique to your own process (your exact test port, or "$PWD/public"). Never pkill/killall on bun, node, src/index.ts, agent-relay, humwick, or their runner packages.'
44
+ FRATRICIDE_KILL_GUIDANCE='Blocked a broad process-kill (fleet-fratricide guard): this pattern would match sibling agents'\'' runners, because every managed agent runs "bun run.../agent-relay-runner/src/index.ts". Kill only a PID you own — capture it when you spawn the server (SERVER_PID=$!; kill "$SERVER_PID") — or pkill -f a token that is unique to your own process (your exact test port, or "$PWD/public"). Never pkill/killall on bun, node, src/index.ts, agent-relay, humwick, or their runner packages.'
45
45
  # The segment matcher reads raw text, so it cannot tell a command from prose.
46
46
  FRATRICIDE_PATTERN_GUIDANCE="${FRATRICIDE_KILL_GUIDANCE}"' If this command only MENTIONS a kill in prose (an issue body, a commit message, a heredoc), this guard cannot tell: write the text to a file with the Write tool and pass it by file (gh --body-file, git commit -F), or drop the fleet token from the prose.'
47
47
 
@@ -1,4 +1,4 @@
1
- // Fleet-fratricide parser (#753, #3117). stdin: command text. stdout: `block:<command>` for an executed
1
+ // Fleet-fratricide parser. stdin: command text. stdout: `block:<command>` for an executed
2
2
  // broad kill, `static` when nothing in the command executes text (so a kill word in an argument, heredoc
3
3
  // or comment is prose), or `sink` when text may reach a dynamic executor and kill-guard.sh's segment
4
4
  // matcher must decide. A non-zero exit means "parser unavailable". Bundled to kill-guard.provisioned.mjs.
@@ -17,7 +17,7 @@ const PLAIN_READERS = new Set(["cat", "tee", "head", "tail", "wc", "tr", "cut",
17
17
  // (`git -c alias.x='!sh' x`, a gh alias or extension) may run the text.
18
18
  const GIT_BODY_COMMANDS = new Set(["commit", "tag", "notes"]);
19
19
  const GH_BODY_COMMANDS = new Set(["issue create", "issue comment", "issue edit", "pr create", "pr comment", "pr edit", "pr review", "release create", "release edit", "gist create"]);
20
- const RELAY_BODY_COMMANDS = new Set(["message", "/message", "reply", "/reply", "pair", "/pair"]);
20
+ const RELAY_BODY_COMMANDS = new Set(["message", "/message", "reply", "/reply"]);
21
21
  const STDIN_PATHS = new Set(["/dev/stdin", "/dev/fd/0", "/proc/self/fd/0"]);
22
22
  // Builtins that change what a later command name runs.
23
23
  const REDEFINERS = new Set(["alias", "shopt", "enable", "hash"]);
@@ -3,7 +3,7 @@ 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 permission-request
5
5
 
6
- port="${AGENT_RELAY_RUNNER_PORT:-}"
6
+ port="${HUMWICK_RUNNER_PORT:-}"
7
7
  if [[ -z "$port" ]]; then
8
8
  exit 0
9
9
  fi
@@ -3,7 +3,7 @@ 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 post-compact
5
5
 
6
- # #3398 — the trigger (manual for our /compact, auto for Claude's own) tells the runner which input settled.
6
+ # the trigger (manual for our /compact, auto for Claude's own) tells the runner which input settled.
7
7
  trigger="$(relay_json_string_field trigger "$(cat || true)")"
8
8
  metadata=""
9
9
  [ -n "$trigger" ] && metadata="{\"compactTrigger\":\"$(relay_json_escape "$trigger")\"}"
@@ -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 post-tool-use
5
- [ -n "${AGENT_RELAY_RUNNER_PORT:-}" ] || exit 0
6
- # #3646: stdout belongs to this tool result, before Claude can make its next call.
7
- context="$(relay_post_json "$AGENT_RELAY_RUNNER_PORT" /tool-use 4 || true)"
5
+ [ -n "${HUMWICK_RUNNER_PORT:-}" ] || exit 0
6
+ # stdout belongs to this tool result, before Claude can make its next call.
7
+ context="$(relay_post_json "${HUMWICK_RUNNER_PORT-}" /tool-use 4 || true)"
8
8
  relay_emit_additional_context PostToolUse "$context"
@@ -7,6 +7,6 @@ payload="$(cat || true)"
7
7
  transcript_path="$(relay_json_string_field transcript_path "$payload")"
8
8
 
9
9
  relay_post_timeline_status busy provider-turn "" compacting
10
- # Pre-destroy seam (#183): compaction is about to discard context — capture this segment's
11
- # Insights (#184) from the full transcript first. The most common boundary in practice.
10
+ # Pre-destroy seam: compaction is about to discard context — capture this segment's
11
+ # Insights from the full transcript first. The most common boundary in practice.
12
12
  relay_post_session_boundary "$transcript_path" compact
@@ -7,7 +7,7 @@ set -euo pipefail
7
7
  HOOK_DIR="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/hooks"
8
8
  source "${HOOK_DIR}/relay-status.sh"
9
9
  relay_install_hook_guard read-only-bash-guard
10
- # Shared fleet-fratricide kill-pattern matcher (#753): trim_shell_text,
10
+ # Shared fleet-fratricide kill-pattern matcher: trim_shell_text,
11
11
  # split_segments, shell_words and fratricide_deny_reason live here.
12
12
  source "${HOOK_DIR}/kill-guard.sh"
13
13
 
@@ -32,7 +32,7 @@ if command -v jq >/dev/null 2>&1; then
32
32
  command_text="$(printf '%s' "$payload" | jq -r '.tool_input.command // empty' 2>/dev/null || true)"
33
33
  fi
34
34
 
35
- # --- Fleet-fratricide guard: ACTIVE IN ALL APPROVAL MODES (#753) ---
35
+ # --- Fleet-fratricide guard: ACTIVE IN ALL APPROVAL MODES ---
36
36
  # A broad pkill/killall/kill can SIGTERM every sibling agent's runner host-wide,
37
37
  # so this block runs before (and independent of) the read-only allow-list.
38
38
  if (( jq_available )); then
@@ -51,7 +51,7 @@ else
51
51
  fi
52
52
 
53
53
  # --- Read-only allow-list: only the read-only approval mode below this point ---
54
- case "${AGENT_RELAY_APPROVAL:-}" in
54
+ case "${HUMWICK_APPROVAL:-}" in
55
55
  open|guarded)
56
56
  exit 0
57
57
  ;;
@@ -556,7 +556,7 @@ validate_segment() {
556
556
  validate_bun "$((i + 1))"
557
557
  return $?
558
558
  ;;
559
- agent-relay)
559
+ humwick|agent-relay)
560
560
  validate_agent_relay "$((i + 1))"
561
561
  return $?
562
562
  ;;