@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,9 +1,9 @@
1
1
  import { readdir } from "node:fs/promises";
2
2
  import { basename, dirname, join } from "node:path";
3
- // #2482 — per-turn Claude token-usage capture: the runner-side half of the token-usage
3
+ // per-turn Claude token-usage capture: the runner-side half of the token-usage
4
4
  // spine's first capture seam. On every Stop-hook session turn (runner-core's
5
5
  // publishSessionTurn) the transcript's APPENDED tail is read and every NEW root-session
6
- // assistant entry's API-reported usage is extracted (the #2482 sibling parser beside
6
+ // assistant entry's API-reported usage is extracted (the sibling parser beside
7
7
  // extractLatestContextUsage in adapters/claude-transcript.ts) and one spine record is
8
8
  // POSTed per entry, keyed dedupeKey=entry-uuid so the spine's dedupe_key upsert makes
9
9
  // replays and retries idempotent by construction.
@@ -33,7 +33,7 @@ import { claudeSessionIdFromTranscriptPath, TranscriptTokenUsageExtractor, type
33
33
  import { incrementalFileNeedsReset, readIncrementalFileRange, splitIncrementalFileLines, statIncrementalFile, type IncrementalFileInfo, type IncrementalFileLineBuffer, type IncrementalFileLinePolicy, type IncrementalFilePosition } from "./incremental-file";
34
34
  import type { ProviderTokenUsageRecord } from "../adapter";
35
35
 
36
- /** The spine's turn-less report shape (POST /api/agents/:id/token-usage, #2485). */
36
+ /** The spine's turn-less report shape. */
37
37
  export type TranscriptTokenUsageSpineRecord = ProviderTokenUsageRecord & { provider: "claude" };
38
38
 
39
39
  // Claude assistant transcript entries carry both the full model output and usage. Eight
@@ -142,13 +142,13 @@ export class ClaudeTranscriptTokenUsageCapture {
142
142
 
143
143
  private async settleTranscript(transcriptPath: string, options: { pollIntervalMs: number; timeoutMs: number; now?: () => number; sleep?: (ms: number) => Promise<unknown> }): Promise<number> {
144
144
  // now/sleep are injectable so tests can drive the settle window on a virtual
145
- // clock instead of racing real timers against host load (#2714 flake).
145
+ // clock instead of racing real timers against host load.
146
146
  const now = options.now ?? Date.now;
147
147
  const sleep = options.sleep ?? Bun.sleep;
148
148
  const deadline = now() + options.timeoutMs;
149
149
  const pollIntervalMs = Math.max(1, options.pollIntervalMs);
150
150
  const quietWindowMs = Math.min(options.timeoutMs, Math.max(pollIntervalMs * 2, 25));
151
- // #2491 review round 3 (reverts round 2's watermark bail, which was WRONG — it exited
151
+ // review round 3 (reverts round 2's watermark bail, which was WRONG — it exited
152
152
  // exactly when the watermark hadn't moved yet, which is precisely the state a still-
153
153
  // flushing final entry looks like before it lands). Seed the quiet-window baseline at
154
154
  // settle START rather than leaving it undefined until something is first found: without
@@ -5,13 +5,13 @@ import type { AgentProfileProviderOptions } from "@humwick/sdk";
5
5
  import { isRecord } from "@humwick/sdk/types/guards";
6
6
  import { claudeDisallowedWebTools } from "../web-tools";
7
7
 
8
- // ── #2453 — eager "System tools" context trim for the coding/review profiles ─────────────────
8
+ // ── — eager "System tools" context trim for the coding/review profiles ─────────────────
9
9
  // A BARE tool name on Claude Code's --disallowedTools removes the tool's schema from the
10
10
  // model's eager context (the /context "System tools" bucket) WITHOUT touching MCP (mcp__*),
11
11
  // skills, or core coding tools — which an allowlist (--tools) would put at risk. The Artifact
12
12
  // family + Workflow carry the heaviest eager docstrings and coding/review agents never publish
13
13
  // artifacts or run workflows; SendFeedback is misused by autonomous agents (also env-suppressed
14
- // fleet-wide since T3182 — this is the per-profile context-trim path); ScheduleWakeup is
14
+ // fleet-wide since — this is the per-profile context-trim path); ScheduleWakeup is
15
15
  // loop-only; ReportFindings duplicates relay report-up.
16
16
  export const CLAUDE_CONTEXT_TRIM_DISALLOWED_TOOLS = ["Artifact", "ArtifactComments", "ArtifactData", "ArtifactCheck", "Workflow", "SendFeedback", "ScheduleWakeup", "ReportFindings"];
17
17
 
@@ -23,7 +23,7 @@ const CLAUDE_CONTEXT_TRIM_DEFAULT_PROFILES = new Set(["worker", "debugger", "rev
23
23
 
24
24
  const CLAUDE_DISALLOWED_TOOLS_ARG = /^--(?:disallowedTools|disallowed-tools)(?:=(.*))?$/;
25
25
 
26
- /** Effective #2453 denylist for this launch: a profile-configured array REPLACES the default,
26
+ /** Effective denylist for this launch: a profile-configured array REPLACES the default,
27
27
  * `null` opts the profile out entirely, absent falls back to the default — and only for the
28
28
  * coding/review profiles. Resolves the profile via the established
29
29
  * `agentProfile?.name || profile` pattern. */
@@ -41,12 +41,12 @@ export function claudeProfileDisallowedTools(config: Pick<RunnerSpawnConfig, "pr
41
41
  }
42
42
  const profileName = config.agentProfile?.name || config.profile || "";
43
43
  if (!CLAUDE_CONTEXT_TRIM_DEFAULT_PROFILES.has(profileName)) return [];
44
- // A profile that switches the Artifact or Workflow tool back on (#3171) gets it.
44
+ // A profile that switches the Artifact or Workflow tool back on gets it.
45
45
  const harness = config.agentProfile ? claudeHarnessOptions(config) : CLAUDE_HARNESS_DEFAULTS;
46
46
  return CLAUDE_CONTEXT_TRIM_DISALLOWED_TOOLS.filter((tool) => tool === "Workflow" ? !harness.workflows : !tool.startsWith("Artifact") || !harness.artifacts);
47
47
  }
48
48
 
49
- // ── #3171 — harness context trim: Claude Code built-ins Relay agents never use ──────────────────
49
+ // ── — harness context trim: Claude Code built-ins Relay agents never use ──────────────────
50
50
  export type ClaudeAgentTypes = NonNullable<NonNullable<AgentProfileProviderOptions["claude"]>["agentTypes"]>;
51
51
  const CLAUDE_AGENT_TYPES: readonly ClaudeAgentTypes[] = ["all", "general-purpose", "none"];
52
52
  export interface ClaudeHarnessOptions {
@@ -146,7 +146,7 @@ function splitDisallowedToolsList(value: string): string[] {
146
146
  return value.split(",").map((name) => name.trim()).filter(Boolean);
147
147
  }
148
148
 
149
- /** Appends the profile's #2453 denylist to the launch args, merging with any inherited
149
+ /** Appends the profile's denylist to the launch args, merging with any inherited
150
150
  * --disallowedTools entries into ONE canonical trailing occurrence (union, never clobber).
151
151
  * No-op (args returned as-is) when the profile resolves no denylist. The single launch seam
152
152
  * for this trim is ClaudeAdapter.buildSpawnArgs.
@@ -156,7 +156,7 @@ function splitDisallowedToolsList(value: string): string[] {
156
156
  * launch would eat the prompt as a deny value (silent no-prompt launch). The `=` form
157
157
  * terminates the flag so following positionals survive. */
158
158
  export function claudeProfileDisallowedToolsArgs(args: string[], config: Pick<RunnerSpawnConfig, "harnessSubagents" | "profile" | "agentProfile">): string[] {
159
- // #3024 — a profile's switched-off web tools are hidden whatever its denylist says.
159
+ // a profile's switched-off web tools are hidden whatever its denylist says.
160
160
  const deny = [...(harnessSubagentsEnabled(config) ? [] : ["Agent", "Task", "TeamCreate", "TeamDelete", "SendMessage"]), ...claudeProfileDisallowedTools(config), ...claudeHarnessTrim(config).deny, ...claudeDisallowedWebTools(config)];
161
161
  if (!deny.length) return args;
162
162
  const { kept, inherited } = partitionClaudeDisallowedToolsArgs(args);
@@ -32,11 +32,11 @@ export interface TurnStep {
32
32
  label?: string;
33
33
  category?: ToolCallCategory;
34
34
  occurredAt?: number;
35
- /** #2437 — redacted, size-capped tool input, only set for type "tool". */
35
+ /** redacted, size-capped tool input, only set for type "tool". */
36
36
  params?: unknown;
37
37
  /** The native tool_use id, only set for type "tool"; pairs the call with its tool_result. */
38
38
  toolUseId?: string;
39
- /** #3411 — absolute file paths the tool reads or edits, only set for type "tool". */
39
+ /** absolute file paths the tool reads or edits, only set for type "tool". */
40
40
  paths?: string[];
41
41
  }
42
42
 
@@ -47,7 +47,7 @@ export interface TranscriptMessage {
47
47
  // Assistant entries carry the model id and the API-reported token usage for
48
48
  // the turn. `usage.{input,cache_creation_input,cache_read_input}_tokens` sum to
49
49
  // the same context-size figure the status-line probe reports — read here so the
50
- // runner can keep context stats advancing every turn without the probe (#1512).
50
+ // runner can keep context stats advancing every turn without the probe.
51
51
  model?: string;
52
52
  usage?: TranscriptUsage;
53
53
  }
@@ -59,7 +59,7 @@ export interface TranscriptUsage {
59
59
  output_tokens?: number;
60
60
  }
61
61
 
62
- /** Fresh, per-turn context usage read straight from the transcript (#1512). */
62
+ /** Fresh, per-turn context usage read straight from the transcript. */
63
63
  export interface TranscriptContextUsage {
64
64
  /** input + cache-creation + cache-read tokens — the context size sent this turn. */
65
65
  tokensUsed: number;
@@ -80,7 +80,7 @@ interface TranscriptEntry {
80
80
  // sidechain entries to keep a subagent's reasoning/tools/responses from
81
81
  // leaking into the parent agent's chat. Insights parsers (collectClaudeSession-
82
82
  // Events/countSubstantiveTurns) intentionally do NOT filter — changing them
83
- // would shift the #184/#185 baselines, a separate concern.
83
+ // would shift the baselines, a separate concern.
84
84
  isSidechain?: boolean;
85
85
  // Every entry carries its own `uuid` and its `parentUuid` (the entry it was
86
86
  // appended after), forming a causal chain for the whole session. A `user`-type
@@ -113,7 +113,7 @@ function isRealUserPrompt(entry: TranscriptEntry): boolean {
113
113
  return blocks(entry.message).some((b) => b.type === "text" && Boolean(b.text?.trim()));
114
114
  }
115
115
 
116
- // #2840 — `closingOnly` keeps just the text after the turn's last tool call (the closing message,
116
+ // `closingOnly` keeps just the text after the turn's last tool call (the closing message,
117
117
  // without narration the reasoning tail already mirrored); a turn ending on a tool keeps its last text.
118
118
  class AssistantTurnText {
119
119
  private texts: string[] = [];
@@ -282,7 +282,7 @@ interface QueueOperationEntry extends TranscriptEntry {
282
282
  }
283
283
 
284
284
  /**
285
- * #2919 — prompts left in Claude's input queue at the end of `jsonl`: a mid-turn prompt is `enqueue`d,
285
+ * prompts left in Claude's input queue at the end of `jsonl`: a mid-turn prompt is `enqueue`d,
286
286
  * then `remove`d when a tool boundary absorbs it, or `dequeue`d (every queued prompt at once) to run as
287
287
  * the next turn after the Stop. So a dequeue or a new promptId empties the queue.
288
288
  */
@@ -323,13 +323,13 @@ function canonicalJson(value: unknown): string {
323
323
 
324
324
  /**
325
325
  * True when the transcript already contains the exact assistant tool_use block that
326
- * triggered a PreToolUse hook — the settle-poll anchor (#1116). The hook payload's own
326
+ * triggered a PreToolUse hook — the settle-poll anchor. The hook payload's own
327
327
  * `tool_name`/`tool_input` are the precise call that fired it, so matching them against
328
328
  * the transcript's tool_use blocks (name + structural input equality) is exact, unlike
329
329
  * guessing from transcript shape alone. Claude's JSONL flush is async/bursty and can
330
330
  * lag well behind the hook firing, so the entry backing the hook's own call may still be
331
331
  * missing from disk the instant the hook runs — this is what the settle-poll waits for.
332
- * #1086 should adopt this same anchor for its own turn-final settle marker rather than
332
+ * should adopt this same anchor for its own turn-final settle marker rather than
333
333
  * inventing a second one.
334
334
  */
335
335
  export function transcriptHasToolUseAnchor(jsonl: string, toolName: string, toolInput: unknown): boolean {
@@ -357,7 +357,7 @@ export function transcriptHasToolUseAnchor(jsonl: string, toolName: string, tool
357
357
  * transcriptHasToolUseAnchor above). Used to stamp a resolved permission prompt with the
358
358
  * tool call's real event time — a hook's own wall-clock receipt time can end up earlier than
359
359
  * the entry the provider eventually flushes for that same call, which otherwise sorts the
360
- * resolved prompt ahead of the narration that led up to it (#1185).
360
+ * resolved prompt ahead of the narration that led up to it.
361
361
  */
362
362
  export function transcriptToolUseOccurredAt(jsonl: string, toolName: string, toolInput: unknown): number | undefined {
363
363
  const wantInput = canonicalJson(toolInput ?? {});
@@ -461,7 +461,7 @@ export class LatestTurnStepAccumulator {
461
461
  }
462
462
  }
463
463
 
464
- /** Narration, reasoning and tool steps of one assistant message, shared by the transcript tail and the headless stream (#2771). */
464
+ /** Narration, reasoning and tool steps of one assistant message, shared by the transcript tail and the headless stream. */
465
465
  export function claudeAssistantSteps(message: TranscriptMessage | undefined, occurredAt?: number): TurnStep[] {
466
466
  const steps: TurnStep[] = [];
467
467
  for (const b of blocks(message)) {
@@ -477,7 +477,7 @@ export function claudeAssistantSteps(message: TranscriptMessage | undefined, occ
477
477
  return steps;
478
478
  }
479
479
 
480
- // #3411 — Claude's file tools and the input field naming their file. Keyed on the tool name, not the
480
+ // Claude's file tools and the input field naming their file. Keyed on the tool name, not the
481
481
  // category: MultiEdit is "generic". Claude's file tools take absolute paths only.
482
482
  const CLAUDE_TOOL_PATH_FIELDS: Record<string, string> = {
483
483
  Read: "file_path",
@@ -493,7 +493,7 @@ export function claudeToolPaths(name: string, input: Record<string, unknown> | u
493
493
  return field && input ? absoluteToolPaths([input[field]]) : undefined;
494
494
  }
495
495
 
496
- /** The raw PostToolUse payload uses the same path contract as transcript tools (#3646). */
496
+ /** The raw PostToolUse payload uses the same path contract as transcript tools. */
497
497
  export function claudeToolHookPaths(input: unknown): string[] | undefined {
498
498
  return isRecord(input) && typeof input.tool_name === "string"
499
499
  ? claudeToolPaths(input.tool_name, isRecord(input.tool_input) ? input.tool_input : undefined) : undefined;
@@ -529,7 +529,7 @@ function transcriptEntryOccurredAt(entry: TranscriptEntry): number | undefined {
529
529
  * Stable dedup keys for a turn's steps, in order. Each key is salted with how many
530
530
  * identical (type,label,text) steps preceded it in the same window — so running the
531
531
  * same tool twice with identical input within a turn yields two distinct keys and
532
- * both show in the activity trace (#265). Keying on occurrence-within-window rather
532
+ * both show in the activity trace. Keying on occurrence-within-window rather
533
533
  * than raw transcript index keeps the reasoning tailer idempotent when the "latest
534
534
  * turn" window shrinks/resets mid-poll: a surviving step recomputes to the same or a
535
535
  * lower occurrence, so an already-emitted step never re-fires.
@@ -544,7 +544,7 @@ export function stepDedupKeys(steps: TurnStep[]): string[] {
544
544
  });
545
545
  }
546
546
 
547
- // #1498: Claude's native tool names → the provider-independent category taxonomy. Tools with
547
+ // Claude's native tool names → the provider-independent category taxonomy. Tools with
548
548
  // no dedicated category (Grep, Glob, LS, WebFetch, WebSearch, ...) fall to "generic" rather than
549
549
  // being force-fit into a category that doesn't really describe them — the fallback exists
550
550
  // precisely so nothing is hidden from the dashboard's activity trace.
@@ -560,7 +560,7 @@ const CLAUDE_TOOL_CATEGORIES: Record<string, ToolCallCategory> = {
560
560
  ToolSearch: "mcp-tool-search",
561
561
  };
562
562
 
563
- /** Map a Claude tool_use name onto the provider-independent tool-call category (#1498). */
563
+ /** Map a Claude tool_use name onto the provider-independent tool-call category. */
564
564
  export function claudeToolCategory(name: string): ToolCallCategory {
565
565
  if (name.startsWith("mcp__")) return "mcp-tool-call";
566
566
  return CLAUDE_TOOL_CATEGORIES[name] ?? "generic";
@@ -575,7 +575,7 @@ export function summarizeToolUse(name: string, input: Record<string, unknown> |
575
575
  return clipToolSummary(summary);
576
576
  }
577
577
 
578
- // --- Insights #184: context-gathering ratio (epic #183, docs/self-improvement.md) ---
578
+ // --- Insights: context-gathering ratio ---
579
579
  //
580
580
  // Computed mechanically from the whole-session transcript at session end — no model
581
581
  // involvement, so it costs zero agent tokens and the agent can't game it. The ratio is
@@ -584,7 +584,7 @@ export function summarizeToolUse(name: string, input: Record<string, unknown> |
584
584
 
585
585
  /**
586
586
  * Normalize a full Claude transcript into the provider-agnostic `SessionEvent` stream
587
- * (#183/#184). The classifier and ratio math live in `session-insights.ts` and are shared
587
+ * The classifier and ratio math live in `session-insights.ts` and are shared
588
588
  * across providers; this only knows the Claude JSONL shape. Events are emitted in
589
589
  * transcript order so `leadingGather` is meaningful.
590
590
  */
@@ -628,7 +628,7 @@ export function analyzeSession(jsonl: string): SessionAnalysis | null {
628
628
  return computeContextRatio(collectClaudeSessionEvents(jsonl));
629
629
  }
630
630
 
631
- /** Count substantive assistant turns — used by the #185 introspection gate. */
631
+ /** Count substantive assistant turns — used by the introspection gate. */
632
632
  export function countSubstantiveTurns(jsonl: string): number {
633
633
  let turns = 0;
634
634
  for (const line of jsonl.split("\n")) {
@@ -650,7 +650,7 @@ export function countSubstantiveTurns(jsonl: string): number {
650
650
  }
651
651
 
652
652
  // Walk the transcript from the end and return the most recent root-session
653
- // assistant turn's token usage (#1512). This is the SAME input+cache token sum
653
+ // assistant turn's token usage. This is the SAME input+cache token sum
654
654
  // the Claude status-line probe reports, but read directly from the transcript —
655
655
  // which the Stop hook hands the runner every turn — so context stats keep
656
656
  // advancing across compact/clear/native-resume even when the status-line probe
@@ -697,7 +697,7 @@ export function sumUsageTokens(usage: TranscriptUsage): number | undefined {
697
697
  return seen ? total : undefined;
698
698
  }
699
699
 
700
- // #2482 — the token-usage spine's capture parser. Where extractLatestContextUsage
700
+ // the token-usage spine's capture parser. Where extractLatestContextUsage
701
701
  // collapses a turn's usage into one context-size sum, this sibling keeps the RAW
702
702
  // per-entry breakdown the spine records, one record per assistant transcript entry:
703
703
  // dedupeKey = the entry `uuid` (entries never move once written, so the uuid is the
@@ -716,7 +716,7 @@ export interface TranscriptTokenUsageEntry {
716
716
  cacheReadTokens: number;
717
717
  cacheWriteTokens: number;
718
718
  occurredAt: number;
719
- /** #3351 — an API assistant entry without a usage block: spend happened, counts are unknown. */
719
+ /** an API assistant entry without a usage block: spend happened, counts are unknown. */
720
720
  usageStatus?: "unknown";
721
721
  }
722
722
 
@@ -758,7 +758,7 @@ function usageEntryFromTranscriptEntry(entry: TranscriptEntry, byUuid: ReadonlyM
758
758
  }
759
759
 
760
760
  /**
761
- * Incremental #2482 extractor: feeds transcript lines one at a time so a caller can
761
+ * Incremental extractor: feeds transcript lines one at a time so a caller can
762
762
  * consume only newly-appended data without re-walking the file. promptId is resolved
763
763
  * against the entries THIS instance has seen (the uuid→entry map) — feed a whole file
764
764
  * for whole-transcript resolution, or feed only an appended tail and accept that an
@@ -794,7 +794,7 @@ function usageCount(value: number | undefined): number {
794
794
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
795
795
  }
796
796
 
797
- /** Claude names its transcript file `<sessionId>.jsonl` (#1235), so the provider's own
797
+ /** Claude names its transcript file `<sessionId>.jsonl`, so the provider's own
798
798
  * session uuid is recoverable from the path even when the status probe is silent. */
799
799
  export function claudeSessionIdFromTranscriptPath(transcriptPath: string): string {
800
800
  const file = transcriptPath.split(/[\\/]/).pop() ?? "";