@gethmy/agent 1.10.4 → 1.10.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 (4) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +371 -225
  3. package/dist/index.js +371 -225
  4. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -396,8 +396,8 @@ var init_types = __esm(() => {
396
396
  postSummary: true
397
397
  },
398
398
  claude: {
399
- model: "opus",
400
- escalateModel: "claude-fable-5",
399
+ model: "claude-opus-4-8",
400
+ escalateModel: "claude-opus-4-8",
401
401
  escalateAfterAttempts: 2,
402
402
  tiers: {
403
403
  simple: "claude-haiku-4-5",
@@ -2081,8 +2081,127 @@ var init_git_diff_stat = __esm(() => {
2081
2081
  init_log();
2082
2082
  });
2083
2083
 
2084
+ // src/project-type.ts
2085
+ import { execFileSync as execFileSync6 } from "node:child_process";
2086
+ import { existsSync as existsSync4, readdirSync } from "node:fs";
2087
+ function detect(dir) {
2088
+ const cached2 = _cache.get(dir);
2089
+ if (cached2)
2090
+ return cached2;
2091
+ const result = detectUncached(dir);
2092
+ _cache.set(dir, result);
2093
+ log.info(TAG11, `Detected project type in ${dir}: ${result.kind}`);
2094
+ return result;
2095
+ }
2096
+ function detectUncached(dir) {
2097
+ if (existsSync4(`${dir}/package.json`))
2098
+ return { kind: "node" };
2099
+ if (existsSync4(`${dir}/Package.swift`))
2100
+ return { kind: "swift-spm" };
2101
+ const entries = safeReaddir(dir);
2102
+ const workspace = entries.find((e) => e.endsWith(".xcworkspace"));
2103
+ if (workspace) {
2104
+ return {
2105
+ kind: "swift-xcode",
2106
+ xcodeContainer: `${dir}/${workspace}`,
2107
+ xcodeIsWorkspace: true
2108
+ };
2109
+ }
2110
+ const project = entries.find((e) => e.endsWith(".xcodeproj"));
2111
+ if (project) {
2112
+ return {
2113
+ kind: "swift-xcode",
2114
+ xcodeContainer: `${dir}/${project}`,
2115
+ xcodeIsWorkspace: false
2116
+ };
2117
+ }
2118
+ return { kind: "unknown" };
2119
+ }
2120
+ function safeReaddir(dir) {
2121
+ try {
2122
+ return readdirSync(dir);
2123
+ } catch {
2124
+ return [];
2125
+ }
2126
+ }
2127
+ function buildCommand(dir) {
2128
+ const pt = detect(dir);
2129
+ switch (pt.kind) {
2130
+ case "node": {
2131
+ const [cmd, args] = spawnRunArgs("build");
2132
+ return { cmd, args };
2133
+ }
2134
+ case "swift-spm":
2135
+ return { cmd: "swift", args: ["build"] };
2136
+ case "swift-xcode":
2137
+ return xcodeBuildCommand(pt);
2138
+ case "unknown":
2139
+ return null;
2140
+ }
2141
+ }
2142
+ function lintCommand(dir) {
2143
+ const pt = detect(dir);
2144
+ switch (pt.kind) {
2145
+ case "node": {
2146
+ const [cmd, args] = spawnRunArgs("lint");
2147
+ return { cmd, args };
2148
+ }
2149
+ case "swift-spm":
2150
+ case "swift-xcode":
2151
+ case "unknown":
2152
+ return null;
2153
+ }
2154
+ }
2155
+ function supportsDevServer(dir) {
2156
+ return detect(dir).kind === "node";
2157
+ }
2158
+ function xcodeBuildCommand(pt) {
2159
+ const container = pt.xcodeContainer;
2160
+ if (!container)
2161
+ return null;
2162
+ const scheme = resolveXcodeScheme(pt);
2163
+ if (!scheme) {
2164
+ log.warn(TAG11, "Could not resolve an Xcode scheme — skipping build (best-effort)");
2165
+ return null;
2166
+ }
2167
+ const containerFlag = pt.xcodeIsWorkspace ? "-workspace" : "-project";
2168
+ return {
2169
+ cmd: "xcodebuild",
2170
+ args: [
2171
+ containerFlag,
2172
+ container,
2173
+ "-scheme",
2174
+ scheme,
2175
+ "-destination",
2176
+ "generic/platform=iOS",
2177
+ "CODE_SIGNING_ALLOWED=NO",
2178
+ "build"
2179
+ ]
2180
+ };
2181
+ }
2182
+ function resolveXcodeScheme(pt) {
2183
+ if (!pt.xcodeContainer)
2184
+ return null;
2185
+ const flag = pt.xcodeIsWorkspace ? "-workspace" : "-project";
2186
+ try {
2187
+ const out = execFileSync6("xcodebuild", ["-list", "-json", flag, pt.xcodeContainer], { encoding: "utf-8", timeout: 30000, stdio: "pipe" });
2188
+ const parsed = JSON.parse(out);
2189
+ const schemes = pt.xcodeIsWorkspace ? parsed.workspace?.schemes ?? [] : parsed.project?.schemes ?? [];
2190
+ return schemes[0] ?? null;
2191
+ } catch (err) {
2192
+ log.warn(TAG11, `xcodebuild -list failed: ${err instanceof Error ? err.message : err}`);
2193
+ return null;
2194
+ }
2195
+ }
2196
+ var TAG11 = "project-type", _cache;
2197
+ var init_project_type = __esm(() => {
2198
+ init_log();
2199
+ init_pm();
2200
+ _cache = new Map;
2201
+ });
2202
+
2084
2203
  // src/verification.ts
2085
- import { execFileSync as execFileSync6, spawn } from "node:child_process";
2204
+ import { execFileSync as execFileSync7, spawn } from "node:child_process";
2086
2205
  async function runVerification(worktreePath, config, workerId) {
2087
2206
  const result = {
2088
2207
  passed: true,
@@ -2091,39 +2210,43 @@ async function runVerification(worktreePath, config, workerId) {
2091
2210
  reviewFindings: []
2092
2211
  };
2093
2212
  if (config.verification.build) {
2094
- log.info(TAG11, `[worker:${workerId}] Running build...`);
2213
+ log.info(TAG12, `[worker:${workerId}] Running build...`);
2095
2214
  result.buildErrors = runBuild(worktreePath, config.verification.timeout);
2096
2215
  if (result.buildErrors.length > 0) {
2097
- log.warn(TAG11, `[worker:${workerId}] Build failed with ${result.buildErrors.length} error(s)`);
2216
+ log.warn(TAG12, `[worker:${workerId}] Build failed with ${result.buildErrors.length} error(s)`);
2098
2217
  result.passed = false;
2099
2218
  } else {
2100
- log.info(TAG11, `[worker:${workerId}] Build passed`);
2219
+ log.info(TAG12, `[worker:${workerId}] Build passed`);
2101
2220
  }
2102
2221
  }
2103
2222
  if (config.verification.lint) {
2104
- log.info(TAG11, `[worker:${workerId}] Running lint...`);
2223
+ log.info(TAG12, `[worker:${workerId}] Running lint...`);
2105
2224
  result.lintWarnings = runLint(worktreePath, config.verification.timeout);
2106
2225
  if (result.lintWarnings.length > 0) {
2107
- log.warn(TAG11, `[worker:${workerId}] Lint found ${result.lintWarnings.length} issue(s)`);
2226
+ log.warn(TAG12, `[worker:${workerId}] Lint found ${result.lintWarnings.length} issue(s)`);
2108
2227
  } else {
2109
- log.info(TAG11, `[worker:${workerId}] Lint passed`);
2228
+ log.info(TAG12, `[worker:${workerId}] Lint passed`);
2110
2229
  }
2111
2230
  }
2112
2231
  if (config.verification.deepReview) {
2113
- log.info(TAG11, `[worker:${workerId}] Running deep review...`);
2232
+ log.info(TAG12, `[worker:${workerId}] Running deep review...`);
2114
2233
  result.reviewFindings = await runDeepReview(worktreePath, config, workerId);
2115
2234
  if (result.reviewFindings.length > 0) {
2116
- log.warn(TAG11, `[worker:${workerId}] Deep review found ${result.reviewFindings.length} finding(s)`);
2235
+ log.warn(TAG12, `[worker:${workerId}] Deep review found ${result.reviewFindings.length} finding(s)`);
2117
2236
  } else {
2118
- log.info(TAG11, `[worker:${workerId}] Deep review passed`);
2237
+ log.info(TAG12, `[worker:${workerId}] Deep review passed`);
2119
2238
  }
2120
2239
  }
2121
2240
  return result;
2122
2241
  }
2123
2242
  function runBuild(worktreePath, timeout) {
2243
+ const command = buildCommand(worktreePath);
2244
+ if (!command) {
2245
+ log.warn(TAG12, `No known build toolchain for ${worktreePath} — skipping build`);
2246
+ return [];
2247
+ }
2124
2248
  try {
2125
- const [cmd, args] = spawnRunArgs("build");
2126
- execFileSync6(cmd, args, {
2249
+ execFileSync7(command.cmd, command.args, {
2127
2250
  cwd: worktreePath,
2128
2251
  timeout,
2129
2252
  stdio: "pipe"
@@ -2134,9 +2257,13 @@ function runBuild(worktreePath, timeout) {
2134
2257
  }
2135
2258
  }
2136
2259
  function runLint(worktreePath, timeout) {
2260
+ const command = lintCommand(worktreePath);
2261
+ if (!command) {
2262
+ log.info(TAG12, `No lint step for detected toolchain in ${worktreePath} — skipping lint`);
2263
+ return [];
2264
+ }
2137
2265
  try {
2138
- const [cmd, args] = spawnRunArgs("lint");
2139
- execFileSync6(cmd, args, {
2266
+ execFileSync7(command.cmd, command.args, {
2140
2267
  cwd: worktreePath,
2141
2268
  timeout,
2142
2269
  stdio: "pipe"
@@ -2147,6 +2274,10 @@ function runLint(worktreePath, timeout) {
2147
2274
  }
2148
2275
  }
2149
2276
  async function runDeepReview(worktreePath, config, workerId) {
2277
+ if (!supportsDevServer(worktreePath)) {
2278
+ log.info(TAG12, `[worker:${workerId}] Detected non-web toolchain — skipping deep review`);
2279
+ return [];
2280
+ }
2150
2281
  const port = config.verification.devServerBasePort + workerId;
2151
2282
  let devServer = null;
2152
2283
  try {
@@ -2159,12 +2290,12 @@ async function runDeepReview(worktreePath, config, workerId) {
2159
2290
  await waitForDevServer(devServer, 30000);
2160
2291
  await probeDevServer(port);
2161
2292
  } catch (err) {
2162
- log.error(TAG11, `Dev server did not become ready: ${err instanceof Error ? err.message : err}`);
2293
+ log.error(TAG12, `Dev server did not become ready: ${err instanceof Error ? err.message : err}`);
2163
2294
  return [];
2164
2295
  }
2165
2296
  let diff = "";
2166
2297
  try {
2167
- diff = execFileSync6("git", ["diff", `origin/${config.worktree.baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8", timeout: 30000 });
2298
+ diff = execFileSync7("git", ["diff", `origin/${config.worktree.baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8", timeout: 30000 });
2168
2299
  } catch {
2169
2300
  diff = "(unable to retrieve diff)";
2170
2301
  }
@@ -2181,7 +2312,7 @@ async function runDeepReview(worktreePath, config, workerId) {
2181
2312
  ].join(`
2182
2313
  `);
2183
2314
  const leanSources = config.claude.leanSettingSources;
2184
- const output = execFileSync6("claude", [
2315
+ const output = execFileSync7("claude", [
2185
2316
  "--print",
2186
2317
  "--model",
2187
2318
  "sonnet",
@@ -2198,7 +2329,7 @@ async function runDeepReview(worktreePath, config, workerId) {
2198
2329
  });
2199
2330
  return parseReviewFindings(output);
2200
2331
  } catch (err) {
2201
- log.error(TAG11, `Deep review failed: ${err instanceof Error ? err.message : err}`);
2332
+ log.error(TAG12, `Deep review failed: ${err instanceof Error ? err.message : err}`);
2202
2333
  return [];
2203
2334
  } finally {
2204
2335
  if (devServer && !devServer.killed) {
@@ -2234,8 +2365,8 @@ function attemptAutoFix(worktreePath, config, errors) {
2234
2365
  "--",
2235
2366
  fixPrompt
2236
2367
  ];
2237
- log.info(TAG11, "Spawning Claude for auto-fix...");
2238
- execFileSync6("claude", args, {
2368
+ log.info(TAG12, "Spawning Claude for auto-fix...");
2369
+ execFileSync7("claude", args, {
2239
2370
  cwd: worktreePath,
2240
2371
  timeout: config.verification.timeout,
2241
2372
  stdio: "pipe"
@@ -2265,7 +2396,7 @@ async function reportFindings(client, cardId, result, recovery) {
2265
2396
  try {
2266
2397
  await client.createSubtask(cardId, title);
2267
2398
  } catch (err) {
2268
- log.error(TAG11, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
2399
+ log.error(TAG12, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
2269
2400
  }
2270
2401
  }));
2271
2402
  if (overflow > 0) {
@@ -2273,7 +2404,7 @@ async function reportFindings(client, cardId, result, recovery) {
2273
2404
  await client.createSubtask(cardId, `...and ${overflow} more issues`);
2274
2405
  } catch {}
2275
2406
  }
2276
- log.info(TAG11, `Reported ${Math.min(items.length, maxSubtasks)} finding(s) as subtasks on card ${cardId}`);
2407
+ log.info(TAG12, `Reported ${Math.min(items.length, maxSubtasks)} finding(s) as subtasks on card ${cardId}`);
2277
2408
  }
2278
2409
  function parseErrorOutput(err) {
2279
2410
  const stderr = err?.stderr?.toString() ?? "";
@@ -2357,10 +2488,11 @@ async function probeDevServer(port, timeoutMs = 5000) {
2357
2488
  clearTimeout(timer);
2358
2489
  }
2359
2490
  }
2360
- var TAG11 = "verification", DevServerReadinessError;
2491
+ var TAG12 = "verification", DevServerReadinessError;
2361
2492
  var init_verification = __esm(() => {
2362
2493
  init_log();
2363
2494
  init_pm();
2495
+ init_project_type();
2364
2496
  DevServerReadinessError = class DevServerReadinessError extends Error {
2365
2497
  constructor(message) {
2366
2498
  super(message);
@@ -2370,7 +2502,7 @@ var init_verification = __esm(() => {
2370
2502
  });
2371
2503
 
2372
2504
  // src/completion.ts
2373
- import { execFileSync as execFileSync7 } from "node:child_process";
2505
+ import { execFileSync as execFileSync8 } from "node:child_process";
2374
2506
  function formatTokenCount(tokens) {
2375
2507
  if (tokens >= 1e6)
2376
2508
  return `${(tokens / 1e6).toFixed(1)}M`;
@@ -2400,7 +2532,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2400
2532
  };
2401
2533
  const hasCommits = checkHasCommits(worktreePath, config.worktree.baseBranch);
2402
2534
  if (!hasCommits) {
2403
- log.warn(TAG12, `No commits on branch ${branchName} — skipping completion`);
2535
+ log.warn(TAG13, `No commits on branch ${branchName} — skipping completion`);
2404
2536
  await client.endAgentSession(card.id, {
2405
2537
  status: "completed",
2406
2538
  progressPercent: 100,
@@ -2409,13 +2541,13 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2409
2541
  cleanupWorktree(worktreePath, branchName);
2410
2542
  return true;
2411
2543
  }
2412
- log.info(TAG12, `Pushing branch ${branchName} (pre-verify)...`);
2544
+ log.info(TAG13, `Pushing branch ${branchName} (pre-verify)...`);
2413
2545
  let lastPushedSha = null;
2414
2546
  try {
2415
2547
  pushBranch(branchName, worktreePath);
2416
2548
  lastPushedSha = readHeadSha(worktreePath);
2417
2549
  } catch (err) {
2418
- log.error(TAG12, `pre-verify push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2550
+ log.error(TAG13, `pre-verify push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2419
2551
  }
2420
2552
  const recoveryUrl = lastPushedSha ? getBranchWebUrl(branchName, worktreePath) : null;
2421
2553
  if (config.verification.enabled) {
@@ -2430,7 +2562,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2430
2562
  let autoFixAttempts = 0;
2431
2563
  if (!result.passed && config.verification.autoFix) {
2432
2564
  for (let attempt = 0;attempt < config.verification.maxFixAttempts; attempt++) {
2433
- log.info(TAG12, `Auto-fix attempt ${attempt + 1}/${config.verification.maxFixAttempts}`);
2565
+ log.info(TAG13, `Auto-fix attempt ${attempt + 1}/${config.verification.maxFixAttempts}`);
2434
2566
  await client.updateAgentProgress(card.id, {
2435
2567
  agentIdentifier: agentIdentifier(workerId),
2436
2568
  agentName: AGENT_NAME,
@@ -2443,14 +2575,14 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2443
2575
  result = await runVerification(worktreePath, config, workerId);
2444
2576
  autoFixAttempts = attempt + 1;
2445
2577
  if (result.passed) {
2446
- log.info(TAG12, `Auto-fix succeeded on attempt ${attempt + 1}`);
2578
+ log.info(TAG13, `Auto-fix succeeded on attempt ${attempt + 1}`);
2447
2579
  const sha = readHeadSha(worktreePath);
2448
2580
  if (sha && sha !== lastPushedSha) {
2449
2581
  try {
2450
2582
  pushBranch(branchName, worktreePath);
2451
2583
  lastPushedSha = sha;
2452
2584
  } catch (err) {
2453
- log.warn(TAG12, `post-fix push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2585
+ log.warn(TAG13, `post-fix push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2454
2586
  }
2455
2587
  }
2456
2588
  break;
@@ -2459,14 +2591,14 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2459
2591
  }
2460
2592
  verificationResult = result;
2461
2593
  if (!result.passed) {
2462
- log.warn(TAG12, `Verification failed for #${card.short_id} — reporting findings`);
2594
+ log.warn(TAG13, `Verification failed for #${card.short_id} — reporting findings`);
2463
2595
  const failSha = readHeadSha(worktreePath);
2464
2596
  if (failSha && failSha !== lastPushedSha) {
2465
2597
  try {
2466
2598
  pushBranch(branchName, worktreePath);
2467
2599
  lastPushedSha = failSha;
2468
2600
  } catch (err) {
2469
- log.warn(TAG12, `post-fail push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2601
+ log.warn(TAG13, `post-fail push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
2470
2602
  }
2471
2603
  }
2472
2604
  const failureSummary = buildVerificationFailureSummary(result, autoFixAttempts);
@@ -2477,7 +2609,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2477
2609
  recoveryBranch: branchName
2478
2610
  });
2479
2611
  } catch (err) {
2480
- log.debug(TAG12, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
2612
+ log.debug(TAG13, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
2481
2613
  }
2482
2614
  await reportFindings(client, card.id, result, lastPushedSha ? { branchName, branchUrl: recoveryUrl } : null);
2483
2615
  await moveCardToColumn(client, card, config.verification.failColumn);
@@ -2491,7 +2623,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2491
2623
  cleanupWorktree(worktreePath, branchName);
2492
2624
  return false;
2493
2625
  }
2494
- log.info(TAG12, `Verification passed for #${card.short_id}`);
2626
+ log.info(TAG13, `Verification passed for #${card.short_id}`);
2495
2627
  }
2496
2628
  let prUrl = null;
2497
2629
  if (config.completion.createPR) {
@@ -2504,7 +2636,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2504
2636
  try {
2505
2637
  await onMovedToCompletion(card);
2506
2638
  } catch (err) {
2507
- log.warn(TAG12, `successor promotion failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
2639
+ log.warn(TAG13, `successor promotion failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
2508
2640
  }
2509
2641
  }
2510
2642
  }
@@ -2538,7 +2670,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
2538
2670
  });
2539
2671
  }
2540
2672
  cleanupWorktree(worktreePath, branchName);
2541
- log.info(TAG12, `Completion done for #${card.short_id}${prUrl ? ` — PR: ${prUrl}` : ""}`);
2673
+ log.info(TAG13, `Completion done for #${card.short_id}${prUrl ? ` — PR: ${prUrl}` : ""}`);
2542
2674
  return true;
2543
2675
  }
2544
2676
  function buildVerificationFailureSummary(result, autoFixAttempts) {
@@ -2558,7 +2690,7 @@ function buildVerificationFailureSummary(result, autoFixAttempts) {
2558
2690
  }
2559
2691
  function readHeadSha(worktreePath) {
2560
2692
  try {
2561
- return execFileSync7("git", ["rev-parse", "HEAD"], {
2693
+ return execFileSync8("git", ["rev-parse", "HEAD"], {
2562
2694
  cwd: worktreePath,
2563
2695
  encoding: "utf-8"
2564
2696
  }).trim();
@@ -2568,7 +2700,7 @@ function readHeadSha(worktreePath) {
2568
2700
  }
2569
2701
  function checkHasCommits(worktreePath, baseBranch) {
2570
2702
  try {
2571
- const count = execFileSync7("git", ["rev-list", "--count", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
2703
+ const count = execFileSync8("git", ["rev-list", "--count", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
2572
2704
  return parseInt(count, 10) > 0;
2573
2705
  } catch {
2574
2706
  return false;
@@ -2577,7 +2709,7 @@ function checkHasCommits(worktreePath, baseBranch) {
2577
2709
  async function postSummary(client, card, branchName, worktreePath, prUrl, baseBranch, sessionStats) {
2578
2710
  let commitLog = "";
2579
2711
  try {
2580
- commitLog = execFileSync7("git", ["log", "--oneline", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
2712
+ commitLog = execFileSync8("git", ["log", "--oneline", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
2581
2713
  } catch {}
2582
2714
  const SUMMARY_MARKER = `---
2583
2715
  **Agent completed**`;
@@ -2622,12 +2754,12 @@ ${commitLog}
2622
2754
  description: baseDesc + parts.join(`
2623
2755
  `)
2624
2756
  });
2625
- log.info(TAG12, `Posted completion summary to #${card.short_id}`);
2757
+ log.info(TAG13, `Posted completion summary to #${card.short_id}`);
2626
2758
  } catch (err) {
2627
- log.error(TAG12, `Failed to post summary: ${err instanceof Error ? err.message : err}`);
2759
+ log.error(TAG13, `Failed to post summary: ${err instanceof Error ? err.message : err}`);
2628
2760
  }
2629
2761
  }
2630
- var TAG12 = "completion";
2762
+ var TAG13 = "completion";
2631
2763
  var init_completion = __esm(() => {
2632
2764
  init_board_helpers();
2633
2765
  init_episode_writer();
@@ -2647,7 +2779,12 @@ function spawnInGroup(command, args, options = {}) {
2647
2779
  return spawn2(command, args, {
2648
2780
  ...options,
2649
2781
  detached: true,
2650
- stdio: options.stdio ?? ["ignore", "pipe", "pipe"]
2782
+ stdio: options.stdio ?? ["ignore", "pipe", "pipe"],
2783
+ env: {
2784
+ ...process.env,
2785
+ ...options.env,
2786
+ CMUX_CLAUDE_HOOKS_DISABLED: "1"
2787
+ }
2651
2788
  });
2652
2789
  }
2653
2790
  function signalGroup(proc, signal) {
@@ -2662,7 +2799,7 @@ function signalGroup(proc, signal) {
2662
2799
  } catch (err) {
2663
2800
  const code = err.code;
2664
2801
  if (code !== "ESRCH") {
2665
- log.warn(TAG13, `signal ${signal} to pgid ${proc.pid} failed: ${err instanceof Error ? err.message : err}`);
2802
+ log.warn(TAG14, `signal ${signal} to pgid ${proc.pid} failed: ${err instanceof Error ? err.message : err}`);
2666
2803
  }
2667
2804
  }
2668
2805
  }
@@ -2687,7 +2824,7 @@ async function terminateGroup(proc, opts) {
2687
2824
  return;
2688
2825
  signalGroup(proc, "SIGKILL");
2689
2826
  }
2690
- var TAG13 = "pgroup";
2827
+ var TAG14 = "pgroup";
2691
2828
  var init_process_group = __esm(() => {
2692
2829
  init_log();
2693
2830
  });
@@ -2790,7 +2927,7 @@ class ProgressTracker {
2790
2927
  }
2791
2928
  onToolStart(name, input) {
2792
2929
  this.toolCallCount++;
2793
- log.debug(TAG14, `Tool: ${name} (count: ${this.toolCallCount}, phase: ${this.phase})`);
2930
+ log.debug(TAG15, `Tool: ${name} (count: ${this.toolCallCount}, phase: ${this.phase})`);
2794
2931
  const filePath = this.extractString(input, "file_path");
2795
2932
  if (filePath) {
2796
2933
  if (EDIT_TOOLS.has(name)) {
@@ -2861,7 +2998,7 @@ class ProgressTracker {
2861
2998
  transitionTo(newPhase) {
2862
2999
  if (PHASE_ORDER[newPhase] <= PHASE_ORDER[this.phase])
2863
3000
  return;
2864
- log.info(TAG14, `Phase: ${this.phase} → ${newPhase}`);
3001
+ log.info(TAG15, `Phase: ${this.phase} → ${newPhase}`);
2865
3002
  this.phase = newPhase;
2866
3003
  this.progress = Math.max(this.progress, PHASES[newPhase].min);
2867
3004
  this.lastAction = "";
@@ -2960,7 +3097,7 @@ class ProgressTracker {
2960
3097
  }
2961
3098
  sendUpdate(currentTask) {
2962
3099
  this.lastUpdateAt = Date.now();
2963
- log.debug(TAG14, `Progress: ${this.progress}% — ${currentTask}`);
3100
+ log.debug(TAG15, `Progress: ${this.progress}% — ${currentTask}`);
2964
3101
  this.client.updateAgentProgress(this.cardId, {
2965
3102
  agentIdentifier: agentIdentifier(this.workerId),
2966
3103
  agentName: AGENT_NAME,
@@ -2977,7 +3114,7 @@ class ProgressTracker {
2977
3114
  modelName: this.lastCost?.modelName,
2978
3115
  numTurns: this.lastCost?.numTurns ?? 0
2979
3116
  }).catch((err) => {
2980
- log.warn(TAG14, `Failed to send progress update: ${err}`);
3117
+ log.warn(TAG15, `Failed to send progress update: ${err}`);
2981
3118
  });
2982
3119
  this.flushActivityLog();
2983
3120
  }
@@ -3018,7 +3155,7 @@ class ProgressTracker {
3018
3155
  toolName: e.toolName ?? undefined
3019
3156
  }))
3020
3157
  }).catch((err) => {
3021
- log.warn(TAG14, `Failed to flush activity log: ${err}`);
3158
+ log.warn(TAG15, `Failed to flush activity log: ${err}`);
3022
3159
  this.logBuffer.unshift(...raw);
3023
3160
  if (this.logBuffer.length > MAX_LOG_BUFFER) {
3024
3161
  this.logBuffer.length = MAX_LOG_BUFFER;
@@ -3049,7 +3186,7 @@ class ProgressTracker {
3049
3186
  return null;
3050
3187
  }
3051
3188
  }
3052
- var TAG14 = "progress-tracker", THROTTLE_MS = 5000, HEARTBEAT_MS = 60000, MAX_TASK_LENGTH = 120, MAX_LOG_BUFFER = 500, MAX_TEXT_BLOCKS = 40, SENTENCE_SPLIT, ACTION_PREFIX, GIT_COMMIT_RE, BUILD_CMD_RE, PHASES, PHASE_ORDER, EDIT_TOOLS, FILE_TOOL_VERBS;
3189
+ var TAG15 = "progress-tracker", THROTTLE_MS = 5000, HEARTBEAT_MS = 60000, MAX_TASK_LENGTH = 120, MAX_LOG_BUFFER = 500, MAX_TEXT_BLOCKS = 40, SENTENCE_SPLIT, ACTION_PREFIX, GIT_COMMIT_RE, BUILD_CMD_RE, PHASES, PHASE_ORDER, EDIT_TOOLS, FILE_TOOL_VERBS;
3053
3190
  var init_progress_tracker = __esm(() => {
3054
3191
  init_log();
3055
3192
  init_types();
@@ -3124,7 +3261,7 @@ function parseReviewOutput(stdout) {
3124
3261
  try {
3125
3262
  const parsed = JSON.parse(raw);
3126
3263
  if (parsed && typeof parsed === "object" && "verdict" in parsed) {
3127
- log.debug(TAG15, "Parsed review output from fenced JSON block");
3264
+ log.debug(TAG16, "Parsed review output from fenced JSON block");
3128
3265
  return extractResult(parsed);
3129
3266
  }
3130
3267
  } catch {}
@@ -3150,21 +3287,21 @@ function parseReviewOutput(stdout) {
3150
3287
  try {
3151
3288
  const parsed = JSON.parse(candidates[i]);
3152
3289
  if (parsed && typeof parsed === "object" && "verdict" in parsed) {
3153
- log.debug(TAG15, "Parsed review output from raw JSON object");
3290
+ log.debug(TAG16, "Parsed review output from raw JSON object");
3154
3291
  return extractResult(parsed);
3155
3292
  }
3156
3293
  } catch {}
3157
3294
  }
3158
3295
  const verdictMatch = stdout.match(/"verdict"\s*:\s*"(approved|rejected)"/i);
3159
3296
  if (verdictMatch) {
3160
- log.warn(TAG15, `Parsed verdict via regex fallback — findings lost (${verdictMatch[1]})`);
3297
+ log.warn(TAG16, `Parsed verdict via regex fallback — findings lost (${verdictMatch[1]})`);
3161
3298
  return {
3162
3299
  verdict: verdictMatch[1].toLowerCase(),
3163
3300
  summary: "Parsed via regex fallback — original JSON was malformed. Check run log.",
3164
3301
  findings: []
3165
3302
  };
3166
3303
  }
3167
- log.warn(TAG15, "Failed to parse review JSON output — returning error verdict (card stays in Review)");
3304
+ log.warn(TAG16, "Failed to parse review JSON output — returning error verdict (card stays in Review)");
3168
3305
  return {
3169
3306
  verdict: "error",
3170
3307
  summary: stdout.slice(0, 500),
@@ -3197,7 +3334,7 @@ async function postReviewComment(client, card, commentType, body) {
3197
3334
  try {
3198
3335
  await client.addComment(card.id, body, { commentType });
3199
3336
  } catch (err) {
3200
- log.error(TAG15, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
3337
+ log.error(TAG16, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
3201
3338
  }
3202
3339
  }
3203
3340
  async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore) {
@@ -3211,11 +3348,11 @@ async function runReviewCompletion(client, card, result, config, worktreePath, b
3211
3348
  const currentCycle = getReviewCycle(freshDesc) + 1;
3212
3349
  const maxCycles = config.review.maxReviewCycles;
3213
3350
  if (result.verdict === "error") {
3214
- log.warn(TAG15, `#${card.short_id} review output unparseable — labelling "${NEED_REVIEW_LABEL}" for manual inspection`);
3351
+ log.warn(TAG16, `#${card.short_id} review output unparseable — labelling "${NEED_REVIEW_LABEL}" for manual inspection`);
3215
3352
  try {
3216
3353
  await addLabelByName(client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
3217
3354
  } catch (err) {
3218
- log.warn(TAG15, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
3355
+ log.warn(TAG16, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
3219
3356
  }
3220
3357
  if (config.review.postFindings) {
3221
3358
  const rawTail = runLogPath ? tailRunLog(runLogPath) : null;
@@ -3258,7 +3395,7 @@ ${runLogTail}
3258
3395
  renameRemoteBranch(branchName, newRef, worktreePath);
3259
3396
  approvedBranch = newRef;
3260
3397
  } catch (err) {
3261
- log.warn(TAG15, `Branch rename failed (continuing on ${branchName}): ${err instanceof Error ? err.message : err}`);
3398
+ log.warn(TAG16, `Branch rename failed (continuing on ${branchName}): ${err instanceof Error ? err.message : err}`);
3262
3399
  }
3263
3400
  }
3264
3401
  if (config.review.createPR && approvedBranch) {
@@ -3285,14 +3422,14 @@ ${runLogTail}
3285
3422
  progressPercent: 100,
3286
3423
  ...buildTokenPayload(sessionStats)
3287
3424
  });
3288
- log.info(TAG15, `#${card.short_id} approved${prUrl ? ` — PR: ${prUrl}` : ""} — labeled "${config.review.approvedLabel}"`);
3425
+ log.info(TAG16, `#${card.short_id} approved${prUrl ? ` — PR: ${prUrl}` : ""} — labeled "${config.review.approvedLabel}"`);
3289
3426
  } else {
3290
3427
  const criticalFindings = result.findings.filter((f) => f.severity === "critical").slice(0, MAX_FINDINGS);
3291
3428
  const majorFindings = result.findings.filter((f) => f.severity === "major").slice(0, MAX_FINDINGS);
3292
3429
  const linkedFindings = [...criticalFindings, ...majorFindings];
3293
3430
  const minorFindings = result.findings.filter((f) => f.severity === "minor").slice(0, MAX_FINDINGS);
3294
3431
  if (currentCycle >= maxCycles) {
3295
- log.warn(TAG15, `#${card.short_id} reached max review cycles (${maxCycles}), moving to Done with note`);
3432
+ log.warn(TAG16, `#${card.short_id} reached max review cycles (${maxCycles}), moving to Done with note`);
3296
3433
  await moveCardToColumn(client, card, config.review.moveToColumn);
3297
3434
  const body = [
3298
3435
  "**Review — needs human review.**",
@@ -3343,7 +3480,7 @@ ${finding.description}${locationLine}`
3343
3480
  await client.addLinkToCard(card.id, newCardId, "relates_to");
3344
3481
  }
3345
3482
  } catch (err) {
3346
- log.error(TAG15, `Failed to create finding card: ${err instanceof Error ? err.message : err}`);
3483
+ log.error(TAG16, `Failed to create finding card: ${err instanceof Error ? err.message : err}`);
3347
3484
  }
3348
3485
  }));
3349
3486
  await Promise.all(minorFindings.map(async (finding) => {
@@ -3351,7 +3488,7 @@ ${finding.description}${locationLine}`
3351
3488
  const title = finding.title.length > 120 ? `${finding.title.slice(0, 117)}...` : finding.title;
3352
3489
  await client.createSubtask(card.id, title);
3353
3490
  } catch (err) {
3354
- log.error(TAG15, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
3491
+ log.error(TAG16, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
3355
3492
  }
3356
3493
  }));
3357
3494
  const baseDesc = stripReviewSummary(freshDesc);
@@ -3359,7 +3496,7 @@ ${finding.description}${locationLine}`
3359
3496
  try {
3360
3497
  await client.updateCard(card.id, { description: updatedDesc });
3361
3498
  } catch (err) {
3362
- log.error(TAG15, `Failed to update review cycle marker: ${err instanceof Error ? err.message : err}`);
3499
+ log.error(TAG16, `Failed to update review cycle marker: ${err instanceof Error ? err.message : err}`);
3363
3500
  }
3364
3501
  const scopeLine = result.scopeCheck ? `Scope: ${result.scopeCheck.status}${result.scopeCheck.notes ? ` — ${result.scopeCheck.notes}` : ""}` : "";
3365
3502
  const body = [
@@ -3375,9 +3512,9 @@ ${finding.description}${locationLine}`
3375
3512
  if (config.planning.enabled && card.plan_id) {
3376
3513
  try {
3377
3514
  await client.updateCard(card.id, { needsPlanRefresh: true });
3378
- log.info(TAG15, `#${card.short_id} flagged needs_plan_refresh after rejected review`);
3515
+ log.info(TAG16, `#${card.short_id} flagged needs_plan_refresh after rejected review`);
3379
3516
  } catch (err) {
3380
- log.warn(TAG15, `Failed to flag needs_plan_refresh for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
3517
+ log.warn(TAG16, `Failed to flag needs_plan_refresh for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
3381
3518
  }
3382
3519
  }
3383
3520
  await moveCardToColumn(client, card, config.review.failColumn);
@@ -3391,10 +3528,10 @@ ${finding.description}${locationLine}`
3391
3528
  recoveryBranch
3392
3529
  });
3393
3530
  } catch (err) {
3394
- log.debug(TAG15, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
3531
+ log.debug(TAG16, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
3395
3532
  }
3396
3533
  if (recoveryBranch) {
3397
- log.info(TAG15, `#${card.short_id} recovery branch ${recoveryBranch}${recoveryUrl ? ` (${recoveryUrl})` : ""}`);
3534
+ log.info(TAG16, `#${card.short_id} recovery branch ${recoveryBranch}${recoveryUrl ? ` (${recoveryUrl})` : ""}`);
3398
3535
  }
3399
3536
  await client.endAgentSession(card.id, {
3400
3537
  status: "failed",
@@ -3403,7 +3540,7 @@ ${finding.description}${locationLine}`
3403
3540
  recoveryBranch,
3404
3541
  ...buildTokenPayload(sessionStats)
3405
3542
  });
3406
- log.info(TAG15, `#${card.short_id} rejected (cycle ${currentCycle}/${maxCycles}) — moved to "${config.review.failColumn}"`);
3543
+ log.info(TAG16, `#${card.short_id} rejected (cycle ${currentCycle}/${maxCycles}) — moved to "${config.review.failColumn}"`);
3407
3544
  }
3408
3545
  if (workspaceId && (result.verdict === "approved" || result.verdict === "rejected")) {
3409
3546
  const originalEpisodeId = await findLatestImplementEpisode(client, workspaceId, card.project_id, card.short_id);
@@ -3425,7 +3562,7 @@ ${finding.description}${locationLine}`
3425
3562
  cleanupWorktree(worktreePath, branchName);
3426
3563
  }
3427
3564
  }
3428
- var TAG15 = "review-completion", MAX_FINDINGS = 10, REVIEW_MARKER = `---
3565
+ var TAG16 = "review-completion", MAX_FINDINGS = 10, REVIEW_MARKER = `---
3429
3566
  **Review:`, RUN_LOG_TAIL_BYTES = 2048;
3430
3567
  var init_review_completion = __esm(() => {
3431
3568
  init_board_helpers();
@@ -3785,7 +3922,7 @@ __export(exports_state_store, {
3785
3922
  StateStore: () => StateStore
3786
3923
  });
3787
3924
  import {
3788
- existsSync as existsSync4,
3925
+ existsSync as existsSync5,
3789
3926
  mkdirSync as mkdirSync2,
3790
3927
  readFileSync as readFileSync3,
3791
3928
  renameSync,
@@ -3827,18 +3964,18 @@ class StateStore {
3827
3964
  static open(path) {
3828
3965
  const resolved = path ?? defaultStatePath();
3829
3966
  const dir = dirname(resolved);
3830
- if (!existsSync4(dir))
3967
+ if (!existsSync5(dir))
3831
3968
  mkdirSync2(dir, { recursive: true });
3832
3969
  return new StateStore(resolved);
3833
3970
  }
3834
3971
  load() {
3835
- if (!existsSync4(this.path))
3972
+ if (!existsSync5(this.path))
3836
3973
  return emptyState();
3837
3974
  try {
3838
3975
  const raw = readFileSync3(this.path, "utf-8");
3839
3976
  const parsed = JSON.parse(raw);
3840
3977
  if (parsed?.version !== SCHEMA_VERSION) {
3841
- log.warn(TAG16, `state file has version ${parsed?.version}, expected ${SCHEMA_VERSION} — starting fresh`);
3978
+ log.warn(TAG17, `state file has version ${parsed?.version}, expected ${SCHEMA_VERSION} — starting fresh`);
3842
3979
  return emptyState();
3843
3980
  }
3844
3981
  return {
@@ -3851,7 +3988,7 @@ class StateStore {
3851
3988
  daily: parsed.daily ?? []
3852
3989
  };
3853
3990
  } catch (err) {
3854
- log.error(TAG16, `failed to read state file: ${err instanceof Error ? err.message : err}`);
3991
+ log.error(TAG17, `failed to read state file: ${err instanceof Error ? err.message : err}`);
3855
3992
  return emptyState();
3856
3993
  }
3857
3994
  }
@@ -4007,7 +4144,7 @@ class StateStore {
4007
4144
  return this.state.daily.find((d) => d.date === key)?.costCents ?? 0;
4008
4145
  }
4009
4146
  }
4010
- var TAG16 = "state-store", SCHEMA_VERSION = 1;
4147
+ var TAG17 = "state-store", SCHEMA_VERSION = 1;
4011
4148
  var init_state_store = __esm(() => {
4012
4149
  init_log();
4013
4150
  });
@@ -4034,7 +4171,7 @@ function normalizeToolResultContent(raw) {
4034
4171
  return String(raw);
4035
4172
  }
4036
4173
  }
4037
- var TAG17 = "stream-parser", StreamParser;
4174
+ var TAG18 = "stream-parser", StreamParser;
4038
4175
  var init_stream_parser = __esm(() => {
4039
4176
  init_log();
4040
4177
  StreamParser = class StreamParser extends EventEmitter {
@@ -4078,14 +4215,14 @@ var init_stream_parser = __esm(() => {
4078
4215
  try {
4079
4216
  msg = JSON.parse(line);
4080
4217
  } catch {
4081
- log.debug(TAG17, `Non-JSON line: ${line.slice(0, 100)}`);
4218
+ log.debug(TAG18, `Non-JSON line: ${line.slice(0, 100)}`);
4082
4219
  return;
4083
4220
  }
4084
4221
  try {
4085
4222
  this.handleMessage(msg);
4086
4223
  } catch (err) {
4087
4224
  const errMsg = err instanceof Error ? err.message : String(err);
4088
- log.warn(TAG17, `Error handling stream event: ${errMsg}`);
4225
+ log.warn(TAG18, `Error handling stream event: ${errMsg}`);
4089
4226
  this.emit("parse_error", errMsg);
4090
4227
  }
4091
4228
  }
@@ -4167,7 +4304,7 @@ async function withRetry(step, cardShortId, op, attempts, backoffMs) {
4167
4304
  const msg2 = err instanceof Error ? err.message : String(err);
4168
4305
  if (i < attempts - 1) {
4169
4306
  const wait = backoffMs * 2 ** i;
4170
- log.warn(TAG18, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
4307
+ log.warn(TAG19, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
4171
4308
  await new Promise((r) => setTimeout(r, wait));
4172
4309
  }
4173
4310
  }
@@ -4189,10 +4326,10 @@ async function runTransition(client, card, plan, opts = {}) {
4189
4326
  if (opts.strictColumn) {
4190
4327
  throw new TransitionError("move", 1, msg);
4191
4328
  }
4192
- log.warn(TAG18, `#${shortId}: ${msg} — skipping move`);
4329
+ log.warn(TAG19, `#${shortId}: ${msg} — skipping move`);
4193
4330
  } else if (card.column_id !== target.id) {
4194
4331
  await withRetry("move", shortId, () => client.moveCard(card.id, target.id), attempts, backoffMs);
4195
- log.info(TAG18, `#${shortId} → "${target.name}"`);
4332
+ log.info(TAG19, `#${shortId} → "${target.name}"`);
4196
4333
  card.column_id = target.id;
4197
4334
  }
4198
4335
  }
@@ -4205,7 +4342,7 @@ async function runTransition(client, card, plan, opts = {}) {
4205
4342
  continue;
4206
4343
  await withRetry("addLabel", shortId, () => client.addLabelToCard(card.id, labelId), attempts, backoffMs);
4207
4344
  existing.add(labelId);
4208
- log.info(TAG18, `#${shortId} +label "${name}"`);
4345
+ log.info(TAG19, `#${shortId} +label "${name}"`);
4209
4346
  }
4210
4347
  card.labelIds = Array.from(existing);
4211
4348
  }
@@ -4217,17 +4354,17 @@ async function runTransition(client, card, plan, opts = {}) {
4217
4354
  continue;
4218
4355
  await withRetry("removeLabel", shortId, () => client.removeLabelFromCard(card.id, match.id), attempts, backoffMs);
4219
4356
  existing.delete(match.id);
4220
- log.info(TAG18, `#${shortId} -label "${name}"`);
4357
+ log.info(TAG19, `#${shortId} -label "${name}"`);
4221
4358
  }
4222
4359
  card.labelIds = Array.from(existing);
4223
4360
  }
4224
4361
  if (plan.updateCard) {
4225
4362
  await withRetry("updateCard", shortId, () => client.updateCard(card.id, plan.updateCard), attempts, backoffMs);
4226
- log.info(TAG18, `#${shortId} updated`);
4363
+ log.info(TAG19, `#${shortId} updated`);
4227
4364
  }
4228
4365
  if (plan.endSession) {
4229
4366
  await withRetry("endSession", shortId, () => client.endAgentSession(card.id, plan.endSession), attempts, backoffMs);
4230
- log.info(TAG18, `#${shortId} session ended (${plan.endSession.status})`);
4367
+ log.info(TAG19, `#${shortId} session ended (${plan.endSession.status})`);
4231
4368
  }
4232
4369
  if (opts.store && opts.runId) {
4233
4370
  try {
@@ -4240,11 +4377,11 @@ async function ensureLabel(client, projectId, name, color, attempts, backoffMs)
4240
4377
  const result = await withRetry("addLabel", 0, () => client.createLabel(projectId, { name, color: color ?? "#8b5cf6" }), attempts, backoffMs);
4241
4378
  return result?.label?.id ?? null;
4242
4379
  } catch (err) {
4243
- log.warn(TAG18, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
4380
+ log.warn(TAG19, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
4244
4381
  return null;
4245
4382
  }
4246
4383
  }
4247
- var TAG18 = "transition", TransitionError;
4384
+ var TAG19 = "transition", TransitionError;
4248
4385
  var init_transitions = __esm(() => {
4249
4386
  init_log();
4250
4387
  TransitionError = class TransitionError extends Error {
@@ -4262,7 +4399,7 @@ var init_transitions = __esm(() => {
4262
4399
  });
4263
4400
 
4264
4401
  // src/review-worker.ts
4265
- import { execFileSync as execFileSync8 } from "node:child_process";
4402
+ import { execFileSync as execFileSync9 } from "node:child_process";
4266
4403
 
4267
4404
  class ReviewWorker {
4268
4405
  config;
@@ -4328,7 +4465,7 @@ class ReviewWorker {
4328
4465
  }
4329
4466
  }
4330
4467
  get tag() {
4331
- return `${TAG19}:${this.id}`;
4468
+ return `${TAG20}:${this.id}`;
4332
4469
  }
4333
4470
  get isIdle() {
4334
4471
  return this.state === "idle";
@@ -4385,7 +4522,7 @@ class ReviewWorker {
4385
4522
  let localDiff = null;
4386
4523
  if (localMode) {
4387
4524
  log.info(this.tag, `No branch found for #${card.short_id}, attempting local review`);
4388
- this.worktreePath = execFileSync8("git", ["rev-parse", "--show-toplevel"], {
4525
+ this.worktreePath = execFileSync9("git", ["rev-parse", "--show-toplevel"], {
4389
4526
  encoding: "utf-8",
4390
4527
  timeout: 5000
4391
4528
  }).trim();
@@ -4452,7 +4589,7 @@ class ReviewWorker {
4452
4589
  if (localMode) {
4453
4590
  diff = localDiff ?? "";
4454
4591
  } else {
4455
- diff = execFileSync8("git", ["diff", `origin/${this.config.worktree.baseBranch}..HEAD`], { cwd, encoding: "utf-8", timeout: 30000 });
4592
+ diff = execFileSync9("git", ["diff", `origin/${this.config.worktree.baseBranch}..HEAD`], { cwd, encoding: "utf-8", timeout: 30000 });
4456
4593
  }
4457
4594
  } catch {
4458
4595
  diff = "(unable to retrieve diff)";
@@ -4732,7 +4869,7 @@ class ReviewWorker {
4732
4869
  }
4733
4870
  resolveLocalChanges(repoRoot, shortId) {
4734
4871
  try {
4735
- const localChanges = execFileSync8("git", ["diff", "HEAD"], {
4872
+ const localChanges = execFileSync9("git", ["diff", "HEAD"], {
4736
4873
  cwd: repoRoot,
4737
4874
  encoding: "utf-8",
4738
4875
  timeout: 5000
@@ -4744,7 +4881,7 @@ class ReviewWorker {
4744
4881
  log.warn(this.tag, "Failed to check uncommitted changes");
4745
4882
  }
4746
4883
  try {
4747
- const matchingCommits = execFileSync8("git", ["log", "--format=%H", "-20", `--grep=#${shortId}`], { cwd: repoRoot, encoding: "utf-8", timeout: 1e4 }).trim();
4884
+ const matchingCommits = execFileSync9("git", ["log", "--format=%H", "-20", `--grep=#${shortId}`], { cwd: repoRoot, encoding: "utf-8", timeout: 1e4 }).trim();
4748
4885
  if (matchingCommits) {
4749
4886
  const hashes = matchingCommits.split(`
4750
4887
  `).filter((h) => /^[0-9a-f]{4,40}$/i.test(h));
@@ -4754,7 +4891,7 @@ class ReviewWorker {
4754
4891
  const diffs = [];
4755
4892
  for (const hash of hashes) {
4756
4893
  try {
4757
- const commitDiff = execFileSync8("git", ["diff", `${hash}~1..${hash}`], { cwd: repoRoot, encoding: "utf-8", timeout: 30000 });
4894
+ const commitDiff = execFileSync9("git", ["diff", `${hash}~1..${hash}`], { cwd: repoRoot, encoding: "utf-8", timeout: 30000 });
4758
4895
  if (commitDiff)
4759
4896
  diffs.push(commitDiff);
4760
4897
  } catch {
@@ -4797,7 +4934,7 @@ class ReviewWorker {
4797
4934
  this.lastSessionStats = null;
4798
4935
  }
4799
4936
  }
4800
- var TAG19 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
4937
+ var TAG20 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
4801
4938
  var init_review_worker = __esm(() => {
4802
4939
  init_board_helpers();
4803
4940
  init_completion();
@@ -4846,7 +4983,7 @@ class SleepGuard {
4846
4983
  if (!this.child.killed)
4847
4984
  this.child.kill("SIGTERM");
4848
4985
  this.child = null;
4849
- log.info(TAG20, "sleep assertion released");
4986
+ log.info(TAG21, "sleep assertion released");
4850
4987
  }
4851
4988
  }
4852
4989
  start() {
@@ -4861,7 +4998,7 @@ class SleepGuard {
4861
4998
  spawned = true;
4862
4999
  });
4863
5000
  child.on("error", (err) => {
4864
- log.warn(TAG20, `caffeinate unavailable: ${err.message}`);
5001
+ log.warn(TAG21, `caffeinate unavailable: ${err.message}`);
4865
5002
  if (this.child === child)
4866
5003
  this.child = null;
4867
5004
  });
@@ -4874,13 +5011,13 @@ class SleepGuard {
4874
5011
  });
4875
5012
  child.unref();
4876
5013
  this.child = child;
4877
- log.info(TAG20, "sleep assertion acquired (caffeinate -i)");
5014
+ log.info(TAG21, "sleep assertion acquired (caffeinate -i)");
4878
5015
  } catch (err) {
4879
- log.warn(TAG20, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
5016
+ log.warn(TAG21, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
4880
5017
  }
4881
5018
  }
4882
5019
  }
4883
- var TAG20 = "sleep-guard";
5020
+ var TAG21 = "sleep-guard";
4884
5021
  var init_sleep_guard = __esm(() => {
4885
5022
  init_log();
4886
5023
  });
@@ -4891,7 +5028,7 @@ async function fetchBlocksLinks(client, cardId) {
4891
5028
  const { links } = await client.getCardLinks(cardId);
4892
5029
  return links.filter((l) => l.link_type === "blocks");
4893
5030
  } catch (err) {
4894
- log.warn(TAG21, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
5031
+ log.warn(TAG22, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
4895
5032
  return null;
4896
5033
  }
4897
5034
  }
@@ -4923,42 +5060,49 @@ async function promoteUnblockedSuccessors(completedCard, deps) {
4923
5060
  const successors = links.filter((l) => l.direction === "outgoing" && !l.target_card.done);
4924
5061
  if (successors.length === 0)
4925
5062
  return;
4926
- log.info(TAG21, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
5063
+ log.info(TAG22, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
4927
5064
  for (const link of successors) {
4928
5065
  const successorId = link.target_card.id;
4929
5066
  try {
4930
5067
  const { card } = await deps.client.getCard(successorId);
4931
5068
  if (card.assigned_agent_id === deps.agentId) {} else if (card.assigned_agent_id === null && !card.assignee_id) {
4932
- log.info(TAG21, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
5069
+ log.info(TAG22, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
4933
5070
  await deps.client.updateCard(successorId, {
4934
5071
  assignedAgentId: deps.agentId
4935
5072
  });
4936
5073
  } else {
4937
- log.debug(TAG21, `successor #${card.short_id} assigned to different entity — skipping`);
5074
+ log.debug(TAG22, `successor #${card.short_id} assigned to different entity — skipping`);
4938
5075
  continue;
4939
5076
  }
4940
5077
  await deps.enqueue(successorId);
4941
5078
  } catch (err) {
4942
- log.warn(TAG21, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
5079
+ log.warn(TAG22, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
4943
5080
  }
4944
5081
  }
4945
5082
  }
4946
- var TAG21 = "unblock";
5083
+ var TAG22 = "unblock";
4947
5084
  var init_unblock = __esm(() => {
4948
5085
  init_log();
4949
5086
  });
4950
5087
 
4951
5088
  // src/model-tier.ts
5089
+ function clampWithdrawn(model) {
5090
+ return WITHDRAWN_MODEL.test(model) ? MAX_IMPLEMENT_MODEL : model;
5091
+ }
4952
5092
  function chooseImplementModel(claude, card, attempts) {
4953
5093
  if (card.model_override) {
4954
- return { model: card.model_override, escalated: false, source: "override" };
5094
+ return {
5095
+ model: clampWithdrawn(card.model_override),
5096
+ escalated: false,
5097
+ source: "override"
5098
+ };
4955
5099
  }
4956
5100
  if (isModelTier(card.model_tier)) {
4957
5101
  const retry = attempts >= claude.escalateAfterAttempts;
4958
5102
  const tier = retry ? escalateTier(card.model_tier) : card.model_tier;
4959
5103
  const mapped = claude.tiers?.[tier];
4960
5104
  return {
4961
- model: mapped && mapped.length > 0 ? mapped : claude.model,
5105
+ model: clampWithdrawn(mapped && mapped.length > 0 ? mapped : claude.model),
4962
5106
  escalated: retry,
4963
5107
  source: "tier"
4964
5108
  };
@@ -4966,13 +5110,15 @@ function chooseImplementModel(claude, card, attempts) {
4966
5110
  const highPriority = card.priority === "high" || card.priority === "urgent";
4967
5111
  const escalated = highPriority || attempts >= claude.escalateAfterAttempts;
4968
5112
  return {
4969
- model: escalated ? claude.escalateModel : claude.model,
5113
+ model: clampWithdrawn(escalated ? claude.escalateModel : claude.model),
4970
5114
  escalated,
4971
5115
  source: "policy"
4972
5116
  };
4973
5117
  }
5118
+ var MAX_IMPLEMENT_MODEL = "claude-opus-4-8", WITHDRAWN_MODEL;
4974
5119
  var init_model_tier = __esm(() => {
4975
5120
  init_dist();
5121
+ WITHDRAWN_MODEL = /fable/i;
4976
5122
  });
4977
5123
 
4978
5124
  // src/prompt.ts
@@ -4989,11 +5135,11 @@ async function buildPrompt(enriched, branchName, worktreePath, client, workspace
4989
5135
  Do NOT push to main. All your work stays on \`${branchName}\`.
4990
5136
  When finished, call harmony_end_agent_session with status="completed".`
4991
5137
  });
4992
- log.info(TAG22, `Generated prompt for #${card.short_id} — ${result.contextSummary.memoryCount} memories, ${result.tokenEstimate} tokens`);
5138
+ log.info(TAG23, `Generated prompt for #${card.short_id} — ${result.contextSummary.memoryCount} memories, ${result.tokenEstimate} tokens`);
4993
5139
  return result.prompt + pastEpisodesSection;
4994
5140
  } catch (err) {
4995
5141
  const msg = err instanceof Error ? err.message : String(err);
4996
- log.warn(TAG22, `Failed to generate prompt via API, using fallback: ${msg}`);
5142
+ log.warn(TAG23, `Failed to generate prompt via API, using fallback: ${msg}`);
4997
5143
  const commentsSection = await renderCommentsSection(client, card.id);
4998
5144
  return buildFallbackPrompt(enriched, branchName, worktreePath) + commentsSection + pastEpisodesSection;
4999
5145
  }
@@ -5011,7 +5157,7 @@ async function renderCommentsSection(client, cardId) {
5011
5157
 
5012
5158
  ${section}` : "";
5013
5159
  } catch (err) {
5014
- log.warn(TAG22, "comment-thread fetch failed", {
5160
+ log.warn(TAG23, "comment-thread fetch failed", {
5015
5161
  event: "comment_fetch_failed",
5016
5162
  error: err instanceof Error ? err.message : String(err)
5017
5163
  });
@@ -5061,7 +5207,7 @@ ${description}`.trim();
5061
5207
  ## Similar past tasks
5062
5208
  ${bullets}`;
5063
5209
  } catch (err) {
5064
- log.warn(TAG22, "past-episodes recall failed", {
5210
+ log.warn(TAG23, "past-episodes recall failed", {
5065
5211
  event: "episode_recall_failed",
5066
5212
  error: err instanceof Error ? err.message : String(err)
5067
5213
  });
@@ -5102,7 +5248,7 @@ ${subtaskStr}
5102
5248
  You are working in a git worktree at \`${worktreePath}\` on branch \`${branchName}\`.
5103
5249
  Do NOT push to main. All your work stays on \`${branchName}\`.`;
5104
5250
  }
5105
- var TAG22 = "prompt";
5251
+ var TAG23 = "prompt";
5106
5252
  var init_prompt = __esm(() => {
5107
5253
  init_dist();
5108
5254
  init_log();
@@ -5181,7 +5327,7 @@ class Worker {
5181
5327
  }
5182
5328
  }
5183
5329
  get tag() {
5184
- return `${TAG23}:${this.id}`;
5330
+ return `${TAG24}:${this.id}`;
5185
5331
  }
5186
5332
  get isIdle() {
5187
5333
  return this.state === "idle";
@@ -5240,7 +5386,7 @@ class Worker {
5240
5386
  });
5241
5387
  const sid = session && typeof session === "object" && "id" in session ? session.id : null;
5242
5388
  if (!sid) {
5243
- log.warn(TAG23, "startAgentSession returned no session id");
5389
+ log.warn(TAG24, "startAgentSession returned no session id");
5244
5390
  }
5245
5391
  this.sessionId = sid;
5246
5392
  await this.recordPhase("preparing");
@@ -5748,7 +5894,7 @@ class Worker {
5748
5894
  this.runTurns = 0;
5749
5895
  }
5750
5896
  }
5751
- var TAG23 = "worker", CANCEL_SIGINT_TIMEOUT2 = 30000, CANCEL_SIGTERM_TIMEOUT2 = 1e4, PLAN_ALLOWED_TOOLS = "Read,Grep,Glob,mcp__harmony__*", IMPLEMENT_ALLOWED_TOOLS = "Bash,Read,Write,Edit,Glob,Grep,Agent,mcp__harmony__*", PLAN_PHASE_TIMEOUT;
5897
+ var TAG24 = "worker", CANCEL_SIGINT_TIMEOUT2 = 30000, CANCEL_SIGTERM_TIMEOUT2 = 1e4, PLAN_ALLOWED_TOOLS = "Read,Grep,Glob,mcp__harmony__*", IMPLEMENT_ALLOWED_TOOLS = "Bash,Read,Write,Edit,Glob,Grep,Agent,mcp__harmony__*", PLAN_PHASE_TIMEOUT;
5752
5898
  var init_worker = __esm(() => {
5753
5899
  init_board_helpers();
5754
5900
  init_completion();
@@ -5818,39 +5964,39 @@ class Pool {
5818
5964
  }
5819
5965
  async enqueue(card, column, labels, subtasks, mode = "implement") {
5820
5966
  if (this.implQueue.has(card.id) || this.reviewQueue.has(card.id) || this.isCardActive(card.id)) {
5821
- log.debug(TAG24, `Card ${card.id} already queued or active, skipping`);
5967
+ log.debug(TAG25, `Card ${card.id} already queued or active, skipping`);
5822
5968
  return;
5823
5969
  }
5824
5970
  if (mode === "implement") {
5825
5971
  if (this.authPaused) {
5826
- log.debug(TAG24, `#${card.short_id} held — agent paused (auth error)`);
5972
+ log.debug(TAG25, `#${card.short_id} held — agent paused (auth error)`);
5827
5973
  await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
5828
5974
  return;
5829
5975
  }
5830
5976
  const cooldownMs = this.apiCooldownRemainingMs();
5831
5977
  if (cooldownMs > 0) {
5832
- log.debug(TAG24, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
5978
+ log.debug(TAG25, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
5833
5979
  await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
5834
5980
  return;
5835
5981
  }
5836
5982
  const decision = this.budget.check(card.id);
5837
5983
  if (!decision.allow) {
5838
5984
  if (decision.reason === "daily_budget") {
5839
- log.warn(TAG24, `#${card.short_id} skipped (daily_budget): ${decision.detail}`);
5985
+ log.warn(TAG25, `#${card.short_id} skipped (daily_budget): ${decision.detail}`);
5840
5986
  await this.emitWaiting(card.id, `Daily budget reached — waiting for reset (${decision.detail})`);
5841
5987
  } else {
5842
- log.debug(TAG24, `#${card.short_id} gave up: ${decision.detail}`);
5988
+ log.debug(TAG25, `#${card.short_id} gave up: ${decision.detail}`);
5843
5989
  }
5844
5990
  return;
5845
5991
  }
5846
5992
  const blockers = await getUnresolvedBlockers(this.client, card, this.projectId);
5847
5993
  if (blockers === null) {
5848
- log.warn(TAG24, `#${card.short_id} blocker check failed — deferring to next tick`);
5994
+ log.warn(TAG25, `#${card.short_id} blocker check failed — deferring to next tick`);
5849
5995
  return;
5850
5996
  }
5851
5997
  if (blockers.length > 0) {
5852
5998
  const list = blockers.map((b) => `#${b.shortId}`).join(", ");
5853
- log.info(TAG24, `#${card.short_id} blocked by ${list} — waiting`);
5999
+ log.info(TAG25, `#${card.short_id} blocked by ${list} — waiting`);
5854
6000
  await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
5855
6001
  return;
5856
6002
  }
@@ -5879,7 +6025,7 @@ class Pool {
5879
6025
  });
5880
6026
  this.lastWaitingEmit.set(cardId, currentTask);
5881
6027
  } catch (err) {
5882
- log.debug(TAG24, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
6028
+ log.debug(TAG25, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
5883
6029
  }
5884
6030
  }
5885
6031
  noteApiError(err) {
@@ -5887,7 +6033,7 @@ class Pool {
5887
6033
  return;
5888
6034
  if (err.kind === "auth") {
5889
6035
  if (!this.authPaused) {
5890
- log.error(TAG24, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
6036
+ log.error(TAG25, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
5891
6037
  }
5892
6038
  this.authPaused = true;
5893
6039
  return;
@@ -5896,7 +6042,7 @@ class Pool {
5896
6042
  const until = Date.now() + cooldownMs;
5897
6043
  if (until > this.apiCooldownUntil) {
5898
6044
  this.apiCooldownUntil = until;
5899
- log.warn(TAG24, `${describeApiError(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
6045
+ log.warn(TAG25, `${describeApiError(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
5900
6046
  }
5901
6047
  }
5902
6048
  apiCooldownRemainingMs() {
@@ -5909,13 +6055,13 @@ class Pool {
5909
6055
  const removed = queue.remove(cardId);
5910
6056
  if (removed) {
5911
6057
  this.cardDataCache.delete(cardId);
5912
- log.info(TAG24, `Removed #${removed.shortId} from ${removed.mode} queue`);
6058
+ log.info(TAG25, `Removed #${removed.shortId} from ${removed.mode} queue`);
5913
6059
  return;
5914
6060
  }
5915
6061
  }
5916
6062
  const worker = this.implWorkers.find((w) => w.cardId === cardId) ?? this.reviewWorkers.find((w) => w.cardId === cardId);
5917
6063
  if (worker) {
5918
- log.info(TAG24, `Cancelling worker ${worker.id} for card ${cardId}`);
6064
+ log.info(TAG25, `Cancelling worker ${worker.id} for card ${cardId}`);
5919
6065
  await worker.cancel();
5920
6066
  }
5921
6067
  }
@@ -5943,10 +6089,10 @@ class Pool {
5943
6089
  async handleAgentCommand(cardId, command) {
5944
6090
  const worker = this.implWorkers.find((w) => w.cardId === cardId && w.isActive) ?? this.reviewWorkers.find((w) => w.cardId === cardId && w.isActive);
5945
6091
  if (!worker) {
5946
- log.debug(TAG24, `No active worker for card ${cardId}, ignoring ${command}`);
6092
+ log.debug(TAG25, `No active worker for card ${cardId}, ignoring ${command}`);
5947
6093
  return;
5948
6094
  }
5949
- log.info(TAG24, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
6095
+ log.info(TAG25, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
5950
6096
  switch (command) {
5951
6097
  case "pause":
5952
6098
  await worker.pause();
@@ -5994,7 +6140,7 @@ class Pool {
5994
6140
  };
5995
6141
  }
5996
6142
  async shutdown() {
5997
- log.info(TAG24, "Shutting down pool...");
6143
+ log.info(TAG25, "Shutting down pool...");
5998
6144
  this.shuttingDown = true;
5999
6145
  const active = [
6000
6146
  ...this.implWorkers.filter((w) => w.isActive),
@@ -6002,7 +6148,7 @@ class Pool {
6002
6148
  ];
6003
6149
  await Promise.all(active.map((w) => w.cancel()));
6004
6150
  this.sleepGuard.stop();
6005
- log.info(TAG24, "Pool shutdown complete");
6151
+ log.info(TAG25, "Pool shutdown complete");
6006
6152
  }
6007
6153
  cardDataCache = new Map;
6008
6154
  tryDispatchFor(workers, queue, label) {
@@ -6010,7 +6156,7 @@ class Pool {
6010
6156
  return false;
6011
6157
  const idle = workers.find((w) => w.isIdle);
6012
6158
  if (!idle) {
6013
- log.debug(TAG24, `No idle ${label} workers (queue: ${queue.length})`);
6159
+ log.debug(TAG25, `No idle ${label} workers (queue: ${queue.length})`);
6014
6160
  return false;
6015
6161
  }
6016
6162
  const next = queue.dequeue();
@@ -6018,18 +6164,18 @@ class Pool {
6018
6164
  return false;
6019
6165
  const data = this.cardDataCache.get(next.cardId);
6020
6166
  if (!data) {
6021
- log.warn(TAG24, `No cached data for card ${next.cardId}, skipping`);
6167
+ log.warn(TAG25, `No cached data for card ${next.cardId}, skipping`);
6022
6168
  return false;
6023
6169
  }
6024
6170
  this.cardDataCache.delete(next.cardId);
6025
6171
  this.lastWaitingEmit.delete(next.cardId);
6026
- log.info(TAG24, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
6172
+ log.info(TAG25, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
6027
6173
  this.sleepGuard.acquire();
6028
6174
  idle.run(data.card, data.column, data.labels, data.subtasks);
6029
6175
  return true;
6030
6176
  }
6031
6177
  }
6032
- var TAG24 = "pool";
6178
+ var TAG25 = "pool";
6033
6179
  var init_pool = __esm(() => {
6034
6180
  init_error_classifier();
6035
6181
  init_log();
@@ -6050,7 +6196,7 @@ __export(exports_port_registry, {
6050
6196
  clearDaemonPort: () => clearDaemonPort
6051
6197
  });
6052
6198
  import {
6053
- existsSync as existsSync5,
6199
+ existsSync as existsSync6,
6054
6200
  mkdirSync as mkdirSync3,
6055
6201
  readFileSync as readFileSync4,
6056
6202
  renameSync as renameSync2,
@@ -6062,7 +6208,7 @@ function defaultRegistryPath() {
6062
6208
  return join4(homedir4(), ".harmony-mcp", "agent-ports.json");
6063
6209
  }
6064
6210
  function load(path) {
6065
- if (!existsSync5(path))
6211
+ if (!existsSync6(path))
6066
6212
  return {};
6067
6213
  try {
6068
6214
  const raw = readFileSync4(path, "utf-8");
@@ -6071,13 +6217,13 @@ function load(path) {
6071
6217
  return parsed;
6072
6218
  return {};
6073
6219
  } catch (err) {
6074
- log.warn(TAG25, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
6220
+ log.warn(TAG26, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
6075
6221
  return {};
6076
6222
  }
6077
6223
  }
6078
6224
  function save(path, registry) {
6079
6225
  const dir = dirname2(path);
6080
- if (!existsSync5(dir))
6226
+ if (!existsSync6(dir))
6081
6227
  mkdirSync3(dir, { recursive: true });
6082
6228
  const tmp = `${path}.tmp`;
6083
6229
  writeFileSync2(tmp, JSON.stringify(registry, null, 2), "utf-8");
@@ -6089,7 +6235,7 @@ function recordDaemonPort(projectId, entry, path = defaultRegistryPath()) {
6089
6235
  registry[projectId] = { ...entry, updatedAt: Date.now() };
6090
6236
  save(path, registry);
6091
6237
  } catch (err) {
6092
- log.warn(TAG25, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
6238
+ log.warn(TAG26, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
6093
6239
  }
6094
6240
  }
6095
6241
  function lookupDaemonPort(projectId, path = defaultRegistryPath()) {
@@ -6105,10 +6251,10 @@ function clearDaemonPort(projectId, pid, path = defaultRegistryPath()) {
6105
6251
  delete registry[projectId];
6106
6252
  save(path, registry);
6107
6253
  } catch (err) {
6108
- log.warn(TAG25, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
6254
+ log.warn(TAG26, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
6109
6255
  }
6110
6256
  }
6111
- var TAG25 = "port-registry";
6257
+ var TAG26 = "port-registry";
6112
6258
  var init_port_registry = __esm(() => {
6113
6259
  init_log();
6114
6260
  });
@@ -6129,7 +6275,7 @@ async function fetchCardSafely(client, cardId) {
6129
6275
  const { card } = await client.getCard(cardId);
6130
6276
  return card;
6131
6277
  } catch (err) {
6132
- log.warn(TAG26, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
6278
+ log.warn(TAG27, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
6133
6279
  return null;
6134
6280
  }
6135
6281
  }
@@ -6139,7 +6285,7 @@ async function recoverOrphans(store, client, config) {
6139
6285
  return [];
6140
6286
  }
6141
6287
  const outcomes = [];
6142
- log.info(TAG26, `recovering ${active.length} orphan run(s) from prior daemon`);
6288
+ log.info(TAG27, `recovering ${active.length} orphan run(s) from prior daemon`);
6143
6289
  for (const run of active) {
6144
6290
  const outcome = {
6145
6291
  runId: run.runId,
@@ -6151,11 +6297,11 @@ async function recoverOrphans(store, client, config) {
6151
6297
  };
6152
6298
  outcomes.push(outcome);
6153
6299
  if (isProcessAlive(run.daemonPid, process.pid)) {
6154
- log.warn(TAG26, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
6300
+ log.warn(TAG27, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
6155
6301
  outcome.actions.push("skipped: daemon pid still alive");
6156
6302
  continue;
6157
6303
  }
6158
- log.info(TAG26, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
6304
+ log.info(TAG27, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
6159
6305
  await recoverRun(run, store, client, config, outcome);
6160
6306
  }
6161
6307
  return outcomes;
@@ -6173,7 +6319,7 @@ async function recoverRun(run, store, client, config, outcome) {
6173
6319
  } catch (err) {
6174
6320
  const msg = err instanceof Error ? err.message : String(err);
6175
6321
  outcome.errors.push(`endAgentSession: ${msg}`);
6176
- log.warn(TAG26, `endAgentSession failed for ${run.cardId}: ${msg}`);
6322
+ log.warn(TAG27, `endAgentSession failed for ${run.cardId}: ${msg}`);
6177
6323
  }
6178
6324
  const card = await fetchCardSafely(client, run.cardId);
6179
6325
  if (card) {
@@ -6216,9 +6362,9 @@ async function recoverRun(run, store, client, config, outcome) {
6216
6362
  const msg = err instanceof Error ? err.message : String(err);
6217
6363
  outcome.errors.push(`endRun: ${msg}`);
6218
6364
  }
6219
- log.info(TAG26, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
6365
+ log.info(TAG27, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
6220
6366
  }
6221
- var TAG26 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
6367
+ var TAG27 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
6222
6368
  var init_recovery = __esm(() => {
6223
6369
  init_board_helpers();
6224
6370
  init_log();
@@ -6266,7 +6412,7 @@ class Reconciler {
6266
6412
  clearInterval(this.timer);
6267
6413
  this.timer = null;
6268
6414
  }
6269
- log.info(TAG27, "Heartbeat stopped");
6415
+ log.info(TAG28, "Heartbeat stopped");
6270
6416
  }
6271
6417
  async recoverStaleRuns() {
6272
6418
  if (!this.stateStore || !this.agentConfig)
@@ -6283,7 +6429,7 @@ class Reconciler {
6283
6429
  if (!daemonDead && !(heartbeatStale && ourZombie))
6284
6430
  continue;
6285
6431
  const reason = daemonDead ? `foreign daemon ${run.daemonPid} is dead` : `our worker lost card ${run.cardId} with ${Math.round((now - run.lastHeartbeatAt) / 1000)}s stale heartbeat`;
6286
- log.warn(TAG27, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
6432
+ log.warn(TAG28, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
6287
6433
  await recoverRun(run, this.stateStore, this.client, this.agentConfig, {
6288
6434
  runId: run.runId,
6289
6435
  cardId: run.cardId,
@@ -6310,11 +6456,11 @@ class Reconciler {
6310
6456
  const stalledAt = Date.parse(card.updated_at ?? "");
6311
6457
  if (!Number.isFinite(stalledAt) || now - stalledAt < graceMs)
6312
6458
  continue;
6313
- log.warn(TAG27, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
6459
+ log.warn(TAG28, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
6314
6460
  try {
6315
6461
  await this.client.moveCard(card.id, pickupCol.id);
6316
6462
  } catch (err) {
6317
- log.error(TAG27, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6463
+ log.error(TAG28, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6318
6464
  }
6319
6465
  }
6320
6466
  }
@@ -6337,11 +6483,11 @@ class Reconciler {
6337
6483
  const parkedAt = Date.parse(card.updated_at ?? "");
6338
6484
  if (!Number.isFinite(parkedAt) || now - parkedAt < ttlMs)
6339
6485
  continue;
6340
- log.warn(TAG27, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
6486
+ log.warn(TAG28, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
6341
6487
  try {
6342
6488
  await this.client.moveCard(card.id, pickupCol.id);
6343
6489
  } catch (err) {
6344
- log.error(TAG27, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6490
+ log.error(TAG28, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6345
6491
  }
6346
6492
  }
6347
6493
  }
@@ -6370,18 +6516,18 @@ class Reconciler {
6370
6516
  const subtasks = card.subtasks ?? [];
6371
6517
  const mode = reviewColumnIds.has(card.column_id) ? "review" : "implement";
6372
6518
  if (mode === "review" && this.approvedLabel && hasLabel(cardLabels, this.approvedLabel)) {
6373
- log.debug(TAG27, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
6519
+ log.debug(TAG28, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
6374
6520
  continue;
6375
6521
  }
6376
6522
  if (mode === "review" && hasLabel(cardLabels, NEED_REVIEW_LABEL)) {
6377
- log.debug(TAG27, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
6523
+ log.debug(TAG28, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
6378
6524
  continue;
6379
6525
  }
6380
6526
  if (mode === "review" && !extractBranchFromDescription(card.description)) {
6381
- log.debug(TAG27, `Skipping #${card.short_id} — no branch reference (not qualified for auto-review)`);
6527
+ log.debug(TAG28, `Skipping #${card.short_id} — no branch reference (not qualified for auto-review)`);
6382
6528
  continue;
6383
6529
  }
6384
- log.info(TAG27, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
6530
+ log.info(TAG28, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
6385
6531
  await this.pool.enqueue(card, column, cardLabels, subtasks, mode);
6386
6532
  }
6387
6533
  }
@@ -6391,18 +6537,18 @@ class Reconciler {
6391
6537
  await this.recoverStrandedInProgress(cards, columns, knownCardIds);
6392
6538
  for (const knownId of knownCardIds) {
6393
6539
  if (!allAgentCardIds.has(knownId)) {
6394
- log.info(TAG27, `Missed unassign: ${knownId} — removing`);
6540
+ log.info(TAG28, `Missed unassign: ${knownId} — removing`);
6395
6541
  await this.pool.removeCard(knownId);
6396
6542
  }
6397
6543
  }
6398
6544
  await this.releaseStalledApprovals(cards, columns, knownCardIds);
6399
- log.debug(TAG27, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
6545
+ log.debug(TAG28, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
6400
6546
  } catch (err) {
6401
- log.error(TAG27, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
6547
+ log.error(TAG28, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
6402
6548
  }
6403
6549
  }
6404
6550
  }
6405
- var TAG27 = "reconcile";
6551
+ var TAG28 = "reconcile";
6406
6552
  var init_reconcile = __esm(() => {
6407
6553
  init_board_helpers();
6408
6554
  init_log();
@@ -6440,7 +6586,7 @@ function prettyBanner(config, version) {
6440
6586
  checks.push({ kind: "ok", message });
6441
6587
  },
6442
6588
  warn(message) {
6443
- log.warn(TAG28, message);
6589
+ log.warn(TAG29, message);
6444
6590
  checks.push({ kind: "warn", message: message.split(`
6445
6591
  `, 1)[0] });
6446
6592
  },
@@ -6465,25 +6611,25 @@ function prettyBanner(config, version) {
6465
6611
  };
6466
6612
  }
6467
6613
  function jsonBanner(config, version) {
6468
- log.info(TAG28, `Harmony Agent Daemon v${version} starting...`);
6469
- log.info(TAG28, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
6614
+ log.info(TAG29, `Harmony Agent Daemon v${version} starting...`);
6615
+ log.info(TAG29, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
6470
6616
  if (config.agent.review.enabled) {
6471
- log.info(TAG28, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
6617
+ log.info(TAG29, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
6472
6618
  }
6473
6619
  let failed = false;
6474
6620
  return {
6475
6621
  setProjectName(_name) {},
6476
6622
  setGitProvider(provider) {
6477
- log.info(TAG28, `Git provider: ${provider}`);
6623
+ log.info(TAG29, `Git provider: ${provider}`);
6478
6624
  },
6479
6625
  setHttpPort(port) {
6480
- log.info(TAG28, `HTTP server on port ${port}`);
6626
+ log.info(TAG29, `HTTP server on port ${port}`);
6481
6627
  },
6482
6628
  check(message) {
6483
- log.info(TAG28, message);
6629
+ log.info(TAG29, message);
6484
6630
  },
6485
6631
  warn(message) {
6486
- log.warn(TAG28, message);
6632
+ log.warn(TAG29, message);
6487
6633
  },
6488
6634
  fail() {
6489
6635
  failed = true;
@@ -6491,7 +6637,7 @@ function jsonBanner(config, version) {
6491
6637
  async ready(message) {
6492
6638
  if (failed)
6493
6639
  return;
6494
- log.info(TAG28, message);
6640
+ log.info(TAG29, message);
6495
6641
  }
6496
6642
  };
6497
6643
  }
@@ -6568,7 +6714,7 @@ function cyan(s) {
6568
6714
  function yellow(s) {
6569
6715
  return `${ANSI.yellow}${s}${ANSI.reset}`;
6570
6716
  }
6571
- var TAG28 = "daemon", RULE_WIDTH = 70, ANSI;
6717
+ var TAG29 = "daemon", RULE_WIDTH = 70, ANSI;
6572
6718
  var init_startup_banner = __esm(() => {
6573
6719
  init_log();
6574
6720
  ANSI = {
@@ -6715,18 +6861,18 @@ class Watcher {
6715
6861
  }
6716
6862
  async start() {
6717
6863
  if (!isPretty()) {
6718
- log.info(TAG29, "Connecting to Supabase realtime (broadcast)...");
6864
+ log.info(TAG30, "Connecting to Supabase realtime (broadcast)...");
6719
6865
  }
6720
6866
  this.supabase = createClient(this.credentials.supabaseUrl, this.credentials.supabaseAnonKey);
6721
6867
  const presenceChannel = this.supabase.channel(`board-presence-${this.projectId}`);
6722
6868
  const channel = this.supabase.channel(`board-${this.projectId}`).on("broadcast", { event: "card_update" }, (msg) => {
6723
- log.debug(TAG29, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
6869
+ log.debug(TAG30, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
6724
6870
  this.onCardBroadcast({
6725
6871
  event: "card_update",
6726
6872
  payload: msg.payload ?? {}
6727
6873
  });
6728
6874
  }).on("broadcast", { event: "card_created" }, (msg) => {
6729
- log.debug(TAG29, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
6875
+ log.debug(TAG30, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
6730
6876
  this.onCardBroadcast({
6731
6877
  event: "card_created",
6732
6878
  payload: msg.payload ?? {}
@@ -6736,29 +6882,29 @@ class Watcher {
6736
6882
  const cardId = payload.card_id;
6737
6883
  const command = payload.command;
6738
6884
  if (cardId && command) {
6739
- log.info(TAG29, `Broadcast: agent_command ${command} for ${cardId}`);
6885
+ log.info(TAG30, `Broadcast: agent_command ${command} for ${cardId}`);
6740
6886
  this.onAgentCommand?.({ cardId, command });
6741
6887
  }
6742
6888
  }).subscribe((status) => {
6743
6889
  if (status === "SUBSCRIBED") {
6744
6890
  this.connected = true;
6745
6891
  if (!isPretty() || !this.suppressStartupLogs) {
6746
- log.info(TAG29, "Broadcast subscription active");
6892
+ log.info(TAG30, "Broadcast subscription active");
6747
6893
  }
6748
6894
  this.maybeResolveReady();
6749
6895
  } else if (status === "CHANNEL_ERROR") {
6750
6896
  this.connected = false;
6751
- log.error(TAG29, "Broadcast channel error — will rely on reconciliation");
6897
+ log.error(TAG30, "Broadcast channel error — will rely on reconciliation");
6752
6898
  } else if (status === "TIMED_OUT") {
6753
6899
  this.connected = false;
6754
- log.warn(TAG29, "Broadcast subscription timed out — retrying...");
6900
+ log.warn(TAG30, "Broadcast subscription timed out — retrying...");
6755
6901
  } else if (status === "CLOSED") {
6756
6902
  this.connected = false;
6757
6903
  }
6758
6904
  });
6759
6905
  this.channel = channel;
6760
6906
  presenceChannel.on("presence", { event: "sync" }, () => {
6761
- log.debug(TAG29, "Presence sync");
6907
+ log.debug(TAG30, "Presence sync");
6762
6908
  }).subscribe(async (status) => {
6763
6909
  if (status === "SUBSCRIBED") {
6764
6910
  await presenceChannel.track({
@@ -6771,7 +6917,7 @@ class Watcher {
6771
6917
  agentName: this.identity.agentName
6772
6918
  });
6773
6919
  if (!isPretty() || !this.suppressStartupLogs) {
6774
- log.info(TAG29, "Presence tracked on board-presence channel");
6920
+ log.info(TAG30, "Presence tracked on board-presence channel");
6775
6921
  }
6776
6922
  this.presenceTracked = true;
6777
6923
  this.maybeResolveReady();
@@ -6793,10 +6939,10 @@ class Watcher {
6793
6939
  this.supabase = null;
6794
6940
  }
6795
6941
  this.connected = false;
6796
- log.info(TAG29, "Broadcast subscription stopped");
6942
+ log.info(TAG30, "Broadcast subscription stopped");
6797
6943
  }
6798
6944
  }
6799
- var TAG29 = "watcher";
6945
+ var TAG30 = "watcher";
6800
6946
  var init_watcher = __esm(() => {
6801
6947
  init_log();
6802
6948
  });
@@ -6809,8 +6955,8 @@ __export(exports_worktree_gc, {
6809
6955
  isTransientGitNetworkError: () => isTransientGitNetworkError,
6810
6956
  WorktreeGc: () => WorktreeGc
6811
6957
  });
6812
- import { execFileSync as execFileSync9 } from "node:child_process";
6813
- import { readdirSync, statSync as statSync2 } from "node:fs";
6958
+ import { execFileSync as execFileSync10 } from "node:child_process";
6959
+ import { readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
6814
6960
  import { resolve as resolve3 } from "node:path";
6815
6961
  function isTransientGitNetworkError(message) {
6816
6962
  return TRANSIENT_GIT_NETWORK_ERROR.test(message);
@@ -6835,7 +6981,7 @@ function runWorktreeGc(basePath, store, opts = {}) {
6835
6981
  const baseAbs = resolve3(repoRoot, basePath);
6836
6982
  let entries;
6837
6983
  try {
6838
- entries = readdirSync(baseAbs);
6984
+ entries = readdirSync2(baseAbs);
6839
6985
  } catch {
6840
6986
  return result;
6841
6987
  }
@@ -6877,16 +7023,16 @@ function runWorktreeGc(basePath, store, opts = {}) {
6877
7023
  }
6878
7024
  }
6879
7025
  try {
6880
- execFileSync9("git", ["worktree", "prune", "--expire=now"], {
7026
+ execFileSync10("git", ["worktree", "prune", "--expire=now"], {
6881
7027
  cwd: repoRoot,
6882
7028
  stdio: "pipe"
6883
7029
  });
6884
7030
  } catch {}
6885
7031
  if (result.removed.length > 0) {
6886
- log.info(TAG30, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
7032
+ log.info(TAG31, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
6887
7033
  }
6888
7034
  if (result.errors.length > 0) {
6889
- log.warn(TAG30, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
7035
+ log.warn(TAG31, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
6890
7036
  }
6891
7037
  return result;
6892
7038
  }
@@ -6908,7 +7054,7 @@ function pruneFailedRemoteBranches(opts) {
6908
7054
  return result;
6909
7055
  }
6910
7056
  try {
6911
- execFileSync9("git", ["fetch", "--prune", "origin"], {
7057
+ execFileSync10("git", ["fetch", "--prune", "origin"], {
6912
7058
  cwd: repoRoot,
6913
7059
  stdio: "pipe",
6914
7060
  ...GIT_NETWORK_EXEC
@@ -6916,7 +7062,7 @@ function pruneFailedRemoteBranches(opts) {
6916
7062
  } catch (err) {
6917
7063
  const detail = gitErrorDetail(err);
6918
7064
  if (isTransientGitNetworkError(detail)) {
6919
- log.debug(TAG30, `Remote branch GC skipped — remote unreachable: ${detail}`);
7065
+ log.debug(TAG31, `Remote branch GC skipped — remote unreachable: ${detail}`);
6920
7066
  return result;
6921
7067
  }
6922
7068
  result.errors.push({ ref: "fetch", error: detail });
@@ -6924,7 +7070,7 @@ function pruneFailedRemoteBranches(opts) {
6924
7070
  const refPattern = `refs/remotes/origin/${opts.prefix}*`;
6925
7071
  let listing = "";
6926
7072
  try {
6927
- listing = execFileSync9("git", [
7073
+ listing = execFileSync10("git", [
6928
7074
  "for-each-ref",
6929
7075
  "--format=%(refname:strip=3) %(committerdate:unix)",
6930
7076
  refPattern
@@ -6955,11 +7101,11 @@ function pruneFailedRemoteBranches(opts) {
6955
7101
  continue;
6956
7102
  }
6957
7103
  if (clock() > sweepDeadline) {
6958
- log.debug(TAG30, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
7104
+ log.debug(TAG31, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
6959
7105
  break;
6960
7106
  }
6961
7107
  try {
6962
- execFileSync9("git", ["push", "origin", `:refs/heads/${ref}`], {
7108
+ execFileSync10("git", ["push", "origin", `:refs/heads/${ref}`], {
6963
7109
  cwd: repoRoot,
6964
7110
  stdio: "pipe",
6965
7111
  ...GIT_NETWORK_EXEC
@@ -6968,17 +7114,17 @@ function pruneFailedRemoteBranches(opts) {
6968
7114
  } catch (err) {
6969
7115
  const detail = gitErrorDetail(err);
6970
7116
  if (isTransientGitNetworkError(detail)) {
6971
- log.debug(TAG30, `Remote branch GC interrupted — remote unreachable: ${detail}`);
7117
+ log.debug(TAG31, `Remote branch GC interrupted — remote unreachable: ${detail}`);
6972
7118
  break;
6973
7119
  }
6974
7120
  result.errors.push({ ref, error: detail });
6975
7121
  }
6976
7122
  }
6977
7123
  if (result.removed.length > 0) {
6978
- log.info(TAG30, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
7124
+ log.info(TAG31, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
6979
7125
  }
6980
7126
  if (result.errors.length > 0) {
6981
- log.warn(TAG30, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
7127
+ log.warn(TAG31, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
6982
7128
  }
6983
7129
  return result;
6984
7130
  }
@@ -7009,27 +7155,27 @@ class WorktreeGc {
7009
7155
  try {
7010
7156
  runWorktreeGc(this.basePath, this.store);
7011
7157
  } catch (err) {
7012
- log.warn(TAG30, `GC tick failed: ${err instanceof Error ? err.message : err}`);
7158
+ log.warn(TAG31, `GC tick failed: ${err instanceof Error ? err.message : err}`);
7013
7159
  }
7014
7160
  if (this.remoteOpts) {
7015
7161
  try {
7016
7162
  pruneFailedRemoteBranches(this.remoteOpts);
7017
7163
  } catch (err) {
7018
- log.warn(TAG30, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
7164
+ log.warn(TAG31, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
7019
7165
  }
7020
7166
  }
7021
7167
  }
7022
7168
  }
7023
7169
  function getRepoRoot2() {
7024
7170
  try {
7025
- return execFileSync9("git", ["rev-parse", "--show-toplevel"], {
7171
+ return execFileSync10("git", ["rev-parse", "--show-toplevel"], {
7026
7172
  encoding: "utf-8"
7027
7173
  }).trim();
7028
7174
  } catch {
7029
7175
  return null;
7030
7176
  }
7031
7177
  }
7032
- var TAG30 = "worktree-gc", GIT_NETWORK_TIMEOUT_MS = 30000, GIT_SSH_CONNECT_TIMEOUT_SECS = 10, GIT_PRUNE_SWEEP_BUDGET_MS = 60000, GIT_NETWORK_EXEC, TRANSIENT_GIT_NETWORK_ERROR;
7178
+ var TAG31 = "worktree-gc", GIT_NETWORK_TIMEOUT_MS = 30000, GIT_SSH_CONNECT_TIMEOUT_SECS = 10, GIT_PRUNE_SWEEP_BUDGET_MS = 60000, GIT_NETWORK_EXEC, TRANSIENT_GIT_NETWORK_ERROR;
7033
7179
  var init_worktree_gc = __esm(() => {
7034
7180
  init_log();
7035
7181
  init_worktree();
@@ -7063,12 +7209,12 @@ __export(exports_src, {
7063
7209
  validatePrerequisites: () => validatePrerequisites,
7064
7210
  main: () => main
7065
7211
  });
7066
- import { execFileSync as execFileSync10 } from "node:child_process";
7212
+ import { execFileSync as execFileSync11 } from "node:child_process";
7067
7213
  import { randomUUID as randomUUID2 } from "node:crypto";
7068
7214
  import { createRequire as createRequire2 } from "node:module";
7069
7215
  async function validatePrerequisites(config, banner) {
7070
7216
  try {
7071
- const ver = execFileSync10("claude", ["--version"], {
7217
+ const ver = execFileSync11("claude", ["--version"], {
7072
7218
  encoding: "utf-8"
7073
7219
  }).trim();
7074
7220
  banner.check(`Claude CLI ${ver}`);
@@ -7083,14 +7229,14 @@ async function validatePrerequisites(config, banner) {
7083
7229
  validateGitProviderCli(provider);
7084
7230
  }
7085
7231
  try {
7086
- const status = execFileSync10("git", ["status", "--porcelain"], {
7232
+ const status = execFileSync11("git", ["status", "--porcelain"], {
7087
7233
  encoding: "utf-8"
7088
7234
  }).trim();
7089
7235
  if (status) {
7090
7236
  banner.warn(`Working directory has uncommitted changes:
7091
7237
  ${status}`);
7092
7238
  }
7093
- execFileSync10("git", ["rev-parse", "--verify", `origin/${config.agent.worktree.baseBranch}`], {
7239
+ execFileSync11("git", ["rev-parse", "--verify", `origin/${config.agent.worktree.baseBranch}`], {
7094
7240
  encoding: "utf-8",
7095
7241
  stdio: "pipe"
7096
7242
  });
@@ -7133,7 +7279,7 @@ async function main() {
7133
7279
  } catch (err) {
7134
7280
  if (err instanceof ConfigValidationError) {
7135
7281
  banner.fail();
7136
- log.error(TAG31, err.message);
7282
+ log.error(TAG32, err.message);
7137
7283
  process.exit(1);
7138
7284
  }
7139
7285
  throw err;
@@ -7242,7 +7388,7 @@ async function main() {
7242
7388
  if (shuttingDown)
7243
7389
  return;
7244
7390
  shuttingDown = true;
7245
- log.info(TAG31, `Received ${signal}, shutting down gracefully...`);
7391
+ log.info(TAG32, `Received ${signal}, shutting down gracefully...`);
7246
7392
  reconciler.stop();
7247
7393
  mergeMonitor?.stop();
7248
7394
  worktreeGc.stop();
@@ -7252,18 +7398,18 @@ async function main() {
7252
7398
  }
7253
7399
  await watcher.stop();
7254
7400
  await pool.shutdown();
7255
- log.info(TAG31, "Daemon stopped.");
7401
+ log.info(TAG32, "Daemon stopped.");
7256
7402
  process.exit(exitCode);
7257
7403
  };
7258
7404
  process.on("SIGINT", () => shutdown("SIGINT"));
7259
7405
  process.on("SIGTERM", () => shutdown("SIGTERM"));
7260
7406
  process.on("uncaughtException", (err) => {
7261
- log.error(TAG31, `Uncaught exception: ${err.message}`);
7407
+ log.error(TAG32, `Uncaught exception: ${err.message}`);
7262
7408
  exitCode = 1;
7263
7409
  shutdown("uncaughtException");
7264
7410
  });
7265
7411
  process.on("unhandledRejection", (reason) => {
7266
- log.error(TAG31, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
7412
+ log.error(TAG32, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
7267
7413
  exitCode = 1;
7268
7414
  shutdown("unhandledRejection");
7269
7415
  });
@@ -7316,34 +7462,34 @@ async function handleBroadcast(event, client, pool, config, agentId) {
7316
7462
  if (assignedAgentId === undefined)
7317
7463
  return;
7318
7464
  if (assignedAgentId === agentId) {
7319
- log.info(TAG31, `Broadcast: card ${cardId} assigned to agent`);
7465
+ log.info(TAG32, `Broadcast: card ${cardId} assigned to agent`);
7320
7466
  try {
7321
7467
  await tryEnqueueCard(cardId, client, pool, config, agentId);
7322
7468
  } catch (err) {
7323
- log.error(TAG31, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
7469
+ log.error(TAG32, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
7324
7470
  }
7325
7471
  } else if (pool.isCardKnown(cardId)) {
7326
- log.info(TAG31, `Broadcast: card ${cardId} unassigned from agent`);
7472
+ log.info(TAG32, `Broadcast: card ${cardId} unassigned from agent`);
7327
7473
  await pool.removeCard(cardId);
7328
7474
  }
7329
7475
  }
7330
7476
  async function tryEnqueueCard(cardId, client, pool, config, agentId) {
7331
7477
  const { card } = await client.getCard(cardId);
7332
7478
  if (card.assigned_agent_id !== agentId) {
7333
- log.debug(TAG31, `Card ${cardId} no longer assigned to agent — skipping`);
7479
+ log.debug(TAG32, `Card ${cardId} no longer assigned to agent — skipping`);
7334
7480
  return;
7335
7481
  }
7336
7482
  const board = await client.getBoard(config.projectId, { summary: true });
7337
7483
  const columns = board.columns;
7338
7484
  const column = columns.find((c) => c.id === card.column_id);
7339
7485
  if (!column) {
7340
- log.warn(TAG31, `Column not found for card ${cardId}`);
7486
+ log.warn(TAG32, `Column not found for card ${cardId}`);
7341
7487
  return;
7342
7488
  }
7343
7489
  const isPickupColumn = config.agent.pickupColumns.some((name) => name.toLowerCase() === column.name.toLowerCase());
7344
7490
  const isReviewColumn = config.agent.review.enabled && config.agent.review.pickupColumns.some((name) => name.toLowerCase() === column.name.toLowerCase());
7345
7491
  if (!isPickupColumn && !isReviewColumn) {
7346
- log.info(TAG31, `Card #${card.short_id} is in "${column.name}", not a pickup/review column — skipping`);
7492
+ log.info(TAG32, `Card #${card.short_id} is in "${column.name}", not a pickup/review column — skipping`);
7347
7493
  return;
7348
7494
  }
7349
7495
  const mode = isReviewColumn ? "review" : "implement";
@@ -7351,16 +7497,16 @@ async function tryEnqueueCard(cardId, client, pool, config, agentId) {
7351
7497
  const cardLabels = resolveCardLabels(card, labelMap);
7352
7498
  const subtasks = card.subtasks ?? [];
7353
7499
  if (mode === "review" && config.agent.review.approvedLabel && hasLabel(cardLabels, config.agent.review.approvedLabel)) {
7354
- log.debug(TAG31, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
7500
+ log.debug(TAG32, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
7355
7501
  return;
7356
7502
  }
7357
7503
  if (mode === "review" && !extractBranchFromDescription(card.description)) {
7358
- log.info(TAG31, `Card #${card.short_id} has no branch reference — skipping auto-review`);
7504
+ log.info(TAG32, `Card #${card.short_id} has no branch reference — skipping auto-review`);
7359
7505
  return;
7360
7506
  }
7361
7507
  await pool.enqueue(card, column, cardLabels, subtasks, mode);
7362
7508
  }
7363
- var TAG31 = "daemon", PKG_VERSION;
7509
+ var TAG32 = "daemon", PKG_VERSION;
7364
7510
  var init_src = __esm(() => {
7365
7511
  init_board_helpers();
7366
7512
  init_config();