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