@gethmy/agent 1.41.0 → 1.42.0

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 (3) hide show
  1. package/dist/cli.js +639 -997
  2. package/dist/index.js +541 -966
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -860,6 +860,9 @@ function isDaemonAuthoredComment(comment, identity) {
860
860
  return false;
861
861
  return true;
862
862
  }
863
+ // ../harmony-shared/dist/agentPauseAccounting.js
864
+ var init_agentPauseAccounting = () => {};
865
+
863
866
  // ../harmony-shared/dist/agentStaleness.js
864
867
  function isPoolNotice(session) {
865
868
  return !!session && session.driver === NOTICE_DRIVER && !session.agent_id;
@@ -873,6 +876,12 @@ var init_agentStaleness = __esm(() => {
873
876
  AGENT_SWEEP_PAUSED_MS = 4 * 60 * 60 * 1000;
874
877
  ACTIVE_STATUSES = new Set(["working", "blocked", "waiting"]);
875
878
  });
879
+
880
+ // ../harmony-shared/dist/agentRunControl.js
881
+ var init_agentRunControl = __esm(() => {
882
+ init_agentPauseAccounting();
883
+ init_agentStaleness();
884
+ });
876
885
  // ../harmony-shared/dist/branchRef.js
877
886
  function extractBranchRef(description) {
878
887
  if (!description)
@@ -2433,6 +2442,9 @@ var init_stageHandoff = __esm(() => {
2433
2442
  HANDOFF_BLOCK_RE = new RegExp("```json\\s*\\n//\\s*" + HANDOFF_MARKER + "\\s*\\n([\\s\\S]*?)\\n```", "m");
2434
2443
  });
2435
2444
 
2445
+ // ../harmony-shared/dist/sweepPresence.js
2446
+ var init_sweepPresence = () => {};
2447
+
2436
2448
  // ../harmony-shared/dist/types.js
2437
2449
  var init_types = () => {};
2438
2450
 
@@ -2468,6 +2480,8 @@ function untrustedDataBlock(text, options) {
2468
2480
 
2469
2481
  // ../harmony-shared/dist/index.js
2470
2482
  var init_dist = __esm(() => {
2483
+ init_agentPauseAccounting();
2484
+ init_agentRunControl();
2471
2485
  init_agentStaleness();
2472
2486
  init_branchRef();
2473
2487
  init_cardLifecycle();
@@ -2490,6 +2504,7 @@ var init_dist = __esm(() => {
2490
2504
  init_reviewTools();
2491
2505
  init_runRedaction();
2492
2506
  init_stageHandoff();
2507
+ init_sweepPresence();
2493
2508
  init_types();
2494
2509
  });
2495
2510
 
@@ -6511,332 +6526,20 @@ class ReportedConfigCache {
6511
6526
  var TAG17 = "reported-config";
6512
6527
  var init_reported_config_cache = () => {};
6513
6528
 
6514
- // src/episode-writer.ts
6515
- import { log as log19 } from "@gethmy/harness";
6516
- function computeQualityScore(result, opts) {
6517
- if (!result.passed)
6518
- return 0;
6519
- let score = 0;
6520
- if (result.buildErrors.length === 0)
6521
- score += 0.4;
6522
- if (result.lintWarnings.length === 0)
6523
- score += 0.2;
6524
- if (!opts.errorThrown)
6525
- score += 0.2;
6526
- if (opts.runCompletedCleanly)
6527
- score += 0.2;
6528
- return Math.min(1, score);
6529
- }
6530
- function clampConfidence(qualityScore) {
6531
- return Math.max(0.4, Math.min(1, qualityScore));
6532
- }
6533
- function trimApproachSummary(text) {
6534
- const trimmed = text.trim();
6535
- if (trimmed.length === 0)
6536
- return "(no approach summary captured)";
6537
- if (trimmed.length <= MAX_APPROACH_SUMMARY_CHARS)
6538
- return trimmed;
6539
- return `${trimmed.slice(0, MAX_APPROACH_SUMMARY_CHARS - 1).trimEnd()}…`;
6540
- }
6541
- function trimReviewRationale(text) {
6542
- const trimmed = text.trim();
6543
- if (trimmed.length === 0)
6544
- return "(no review rationale captured)";
6545
- if (trimmed.length <= MAX_REVIEW_RATIONALE_CHARS)
6546
- return trimmed;
6547
- return `${trimmed.slice(0, MAX_REVIEW_RATIONALE_CHARS - 1).trimEnd()}…`;
6548
- }
6549
- function buildRichApproachSummary(blocks, fallback) {
6550
- const cleaned = (blocks ?? []).map((b) => b.trim()).filter((b) => b.length > 0);
6551
- if (cleaned.length === 0)
6552
- return trimApproachSummary(fallback);
6553
- const picked = [];
6554
- let total = 0;
6555
- for (let i = cleaned.length - 1;i >= 0; i--) {
6556
- const block = cleaned[i];
6557
- const cost = block.length + (picked.length > 0 ? 2 : 0);
6558
- if (total + cost > MAX_RICH_APPROACH_CHARS && picked.length > 0)
6559
- break;
6560
- picked.unshift(block);
6561
- total += cost;
6562
- if (total >= MAX_RICH_APPROACH_CHARS)
6563
- break;
6564
- }
6565
- const joined = picked.join(`
6566
-
6567
- `).trim();
6568
- if (joined.length === 0)
6569
- return trimApproachSummary(fallback);
6570
- if (joined.length <= MAX_RICH_APPROACH_CHARS)
6571
- return joined;
6572
- return `${joined.slice(0, MAX_RICH_APPROACH_CHARS - 1).trimEnd()}…`;
6573
- }
6574
- function extractKeyInsight(blocks, fallback) {
6575
- const source = blocks && blocks.length > 0 ? blocks.join(`
6576
- `) : fallback;
6577
- const lines = source.split(/\n|(?<=[.!?])\s+/).map((l) => l.trim()).filter((l) => l.length >= 20 && l.length <= 280);
6578
- for (const line of lines) {
6579
- if (INSIGHT_RE.test(line))
6580
- return line;
6581
- }
6582
- return;
6583
- }
6584
- function buildEpisodePayload(input, projectId) {
6585
- if (input.kind === "implement") {
6586
- const qualityScore2 = computeQualityScore(input.result, {
6587
- errorThrown: input.errorMessage !== undefined,
6588
- runCompletedCleanly: input.result.passed
6589
- });
6590
- const type = input.outcome === "success" ? "solution" : "error";
6591
- const importance = input.outcome === "success" ? 7 : 5;
6592
- const approachSummary = buildRichApproachSummary(input.approachBlocks, input.approachSummary);
6593
- const keyInsight = extractKeyInsight(input.approachBlocks, input.approachSummary);
6594
- const changedFiles = (input.changedFiles ?? []).slice(0, MAX_CHANGED_FILES2);
6595
- const outcomeRationale = input.outcome === "success" ? `Build ${input.result.buildErrors.length === 0 ? "passed" : "failed"}, lint ${input.result.lintWarnings.length === 0 ? "clean" : "issues"}.` : `Verification failed: ${input.errorMessage ?? "see findings"}.`;
6596
- const metadata2 = {
6597
- episode_kind: "implement",
6598
- card_short_id: input.card.short_id,
6599
- card_title: input.card.title,
6600
- approach_summary: approachSummary,
6601
- outcome: input.outcome,
6602
- quality_score: qualityScore2,
6603
- duration_ms: input.cost?.durationMs ?? 0,
6604
- token_cost: {
6605
- input: input.cost?.totalInputTokens ?? 0,
6606
- output: input.cost?.totalOutputTokens ?? 0,
6607
- usd: input.cost?.totalCostUsd ?? 0
6608
- },
6609
- files_touched: input.filesEdited,
6610
- num_turns: input.cost?.numTurns ?? 0,
6611
- origin: {
6612
- source: "agent-run",
6613
- source_card_id: input.card.id,
6614
- author: "harmony-agent",
6615
- ...input.agentSessionId ? { source_session_id: input.agentSessionId } : {}
6616
- }
6617
- };
6618
- if (input.errorMessage)
6619
- metadata2.error = input.errorMessage;
6620
- if (changedFiles.length > 0)
6621
- metadata2.changed_files = changedFiles;
6622
- if (input.churn)
6623
- metadata2.churn = input.churn;
6624
- if (keyInsight)
6625
- metadata2.key_insight = keyInsight;
6626
- if (input.agentSessionId)
6627
- metadata2.agent_session_id = input.agentSessionId;
6628
- const changedFilesLine = changedFiles.length > 0 ? `
6629
-
6630
- Changed files (${changedFiles.length}): ${changedFiles.join(", ")}` : "";
6631
- const keyInsightLine = keyInsight ? `
6632
-
6633
- Key insight: ${keyInsight}` : "";
6634
- return {
6635
- workspace_id: input.workspaceId,
6636
- project_id: projectId,
6637
- type,
6638
- memory_tier: "episode",
6639
- scope: "project",
6640
- title: `Agent run implement — #${input.card.short_id}: ${input.card.title}`,
6641
- content: `${approachSummary}
6642
-
6643
- Outcome: ${outcomeRationale}${keyInsightLine}${changedFilesLine}`,
6644
- metadata: metadata2,
6645
- importance,
6646
- confidence: clampConfidence(qualityScore2),
6647
- tags: ["implement", input.outcome, `card:${input.card.short_id}`],
6648
- agent_identifier: "harmony-agent"
6649
- };
6650
- }
6651
- const qualityScore = input.verdict === "approved" ? 1 : 0.4;
6652
- const summary = trimReviewRationale(input.summary || "");
6653
- const metadata = {
6654
- episode_kind: "review",
6655
- card_short_id: input.card.short_id,
6656
- card_title: input.card.title,
6657
- approach_summary: summary,
6658
- outcome: input.verdict === "approved" ? "success" : "failure",
6659
- quality_score: qualityScore,
6660
- duration_ms: input.cost?.durationMs ?? 0,
6661
- token_cost: {
6662
- input: input.cost?.totalInputTokens ?? 0,
6663
- output: input.cost?.totalOutputTokens ?? 0,
6664
- usd: input.cost?.totalCostUsd ?? 0
6665
- },
6666
- files_touched: 0,
6667
- num_turns: input.cost?.numTurns ?? 0,
6668
- origin: {
6669
- source: "agent-run",
6670
- source_card_id: input.card.id,
6671
- author: "harmony-agent",
6672
- ...input.reviewSessionId ?? input.agentSessionId ? {
6673
- source_session_id: input.reviewSessionId ?? input.agentSessionId
6674
- } : {}
6675
- }
6676
- };
6677
- if (input.agentSessionId)
6678
- metadata.agent_session_id = input.agentSessionId;
6679
- if (input.reviewSessionId)
6680
- metadata.review_session_id = input.reviewSessionId;
6681
- if (input.originalEpisodeId)
6682
- metadata.original_episode_id = input.originalEpisodeId;
6683
- return {
6684
- workspace_id: input.workspaceId,
6685
- project_id: projectId,
6686
- type: "decision",
6687
- memory_tier: "episode",
6688
- scope: "project",
6689
- title: `Agent run review — #${input.card.short_id}: ${input.card.title}`,
6690
- content: `Review verdict: ${input.verdict}.
6691
-
6692
- ${summary}`,
6693
- metadata,
6694
- importance: 8,
6695
- confidence: clampConfidence(qualityScore),
6696
- tags: ["review", input.verdict, `card:${input.card.short_id}`],
6697
- agent_identifier: "harmony-agent"
6698
- };
6699
- }
6700
- async function writeEpisode(client, input, options) {
6701
- const payload = buildEpisodePayload(input, input.card.project_id);
6702
- let content = payload.content;
6703
- if (options?.distiller) {
6704
- try {
6705
- const distilled = await options.distiller(input, payload.content);
6706
- if (distilled && distilled.trim().length > 0) {
6707
- content = distilled.trim();
6708
- }
6709
- } catch (err) {
6710
- log19.warn(TAG18, `episode distillation failed for #${input.card.short_id}`, {
6711
- cardId: input.card.id,
6712
- event: "episode_distill_failed",
6713
- kind: input.kind,
6714
- error: err instanceof Error ? err.message : String(err)
6715
- });
6716
- }
6717
- }
6718
- const metadata = payload.metadata;
6719
- try {
6720
- const existingId = await findRollingEpisode(client, input.workspaceId, input.card.project_id, input.card.short_id, input.kind);
6721
- if (existingId) {
6722
- await client.updateMemoryEntity(existingId, {
6723
- title: payload.title,
6724
- content,
6725
- metadata,
6726
- confidence: payload.confidence,
6727
- tags: payload.tags,
6728
- type: payload.type
6729
- });
6730
- log19.info(TAG18, `episode rolled for #${input.card.short_id}`, {
6731
- cardId: input.card.id,
6732
- event: "episode_rolled",
6733
- kind: input.kind,
6734
- entityId: existingId
6735
- });
6736
- return existingId;
6737
- }
6738
- const { entity } = await client.createMemoryEntity({
6739
- ...payload,
6740
- content,
6741
- metadata
6742
- });
6743
- const id = entity && typeof entity === "object" && "id" in entity ? entity.id ?? null : null;
6744
- log19.info(TAG18, `episode written for #${input.card.short_id}`, {
6745
- cardId: input.card.id,
6746
- event: "episode_write",
6747
- kind: input.kind
6748
- });
6749
- return id;
6750
- } catch (err) {
6751
- log19.warn(TAG18, `episode write failed for #${input.card.short_id}`, {
6752
- cardId: input.card.id,
6753
- event: "episode_write_failed",
6754
- kind: input.kind,
6755
- error: err instanceof Error ? err.message : String(err)
6756
- });
6757
- return null;
6758
- }
6759
- }
6760
- async function findRollingEpisode(client, workspaceId, projectId, cardShortId, kind) {
6761
- const type = kind === "implement" ? ["solution", "error"] : ["decision"];
6762
- try {
6763
- const { entities } = await client.harmonyRecall({
6764
- workspaceId,
6765
- projectId,
6766
- type,
6767
- memory_tier: "episode",
6768
- scope: "project",
6769
- tags: [`card:${cardShortId}`],
6770
- topK: 10,
6771
- includeEpisodes: true
6772
- });
6773
- for (const entity of entities) {
6774
- if (!entity || typeof entity !== "object")
6775
- continue;
6776
- const meta = entity.metadata;
6777
- if (meta?.episode_kind !== kind || meta?.origin?.source !== "agent-run") {
6778
- continue;
6779
- }
6780
- const id = entity.id;
6781
- if (typeof id === "string")
6782
- return id;
6783
- }
6784
- return null;
6785
- } catch (err) {
6786
- log19.warn(TAG18, "rolling-episode lookup failed", {
6787
- event: "episode_lookup_failed",
6788
- cardShortId,
6789
- kind,
6790
- error: err instanceof Error ? err.message : String(err)
6791
- });
6792
- return null;
6793
- }
6794
- }
6795
- async function findLatestImplementEpisode(client, workspaceId, projectId, cardShortId) {
6796
- return findRollingEpisode(client, workspaceId, projectId, cardShortId, "implement");
6797
- }
6798
- async function backfillReviewVerdict(client, originalEpisodeId, verdict, reviewEpisodeId) {
6799
- try {
6800
- if (verdict === "approved") {
6801
- const { entity } = await client.getMemoryEntity(originalEpisodeId);
6802
- const current = entity?.confidence ?? 0.4;
6803
- const bumped = Math.min(1, current + 0.05);
6804
- await client.updateMemoryEntity(originalEpisodeId, {
6805
- confidence: bumped
6806
- });
6807
- } else {
6808
- await client.updateMemoryEntity(originalEpisodeId, {
6809
- superseded_by: reviewEpisodeId
6810
- });
6811
- }
6812
- } catch (err) {
6813
- log19.warn(TAG18, "review back-fill failed", {
6814
- event: "episode_backfill_failed",
6815
- originalEpisodeId,
6816
- verdict,
6817
- error: err instanceof Error ? err.message : String(err)
6818
- });
6819
- }
6820
- }
6821
- var TAG18 = "episode-writer", MAX_APPROACH_SUMMARY_CHARS = 400, MAX_RICH_APPROACH_CHARS = 1500, MAX_CHANGED_FILES2 = 30, MAX_REVIEW_RATIONALE_CHARS = 2000, INSIGHT_RE;
6822
- var init_episode_writer = __esm(() => {
6823
- INSIGHT_RE = /\b(root cause|turned out|the (?:issue|problem|bug) (?:was|is)|the fix (?:was|is)|gotcha|caused by|because|the key (?:was|insight)|note that|caveat|the trick (?:was|is))\b/i;
6824
- });
6825
-
6826
6529
  // src/run-closeout.ts
6827
- import { log as log20 } from "@gethmy/harness";
6530
+ import { log as log19 } from "@gethmy/harness";
6828
6531
  async function transferCardToCompletion(deps, card, moveToColumn, onPromoted) {
6829
6532
  await moveCardToColumn(deps.client, card, moveToColumn);
6830
6533
  try {
6831
6534
  await releaseAssignedAgent(deps.client, card.id);
6832
6535
  } catch (err) {
6833
- log20.warn(deps.tag, `assignment release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6536
+ log19.warn(deps.tag, `assignment release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6834
6537
  }
6835
6538
  if (onPromoted) {
6836
6539
  try {
6837
6540
  await onPromoted(card);
6838
6541
  } catch (err) {
6839
- log20.warn(deps.tag, `successor promotion failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6542
+ log19.warn(deps.tag, `successor promotion failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6840
6543
  }
6841
6544
  }
6842
6545
  }
@@ -6850,7 +6553,7 @@ async function endRunSession(deps, card, disposition, extraPayload, onError) {
6850
6553
  } catch (err) {
6851
6554
  if (onError === "throw")
6852
6555
  throw err;
6853
- log20.error(deps.tag, `endAgentSession after the run failed on #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6556
+ log19.error(deps.tag, `endAgentSession after the run failed on #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6854
6557
  }
6855
6558
  }
6856
6559
  var init_run_closeout = __esm(() => {
@@ -6861,13 +6564,12 @@ var init_run_closeout = __esm(() => {
6861
6564
  import { execFileSync as execFileSync5 } from "node:child_process";
6862
6565
  import {
6863
6566
  attemptAutoFix,
6864
- captureDiffStat,
6865
6567
  createPullRequest,
6866
6568
  detectGitProvider as detectGitProvider3,
6867
6569
  extractPrUrl as extractPrUrl2,
6868
6570
  GIT_NO_HOOKS as GIT_NO_HOOKS6,
6869
6571
  getBranchWebUrl,
6870
- log as log21,
6572
+ log as log20,
6871
6573
  pushBranch,
6872
6574
  reportFindings,
6873
6575
  runFormatFix,
@@ -6905,15 +6607,7 @@ function buildTokenPayload(stats) {
6905
6607
  numTurns: stats.cost.numTurns
6906
6608
  };
6907
6609
  }
6908
- async function runCompletion(client, card, branchName, worktreePath, config, workerId, sessionIdentifier, agentId, sessionStats, workspaceId, agentSessionId, stateStore, onMovedToCompletion, onBeforeWorktreeCleanup, runBaselineSha, effectiveMaxTurns, expectsCommits) {
6909
- let verificationResult = {
6910
- passed: true,
6911
- buildErrors: [],
6912
- testFailures: [],
6913
- lintWarnings: [],
6914
- reviewFindings: [],
6915
- revertWarnings: []
6916
- };
6610
+ async function runCompletion(client, card, branchName, worktreePath, config, workerId, sessionIdentifier, agentId, sessionStats, agentSessionId, stateStore, onMovedToCompletion, onBeforeWorktreeCleanup, runBaselineSha, effectiveMaxTurns, expectsCommits) {
6917
6611
  if (config.verification.enabled && config.verification.lint) {
6918
6612
  await runFormatFix(worktreePath, config.verification.timeout, workerId, verificationSandbox(config), config.commands);
6919
6613
  }
@@ -6922,24 +6616,24 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
6922
6616
  if (!hasCommits) {
6923
6617
  const { maxTurnsExhausted, failureSummary } = describeNoCommitFailure(sessionStats?.cost?.numTurns ?? 0, effectiveMaxTurns ?? config.claude.maxTurns);
6924
6618
  if (noCommitOutcome(maxTurnsExhausted, config.budget.pause.enabled) === "park") {
6925
- log21.warn(TAG19, `No commits on branch ${branchName} — ${failureSummary}; parking for a decision`);
6619
+ log20.warn(TAG18, `No commits on branch ${branchName} — ${failureSummary}; parking for a decision`);
6926
6620
  return "park";
6927
6621
  }
6928
6622
  if (expectsCommits === false) {
6929
- log21.info(TAG19, `No commits on branch ${branchName} — this stage's deliverable is not a diff; its gate decides the run`);
6623
+ log20.info(TAG18, `No commits on branch ${branchName} — this stage's deliverable is not a diff; its gate decides the run`);
6930
6624
  if (onBeforeWorktreeCleanup) {
6931
6625
  try {
6932
6626
  await onBeforeWorktreeCleanup(worktreePath);
6933
6627
  } catch (err) {
6934
- log21.warn(TAG19, `onBeforeWorktreeCleanup hook failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6628
+ log20.warn(TAG18, `onBeforeWorktreeCleanup hook failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6935
6629
  }
6936
6630
  } else {
6937
- await endRunSession({ client, tag: TAG19 }, card, { status: "completed" }, buildTokenPayload(sessionStats), "throw");
6631
+ await endRunSession({ client, tag: TAG18 }, card, { status: "completed" }, buildTokenPayload(sessionStats), "throw");
6938
6632
  }
6939
6633
  await teardownWorktree(client, card.id, worktreePath, branchName, agentSessionId);
6940
6634
  return true;
6941
6635
  }
6942
- log21.warn(TAG19, `No commits on branch ${branchName} — ${failureSummary}; counting as a failed attempt`);
6636
+ log20.warn(TAG18, `No commits on branch ${branchName} — ${failureSummary}; counting as a failed attempt`);
6943
6637
  const noCommitHandback = await guardedHandback(client, card.id, {
6944
6638
  agentId,
6945
6639
  workingColumnId: card.column_id
@@ -6956,13 +6650,13 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
6956
6650
  await teardownWorktree(client, card.id, worktreePath, branchName, agentSessionId);
6957
6651
  return false;
6958
6652
  }
6959
- log21.info(TAG19, `Pushing branch ${branchName} (pre-verify)...`);
6653
+ log20.info(TAG18, `Pushing branch ${branchName} (pre-verify)...`);
6960
6654
  let lastPushedSha = null;
6961
6655
  try {
6962
6656
  pushBranch(branchName, worktreePath);
6963
6657
  lastPushedSha = readHeadSha(worktreePath);
6964
6658
  } catch (err) {
6965
- log21.error(TAG19, `pre-verify push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
6659
+ log20.error(TAG18, `pre-verify push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
6966
6660
  }
6967
6661
  const recoveryUrl = lastPushedSha ? getBranchWebUrl(branchName, worktreePath) : null;
6968
6662
  if (lastPushedSha) {
@@ -6980,7 +6674,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
6980
6674
  let autoFixAttempts = 0;
6981
6675
  if (!result.passed && config.verification.autoFix) {
6982
6676
  for (let attempt = 0;attempt < config.verification.maxFixAttempts; attempt++) {
6983
- log21.info(TAG19, `Auto-fix attempt ${attempt + 1}/${config.verification.maxFixAttempts}`);
6677
+ log20.info(TAG18, `Auto-fix attempt ${attempt + 1}/${config.verification.maxFixAttempts}`);
6984
6678
  await client.updateAgentProgress(card.id, {
6985
6679
  agentIdentifier: sessionIdentifier,
6986
6680
  agentName: AGENT_NAME,
@@ -6997,30 +6691,29 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
6997
6691
  result = await runVerification(worktreePath, config, workerId);
6998
6692
  autoFixAttempts = attempt + 1;
6999
6693
  if (result.passed) {
7000
- log21.info(TAG19, `Auto-fix succeeded on attempt ${attempt + 1}`);
6694
+ log20.info(TAG18, `Auto-fix succeeded on attempt ${attempt + 1}`);
7001
6695
  const sha = readHeadSha(worktreePath);
7002
6696
  if (sha && sha !== lastPushedSha) {
7003
6697
  try {
7004
6698
  pushBranch(branchName, worktreePath);
7005
6699
  lastPushedSha = sha;
7006
6700
  } catch (err) {
7007
- log21.warn(TAG19, `post-fix push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
6701
+ log20.warn(TAG18, `post-fix push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
7008
6702
  }
7009
6703
  }
7010
6704
  break;
7011
6705
  }
7012
6706
  }
7013
6707
  }
7014
- verificationResult = result;
7015
6708
  if (!result.passed) {
7016
- log21.warn(TAG19, `Verification failed for #${card.short_id} — reporting findings`);
6709
+ log20.warn(TAG18, `Verification failed for #${card.short_id} — reporting findings`);
7017
6710
  const failSha = readHeadSha(worktreePath);
7018
6711
  if (failSha && failSha !== lastPushedSha) {
7019
6712
  try {
7020
6713
  pushBranch(branchName, worktreePath);
7021
6714
  lastPushedSha = failSha;
7022
6715
  } catch (err) {
7023
- log21.warn(TAG19, `post-fail push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
6716
+ log20.warn(TAG18, `post-fail push failed for ${branchName}: ${err instanceof Error ? err.message : err}`);
7024
6717
  }
7025
6718
  }
7026
6719
  const failureSummary = buildVerificationFailureSummary(result, autoFixAttempts);
@@ -7031,7 +6724,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
7031
6724
  recoveryBranch: branchName
7032
6725
  });
7033
6726
  } catch (err) {
7034
- log21.debug(TAG19, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
6727
+ log20.debug(TAG18, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
7035
6728
  }
7036
6729
  await reportFindings(client, card.id, result, lastPushedSha ? { branchName, branchUrl: recoveryUrl } : null);
7037
6730
  const verifyHandback = await guardedHandback(client, card.id, {
@@ -7051,7 +6744,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
7051
6744
  await teardownWorktree(client, card.id, worktreePath, branchName, agentSessionId);
7052
6745
  return false;
7053
6746
  }
7054
- log21.info(TAG19, `Verification passed for #${card.short_id}`);
6747
+ log20.info(TAG18, `Verification passed for #${card.short_id}`);
7055
6748
  }
7056
6749
  let prUrl = null;
7057
6750
  if (config.completion.createPR) {
@@ -7059,7 +6752,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
7059
6752
  prUrl = createPullRequest(card, branchName, worktreePath, config, provider);
7060
6753
  }
7061
6754
  if (config.completion.moveToColumn) {
7062
- await transferCardToCompletion({ client, tag: TAG19 }, card, config.completion.moveToColumn, onMovedToCompletion);
6755
+ await transferCardToCompletion({ client, tag: TAG18 }, card, config.completion.moveToColumn, onMovedToCompletion);
7063
6756
  }
7064
6757
  if (config.completion.postSummary) {
7065
6758
  await postSummary(client, card, branchName, worktreePath, prUrl, config.worktree.baseBranch, sessionStats);
@@ -7068,35 +6761,14 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
7068
6761
  try {
7069
6762
  await onBeforeWorktreeCleanup(worktreePath);
7070
6763
  } catch (err) {
7071
- log21.warn(TAG19, `onBeforeWorktreeCleanup hook failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6764
+ log20.warn(TAG18, `onBeforeWorktreeCleanup hook failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7072
6765
  }
7073
6766
  }
7074
6767
  if (!onBeforeWorktreeCleanup) {
7075
- await endRunSession({ client, tag: TAG19 }, card, { status: "completed" }, buildTokenPayload(sessionStats), "throw");
7076
- }
7077
- if (workspaceId) {
7078
- const diffStat = captureDiffStat(worktreePath, config.worktree.baseBranch);
7079
- const changedFiles = diffStat && diffStat.files.length > 0 ? diffStat.files : sessionStats?.filesEditedPaths ?? [];
7080
- await writeEpisode(client, {
7081
- kind: "implement",
7082
- card,
7083
- workspaceId,
7084
- outcome: "success",
7085
- approachSummary: sessionStats?.lastAssistantText ?? "",
7086
- approachBlocks: sessionStats?.assistantTextBlocks,
7087
- result: verificationResult,
7088
- cost: sessionStats?.cost ?? null,
7089
- filesEdited: sessionStats?.filesEdited ?? 0,
7090
- changedFiles,
7091
- churn: diffStat ? {
7092
- insertions: diffStat.insertions,
7093
- deletions: diffStat.deletions
7094
- } : undefined,
7095
- agentSessionId: agentSessionId ?? null
7096
- });
6768
+ await endRunSession({ client, tag: TAG18 }, card, { status: "completed" }, buildTokenPayload(sessionStats), "throw");
7097
6769
  }
7098
6770
  await teardownWorktree(client, card.id, worktreePath, branchName, agentSessionId);
7099
- log21.info(TAG19, `Completion done for #${card.short_id}${prUrl ? ` — PR: ${prUrl}` : ""}`);
6771
+ log20.info(TAG18, `Completion done for #${card.short_id}${prUrl ? ` — PR: ${prUrl}` : ""}`);
7100
6772
  return true;
7101
6773
  }
7102
6774
  function buildVerificationFailureSummary(result, autoFixAttempts) {
@@ -7138,7 +6810,7 @@ function commitUncommittedChanges(worktreePath, card) {
7138
6810
  encoding: "utf-8"
7139
6811
  }).trim();
7140
6812
  } catch (err) {
7141
- log21.warn(TAG19, `git status failed in ${worktreePath}: ${err instanceof Error ? err.message : err}`);
6813
+ log20.warn(TAG18, `git status failed in ${worktreePath}: ${err instanceof Error ? err.message : err}`);
7142
6814
  return false;
7143
6815
  }
7144
6816
  if (status.length === 0)
@@ -7154,10 +6826,10 @@ function commitUncommittedChanges(worktreePath, card) {
7154
6826
  cwd: worktreePath,
7155
6827
  encoding: "utf-8"
7156
6828
  });
7157
- log21.warn(TAG19, `Auto-committed uncommitted worktree changes for #${card.short_id} — agent ended without committing`);
6829
+ log20.warn(TAG18, `Auto-committed uncommitted worktree changes for #${card.short_id} — agent ended without committing`);
7158
6830
  return true;
7159
6831
  } catch (err) {
7160
- log21.error(TAG19, `auto-commit failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6832
+ log20.error(TAG18, `auto-commit failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7161
6833
  return false;
7162
6834
  }
7163
6835
  }
@@ -7206,9 +6878,9 @@ async function recordBranchProvenance(client, card, branchName) {
7206
6878
  ${BRANCH_PROVENANCE_MARKER} (pushed — a later run continues it)
7207
6879
  Branch: \`${branchName}\``;
7208
6880
  await client.updateCard(card.id, { description: description + block });
7209
- log21.info(TAG19, `Recorded branch provenance on #${card.short_id}`);
6881
+ log20.info(TAG18, `Recorded branch provenance on #${card.short_id}`);
7210
6882
  } catch (err) {
7211
- log21.warn(TAG19, `Failed to record branch provenance on #${card.short_id}: ${err instanceof Error ? err.message : err}`);
6883
+ log20.warn(TAG18, `Failed to record branch provenance on #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7212
6884
  }
7213
6885
  }
7214
6886
  async function postSummary(client, card, branchName, worktreePath, prUrl, baseBranch, sessionStats) {
@@ -7262,25 +6934,24 @@ ${commitLog}
7262
6934
  description: baseDesc + parts.join(`
7263
6935
  `)
7264
6936
  });
7265
- log21.info(TAG19, `Posted completion summary to #${card.short_id}`);
6937
+ log20.info(TAG18, `Posted completion summary to #${card.short_id}`);
7266
6938
  } catch (err) {
7267
- log21.error(TAG19, `Failed to post summary: ${err instanceof Error ? err.message : err}`);
6939
+ log20.error(TAG18, `Failed to post summary: ${err instanceof Error ? err.message : err}`);
7268
6940
  }
7269
6941
  }
7270
- var TAG19 = "completion", SUMMARY_MARKER = `---
6942
+ var TAG18 = "completion", SUMMARY_MARKER = `---
7271
6943
  **Agent completed**`, BRANCH_PROVENANCE_MARKER = `---
7272
6944
  **Agent branch**`;
7273
6945
  var init_completion = __esm(() => {
7274
6946
  init_dist();
7275
6947
  init_board_helpers();
7276
- init_episode_writer();
7277
6948
  init_handback();
7278
6949
  init_run_closeout();
7279
6950
  init_types2();
7280
6951
  });
7281
6952
 
7282
6953
  // src/progress-tracker.ts
7283
- import { log as log22 } from "@gethmy/harness";
6954
+ import { log as log21 } from "@gethmy/harness";
7284
6955
  function truncate2(str, max) {
7285
6956
  return str.length > max ? `${str.slice(0, max - 3)}...` : str;
7286
6957
  }
@@ -7309,7 +6980,6 @@ class ProgressTracker {
7309
6980
  runEventSink = null;
7310
6981
  lastEmittedProgress = -1;
7311
6982
  lastAssistantText = "";
7312
- assistantTextBlocks = [];
7313
6983
  constructor(client, cardId, sessionIdentifier, subtasks, initialPhase = "exploring") {
7314
6984
  this.client = client;
7315
6985
  this.cardId = cardId;
@@ -7392,17 +7062,15 @@ class ProgressTracker {
7392
7062
  get stats() {
7393
7063
  return {
7394
7064
  filesEdited: this.filesEdited.size,
7395
- filesEditedPaths: [...this.filesEdited],
7396
7065
  filesRead: this.filesRead.size,
7397
7066
  toolCalls: this.toolCallCount,
7398
7067
  cost: this.lastCost,
7399
- lastAssistantText: this.lastAssistantText,
7400
- assistantTextBlocks: [...this.assistantTextBlocks]
7068
+ lastAssistantText: this.lastAssistantText
7401
7069
  };
7402
7070
  }
7403
7071
  onToolStart(name, input) {
7404
7072
  this.toolCallCount++;
7405
- log22.debug(TAG20, `Tool: ${name} (count: ${this.toolCallCount}, phase: ${this.phase})`);
7073
+ log21.debug(TAG19, `Tool: ${name} (count: ${this.toolCallCount}, phase: ${this.phase})`);
7406
7074
  const filePath = this.extractString(input, "file_path");
7407
7075
  if (filePath) {
7408
7076
  if (EDIT_TOOLS.has(name)) {
@@ -7458,10 +7126,6 @@ class ProgressTracker {
7458
7126
  if (trimmed.length < 10)
7459
7127
  return;
7460
7128
  this.lastAssistantText = trimmed;
7461
- this.assistantTextBlocks.push(trimmed);
7462
- if (this.assistantTextBlocks.length > MAX_TEXT_BLOCKS) {
7463
- this.assistantTextBlocks.shift();
7464
- }
7465
7129
  const end = trimmed.search(SENTENCE_SPLIT);
7466
7130
  const firstLine = (end === -1 ? trimmed : trimmed.slice(0, end)).trim();
7467
7131
  if (firstLine.length >= 10 && firstLine.length <= 200) {
@@ -7473,7 +7137,7 @@ class ProgressTracker {
7473
7137
  transitionTo(newPhase) {
7474
7138
  if (PHASE_ORDER[newPhase] <= PHASE_ORDER[this.phase])
7475
7139
  return;
7476
- log22.info(TAG20, `Phase: ${this.phase} → ${newPhase}`);
7140
+ log21.info(TAG19, `Phase: ${this.phase} → ${newPhase}`);
7477
7141
  const previousPhase = this.phase;
7478
7142
  this.runEventSink?.recordPhaseChanged(newPhase, previousPhase);
7479
7143
  this.phase = newPhase;
@@ -7578,7 +7242,7 @@ class ProgressTracker {
7578
7242
  }
7579
7243
  sendUpdate(currentTask) {
7580
7244
  this.lastUpdateAt = Date.now();
7581
- log22.debug(TAG20, `Progress: ${this.progress}% — ${currentTask}`);
7245
+ log21.debug(TAG19, `Progress: ${this.progress}% — ${currentTask}`);
7582
7246
  this.client.updateAgentProgress(this.cardId, {
7583
7247
  agentIdentifier: this.sessionIdentifier,
7584
7248
  agentName: AGENT_NAME,
@@ -7595,7 +7259,7 @@ class ProgressTracker {
7595
7259
  modelName: this.lastCost?.modelName ?? this.requestedModel ?? undefined,
7596
7260
  numTurns: this.lastCost?.numTurns ?? 0
7597
7261
  }).catch((err) => {
7598
- log22.warn(TAG20, `Failed to send progress update: ${err}`);
7262
+ log21.warn(TAG19, `Failed to send progress update: ${err}`);
7599
7263
  });
7600
7264
  if (this.runEventSink && this.progress !== this.lastEmittedProgress) {
7601
7265
  this.lastEmittedProgress = this.progress;
@@ -7626,7 +7290,7 @@ class ProgressTracker {
7626
7290
  return null;
7627
7291
  }
7628
7292
  }
7629
- var TAG20 = "progress-tracker", THROTTLE_MS = 5000, HEARTBEAT_MS = 60000, MAX_TASK_LENGTH = 120, MAX_TEXT_BLOCKS = 40, SENTENCE_SPLIT, ACTION_PREFIX, GIT_COMMIT_RE, BUILD_CMD_RE, PHASES, PHASE_ORDER, EDIT_TOOLS, FILE_TOOL_VERBS;
7293
+ var TAG19 = "progress-tracker", THROTTLE_MS = 5000, HEARTBEAT_MS = 60000, MAX_TASK_LENGTH = 120, SENTENCE_SPLIT, ACTION_PREFIX, GIT_COMMIT_RE, BUILD_CMD_RE, PHASES, PHASE_ORDER, EDIT_TOOLS, FILE_TOOL_VERBS;
7630
7294
  var init_progress_tracker = __esm(() => {
7631
7295
  init_types2();
7632
7296
  SENTENCE_SPLIT = /\.\s|\n/;
@@ -7660,7 +7324,7 @@ var init_progress_tracker = __esm(() => {
7660
7324
  });
7661
7325
 
7662
7326
  // src/prompt.ts
7663
- import { log as log23 } from "@gethmy/harness";
7327
+ import { log as log22 } from "@gethmy/harness";
7664
7328
  import {
7665
7329
  buildMemoryQuery
7666
7330
  } from "@gethmy/mcp/src/api-client.js";
@@ -7698,10 +7362,7 @@ function renderPreviousAttemptsSection(failures) {
7698
7362
  }
7699
7363
  async function buildPrompt(enriched, branchName, worktreePath, client, workspaceId, projectId, onRecallOutcome) {
7700
7364
  const { card } = enriched;
7701
- const [pastEpisodesSection, referenceSection] = await Promise.all([
7702
- renderPastEpisodesSection(client, card.title, card.description ?? "", workspaceId, projectId, onRecallOutcome),
7703
- renderReferenceSection(client, card.title, card.description ?? "", workspaceId, projectId, onRecallOutcome)
7704
- ]);
7365
+ const referenceSection = await renderReferenceSection(client, card.title, card.description ?? "", workspaceId, projectId, onRecallOutcome);
7705
7366
  try {
7706
7367
  const result = await client.generateCardPrompt({
7707
7368
  cardId: card.id,
@@ -7712,13 +7373,13 @@ async function buildPrompt(enriched, branchName, worktreePath, client, workspace
7712
7373
  Do NOT push to main. All your work stays on \`${branchName}\`.
7713
7374
  The daemon owns the run lifecycle: once your work is committed it ends the agent session, pushes the branch, and moves the card to Review for you. Do NOT call harmony_end_agent_session, do NOT start a new session, and do NOT move the card or change its column yourself. If the skill driving this work tells you to move the card or end the session as a final step, SKIP it — it is handled for you (those tools are disabled for this run). Finish the implementation, commit, and stop.`
7714
7375
  });
7715
- log23.info(TAG21, `Generated prompt for #${card.short_id} — ${result.contextSummary.memoryCount} memories, ${result.tokenEstimate} tokens`);
7716
- return result.prompt + pastEpisodesSection + referenceSection;
7376
+ log22.info(TAG20, `Generated prompt for #${card.short_id} — ${result.contextSummary.memoryCount} memories, ${result.tokenEstimate} tokens`);
7377
+ return result.prompt + referenceSection;
7717
7378
  } catch (err) {
7718
7379
  const msg = err instanceof Error ? err.message : String(err);
7719
- log23.warn(TAG21, `Failed to generate prompt via API, using fallback: ${msg}`);
7380
+ log22.warn(TAG20, `Failed to generate prompt via API, using fallback: ${msg}`);
7720
7381
  const commentsSection = await renderCommentsSection(client, card.id);
7721
- return buildFallbackPrompt(enriched, branchName, worktreePath) + commentsSection + pastEpisodesSection + referenceSection;
7382
+ return buildFallbackPrompt(enriched, branchName, worktreePath) + commentsSection + referenceSection;
7722
7383
  }
7723
7384
  }
7724
7385
  async function renderCommentsSection(client, cardId) {
@@ -7737,95 +7398,41 @@ ${untrustedDataBlock(section, {
7737
7398
  purpose: "discussion to take into account"
7738
7399
  })}` : "";
7739
7400
  } catch (err) {
7740
- log23.warn(TAG21, "comment-thread fetch failed", {
7401
+ log22.warn(TAG20, "comment-thread fetch failed", {
7741
7402
  event: "comment_fetch_failed",
7742
7403
  error: err instanceof Error ? err.message : String(err)
7743
7404
  });
7744
7405
  return "";
7745
7406
  }
7746
7407
  }
7747
- async function renderPastEpisodesSection(client, title, description, workspaceId, projectId, onOutcome) {
7748
- if (!projectId)
7749
- return "";
7750
- try {
7751
- const query = buildMemoryQuery(title, description);
7752
- const { entities } = await client.harmonyRecall({
7753
- workspaceId,
7754
- projectId,
7755
- query,
7756
- type: ["solution", "error"],
7757
- memory_tier: "episode",
7758
- scope: "project",
7759
- topK: 3,
7760
- includeEpisodes: true,
7761
- consumer: "agent-prompt"
7762
- });
7763
- onOutcome?.({ flavour: "past_episodes", count: entities.length });
7764
- if (entities.length === 0)
7765
- return "";
7766
- const bullets = entities.map((entity) => {
7767
- const e = entity;
7768
- const meta = e.metadata ?? {};
7769
- const outcomeTag = meta.outcome ? `[${meta.outcome}]` : "[?]";
7770
- const approach = meta.approach_summary ?? "";
7771
- const lines = [
7772
- `- ${outcomeTag} ${e.title ?? "(untitled episode)"}`,
7773
- ` Approach: ${approach}`
7774
- ];
7775
- if (meta.key_insight)
7776
- lines.push(` Key insight: ${meta.key_insight}`);
7777
- if (meta.changed_files && meta.changed_files.length > 0) {
7778
- const shown = meta.changed_files.slice(0, 8);
7779
- const extra = meta.changed_files.length - shown.length;
7780
- const suffix = extra > 0 ? ` (+${extra} more)` : "";
7781
- lines.push(` Changed files: ${shown.join(", ")}${suffix}`);
7782
- }
7783
- return lines.join(`
7784
- `);
7785
- }).join(`
7786
- `);
7787
- return `
7788
-
7789
- ## Similar past tasks
7790
- ${bullets}`;
7791
- } catch (err) {
7792
- const error = err instanceof Error ? err.message : String(err);
7793
- log23.warn(TAG21, "past-episodes recall failed", {
7794
- event: "episode_recall_failed",
7795
- error
7796
- });
7797
- onOutcome?.({ flavour: "past_episodes", count: 0, failure: error });
7798
- return "";
7799
- }
7800
- }
7801
7408
  async function renderReferenceSection(client, title, description, workspaceId, projectId, onOutcome) {
7802
7409
  try {
7803
7410
  const query = buildMemoryQuery(title, description);
7804
- const { entities } = await client.harmonyRecall({
7805
- workspaceId,
7806
- projectId,
7807
- query,
7808
- memory_tier: "reference",
7809
- topK: 5,
7810
- consumer: "agent-prompt"
7411
+ const { entities } = await client.searchMemoryEntities(workspaceId, query, {
7412
+ project_id: projectId,
7413
+ limit: 5
7811
7414
  });
7812
7415
  onOutcome?.({ flavour: "reference", count: entities.length });
7813
7416
  if (entities.length === 0)
7814
7417
  return "";
7815
7418
  const bullets = entities.map((entity) => {
7816
7419
  const e = entity;
7420
+ const type = e.type ? ` (${e.type})` : "";
7817
7421
  const content = (e.content ?? "").slice(0, 300);
7818
- return `- ${e.title ?? "(untitled)"}
7422
+ return `- ${e.title ?? "(untitled)"}${type}
7819
7423
  ${content}`;
7820
7424
  }).join(`
7821
7425
  `);
7822
7426
  return `
7823
7427
 
7824
- ## How we work here
7825
- ${bullets}`;
7428
+ ${untrustedDataBlock(`## How we work here
7429
+ ${bullets}`, {
7430
+ label: "workspace memory",
7431
+ purpose: "conventions to apply where they fit the task"
7432
+ })}`;
7826
7433
  } catch (err) {
7827
7434
  const error = err instanceof Error ? err.message : String(err);
7828
- log23.warn(TAG21, "reference recall failed", {
7435
+ log22.warn(TAG20, "reference recall failed", {
7829
7436
  event: "reference_recall_failed",
7830
7437
  error
7831
7438
  });
@@ -7867,7 +7474,7 @@ ${subtaskStr}
7867
7474
  You are working in a git worktree at \`${worktreePath}\` on branch \`${branchName}\`.
7868
7475
  Do NOT push to main. All your work stays on \`${branchName}\`.`;
7869
7476
  }
7870
- var TAG21 = "prompt", RESUME_CONTINUATION = `Continue from where you stopped.
7477
+ var TAG20 = "prompt", RESUME_CONTINUATION = `Continue from where you stopped.
7871
7478
 
7872
7479
  This is the same session. The task you were given, the work you have already done,
7873
7480
  and everything you read are above in this conversation. None of it has changed, and
@@ -7892,7 +7499,7 @@ import {
7892
7499
  extractPrUrl as extractPrUrl3,
7893
7500
  getBranchWebUrl as getBranchWebUrl2,
7894
7501
  getHeadSha,
7895
- log as log24,
7502
+ log as log23,
7896
7503
  pushBranch as pushBranch2,
7897
7504
  renameRemoteBranch,
7898
7505
  sanitizeCiText as sanitizeCiText2,
@@ -8018,7 +7625,7 @@ function parseReviewOutput(stdout) {
8018
7625
  try {
8019
7626
  const parsed = JSON.parse(raw);
8020
7627
  if (parsed && typeof parsed === "object" && "verdict" in parsed) {
8021
- log24.debug(TAG22, "Parsed review output from fenced JSON block");
7628
+ log23.debug(TAG21, "Parsed review output from fenced JSON block");
8022
7629
  return extractResult(parsed);
8023
7630
  }
8024
7631
  } catch {}
@@ -8044,21 +7651,21 @@ function parseReviewOutput(stdout) {
8044
7651
  try {
8045
7652
  const parsed = JSON.parse(candidates[i]);
8046
7653
  if (parsed && typeof parsed === "object" && "verdict" in parsed) {
8047
- log24.debug(TAG22, "Parsed review output from raw JSON object");
7654
+ log23.debug(TAG21, "Parsed review output from raw JSON object");
8048
7655
  return extractResult(parsed);
8049
7656
  }
8050
7657
  } catch {}
8051
7658
  }
8052
7659
  const verdictMatch = stdout.match(/"verdict"\s*:\s*"(approved|rejected)"/i);
8053
7660
  if (verdictMatch) {
8054
- log24.warn(TAG22, `Parsed verdict via regex fallback — findings lost (${verdictMatch[1]})`);
7661
+ log23.warn(TAG21, `Parsed verdict via regex fallback — findings lost (${verdictMatch[1]})`);
8055
7662
  return {
8056
7663
  verdict: verdictMatch[1].toLowerCase(),
8057
7664
  summary: "Parsed via regex fallback — original JSON was malformed. Check run log.",
8058
7665
  findings: []
8059
7666
  };
8060
7667
  }
8061
- log24.warn(TAG22, "Failed to parse review JSON output — returning error verdict (card stays in Review)");
7668
+ log23.warn(TAG21, "Failed to parse review JSON output — returning error verdict (card stays in Review)");
8062
7669
  return {
8063
7670
  verdict: "error",
8064
7671
  summary: stdout.slice(0, 500),
@@ -8094,10 +7701,10 @@ async function postReviewComment(client, card, commentType, body, agentSessionId
8094
7701
  agentSessionId: agentSessionId ?? undefined
8095
7702
  });
8096
7703
  } catch (err) {
8097
- log24.error(TAG22, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7704
+ log23.error(TAG21, `Failed to post review comment to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
8098
7705
  }
8099
7706
  }
8100
- async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, workspaceId, agentSessionId, stateStore, agentId, resolvedFromPrUrl, visualLensSkipReason) {
7707
+ async function runReviewCompletion(client, card, result, config, worktreePath, branchName, sessionStats, runLogPath, agentSessionId, stateStore, agentId, resolvedFromPrUrl, visualLensSkipReason) {
8101
7708
  let freshDesc;
8102
7709
  let freshCard = null;
8103
7710
  let handbackVerdict;
@@ -8118,7 +7725,7 @@ async function runReviewCompletion(client, card, result, config, worktreePath, b
8118
7725
  };
8119
7726
  }
8120
7727
  if (!handbackVerdict.proceed) {
8121
- log24.info(TAG22, `#${card.short_id}: review outcome will not move the card — ${handbackVerdict.detail} (${handbackVerdict.reason})`);
7728
+ log23.info(TAG21, `#${card.short_id}: review outcome will not move the card — ${handbackVerdict.detail} (${handbackVerdict.reason})`);
8122
7729
  }
8123
7730
  const lensLine = visualLensSkipReason ? `Visual QA did not run — ${sanitizeCiText2(visualLensSkipReason, REVIEW_FAILURE_REASON_MAX)}. Anything that needs a rendered page is ungraded.` : "";
8124
7731
  const LOOPING_REFUSALS = new Set(["unreadable", "released", "done"]);
@@ -8128,19 +7735,19 @@ async function runReviewCompletion(client, card, result, config, worktreePath, b
8128
7735
  }
8129
7736
  try {
8130
7737
  await addLabelByName(client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
8131
- log24.warn(TAG22, `#${card.short_id} labelled "${NEED_REVIEW_LABEL}" (${handbackVerdict.reason}) so the daemon stops re-claiming and re-reviewing it`);
7738
+ log23.warn(TAG21, `#${card.short_id} labelled "${NEED_REVIEW_LABEL}" (${handbackVerdict.reason}) so the daemon stops re-claiming and re-reviewing it`);
8132
7739
  } catch (err) {
8133
- log24.warn(TAG22, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
7740
+ log23.warn(TAG21, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
8134
7741
  }
8135
7742
  }
8136
7743
  const currentCycle = getReviewCycle(freshDesc) + 1;
8137
7744
  const maxCycles = config.review.maxReviewCycles;
8138
7745
  if (result.verdict === "error") {
8139
- log24.warn(TAG22, `#${card.short_id} review output unparseable — labelling "${NEED_REVIEW_LABEL}" for manual inspection`);
7746
+ log23.warn(TAG21, `#${card.short_id} review output unparseable — labelling "${NEED_REVIEW_LABEL}" for manual inspection`);
8140
7747
  try {
8141
7748
  await addLabelByName(client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
8142
7749
  } catch (err) {
8143
- log24.warn(TAG22, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
7750
+ log23.warn(TAG21, `Failed to add "${NEED_REVIEW_LABEL}" label: ${err instanceof Error ? err.message : err}`);
8144
7751
  }
8145
7752
  if (config.review.postFindings) {
8146
7753
  const rawTail = runLogPath ? tailRunLog(runLogPath) : null;
@@ -8183,7 +7790,7 @@ ${runLogTail}
8183
7790
  renameRemoteBranch(branchName, newRef, worktreePath);
8184
7791
  approvedBranch = newRef;
8185
7792
  } catch (err) {
8186
- log24.warn(TAG22, `Branch rename failed (continuing on ${branchName}): ${err instanceof Error ? err.message : err}`);
7793
+ log23.warn(TAG21, `Branch rename failed (continuing on ${branchName}): ${err instanceof Error ? err.message : err}`);
8187
7794
  }
8188
7795
  }
8189
7796
  if (config.review.createPR && approvedBranch) {
@@ -8216,14 +7823,14 @@ ${runLogTail}
8216
7823
  await client.updateCard(card.id, { description: desc });
8217
7824
  }
8218
7825
  } catch (err) {
8219
- log24.warn(TAG22, `Failed to persist PR URL / branch rename to #${card.short_id} description: ${err instanceof Error ? err.message : err}`);
7826
+ log23.warn(TAG21, `Failed to persist PR URL / branch rename to #${card.short_id} description: ${err instanceof Error ? err.message : err}`);
8220
7827
  }
8221
7828
  }
8222
7829
  if (branchName) {
8223
7830
  try {
8224
7831
  await persistReviewedSha(client, card, worktreePath);
8225
7832
  } catch (err) {
8226
- log24.warn(TAG22, `Failed to persist Reviewed-SHA to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7833
+ log23.warn(TAG21, `Failed to persist Reviewed-SHA to #${card.short_id}: ${err instanceof Error ? err.message : err}`);
8227
7834
  }
8228
7835
  }
8229
7836
  if (config.review.postFindings) {
@@ -8246,7 +7853,7 @@ ${runLogTail}
8246
7853
  progressPercent: 100,
8247
7854
  ...buildTokenPayload(sessionStats)
8248
7855
  });
8249
- log24.info(TAG22, `#${card.short_id} approved${prUrl ? ` — PR: ${prUrl}` : ""} — labeled "${config.review.approvedLabel}"`);
7856
+ log23.info(TAG21, `#${card.short_id} approved${prUrl ? ` — PR: ${prUrl}` : ""} — labeled "${config.review.approvedLabel}"`);
8250
7857
  } else {
8251
7858
  const reworkFindings = result.findings.filter((f) => f.relatedToDiff !== false);
8252
7859
  const criticalFindings = reworkFindings.filter((f) => f.severity === "critical").slice(0, MAX_FINDINGS);
@@ -8254,7 +7861,7 @@ ${runLogTail}
8254
7861
  const linkedFindings = [...criticalFindings, ...majorFindings];
8255
7862
  const minorFindings = reworkFindings.filter((f) => f.severity === "minor").slice(0, MAX_FINDINGS);
8256
7863
  if (currentCycle >= maxCycles) {
8257
- log24.warn(TAG22, `#${card.short_id} reached max review cycles (${maxCycles}), moving to Done with note`);
7864
+ log23.warn(TAG21, `#${card.short_id} reached max review cycles (${maxCycles}), moving to Done with note`);
8258
7865
  if (handbackVerdict.proceed) {
8259
7866
  await moveCardToColumn(client, freshCard ?? card, config.review.moveToColumn);
8260
7867
  } else {
@@ -8272,22 +7879,6 @@ ${runLogTail}
8272
7879
  status: "completed",
8273
7880
  ...buildTokenPayload(sessionStats)
8274
7881
  });
8275
- if (workspaceId) {
8276
- const origId = await findLatestImplementEpisode(client, workspaceId, card.project_id, card.short_id);
8277
- const reviewId = await writeEpisode(client, {
8278
- kind: "review",
8279
- card,
8280
- workspaceId,
8281
- verdict: "rejected",
8282
- summary: `Reached max review cycles (${maxCycles}). ${result.summary}`,
8283
- cost: sessionStats?.cost ?? null,
8284
- agentSessionId: agentSessionId ?? null,
8285
- originalEpisodeId: origId
8286
- });
8287
- if (origId) {
8288
- await backfillReviewVerdict(client, origId, "rejected", reviewId);
8289
- }
8290
- }
8291
7882
  if (branchName) {
8292
7883
  cleanupWorktree3(worktreePath, branchName);
8293
7884
  }
@@ -8298,7 +7889,7 @@ ${runLogTail}
8298
7889
  try {
8299
7890
  await client.createSubtask(card.id, clampSubtaskTitle(`[${finding.severity}] ${finding.title}`));
8300
7891
  } catch (err) {
8301
- log24.error(TAG22, `Failed to create finding subtask: ${err instanceof Error ? err.message : err}`);
7892
+ log23.error(TAG21, `Failed to create finding subtask: ${err instanceof Error ? err.message : err}`);
8302
7893
  }
8303
7894
  }));
8304
7895
  if (linkedFindings.length > 0) {
@@ -8310,7 +7901,7 @@ ${runLogTail}
8310
7901
  try {
8311
7902
  await client.createSubtask(card.id, clampSubtaskTitle(finding.title));
8312
7903
  } catch (err) {
8313
- log24.error(TAG22, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
7904
+ log23.error(TAG21, `Failed to create subtask: ${err instanceof Error ? err.message : err}`);
8314
7905
  }
8315
7906
  }));
8316
7907
  if (handbackVerdict.proceed) {
@@ -8319,7 +7910,7 @@ ${runLogTail}
8319
7910
  try {
8320
7911
  await client.updateCard(card.id, { description: updatedDesc });
8321
7912
  } catch (err) {
8322
- log24.error(TAG22, `Failed to update review cycle marker: ${err instanceof Error ? err.message : err}`);
7913
+ log23.error(TAG21, `Failed to update review cycle marker: ${err instanceof Error ? err.message : err}`);
8323
7914
  }
8324
7915
  }
8325
7916
  const scopeLine = result.scopeCheck ? `Scope: ${result.scopeCheck.status}${result.scopeCheck.notes ? ` — ${result.scopeCheck.notes}` : ""}` : "";
@@ -8338,9 +7929,9 @@ ${runLogTail}
8338
7929
  if (handbackVerdict.proceed && config.planning.enabled && card.plan_id) {
8339
7930
  try {
8340
7931
  await client.updateCard(card.id, { needsPlanRefresh: true });
8341
- log24.info(TAG22, `#${card.short_id} flagged needs_plan_refresh after rejected review`);
7932
+ log23.info(TAG21, `#${card.short_id} flagged needs_plan_refresh after rejected review`);
8342
7933
  } catch (err) {
8343
- log24.warn(TAG22, `Failed to flag needs_plan_refresh for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
7934
+ log23.warn(TAG21, `Failed to flag needs_plan_refresh for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
8344
7935
  }
8345
7936
  }
8346
7937
  if (handbackVerdict.proceed) {
@@ -8358,10 +7949,10 @@ ${runLogTail}
8358
7949
  recoveryBranch
8359
7950
  });
8360
7951
  } catch (err) {
8361
- log24.debug(TAG22, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
7952
+ log23.debug(TAG21, `recordFailureSummary failed: ${err instanceof Error ? err.message : err}`);
8362
7953
  }
8363
7954
  if (recoveryBranch) {
8364
- log24.info(TAG22, `#${card.short_id} recovery branch ${recoveryBranch}${recoveryUrl ? ` (${recoveryUrl})` : ""}`);
7955
+ log23.info(TAG21, `#${card.short_id} recovery branch ${recoveryBranch}${recoveryUrl ? ` (${recoveryUrl})` : ""}`);
8365
7956
  }
8366
7957
  await client.endAgentSession(card.id, {
8367
7958
  status: "failed",
@@ -8370,35 +7961,18 @@ ${runLogTail}
8370
7961
  recoveryBranch,
8371
7962
  ...buildTokenPayload(sessionStats)
8372
7963
  });
8373
- log24.info(TAG22, `#${card.short_id} rejected (cycle ${currentCycle}/${maxCycles}) — moved to "${config.review.failColumn}"`);
8374
- }
8375
- if (workspaceId && (result.verdict === "approved" || result.verdict === "rejected")) {
8376
- const originalEpisodeId = await findLatestImplementEpisode(client, workspaceId, card.project_id, card.short_id);
8377
- const reviewEpisodeId = await writeEpisode(client, {
8378
- kind: "review",
8379
- card,
8380
- workspaceId,
8381
- verdict: result.verdict,
8382
- summary: result.summary,
8383
- cost: sessionStats?.cost ?? null,
8384
- agentSessionId: agentSessionId ?? null,
8385
- originalEpisodeId
8386
- });
8387
- if (originalEpisodeId) {
8388
- await backfillReviewVerdict(client, originalEpisodeId, result.verdict, reviewEpisodeId);
8389
- }
7964
+ log23.info(TAG21, `#${card.short_id} rejected (cycle ${currentCycle}/${maxCycles}) — moved to "${config.review.failColumn}"`);
8390
7965
  }
8391
7966
  if (branchName) {
8392
7967
  cleanupWorktree3(worktreePath, branchName);
8393
7968
  }
8394
7969
  }
8395
- var TAG22 = "review-completion", MAX_FINDINGS = 10, MAX_SUBTASK_TITLE = 120, COMMENT_BODY_BUDGET = 9500, REVIEW_MARKER = `---
7970
+ var TAG21 = "review-completion", MAX_FINDINGS = 10, MAX_SUBTASK_TITLE = 120, COMMENT_BODY_BUDGET = 9500, REVIEW_MARKER = `---
8396
7971
  **Review:`, RUN_LOG_TAIL_BYTES = 2048;
8397
7972
  var init_review_completion = __esm(() => {
8398
7973
  init_dist();
8399
7974
  init_board_helpers();
8400
7975
  init_completion();
8401
- init_episode_writer();
8402
7976
  init_handback();
8403
7977
  init_types2();
8404
7978
  });
@@ -8623,7 +8197,7 @@ import {
8623
8197
  mkdirSync as mkdirSync3
8624
8198
  } from "node:fs";
8625
8199
  import { join as join5 } from "node:path";
8626
- import { log as log25 } from "@gethmy/harness";
8200
+ import { log as log24 } from "@gethmy/harness";
8627
8201
  function runLogPath(runId, shortId) {
8628
8202
  return join5(runsDir(), `${runId}-card-${shortId}.log`);
8629
8203
  }
@@ -8637,7 +8211,7 @@ function appendRunLog(tag, runId, shortId, line) {
8637
8211
  `, "utf-8");
8638
8212
  return path;
8639
8213
  } catch (err) {
8640
- log25.warn(tag, `Failed to append to run log: ${err instanceof Error ? err.message : err}`);
8214
+ log24.warn(tag, `Failed to append to run log: ${err instanceof Error ? err.message : err}`);
8641
8215
  return null;
8642
8216
  }
8643
8217
  }
@@ -8649,11 +8223,11 @@ function openRunLog(tag, runId, shortId) {
8649
8223
  const path = runLogPath(runId, shortId);
8650
8224
  const stream = createWriteStream(path, { flags: "a" });
8651
8225
  stream.on("error", (err) => {
8652
- log25.warn(tag, `Run log ${path} failed: ${err.message}`);
8226
+ log24.warn(tag, `Run log ${path} failed: ${err.message}`);
8653
8227
  });
8654
8228
  return { path, stream };
8655
8229
  } catch (err) {
8656
- log25.warn(tag, `Failed to open run log: ${err instanceof Error ? err.message : err}`);
8230
+ log24.warn(tag, `Failed to open run log: ${err instanceof Error ? err.message : err}`);
8657
8231
  return null;
8658
8232
  }
8659
8233
  }
@@ -8690,7 +8264,7 @@ function isOwnNoticeConflict(err) {
8690
8264
  const driver = sessionConflictDriver(err);
8691
8265
  return driver === null || driver === NOTICE_DRIVER;
8692
8266
  }
8693
- async function startSessionYieldingNotice(start, client, cardId, log26) {
8267
+ async function startSessionYieldingNotice(start, client, cardId, log25) {
8694
8268
  try {
8695
8269
  return await start();
8696
8270
  } catch (err) {
@@ -8699,12 +8273,12 @@ async function startSessionYieldingNotice(start, client, cardId, log26) {
8699
8273
  try {
8700
8274
  const { session } = await client.getAgentSession(cardId);
8701
8275
  if (!session) {
8702
- log26.info(`The session that refused the start is already gone — retrying: ${err instanceof Error ? err.message : String(err)}`);
8276
+ log25.info(`The session that refused the start is already gone — retrying: ${err instanceof Error ? err.message : String(err)}`);
8703
8277
  } else if (!isPoolNotice(session)) {
8704
- log26.warn("The session that refused the start is not a pool notice on a re-read — leaving it alone");
8278
+ log25.warn("The session that refused the start is not a pool notice on a re-read — leaving it alone");
8705
8279
  throw err;
8706
8280
  } else {
8707
- log26.info(`Ending this pool's own notice on the card and retrying the session start: ${err instanceof Error ? err.message : String(err)}`);
8281
+ log25.info(`Ending this pool's own notice on the card and retrying the session start: ${err instanceof Error ? err.message : String(err)}`);
8708
8282
  await client.endAgentSession(cardId, {
8709
8283
  status: "failed",
8710
8284
  failureReason: "stale",
@@ -8714,7 +8288,7 @@ async function startSessionYieldingNotice(start, client, cardId, log26) {
8714
8288
  } catch (endErr) {
8715
8289
  if (endErr === err)
8716
8290
  throw err;
8717
- log26.warn(`Could not yield this pool's own notice: ${endErr instanceof Error ? endErr.message : String(endErr)}`);
8291
+ log25.warn(`Could not yield this pool's own notice: ${endErr instanceof Error ? endErr.message : String(endErr)}`);
8718
8292
  throw err;
8719
8293
  }
8720
8294
  return await start();
@@ -8751,7 +8325,7 @@ import {
8751
8325
  writeFileSync as writeFileSync2
8752
8326
  } from "node:fs";
8753
8327
  import { dirname as dirname2, join as join6 } from "node:path";
8754
- import { log as log26 } from "@gethmy/harness";
8328
+ import { log as log25 } from "@gethmy/harness";
8755
8329
  function emptyTokens() {
8756
8330
  return cloneWithoutPrototype({
8757
8331
  inputTokens: 0,
@@ -8890,7 +8464,7 @@ class StateStore {
8890
8464
  const raw = readFileSync6(this.path, "utf-8");
8891
8465
  const parsed = parseJsonWithoutPrototypes(raw);
8892
8466
  if (parsed?.version !== SCHEMA_VERSION) {
8893
- log26.warn(TAG23, `state file has version ${parsed?.version}, expected ${SCHEMA_VERSION} — migrating (preserving card budget/attempts, dropping in-flight runs)`);
8467
+ log25.warn(TAG22, `state file has version ${parsed?.version}, expected ${SCHEMA_VERSION} — migrating (preserving card budget/attempts, dropping in-flight runs)`);
8894
8468
  return cloneWithoutPrototype({
8895
8469
  version: SCHEMA_VERSION,
8896
8470
  daemonId: null,
@@ -8915,7 +8489,7 @@ class StateStore {
8915
8489
  account: parsed.account ?? emptyAccount()
8916
8490
  });
8917
8491
  } catch (err) {
8918
- log26.error(TAG23, `failed to read state file: ${err instanceof Error ? err.message : err}`);
8492
+ log25.error(TAG22, `failed to read state file: ${err instanceof Error ? err.message : err}`);
8919
8493
  return emptyState();
8920
8494
  }
8921
8495
  }
@@ -9273,7 +8847,7 @@ class StateStore {
9273
8847
  return this.state.daily.find((d) => d.date === key)?.costCents ?? 0;
9274
8848
  }
9275
8849
  }
9276
- var TAG23 = "state-store", SCHEMA_VERSION = 1;
8850
+ var TAG22 = "state-store", SCHEMA_VERSION = 1;
9277
8851
  var init_state_store = __esm(() => {
9278
8852
  init_dist();
9279
8853
  init_paths();
@@ -9281,7 +8855,7 @@ var init_state_store = __esm(() => {
9281
8855
 
9282
8856
  // src/stream-parser.ts
9283
8857
  import { EventEmitter } from "node:events";
9284
- import { log as log27 } from "@gethmy/harness";
8858
+ import { log as log26 } from "@gethmy/harness";
9285
8859
  function normalizeToolResultContent(raw) {
9286
8860
  if (raw == null)
9287
8861
  return;
@@ -9302,7 +8876,7 @@ function normalizeToolResultContent(raw) {
9302
8876
  return String(raw);
9303
8877
  }
9304
8878
  }
9305
- var TAG24 = "stream-parser", StreamParser;
8879
+ var TAG23 = "stream-parser", StreamParser;
9306
8880
  var init_stream_parser = __esm(() => {
9307
8881
  StreamParser = class StreamParser extends EventEmitter {
9308
8882
  buffer = "";
@@ -9349,14 +8923,14 @@ var init_stream_parser = __esm(() => {
9349
8923
  try {
9350
8924
  msg = JSON.parse(line);
9351
8925
  } catch {
9352
- log27.debug(TAG24, `Non-JSON line: ${line.slice(0, 100)}`);
8926
+ log26.debug(TAG23, `Non-JSON line: ${line.slice(0, 100)}`);
9353
8927
  return;
9354
8928
  }
9355
8929
  try {
9356
8930
  this.handleMessage(msg);
9357
8931
  } catch (err) {
9358
8932
  const errMsg = err instanceof Error ? err.message : String(err);
9359
- log27.warn(TAG24, `Error handling stream event: ${errMsg}`);
8933
+ log26.warn(TAG23, `Error handling stream event: ${errMsg}`);
9360
8934
  this.emit("parse_error", errMsg);
9361
8935
  }
9362
8936
  }
@@ -9432,7 +9006,7 @@ var init_stream_parser = __esm(() => {
9432
9006
  });
9433
9007
 
9434
9008
  // src/transitions.ts
9435
- import { log as log28 } from "@gethmy/harness";
9009
+ import { log as log27 } from "@gethmy/harness";
9436
9010
  async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9437
9011
  let lastErr;
9438
9012
  for (let i = 0;i < attempts; i++) {
@@ -9443,7 +9017,7 @@ async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9443
9017
  const msg2 = err instanceof Error ? err.message : String(err);
9444
9018
  if (i < attempts - 1) {
9445
9019
  const wait = backoffMs * 2 ** i;
9446
- log28.warn(TAG25, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9020
+ log27.warn(TAG24, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9447
9021
  await new Promise((r) => setTimeout(r, wait));
9448
9022
  }
9449
9023
  }
@@ -9467,10 +9041,10 @@ async function runTransition(client, card, plan, opts = {}) {
9467
9041
  if (opts.strictColumn) {
9468
9042
  throw new TransitionError("move", 1, msg);
9469
9043
  }
9470
- log28.warn(TAG25, `#${shortId}: ${msg} — skipping move`);
9044
+ log27.warn(TAG24, `#${shortId}: ${msg} — skipping move`);
9471
9045
  } else if (card.column_id !== target.id) {
9472
9046
  await withRetry("move", shortId, () => client.moveCard(card.id, target.id), attempts, backoffMs);
9473
- log28.info(TAG25, `#${shortId} → "${target.name}"`);
9047
+ log27.info(TAG24, `#${shortId} → "${target.name}"`);
9474
9048
  card.column_id = target.id;
9475
9049
  moveLanded = true;
9476
9050
  } else {
@@ -9489,7 +9063,7 @@ async function runTransition(client, card, plan, opts = {}) {
9489
9063
  continue;
9490
9064
  await withRetry("addLabel", shortId, () => client.addLabelToCard(card.id, labelId), attempts, backoffMs);
9491
9065
  existing.add(labelId);
9492
- log28.info(TAG25, `#${shortId} +label "${name}"`);
9066
+ log27.info(TAG24, `#${shortId} +label "${name}"`);
9493
9067
  }
9494
9068
  card.labelIds = Array.from(existing);
9495
9069
  }
@@ -9501,23 +9075,23 @@ async function runTransition(client, card, plan, opts = {}) {
9501
9075
  continue;
9502
9076
  await withRetry("removeLabel", shortId, () => client.removeLabelFromCard(card.id, match.id), attempts, backoffMs);
9503
9077
  existing.delete(match.id);
9504
- log28.info(TAG25, `#${shortId} -label "${name}"`);
9078
+ log27.info(TAG24, `#${shortId} -label "${name}"`);
9505
9079
  }
9506
9080
  card.labelIds = Array.from(existing);
9507
9081
  }
9508
9082
  if (plan.updateCard) {
9509
9083
  await withRetry("updateCard", shortId, () => client.updateCard(card.id, plan.updateCard), attempts, backoffMs);
9510
- log28.info(TAG25, `#${shortId} updated`);
9084
+ log27.info(TAG24, `#${shortId} updated`);
9511
9085
  }
9512
9086
  if (plan.endSession) {
9513
9087
  const endResult = await withRetry("endSession", shortId, () => client.endAgentSession(card.id, plan.endSession), attempts, backoffMs);
9514
9088
  result.endSession = endResult;
9515
- log28.info(TAG25, `#${shortId} session ended (${plan.endSession.status})`);
9089
+ log27.info(TAG24, `#${shortId} session ended (${plan.endSession.status})`);
9516
9090
  }
9517
9091
  if (plan.assignAgent !== undefined) {
9518
9092
  const assignedAgentId = plan.assignAgent;
9519
9093
  await withRetry("assignAgent", shortId, () => client.updateCard(card.id, { assignedAgentId }), attempts, backoffMs);
9520
- log28.info(TAG25, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9094
+ log27.info(TAG24, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9521
9095
  }
9522
9096
  if (opts.store && opts.runId) {
9523
9097
  try {
@@ -9531,11 +9105,11 @@ async function ensureLabel(client, projectId, name, color, attempts, backoffMs)
9531
9105
  const result = await withRetry("addLabel", 0, () => client.createLabel(projectId, { name, color: color ?? "#8b5cf6" }), attempts, backoffMs);
9532
9106
  return result?.label?.id ?? null;
9533
9107
  } catch (err) {
9534
- log28.warn(TAG25, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9108
+ log27.warn(TAG24, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9535
9109
  return null;
9536
9110
  }
9537
9111
  }
9538
- var TAG25 = "transition", TransitionError;
9112
+ var TAG24 = "transition", TransitionError;
9539
9113
  var init_transitions = __esm(() => {
9540
9114
  TransitionError = class TransitionError extends Error {
9541
9115
  step;
@@ -9565,7 +9139,7 @@ import {
9565
9139
  formatDiffSummary,
9566
9140
  GIT_NO_HOOKS as GIT_NO_HOOKS7,
9567
9141
  implementRunContainmentCliArgs,
9568
- log as log29,
9142
+ log as log28,
9569
9143
  probeDevServer,
9570
9144
  removeSandboxContainer,
9571
9145
  resolveStageGate,
@@ -9661,11 +9235,11 @@ class ReviewWorker {
9661
9235
  cliSessionId: this.cliSessionId
9662
9236
  });
9663
9237
  } catch (err) {
9664
- log29.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9238
+ log28.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9665
9239
  }
9666
9240
  }
9667
9241
  get tag() {
9668
- return `${TAG26}:${this.id}`;
9242
+ return `${TAG25}:${this.id}`;
9669
9243
  }
9670
9244
  get isIdle() {
9671
9245
  return this.state === "idle";
@@ -9703,7 +9277,7 @@ class ReviewWorker {
9703
9277
  try {
9704
9278
  const after = await this.stateStore.addTurns(cardId, numTurns);
9705
9279
  if (crossedTurnCap(before, after, cap)) {
9706
- log29.warn(TAG26, `#${this.stateStore.getRun(this.runId ?? "")?.cardShortId ?? cardId} reached its per-card turn cap on a review leg — ${after} of ${cap} turns. The implement pipeline will not pick it up again until it is reassigned or the cap is raised.`);
9280
+ log28.warn(TAG25, `#${this.stateStore.getRun(this.runId ?? "")?.cardShortId ?? cardId} reached its per-card turn cap on a review leg — ${after} of ${cap} turns. The implement pipeline will not pick it up again until it is reassigned or the cap is raised.`);
9707
9281
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
9708
9282
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), {
9709
9283
  commentType: "blocker",
@@ -9745,12 +9319,12 @@ class ReviewWorker {
9745
9319
  resumeMessage: null
9746
9320
  });
9747
9321
  } catch (err) {
9748
- log29.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9322
+ log28.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9749
9323
  }
9750
9324
  }
9751
9325
  try {
9752
9326
  this.state = "preparing";
9753
- log29.info(this.tag, resuming ? `Resuming review of #${card.short_id} "${card.title}" with ${this.grantedTurns ?? "the default"} more turns` : `Preparing review for #${card.short_id} "${card.title}"`);
9327
+ log28.info(this.tag, resuming ? `Resuming review of #${card.short_id} "${card.title}" with ${this.grantedTurns ?? "the default"} more turns` : `Preparing review for #${card.short_id} "${card.title}"`);
9754
9328
  this.startHeartbeat();
9755
9329
  if (!resuming) {
9756
9330
  await this.stateStore.insertRun({
@@ -9778,7 +9352,7 @@ class ReviewWorker {
9778
9352
  const resolution = await resolveReviewBranch(card.description, repoRoot);
9779
9353
  if (resolution.kind !== "branch") {
9780
9354
  const why = resolution.kind === "skip" ? resolution.reason : "no branch or PR reference";
9781
- log29.info(this.tag, `#${card.short_id} not auto-reviewable (${why}) — marking for human review (staying in Review)`);
9355
+ log28.info(this.tag, `#${card.short_id} not auto-reviewable (${why}) — marking for human review (staying in Review)`);
9782
9356
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9783
9357
  return;
9784
9358
  }
@@ -9789,13 +9363,13 @@ class ReviewWorker {
9789
9363
  reviewedSha: extractReviewedSha2(card.description ?? null)
9790
9364
  });
9791
9365
  if (continuity.kind === "skip") {
9792
- log29.warn(this.tag, `#${card.short_id} refusing the PR-derived re-review (${continuity.reason}) — marking for human review (staying in Review)`);
9366
+ log28.warn(this.tag, `#${card.short_id} refusing the PR-derived re-review (${continuity.reason}) — marking for human review (staying in Review)`);
9793
9367
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9794
9368
  return;
9795
9369
  }
9796
9370
  }
9797
9371
  this.branchName = resolution.branch;
9798
- log29.info(this.tag, `Review branch: ${this.branchName}`);
9372
+ log28.info(this.tag, `Review branch: ${this.branchName}`);
9799
9373
  let reviewSession;
9800
9374
  try {
9801
9375
  const startSession = () => this.client.startAgentSession(card.id, {
@@ -9811,14 +9385,14 @@ class ReviewWorker {
9811
9385
  awaitingDecisionUntil: null
9812
9386
  });
9813
9387
  const started = await startSessionYieldingNotice(startSession, this.client, card.id, {
9814
- info: (message) => log29.info(this.tag, message),
9815
- warn: (message) => log29.warn(this.tag, message)
9388
+ info: (message) => log28.info(this.tag, message),
9389
+ warn: (message) => log28.warn(this.tag, message)
9816
9390
  });
9817
9391
  reviewSession = started.session;
9818
9392
  } catch (err) {
9819
9393
  if (isSessionConflict(err)) {
9820
9394
  this.sessionConflict = true;
9821
- log29.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9395
+ log28.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9822
9396
  return;
9823
9397
  }
9824
9398
  throw err;
@@ -9839,7 +9413,7 @@ class ReviewWorker {
9839
9413
  const cwd = this.worktreePath;
9840
9414
  const devServer = await this.startDevServer(card, cwd, port);
9841
9415
  if (devServer.skipReason) {
9842
- log29.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9416
+ log28.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9843
9417
  }
9844
9418
  await this.client.updateAgentProgress(card.id, {
9845
9419
  agentIdentifier: this.sessionIdentifier,
@@ -9877,10 +9451,10 @@ class ReviewWorker {
9877
9451
  pinnedContract = extractPinnedContract(comments, this.identity);
9878
9452
  }
9879
9453
  } catch (err) {
9880
- log29.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9454
+ log28.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9881
9455
  }
9882
9456
  if (pinnedContract) {
9883
- log29.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9457
+ log28.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9884
9458
  }
9885
9459
  }
9886
9460
  const systemPrompt = buildReviewSystemPrompt();
@@ -9895,7 +9469,7 @@ class ReviewWorker {
9895
9469
  } else {
9896
9470
  const planCriteria2 = await fetchAcceptanceCriteria(this.client, this.tag, card);
9897
9471
  if (planCriteria2.length > 0) {
9898
- log29.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9472
+ log28.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9899
9473
  }
9900
9474
  userPrompt = buildReviewUserPrompt(enriched, this.branchName, cwd, previewUrl, diffSummary, this.config.worktree.baseBranch, undefined, pinnedContract, planCriteria2, devServer.skipReason);
9901
9475
  if (resuming && this.resumeMessage) {
@@ -9912,7 +9486,7 @@ ${userPrompt}`;
9912
9486
  contextIncluded: { source: "review-knowledge", mode: "review" }
9913
9487
  });
9914
9488
  } catch (err) {
9915
- log29.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9489
+ log28.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9916
9490
  }
9917
9491
  await this.client.updateAgentProgress(card.id, {
9918
9492
  agentIdentifier: this.sessionIdentifier,
@@ -9922,7 +9496,7 @@ ${userPrompt}`;
9922
9496
  progressPercent: 20
9923
9497
  });
9924
9498
  this.timeoutTimer = setTimeout(() => {
9925
- log29.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9499
+ log28.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9926
9500
  this.timedOut = true;
9927
9501
  this.cancel("timeout");
9928
9502
  }, this.config.review.maxTimeout);
@@ -9944,10 +9518,10 @@ ${userPrompt}`;
9944
9518
  }
9945
9519
  this.state = "completing";
9946
9520
  await this.recordPhase("completing");
9947
- log29.info(this.tag, `Claude review finished for #${card.short_id}`);
9521
+ log28.info(this.tag, `Claude review finished for #${card.short_id}`);
9948
9522
  this.killDevServer();
9949
9523
  const result = parseReviewOutput(stdout);
9950
- log29.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9524
+ log28.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9951
9525
  await this.client.updateAgentProgress(card.id, {
9952
9526
  agentIdentifier: this.sessionIdentifier,
9953
9527
  agentName: `${AGENT_NAME} (Review)`,
@@ -9955,7 +9529,7 @@ ${userPrompt}`;
9955
9529
  currentTask: `Processing ${result.verdict} verdict`,
9956
9530
  progressPercent: 80
9957
9531
  });
9958
- await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.workspaceId, this.sessionId, this.stateStore, this.identity.agentId, reviewedFromPrUrl(card.description), devServer.skipReason);
9532
+ await runReviewCompletion(this.client, card, result, this.config, cwd, this.branchName, sessionStats, this.lastRunLogPath, this.sessionId, this.stateStore, this.identity.agentId, reviewedFromPrUrl(card.description), devServer.skipReason);
9959
9533
  await this.collectReviewGate(card, result);
9960
9534
  } catch (err) {
9961
9535
  if (err instanceof BudgetPauseError) {
@@ -9969,7 +9543,7 @@ ${userPrompt}`;
9969
9543
  this.state = "error";
9970
9544
  const msg = err instanceof Error ? err.message : String(err);
9971
9545
  this.lastErrorMessage = msg;
9972
- log29.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9546
+ log28.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9973
9547
  this.lastRunLogPath = appendRunLog(this.tag, this.runId, card.short_id, `[${new Date().toISOString()}] review failed before completion: ${msg}`) ?? this.lastRunLogPath;
9974
9548
  const reviewHandback = await guardedHandback(this.client, card.id, {
9975
9549
  agentId: this.identity.agentId,
@@ -9985,7 +9559,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9985
9559
  agentSessionId: this.sessionId ?? undefined
9986
9560
  });
9987
9561
  } catch (cErr) {
9988
- log29.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9562
+ log28.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9989
9563
  }
9990
9564
  }
9991
9565
  try {
@@ -9997,21 +9571,21 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9997
9571
  }
9998
9572
  });
9999
9573
  } catch (tErr) {
10000
- log29.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
9574
+ log28.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
10001
9575
  }
10002
9576
  if (reviewHandback.verdict.proceed) {
10003
9577
  try {
10004
9578
  await moveCardToColumn(this.client, reviewHandback.card ?? card, this.config.review.failColumn);
10005
- log29.info(this.tag, `Moved #${card.short_id} to "${this.config.review.failColumn}" after error`);
9579
+ log28.info(this.tag, `Moved #${card.short_id} to "${this.config.review.failColumn}" after error`);
10006
9580
  } catch {
10007
- log29.warn(this.tag, "Failed to move card to fail column after error");
9581
+ log28.warn(this.tag, "Failed to move card to fail column after error");
10008
9582
  }
10009
9583
  } else if (reviewHandback.verdict.reason === "unreadable" || reviewHandback.verdict.reason === "released" || reviewHandback.verdict.reason === "done") {
10010
9584
  try {
10011
9585
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
10012
- log29.warn(this.tag, `#${card.short_id} could not be re-read — labelled "${NEED_REVIEW_LABEL}" so reconcile stops re-enqueueing the review`);
9586
+ log28.warn(this.tag, `#${card.short_id} could not be re-read — labelled "${NEED_REVIEW_LABEL}" so reconcile stops re-enqueueing the review`);
10013
9587
  } catch {
10014
- log29.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
9588
+ log28.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
10015
9589
  }
10016
9590
  }
10017
9591
  if (this.runId) {
@@ -10055,7 +9629,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10055
9629
  const holderMessage = err instanceof Error ? err.message : String(err);
10056
9630
  const waitHours = this.config.budget.pause.waitHours;
10057
9631
  const until = computeDecisionDeadline(waitHours);
10058
- log29.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
9632
+ log28.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
10059
9633
  try {
10060
9634
  await this.client.addComment(card.id, formatResumeConflictComment({
10061
9635
  holderMessage,
@@ -10067,7 +9641,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10067
9641
  agentSessionId: this.sessionId ?? undefined
10068
9642
  });
10069
9643
  } catch (commentErr) {
10070
- log29.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
9644
+ log28.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
10071
9645
  }
10072
9646
  if (this.runId) {
10073
9647
  const run = this.stateStore.getRun(this.runId);
@@ -10078,7 +9652,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10078
9652
  awaitingDecisionUntil: until
10079
9653
  });
10080
9654
  } catch (storeErr) {
10081
- log29.error(this.tag, `#${card.short_id} could not be re-parked after a resume conflict — the daemon has no hold on it: ${storeErr}`);
9655
+ log28.error(this.tag, `#${card.short_id} could not be re-parked after a resume conflict — the daemon has no hold on it: ${storeErr}`);
10082
9656
  }
10083
9657
  }
10084
9658
  }
@@ -10091,7 +9665,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10091
9665
  this.progressTracker = null;
10092
9666
  const waitHours = this.config.budget.pause.waitHours;
10093
9667
  const until = computeDecisionDeadline(waitHours);
10094
- log29.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
9668
+ log28.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
10095
9669
  const body = formatBudgetComment({
10096
9670
  trigger,
10097
9671
  numTurns: stats?.cost?.numTurns ?? 0,
@@ -10113,7 +9687,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10113
9687
  });
10114
9688
  commentId = res?.comment?.id ?? null;
10115
9689
  } catch (err) {
10116
- log29.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
9690
+ log28.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
10117
9691
  }
10118
9692
  try {
10119
9693
  await this.client.updateAgentProgress(card.id, {
@@ -10124,7 +9698,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10124
9698
  awaitingDecisionUntil: new Date(until).toISOString()
10125
9699
  });
10126
9700
  } catch (err) {
10127
- log29.warn(this.tag, `Failed to mark the session blocked: ${err}`);
9701
+ log28.warn(this.tag, `Failed to mark the session blocked: ${err}`);
10128
9702
  }
10129
9703
  if (this.runId) {
10130
9704
  try {
@@ -10135,14 +9709,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10135
9709
  ...this.endLedger()
10136
9710
  });
10137
9711
  } catch (err) {
10138
- log29.error(this.tag, `#${card.short_id} parkRun failed after the blocker comment + blocked session were already written — the daemon has no local record of this park: ${err}`);
9712
+ log28.error(this.tag, `#${card.short_id} parkRun failed after the blocker comment + blocked session were already written — the daemon has no local record of this park: ${err}`);
10139
9713
  }
10140
9714
  }
10141
9715
  }
10142
9716
  async pause() {
10143
9717
  if (!this.isActive || !this.process || this.process.killed)
10144
9718
  return;
10145
- log29.info(this.tag, `Pausing review on ${this.cardId}`);
9719
+ log28.info(this.tag, `Pausing review on ${this.cardId}`);
10146
9720
  signalGroup(this.process, "SIGSTOP");
10147
9721
  if (this.timeoutTimer) {
10148
9722
  clearTimeout(this.timeoutTimer);
@@ -10156,17 +9730,17 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10156
9730
  status: "paused"
10157
9731
  });
10158
9732
  } catch {
10159
- log29.warn(this.tag, "Failed to update agent session to paused");
9733
+ log28.warn(this.tag, "Failed to update agent session to paused");
10160
9734
  }
10161
9735
  }
10162
9736
  }
10163
9737
  async resume() {
10164
9738
  if (!this.isActive || !this.process || this.process.killed)
10165
9739
  return;
10166
- log29.info(this.tag, `Resuming review on ${this.cardId}`);
9740
+ log28.info(this.tag, `Resuming review on ${this.cardId}`);
10167
9741
  signalGroup(this.process, "SIGCONT");
10168
9742
  this.timeoutTimer = setTimeout(() => {
10169
- log29.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9743
+ log28.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
10170
9744
  this.timedOut = true;
10171
9745
  this.cancel("timeout");
10172
9746
  }, this.config.review.maxTimeout);
@@ -10178,7 +9752,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10178
9752
  status: "working"
10179
9753
  });
10180
9754
  } catch {
10181
- log29.warn(this.tag, "Failed to update agent session to working");
9755
+ log28.warn(this.tag, "Failed to update agent session to working");
10182
9756
  }
10183
9757
  }
10184
9758
  }
@@ -10187,7 +9761,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10187
9761
  return;
10188
9762
  this.aborted = true;
10189
9763
  this.state = "cancelling";
10190
- log29.info(this.tag, `Cancelling review on ${this.cardId}`);
9764
+ log28.info(this.tag, `Cancelling review on ${this.cardId}`);
10191
9765
  const snapshotStats = this.lastSessionStats ?? this.progressTracker?.stats;
10192
9766
  if (this.progressTracker) {
10193
9767
  this.progressTracker?.stop();
@@ -10240,11 +9814,11 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10240
9814
  "--",
10241
9815
  prompt
10242
9816
  ];
10243
- log29.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
9817
+ log28.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
10244
9818
  const runLog = openRunLog(this.tag, this.runId, shortId);
10245
9819
  this.lastRunLogPath = runLog?.path ?? null;
10246
9820
  if (runLog) {
10247
- log29.info(this.tag, `Run log: ${runLog.path}`);
9821
+ log28.info(this.tag, `Run log: ${runLog.path}`);
10248
9822
  runLog.stream.write(`# run=${this.runId} card=#${shortId} pipeline=review started=${new Date().toISOString()}
10249
9823
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
10250
9824
 
@@ -10263,7 +9837,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10263
9837
  this.captureCliSessionId(parser.sessionId);
10264
9838
  });
10265
9839
  parser.on("parse_error", (msg) => {
10266
- log29.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
9840
+ log28.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
10267
9841
  runLog?.stream.write(`
10268
9842
  [parse_error] ${msg}
10269
9843
  `);
@@ -10342,16 +9916,16 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10342
9916
  const evidence = await collectGateEvidence(registry, context);
10343
9917
  const evaluation = gateEvaluate(resolved.gate, evidence);
10344
9918
  await this.client.request("POST", `/cards/${encodeURIComponent(card.id)}/stage-gate-evidence`, toStageGateEvidenceInsert(context, evidence));
10345
- log29.info(this.tag, `Recorded review_passed gate evidence for #${card.short_id} stage "${resolved.stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
9919
+ log28.info(this.tag, `Recorded review_passed gate evidence for #${card.short_id} stage "${resolved.stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
10346
9920
  } catch (err) {
10347
- log29.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9921
+ log28.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10348
9922
  }
10349
9923
  }
10350
9924
  async startDevServer(card, cwd, port) {
10351
9925
  const declined = devServerSkipReason(cwd, this.config.commands);
10352
9926
  if (declined)
10353
9927
  return { previewUrl: null, skipReason: declined };
10354
- log29.info(this.tag, `Starting dev server on port ${port}...`);
9928
+ log28.info(this.tag, `Starting dev server on port ${port}...`);
10355
9929
  const launch = devServerLaunch({
10356
9930
  worktreePath: cwd,
10357
9931
  port,
@@ -10392,14 +9966,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10392
9966
  skipReason: launch.origin ? `${launch.origin}, and ${failure}` : failure
10393
9967
  };
10394
9968
  }
10395
- log29.info(this.tag, `Dev server ready on port ${port}`);
9969
+ log28.info(this.tag, `Dev server ready on port ${port}`);
10396
9970
  return { previewUrl: `http://localhost:${port}`, skipReason: null };
10397
9971
  }
10398
9972
  killDevServer() {
10399
9973
  if (this.devServerProcess && !this.devServerProcess.killed) {
10400
9974
  signalGroup(this.devServerProcess, "SIGTERM");
10401
9975
  this.devServerProcess = null;
10402
- log29.debug(this.tag, "Killed dev server group");
9976
+ log28.debug(this.tag, "Killed dev server group");
10403
9977
  }
10404
9978
  if (this.devServerContainer) {
10405
9979
  const name = this.devServerContainer;
@@ -10422,7 +9996,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10422
9996
  try {
10423
9997
  cleanupWorktree4(this.worktreePath);
10424
9998
  } catch {
10425
- log29.warn(this.tag, "Failed to cleanup review worktree");
9999
+ log28.warn(this.tag, "Failed to cleanup review worktree");
10426
10000
  }
10427
10001
  }
10428
10002
  this.process = null;
@@ -10434,7 +10008,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10434
10008
  this.lastSessionStats = null;
10435
10009
  }
10436
10010
  }
10437
- var TAG26 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10011
+ var TAG25 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10438
10012
  var init_review_worker = __esm(() => {
10439
10013
  init_dist();
10440
10014
  init_board_helpers();
@@ -10458,7 +10032,7 @@ var init_review_worker = __esm(() => {
10458
10032
 
10459
10033
  // src/sleep-guard.ts
10460
10034
  import { spawn } from "node:child_process";
10461
- import { log as log30 } from "@gethmy/harness";
10035
+ import { log as log29 } from "@gethmy/harness";
10462
10036
 
10463
10037
  class SleepGuard {
10464
10038
  platform;
@@ -10486,7 +10060,7 @@ class SleepGuard {
10486
10060
  if (!this.child.killed)
10487
10061
  this.child.kill("SIGTERM");
10488
10062
  this.child = null;
10489
- log30.info(TAG27, "sleep assertion released");
10063
+ log29.info(TAG26, "sleep assertion released");
10490
10064
  }
10491
10065
  }
10492
10066
  start() {
@@ -10501,7 +10075,7 @@ class SleepGuard {
10501
10075
  spawned = true;
10502
10076
  });
10503
10077
  child.on("error", (err) => {
10504
- log30.warn(TAG27, `caffeinate unavailable: ${err.message}`);
10078
+ log29.warn(TAG26, `caffeinate unavailable: ${err.message}`);
10505
10079
  if (this.child === child)
10506
10080
  this.child = null;
10507
10081
  });
@@ -10514,23 +10088,23 @@ class SleepGuard {
10514
10088
  });
10515
10089
  child.unref();
10516
10090
  this.child = child;
10517
- log30.info(TAG27, "sleep assertion acquired (caffeinate -i)");
10091
+ log29.info(TAG26, "sleep assertion acquired (caffeinate -i)");
10518
10092
  } catch (err) {
10519
- log30.warn(TAG27, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10093
+ log29.warn(TAG26, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10520
10094
  }
10521
10095
  }
10522
10096
  }
10523
- var TAG27 = "sleep-guard";
10097
+ var TAG26 = "sleep-guard";
10524
10098
  var init_sleep_guard = () => {};
10525
10099
 
10526
10100
  // src/unblock.ts
10527
- import { log as log31 } from "@gethmy/harness";
10101
+ import { log as log30 } from "@gethmy/harness";
10528
10102
  async function fetchBlocksLinks(client, cardId) {
10529
10103
  try {
10530
10104
  const { links } = await client.getCardLinks(cardId);
10531
10105
  return links.filter((l) => l.link_type === "blocks");
10532
10106
  } catch (err) {
10533
- log31.warn(TAG28, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10107
+ log30.warn(TAG27, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10534
10108
  return null;
10535
10109
  }
10536
10110
  }
@@ -10564,31 +10138,31 @@ async function promoteUnblockedSuccessors(completedCard, deps) {
10564
10138
  const successors = links.filter((l) => l.direction === "outgoing" && !l.target_card.done);
10565
10139
  if (successors.length === 0)
10566
10140
  return;
10567
- log31.info(TAG28, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10141
+ log30.info(TAG27, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10568
10142
  for (const link of successors) {
10569
10143
  const successorId = link.target_card.id;
10570
10144
  try {
10571
10145
  const { card } = await deps.client.getCard(successorId);
10572
10146
  if (card.assigned_agent_id === deps.agentId) {} else if (card.assigned_agent_id === null && !card.assignee_id) {
10573
- log31.info(TAG28, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
10147
+ log30.info(TAG27, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
10574
10148
  await deps.client.updateCard(successorId, {
10575
10149
  assignedAgentId: deps.agentId
10576
10150
  });
10577
10151
  } else {
10578
- log31.debug(TAG28, `successor #${card.short_id} assigned to different entity — skipping`);
10152
+ log30.debug(TAG27, `successor #${card.short_id} assigned to different entity — skipping`);
10579
10153
  continue;
10580
10154
  }
10581
10155
  await deps.enqueue(successorId);
10582
10156
  } catch (err) {
10583
- log31.warn(TAG28, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10157
+ log30.warn(TAG27, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10584
10158
  }
10585
10159
  }
10586
10160
  }
10587
- var TAG28 = "unblock";
10161
+ var TAG27 = "unblock";
10588
10162
  var init_unblock = () => {};
10589
10163
 
10590
10164
  // src/cli-agent-runner.ts
10591
- import { log as log32 } from "@gethmy/harness";
10165
+ import { log as log31 } from "@gethmy/harness";
10592
10166
  function truncateOutput(value) {
10593
10167
  return value === undefined ? undefined : value.slice(0, MAX_OUTPUT_CHARS);
10594
10168
  }
@@ -10753,7 +10327,7 @@ class CliAgentRunner {
10753
10327
  return;
10754
10328
  const draft = sanitizeRunEventDraft(body);
10755
10329
  if (runEventPayloadExceedsLimit(draft.payload)) {
10756
- log32.warn(TAG29, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10330
+ log31.warn(TAG28, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10757
10331
  return;
10758
10332
  }
10759
10333
  this.buffer.push({ ...draft, createdAt: new Date().toISOString() });
@@ -10785,15 +10359,15 @@ class CliAgentRunner {
10785
10359
  this.requeue(batch);
10786
10360
  if (batch.length > 1) {
10787
10361
  this.nextBatchSize = Math.ceil(batch.length / 2);
10788
- log32.warn(TAG29, `Flush of ${batch.length} run event(s) failed ${MAX_BATCH_ATTEMPTS}×; bisecting to ${this.nextBatchSize}: ${err}`);
10362
+ log31.warn(TAG28, `Flush of ${batch.length} run event(s) failed ${MAX_BATCH_ATTEMPTS}×; bisecting to ${this.nextBatchSize}: ${err}`);
10789
10363
  return;
10790
10364
  }
10791
10365
  const dropped = this.buffer.shift();
10792
10366
  this.nextBatchSize = MAX_BUFFER;
10793
- log32.warn(TAG29, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10367
+ log31.warn(TAG28, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10794
10368
  return;
10795
10369
  }
10796
- log32.warn(TAG29, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10370
+ log31.warn(TAG28, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10797
10371
  this.requeue(batch);
10798
10372
  } finally {
10799
10373
  this.flushing = false;
@@ -10836,26 +10410,26 @@ function mapCost(cost) {
10836
10410
  durationMs: cost.durationMs
10837
10411
  };
10838
10412
  }
10839
- var TAG29 = "cli-agent-runner", FLUSH_INTERVAL_MS = 2000, MAX_BUFFER = 1000, MAX_TEXT_LEN = 8000, MAX_BATCH_ATTEMPTS = 3, FINAL_FLUSH_ATTEMPTS = 40;
10413
+ var TAG28 = "cli-agent-runner", FLUSH_INTERVAL_MS = 2000, MAX_BUFFER = 1000, MAX_TEXT_LEN = 8000, MAX_BATCH_ATTEMPTS = 3, FINAL_FLUSH_ATTEMPTS = 40;
10840
10414
  var init_cli_agent_runner = __esm(() => {
10841
10415
  init_dist();
10842
10416
  });
10843
10417
 
10844
10418
  // src/fanout.ts
10845
- import { log as log33 } from "@gethmy/harness";
10419
+ import { log as log32 } from "@gethmy/harness";
10846
10420
  async function fetchLinks(client, cardId) {
10847
10421
  try {
10848
10422
  const { links } = await client.getCardLinks(cardId);
10849
10423
  return links;
10850
10424
  } catch (err) {
10851
- log33.warn(TAG30, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10425
+ log32.warn(TAG29, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10852
10426
  return null;
10853
10427
  }
10854
10428
  }
10855
10429
  async function isFanoutChildOf(card, stage, client) {
10856
10430
  const links = await fetchLinks(client, card.id);
10857
10431
  if (links === null) {
10858
- log33.warn(TAG30, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10432
+ log32.warn(TAG29, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10859
10433
  return true;
10860
10434
  }
10861
10435
  const parents = links.filter((l) => l.direction === "outgoing" && l.link_type === "is_part_of");
@@ -10942,7 +10516,7 @@ async function readStageHandoff(card, fromStage, deps) {
10942
10516
  }
10943
10517
  return null;
10944
10518
  } catch (err) {
10945
- log33.warn(TAG30, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10519
+ log32.warn(TAG29, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10946
10520
  return null;
10947
10521
  }
10948
10522
  }
@@ -11043,7 +10617,7 @@ async function dispatchWave(parent, stage, plan, items, deps) {
11043
10617
  });
11044
10618
  spawned = res.children ?? [];
11045
10619
  } catch (err) {
11046
- log33.warn(TAG30, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
10620
+ log32.warn(TAG29, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
11047
10621
  return 0;
11048
10622
  }
11049
10623
  let created = 0;
@@ -11098,10 +10672,10 @@ async function seedChildHandoff(parent, stage, item, total, childId, deps) {
11098
10672
  try {
11099
10673
  await deps.client.addComment(childId, body, { commentType: "decision" });
11100
10674
  } catch (err) {
11101
- log33.warn(TAG30, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
10675
+ log32.warn(TAG29, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
11102
10676
  }
11103
10677
  }
11104
- var TAG30 = "fanout";
10678
+ var TAG29 = "fanout";
11105
10679
  var init_fanout = __esm(() => {
11106
10680
  init_dist();
11107
10681
  });
@@ -11336,7 +10910,7 @@ function runSizedPayload(input) {
11336
10910
  }
11337
10911
 
11338
10912
  // src/stage-advance.ts
11339
- import { gateConfigErrorReason, log as log34 } from "@gethmy/harness";
10913
+ import { gateConfigErrorReason, log as log33 } from "@gethmy/harness";
11340
10914
  function endDispositionFor(outcome) {
11341
10915
  return "endDisposition" in outcome && outcome.endDisposition ? outcome.endDisposition : { status: "completed" };
11342
10916
  }
@@ -11367,7 +10941,7 @@ async function resolveStageColumnName(client, card, stage) {
11367
10941
  const match = board.columns.find((c) => c.id === target || c.name.toLowerCase() === target.toLowerCase());
11368
10942
  return match ? match.name : null;
11369
10943
  } catch (err) {
11370
- log34.warn(TAG31, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10944
+ log33.warn(TAG30, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11371
10945
  return null;
11372
10946
  }
11373
10947
  }
@@ -11406,7 +10980,7 @@ async function holdGateMisconfigured(card, stage, detail, deps) {
11406
10980
  });
11407
10981
  } catch {}
11408
10982
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, { agentSessionId: deps.agentSessionId });
11409
- log34.info(TAG31, `#${card.short_id} GateMisconfigured: ${reason}`);
10983
+ log33.info(TAG30, `#${card.short_id} GateMisconfigured: ${reason}`);
11410
10984
  return { kind: "held_misconfigured", reason, endDisposition };
11411
10985
  }
11412
10986
  function firstErrorMessage(evaluation) {
@@ -11437,7 +11011,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11437
11011
  evidence,
11438
11012
  summary
11439
11013
  });
11440
- log34.info(TAG31, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11014
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11441
11015
  if (decision === "exit") {
11442
11016
  await deps.stateStore.resetLoopIterations(card.id).catch(() => {});
11443
11017
  deps.sink?.recordLoopCompleted?.({
@@ -11482,7 +11056,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11482
11056
  blockers: [reason],
11483
11057
  agentSessionId: deps.agentSessionId
11484
11058
  });
11485
- log34.info(TAG31, `#${card.short_id} LoopExhausted: ${reason}`);
11059
+ log33.info(TAG30, `#${card.short_id} LoopExhausted: ${reason}`);
11486
11060
  return { kind: "held_gate_unmet", reason, endDisposition };
11487
11061
  }
11488
11062
  const guard = await guardStageReclaim(card, `converge-loop iteration of "${stage.name}"`, deps);
@@ -11507,7 +11081,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11507
11081
  addLabels: [{ name: AGENT_LABEL }],
11508
11082
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11509
11083
  }, { store: deps.stateStore, runId: deps.runId });
11510
- log34.info(TAG31, `#${card.short_id} converge loop "${stage.name}" — requeued to "${toColumn}" for iteration ${iteration + 1}/${maxIterations}`);
11084
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}" — requeued to "${toColumn}" for iteration ${iteration + 1}/${maxIterations}`);
11511
11085
  return { kind: "requeued_gate_unmet", toColumn };
11512
11086
  }
11513
11087
  async function writeIterationHandoff(card, stage, iteration, maxIterations, evaluation, deps) {
@@ -11529,7 +11103,7 @@ ${findings.map((f) => `- [${f.level}] ${f.message}`).join(`
11529
11103
  agentSessionId: deps.agentSessionId ?? undefined
11530
11104
  });
11531
11105
  } catch (err) {
11532
- log34.warn(TAG31, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11106
+ log33.warn(TAG30, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11533
11107
  }
11534
11108
  }
11535
11109
  async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps) {
@@ -11557,7 +11131,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11557
11131
  reason: "Playbook complete — final stage gate passed."
11558
11132
  });
11559
11133
  deps.stateStore.recordOutcome(card.id, "success").catch(() => {});
11560
- log34.info(TAG31, `#${card.short_id} terminal stage "${stage.name}" passed — playbook complete (done left to the column)`);
11134
+ log33.info(TAG30, `#${card.short_id} terminal stage "${stage.name}" passed — playbook complete (done left to the column)`);
11561
11135
  return { kind: "completed_terminal" };
11562
11136
  }
11563
11137
  if (next.kind === "out_of_range") {
@@ -11589,7 +11163,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11589
11163
  ...isAgentRunnableOwner(next.stage.owner) ? { assignAgent: deps.agentId } : {}
11590
11164
  }, { store: deps.stateStore, runId: deps.runId });
11591
11165
  deps.stateStore.recordOutcome(card.id, "success").catch(() => {});
11592
- log34.info(TAG31, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11166
+ log33.info(TAG30, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11593
11167
  if (next.stage.owner === "human") {
11594
11168
  const reason = `Stage "${next.stage.name}" is yours: ${handoffText(next.stage)}`;
11595
11169
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, {
@@ -11626,7 +11200,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11626
11200
  blockers: [reason],
11627
11201
  agentSessionId: deps.agentSessionId
11628
11202
  });
11629
- log34.info(TAG31, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11203
+ log33.info(TAG30, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11630
11204
  return { kind: "held_gate_unmet", reason, endDisposition };
11631
11205
  }
11632
11206
  const guard = await guardStageReclaim(card, `gate-unmet re-run of "${stage.name}"`, deps);
@@ -11649,7 +11223,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11649
11223
  addLabels: [{ name: AGENT_LABEL }],
11650
11224
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11651
11225
  }, { store: deps.stateStore, runId: deps.runId });
11652
- log34.info(TAG31, `#${card.short_id} gate unmet for "${stage.name}" — requeued to "${toColumn}" for re-run (attempt ${attempts}/${deps.maxAttempts})`);
11226
+ log33.info(TAG30, `#${card.short_id} gate unmet for "${stage.name}" — requeued to "${toColumn}" for re-run (attempt ${attempts}/${deps.maxAttempts})`);
11653
11227
  return { kind: "requeued_gate_unmet", toColumn };
11654
11228
  }
11655
11229
  async function guardStageReclaim(card, what, deps) {
@@ -11675,10 +11249,10 @@ async function guardStageReclaim(card, what, deps) {
11675
11249
  }, { store: deps.stateStore, runId: deps.runId });
11676
11250
  released = stillOurs;
11677
11251
  } catch (err) {
11678
- log34.warn(TAG31, `#${card.short_id} could not hand the card over after refusing the ${what}: ${err instanceof Error ? err.message : err}${stillOurs ? " — the claim is still ours, so the next reconcile tick may re-pick the card" : ""}`);
11252
+ log33.warn(TAG30, `#${card.short_id} could not hand the card over after refusing the ${what}: ${err instanceof Error ? err.message : err}${stillOurs ? " — the claim is still ours, so the next reconcile tick may re-pick the card" : ""}`);
11679
11253
  }
11680
11254
  }
11681
- log34.info(TAG31, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11255
+ log33.info(TAG30, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11682
11256
  try {
11683
11257
  await deps.client.addComment(card.id, `Stopped the ${what} — ${detail}. The card is not the daemon's to reclaim, so this stage will not re-run until it is assigned back.`, {
11684
11258
  commentType: "decision",
@@ -11700,7 +11274,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11700
11274
  try {
11701
11275
  await runTransition(client, card, { removeLabels: [AGENT_LABEL] }, { store: stateStore, runId });
11702
11276
  } catch (err) {
11703
- log34.warn(TAG31, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11277
+ log33.warn(TAG30, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11704
11278
  }
11705
11279
  return {
11706
11280
  status: opts.endStatus ?? "paused",
@@ -11709,7 +11283,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11709
11283
  failureSummary: reason.slice(0, 300)
11710
11284
  };
11711
11285
  }
11712
- var TAG31 = "stage-advance", AGENT_LABEL = "agent";
11286
+ var TAG30 = "stage-advance", AGENT_LABEL = "agent";
11713
11287
  var init_stage_advance = __esm(() => {
11714
11288
  init_dist();
11715
11289
  init_handback();
@@ -11785,7 +11359,7 @@ import {
11785
11359
  GIT_NO_HOOKS as GIT_NO_HOOKS8,
11786
11360
  implementRunContainment,
11787
11361
  implementRunContainmentCliArgs as implementRunContainmentCliArgs2,
11788
- log as log35,
11362
+ log as log34,
11789
11363
  makeBranchName,
11790
11364
  normalizeGateSpec,
11791
11365
  pushBranch as pushBranch3,
@@ -11991,11 +11565,11 @@ class Worker {
11991
11565
  sessionId: this.sessionId
11992
11566
  });
11993
11567
  } catch (err) {
11994
- log35.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11568
+ log34.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11995
11569
  }
11996
11570
  }
11997
11571
  get tag() {
11998
- return `${TAG32}:${this.id}`;
11572
+ return `${TAG31}:${this.id}`;
11999
11573
  }
12000
11574
  get isIdle() {
12001
11575
  return this.state === "idle";
@@ -12057,12 +11631,12 @@ class Worker {
12057
11631
  }
12058
11632
  if (!crossedTurnCap(before, after, cap))
12059
11633
  return;
12060
- log35.warn(TAG32, `#${shortId ?? cardId} reached its per-card turn cap — ${after} of ${cap} turns. It will not be picked up again until it is reassigned or the cap is raised.`);
11634
+ log34.warn(TAG31, `#${shortId ?? cardId} reached its per-card turn cap — ${after} of ${cap} turns. It will not be picked up again until it is reassigned or the cap is raised.`);
12061
11635
  try {
12062
11636
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
12063
11637
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), { commentType: "blocker", agentSessionId: this.sessionId ?? undefined });
12064
11638
  } catch (err) {
12065
- log35.warn(TAG32, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
11639
+ log34.warn(TAG31, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
12066
11640
  }
12067
11641
  }
12068
11642
  async run(card, column, labels, subtasks) {
@@ -12117,7 +11691,7 @@ class Worker {
12117
11691
  resumeReason: null
12118
11692
  });
12119
11693
  } catch (err) {
12120
- log35.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
11694
+ log34.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
12121
11695
  }
12122
11696
  }
12123
11697
  try {
@@ -12125,20 +11699,20 @@ class Worker {
12125
11699
  if (!resuming) {
12126
11700
  this.branchName = makeBranchName(card.short_id, card.title, this.config.worktree.failedBranchPrefix);
12127
11701
  }
12128
- log35.info(this.tag, resuming ? `Resuming #${card.short_id} "${card.title}" with ${this.grantedTurns ?? "the default"} more turns` : `Preparing #${card.short_id} "${card.title}"`);
11702
+ log34.info(this.tag, resuming ? `Resuming #${card.short_id} "${card.title}" with ${this.grantedTurns ?? "the default"} more turns` : `Preparing #${card.short_id} "${card.title}"`);
12129
11703
  const attemptCount = await this.stateStore.incrementAttempt(card.id);
12130
11704
  const isRework = attemptCount > 1;
12131
11705
  const runStarts = this.stateStore.getCardRunStarts(card.id);
12132
11706
  const runCap = this.config.budget.maxRunsPerCard;
12133
11707
  if (crossedTurnCap(runStarts - 1, runStarts, runCap)) {
12134
- log35.warn(this.tag, `#${card.short_id} reached its per-card run backstop — ${runStarts} of ${runCap} run starts. It will not be picked up again until it is reassigned or the cap is raised.`);
11708
+ log34.warn(this.tag, `#${card.short_id} reached its per-card run backstop — ${runStarts} of ${runCap} run starts. It will not be picked up again until it is reassigned or the cap is raised.`);
12135
11709
  try {
12136
11710
  await this.client.addComment(card.id, buildRunCapComment(runStarts, runCap), {
12137
11711
  commentType: "blocker",
12138
11712
  agentSessionId: this.sessionId ?? undefined
12139
11713
  });
12140
11714
  } catch (err) {
12141
- log35.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
11715
+ log34.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
12142
11716
  }
12143
11717
  }
12144
11718
  const recordedBranch = recordedBranchForCard(card.description, card.short_id, [
@@ -12148,10 +11722,10 @@ class Worker {
12148
11722
  const continuesPushedWork = isRework || recordedBranch !== null;
12149
11723
  if (!resuming && recordedBranch) {
12150
11724
  if (recordedBranch !== this.branchName) {
12151
- log35.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
11725
+ log34.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
12152
11726
  this.branchName = recordedBranch;
12153
11727
  } else if (!isRework) {
12154
- log35.info(this.tag, `Card records pushed work on ${this.branchName} — continuing that branch instead of rebuilding from ${this.config.worktree.baseBranch}`);
11728
+ log34.info(this.tag, `Card records pushed work on ${this.branchName} — continuing that branch instead of rebuilding from ${this.config.worktree.baseBranch}`);
12155
11729
  }
12156
11730
  }
12157
11731
  this.startHeartbeat();
@@ -12193,14 +11767,14 @@ class Worker {
12193
11767
  awaitingDecisionUntil: null
12194
11768
  });
12195
11769
  const started = await startSessionYieldingNotice(startSession, this.client, card.id, {
12196
- info: (message) => log35.info(this.tag, message),
12197
- warn: (message) => log35.warn(this.tag, message)
11770
+ info: (message) => log34.info(this.tag, message),
11771
+ warn: (message) => log34.warn(this.tag, message)
12198
11772
  });
12199
11773
  session = started.session;
12200
11774
  } catch (err) {
12201
11775
  if (isSessionConflict(err)) {
12202
11776
  this.sessionConflict = true;
12203
- log35.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
11777
+ log34.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
12204
11778
  await this.stateStore.decrementAttempt(card.id);
12205
11779
  return;
12206
11780
  }
@@ -12208,7 +11782,7 @@ class Worker {
12208
11782
  }
12209
11783
  const sid = session && typeof session === "object" && "id" in session ? session.id : null;
12210
11784
  if (!sid) {
12211
- log35.warn(TAG32, "startAgentSession returned no session id");
11785
+ log34.warn(TAG31, "startAgentSession returned no session id");
12212
11786
  }
12213
11787
  this.sessionId = sid;
12214
11788
  }
@@ -12226,7 +11800,7 @@ class Worker {
12226
11800
  if (!resuming) {
12227
11801
  const moved = await moveCardAndAddLabel(this.client, card, IN_PROGRESS_COLUMN, "agent");
12228
11802
  if (!moved) {
12229
- log35.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
11803
+ log34.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
12230
11804
  }
12231
11805
  }
12232
11806
  if (this.aborted)
@@ -12253,10 +11827,10 @@ class Worker {
12253
11827
  }).trim();
12254
11828
  const target = resolveContinuationTarget(this.branchName, continueRequested, this.config.worktree.failedBranchPrefix, this.config.worktree.approvedBranchPrefix, (ref) => fetchExistingBranch(repoRoot, ref));
12255
11829
  if (target.branchName !== this.branchName) {
12256
- log35.info(this.tag, `Branch ${this.branchName} is gone from origin but its approved rename ${target.branchName} exists — continuing that branch`);
11830
+ log34.info(this.tag, `Branch ${this.branchName} is gone from origin but its approved rename ${target.branchName} exists — continuing that branch`);
12257
11831
  this.branchName = target.branchName;
12258
11832
  } else if (target.reason === "exists_on_origin") {
12259
- log35.info(this.tag, `Branch ${this.branchName} exists on origin with no card record — continuing it rather than resetting it`);
11833
+ log34.info(this.tag, `Branch ${this.branchName} exists on origin with no card record — continuing it rather than resetting it`);
12260
11834
  }
12261
11835
  this.worktreePath = createWorktree(this.config.worktree.basePath, this.config.worktree.baseBranch, this.branchName, {
12262
11836
  continueExisting: target.continueExisting,
@@ -12290,7 +11864,7 @@ class Worker {
12290
11864
  if (this.aborted)
12291
11865
  return;
12292
11866
  if (parked) {
12293
- log35.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
11867
+ log34.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
12294
11868
  return;
12295
11869
  }
12296
11870
  }
@@ -12311,7 +11885,7 @@ class Worker {
12311
11885
  progressPercent: 10
12312
11886
  });
12313
11887
  this.timeoutTimer = setTimeout(() => {
12314
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
11888
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
12315
11889
  this.timedOut = true;
12316
11890
  this.cancel("timeout");
12317
11891
  }, this.config.maxTimeout);
@@ -12338,7 +11912,7 @@ class Worker {
12338
11912
  }
12339
11913
  this.state = "verifying";
12340
11914
  await this.recordPhase("verifying");
12341
- log35.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
11915
+ log34.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
12342
11916
  await this.client.updateAgentProgress(card.id, {
12343
11917
  agentIdentifier: this.sessionIdentifier,
12344
11918
  agentName: AGENT_NAME,
@@ -12354,7 +11928,7 @@ class Worker {
12354
11928
  const onBeforeWorktreeCleanup = stageRun ? async (worktreePath) => {
12355
11929
  stageGateEvaluation = await this.collectStageGateEvidence(card, stageRun.stage, worktreePath, subtasks);
12356
11930
  } : undefined;
12357
- const completed = await runCompletion(this.client, card, this.branchName, this.worktreePath, this.config, this.id, this.sessionIdentifier, this.identity.agentId, this.lastSessionStats, this.workspaceId, this.sessionId, this.stateStore, this.onCardCompleted, onBeforeWorktreeCleanup, this.runBaselineSha, this.effectiveMaxTurns, this.runExpectsCommits);
11931
+ const completed = await runCompletion(this.client, card, this.branchName, this.worktreePath, this.config, this.id, this.sessionIdentifier, this.identity.agentId, this.lastSessionStats, this.sessionId, this.stateStore, this.onCardCompleted, onBeforeWorktreeCleanup, this.runBaselineSha, this.effectiveMaxTurns, this.runExpectsCommits);
12358
11932
  if (completed === "park") {
12359
11933
  await this.parkForDecision(card, "max_turns");
12360
11934
  return;
@@ -12373,7 +11947,7 @@ class Worker {
12373
11947
  break;
12374
11948
  case "reclaim_refused":
12375
11949
  this.held = true;
12376
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
11950
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12377
11951
  break;
12378
11952
  case "advanced":
12379
11953
  case "completed_terminal":
@@ -12411,7 +11985,7 @@ class Worker {
12411
11985
  return;
12412
11986
  }
12413
11987
  this.state = "error";
12414
- log35.error(this.tag, `Error on #${card.short_id}: ${msg}`);
11988
+ log34.error(this.tag, `Error on #${card.short_id}: ${msg}`);
12415
11989
  const apiError = errClass.kind !== null;
12416
11990
  const baseError = err instanceof WorktreeBaseError;
12417
11991
  const noBudgetBurn = apiError || baseError;
@@ -12429,7 +12003,7 @@ class Worker {
12429
12003
  try {
12430
12004
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12431
12005
  } catch {
12432
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12006
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12433
12007
  }
12434
12008
  this.worktreePath = null;
12435
12009
  }
@@ -12454,7 +12028,7 @@ class Worker {
12454
12028
  }
12455
12029
  });
12456
12030
  } catch (tErr) {
12457
- log35.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12031
+ log34.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12458
12032
  }
12459
12033
  if (this.runId) {
12460
12034
  try {
@@ -12490,7 +12064,7 @@ class Worker {
12490
12064
  try {
12491
12065
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12492
12066
  } catch {
12493
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12067
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12494
12068
  }
12495
12069
  this.worktreePath = null;
12496
12070
  }
@@ -12513,7 +12087,7 @@ class Worker {
12513
12087
  }
12514
12088
  });
12515
12089
  } catch (tErr) {
12516
- log35.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12090
+ log34.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12517
12091
  }
12518
12092
  try {
12519
12093
  await this.stateStore.endRun(this.runId, "failed", {
@@ -12527,15 +12101,15 @@ class Worker {
12527
12101
  try {
12528
12102
  await this.client.updateCard(card.id, { assignedAgentId: null });
12529
12103
  } catch (err) {
12530
- log35.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12104
+ log34.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12531
12105
  }
12532
12106
  try {
12533
12107
  await runTransition(this.client, card, { removeLabels: ["agent"] });
12534
12108
  } catch (tErr) {
12535
- log35.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12109
+ log34.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12536
12110
  }
12537
12111
  } else {
12538
- log35.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12112
+ log34.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12539
12113
  }
12540
12114
  try {
12541
12115
  await this.stateStore.endRun(this.runId, "paused", {
@@ -12599,28 +12173,28 @@ class Worker {
12599
12173
  };
12600
12174
  const { pick, reason } = selectAutoPlaybook(subject, playbooks ?? []);
12601
12175
  if (!pick) {
12602
- log35.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12176
+ log34.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12603
12177
  return card;
12604
12178
  }
12605
12179
  const undeclared = undeclaredGateMetricsIn(pick, declaredMetricSet(this.config));
12606
12180
  if (undeclared.length > 0) {
12607
- log35.warn(this.tag, `Not binding "${pick.name}" to #${card.short_id}: stage ` + undeclared.map((u) => `"${u.stageName}" gates on metric "${u.metric}" (declare \`agent.playbooks.metrics.${u.metric}\`)`).join(", ") + " — this daemon cannot measure it, so the card runs the generic path instead.");
12181
+ log34.warn(this.tag, `Not binding "${pick.name}" to #${card.short_id}: stage ` + undeclared.map((u) => `"${u.stageName}" gates on metric "${u.metric}" (declare \`agent.playbooks.metrics.${u.metric}\`)`).join(", ") + " — this daemon cannot measure it, so the card runs the generic path instead.");
12608
12182
  return card;
12609
12183
  }
12610
12184
  const applyResult = await this.client.request("POST", `/cards/${card.id}/apply-playbook`, {
12611
12185
  playbookId: pick.id
12612
12186
  });
12613
- log35.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12187
+ log34.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12614
12188
  try {
12615
12189
  await this.client.addComment(card.id, `Bound playbook "${pick.name}" automatically — ${reason} Apply a different playbook from the card's stage rail to override, or turn the rule off in the playbook editor.`);
12616
12190
  } catch (commentErr) {
12617
- log35.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12191
+ log34.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12618
12192
  }
12619
12193
  try {
12620
12194
  const { card: fresh } = await this.client.getCard(card.id);
12621
12195
  return fresh;
12622
12196
  } catch (fetchErr) {
12623
- log35.warn(this.tag, `Auto-bind re-fetch failed for #${card.short_id} after binding playbook "${pick.name}" — using the apply-playbook response's fields for this pickup: ${fetchErr instanceof Error ? fetchErr.message : String(fetchErr)}`);
12197
+ log34.warn(this.tag, `Auto-bind re-fetch failed for #${card.short_id} after binding playbook "${pick.name}" — using the apply-playbook response's fields for this pickup: ${fetchErr instanceof Error ? fetchErr.message : String(fetchErr)}`);
12624
12198
  return {
12625
12199
  ...card,
12626
12200
  playbook_id: applyResult.card.playbook_id,
@@ -12629,7 +12203,7 @@ class Worker {
12629
12203
  };
12630
12204
  }
12631
12205
  } catch (err) {
12632
- log35.warn(this.tag, `Auto-bind playbook check failed for #${card.short_id}, continuing unbound: ${err instanceof Error ? err.message : String(err)}`);
12206
+ log34.warn(this.tag, `Auto-bind playbook check failed for #${card.short_id}, continuing unbound: ${err instanceof Error ? err.message : String(err)}`);
12633
12207
  return card;
12634
12208
  }
12635
12209
  }
@@ -12741,7 +12315,7 @@ class Worker {
12741
12315
  });
12742
12316
  } catch (err) {
12743
12317
  const detail = err instanceof Error ? err.message : String(err);
12744
- log35.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12318
+ log34.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12745
12319
  await this.holdStageCard(card, `Fan-out stage "${ctx.stage.name}" could not run: ${detail}`);
12746
12320
  return;
12747
12321
  }
@@ -12750,7 +12324,7 @@ class Worker {
12750
12324
  case "waiting": {
12751
12325
  const total = outcome.kind === "dispatched" ? outcome.total : outcome.total;
12752
12326
  const note = outcome.kind === "dispatched" ? `Fan-out stage "${ctx.stage.name}": dispatched ${outcome.created} of ${total} item(s); ${outcome.inFlight} in flight.` : `Fan-out stage "${ctx.stage.name}": ${outcome.settled} of ${total} item(s) settled; waiting on the rest.`;
12753
- log35.info(this.tag, `#${card.short_id} ${note}`);
12327
+ log34.info(this.tag, `#${card.short_id} ${note}`);
12754
12328
  await this.client.updateAgentProgress(card.id, {
12755
12329
  agentIdentifier: "claude-code-stage",
12756
12330
  agentName: "Harmony Agent",
@@ -12778,7 +12352,7 @@ class Worker {
12778
12352
  if (advance.kind === "advanced" || advance.kind === "completed_terminal") {
12779
12353
  this.held = false;
12780
12354
  }
12781
- log35.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12355
+ log34.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12782
12356
  return;
12783
12357
  }
12784
12358
  case "halted": {
@@ -12798,7 +12372,7 @@ class Worker {
12798
12372
  }
12799
12373
  }
12800
12374
  async holdStageCard(card, reason, wait = false) {
12801
- log35.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12375
+ log34.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12802
12376
  await this.stateStore.decrementAttempt(card.id);
12803
12377
  try {
12804
12378
  await this.client.addComment(card.id, reason, {
@@ -12817,7 +12391,7 @@ class Worker {
12817
12391
  }
12818
12392
  });
12819
12393
  } catch (tErr) {
12820
- log35.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12394
+ log34.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12821
12395
  }
12822
12396
  if (this.runId) {
12823
12397
  try {
@@ -12835,7 +12409,7 @@ class Worker {
12835
12409
  const holderMessage = err instanceof Error ? err.message : String(err);
12836
12410
  const waitHours = this.config.budget.pause.waitHours;
12837
12411
  const until = computeDecisionDeadline(waitHours);
12838
- log35.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12412
+ log34.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12839
12413
  try {
12840
12414
  await this.client.addComment(card.id, formatResumeConflictComment({
12841
12415
  holderMessage,
@@ -12847,7 +12421,7 @@ class Worker {
12847
12421
  agentSessionId: this.sessionId ?? undefined
12848
12422
  });
12849
12423
  } catch (commentErr) {
12850
- log35.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12424
+ log34.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12851
12425
  }
12852
12426
  if (this.runId) {
12853
12427
  const run = this.stateStore.getRun(this.runId);
@@ -12858,7 +12432,7 @@ class Worker {
12858
12432
  awaitingDecisionUntil: until
12859
12433
  });
12860
12434
  } catch (storeErr) {
12861
- log35.error(this.tag, `#${card.short_id} could not be re-parked after a resume conflict — the daemon has no hold on it: ${storeErr}`);
12435
+ log34.error(this.tag, `#${card.short_id} could not be re-parked after a resume conflict — the daemon has no hold on it: ${storeErr}`);
12862
12436
  }
12863
12437
  }
12864
12438
  }
@@ -12870,7 +12444,7 @@ class Worker {
12870
12444
  this.progressTracker = null;
12871
12445
  const waitHours = this.config.budget.pause.waitHours;
12872
12446
  const until = computeDecisionDeadline(waitHours);
12873
- log35.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12447
+ log34.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12874
12448
  const measured = this.worktreePath && this.runExpectsCommits ? measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha) : "unknown";
12875
12449
  const hasCommits = measured === "unknown" ? undefined : measured === "committed";
12876
12450
  if (hasCommits === false && !this.noCommitNoticeSettled) {
@@ -12900,7 +12474,7 @@ class Worker {
12900
12474
  });
12901
12475
  commentId = res?.comment?.id ?? null;
12902
12476
  } catch (err) {
12903
- log35.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12477
+ log34.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12904
12478
  }
12905
12479
  const cardCostCents = this.stateStore.getCardCostCents(card.id) + Math.max(0, this.runCostCents - this.chargedCents);
12906
12480
  const readout = [
@@ -12921,7 +12495,7 @@ class Worker {
12921
12495
  awaitingDecisionUntil: new Date(until).toISOString()
12922
12496
  });
12923
12497
  } catch (err) {
12924
- log35.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12498
+ log34.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12925
12499
  }
12926
12500
  if (this.runId) {
12927
12501
  try {
@@ -12932,7 +12506,7 @@ class Worker {
12932
12506
  ...this.runLedger()
12933
12507
  });
12934
12508
  } catch (err) {
12935
- log35.error(this.tag, `#${card.short_id} parkRun failed after the blocker comment + blocked session were already written — the daemon has no local record of this park: ${err}`);
12509
+ log34.error(this.tag, `#${card.short_id} parkRun failed after the blocker comment + blocked session were already written — the daemon has no local record of this park: ${err}`);
12936
12510
  }
12937
12511
  }
12938
12512
  }
@@ -12963,11 +12537,11 @@ class Worker {
12963
12537
  });
12964
12538
  const gate = normalizeGateSpec(ctx.stage.gate);
12965
12539
  const metricsPath = gate?.kind === "custom" ? writeMetricsFile(this.config.playbooks.metrics ?? {}) : null;
12966
- log35.info(this.tag, `Running stage "${ctx.stage.name}" (role ${ctx.role}) for #${card.short_id} under the harness motor`);
12540
+ log34.info(this.tag, `Running stage "${ctx.stage.name}" (role ${ctx.role}) for #${card.short_id} under the harness motor`);
12967
12541
  const motorAbort = new AbortController;
12968
12542
  this.motorAbort = motorAbort;
12969
12543
  this.timeoutTimer = setTimeout(() => {
12970
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12544
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12971
12545
  this.timedOut = true;
12972
12546
  this.cancel("timeout");
12973
12547
  }, this.config.maxTimeout);
@@ -12978,12 +12552,12 @@ class Worker {
12978
12552
  let motorRunSettled = false;
12979
12553
  const onMotorLine = (line) => {
12980
12554
  if (line.type !== "agent_event") {
12981
- log35.info(this.tag, `motor: ${line.type}`);
12555
+ log34.info(this.tag, `motor: ${line.type}`);
12982
12556
  return;
12983
12557
  }
12984
12558
  if (motorRunSettled)
12985
12559
  return;
12986
- log35.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12560
+ log34.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12987
12561
  if (line.event.kind === "tool_started" && STAGE_DAEMON_OWNED_TOOLS.includes(line.event.payload.toolName)) {
12988
12562
  return;
12989
12563
  }
@@ -13003,7 +12577,7 @@ class Worker {
13003
12577
  currentTask: motorTask,
13004
12578
  progressPercent: MOTOR_RUN_PROGRESS_PERCENT
13005
12579
  }).catch((err) => {
13006
- log35.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12580
+ log34.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13007
12581
  });
13008
12582
  }, MOTOR_SESSION_HEARTBEAT_MS);
13009
12583
  heartbeat.unref?.();
@@ -13077,7 +12651,7 @@ class Worker {
13077
12651
  break;
13078
12652
  case "reclaim_refused":
13079
12653
  this.held = true;
13080
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12654
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
13081
12655
  break;
13082
12656
  case "advanced":
13083
12657
  case "completed_terminal":
@@ -13099,7 +12673,7 @@ class Worker {
13099
12673
  try {
13100
12674
  pushBranch3(this.branchName, worktreePath);
13101
12675
  } catch (err) {
13102
- log35.error(this.tag, `push after the motor stage "${ctx.stage.name}" failed for ${this.branchName}: ${err instanceof Error ? err.message : err}`);
12676
+ log34.error(this.tag, `push after the motor stage "${ctx.stage.name}" failed for ${this.branchName}: ${err instanceof Error ? err.message : err}`);
13103
12677
  }
13104
12678
  }
13105
12679
  }
@@ -13107,7 +12681,7 @@ class Worker {
13107
12681
  if (completionColumn) {
13108
12682
  await transferCardToCompletion({ client: this.client, tag: this.tag }, card, completionColumn, this.onCardCompleted);
13109
12683
  } else {
13110
- log35.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
12684
+ log34.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
13111
12685
  }
13112
12686
  await this.closeoutMotorWorktree(card);
13113
12687
  }
@@ -13118,7 +12692,7 @@ class Worker {
13118
12692
  try {
13119
12693
  await teardownWorktree2(this.client, card.id, worktreePath, this.branchName ?? undefined, this.sessionId);
13120
12694
  } catch {
13121
- log35.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
12695
+ log34.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
13122
12696
  }
13123
12697
  this.worktreePath = null;
13124
12698
  }
@@ -13175,7 +12749,7 @@ ${prompt}`;
13175
12749
  });
13176
12750
  return handoff ? renderInheritedHandoffSection(handoff) : "";
13177
12751
  } catch (err) {
13178
- log35.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
12752
+ log34.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13179
12753
  return "";
13180
12754
  }
13181
12755
  }
@@ -13195,9 +12769,9 @@ ${prompt}`;
13195
12769
  commentType: "decision",
13196
12770
  agentSessionId: this.sessionId ?? undefined
13197
12771
  });
13198
- log35.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
12772
+ log34.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
13199
12773
  } catch (err) {
13200
- log35.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12774
+ log34.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13201
12775
  }
13202
12776
  }
13203
12777
  async collectStageGateEvidence(card, stage, worktreePath, subtasks) {
@@ -13209,12 +12783,12 @@ ${prompt}`;
13209
12783
  return null;
13210
12784
  }
13211
12785
  if (gate.pendingEngine === true) {
13212
- log35.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
12786
+ log34.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
13213
12787
  return null;
13214
12788
  }
13215
12789
  const review = gate.kind === "review_passed" ? parseReviewOutput(this.lastRunText) : undefined;
13216
12790
  if (review) {
13217
- log35.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
12791
+ log34.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
13218
12792
  }
13219
12793
  const registry = buildGateCollectorRegistry2({
13220
12794
  build: {
@@ -13231,7 +12805,7 @@ ${prompt}`;
13231
12805
  return [];
13232
12806
  const criteria = await fetchAcceptanceCriteria(this.client, this.tag, card);
13233
12807
  if (criteria.length > 0) {
13234
- log35.info(this.tag, `Grading the artifact gate for #${card.short_id} against ${criteria.length} plan criteria instead of the stage's own rubric`);
12808
+ log34.info(this.tag, `Grading the artifact gate for #${card.short_id} against ${criteria.length} plan criteria instead of the stage's own rubric`);
13235
12809
  }
13236
12810
  return criteria;
13237
12811
  })()
@@ -13253,10 +12827,10 @@ ${prompt}`;
13253
12827
  const evaluation = gateEvaluate(gate, evidence);
13254
12828
  const insert = toStageGateEvidenceInsert(context, evidence);
13255
12829
  await this.client.request("POST", `/cards/${encodeURIComponent(card.id)}/stage-gate-evidence`, insert);
13256
- log35.info(this.tag, `Recorded ${gate.kind} gate evidence for #${card.short_id} stage "${stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
12830
+ log34.info(this.tag, `Recorded ${gate.kind} gate evidence for #${card.short_id} stage "${stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
13257
12831
  return evaluation;
13258
12832
  } catch (err) {
13259
- log35.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12833
+ log34.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13260
12834
  return null;
13261
12835
  }
13262
12836
  }
@@ -13274,7 +12848,7 @@ ${prompt}`;
13274
12848
  agentSessionId: this.sessionId
13275
12849
  });
13276
12850
  } catch (err) {
13277
- log35.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12851
+ log34.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13278
12852
  return { kind: "no_advance" };
13279
12853
  }
13280
12854
  }
@@ -13300,7 +12874,7 @@ ${prompt}`;
13300
12874
  this.modelChoice = choice;
13301
12875
  const { model, escalated, source } = choice;
13302
12876
  if (source !== "policy" || escalated) {
13303
- log35.info(this.tag, `Implement model "${model}" (source=${source}, escalated=${escalated}, attempts=${attempts}, priority=${card.priority ?? "none"}, tier=${this.sizing?.tier ?? "none"})`);
12877
+ log34.info(this.tag, `Implement model "${model}" (source=${source}, escalated=${escalated}, attempts=${attempts}, priority=${card.priority ?? "none"}, tier=${this.sizing?.tier ?? "none"})`);
13304
12878
  }
13305
12879
  return model;
13306
12880
  }
@@ -13315,7 +12889,7 @@ ${prompt}`;
13315
12889
  encoding: "utf-8"
13316
12890
  }).trim();
13317
12891
  } catch (err) {
13318
- log35.warn(this.tag, `Sizing #${card.short_id} failed (spawn): could not resolve the repo root (${err instanceof Error ? err.message : String(err)}) — using the policy fallback`);
12892
+ log34.warn(this.tag, `Sizing #${card.short_id} failed (spawn): could not resolve the repo root (${err instanceof Error ? err.message : String(err)}) — using the policy fallback`);
13319
12893
  return { status: "failed", reason: "spawn" };
13320
12894
  }
13321
12895
  const outcome = await sizeRun({
@@ -13329,21 +12903,22 @@ ${prompt}`;
13329
12903
  scoreBands: claude.scoreBands
13330
12904
  });
13331
12905
  if (outcome.status === "sized") {
13332
- log35.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
12906
+ log34.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
13333
12907
  } else if (outcome.status === "failed") {
13334
- log35.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
12908
+ log34.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
13335
12909
  }
13336
12910
  return outcome;
13337
12911
  }
13338
12912
  recordPromptAssembled(outcomes) {
13339
- const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count ?? 0;
12913
+ const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count;
13340
12914
  const failures = outcomes.flatMap((o) => o.failure ? [{ flavour: o.flavour, message: o.failure.slice(0, 300) }] : []);
12915
+ const episodeCount = countOf("past_episodes");
13341
12916
  this.cliRunner?.record({
13342
12917
  kind: "prompt_assembled",
13343
12918
  source: "system",
13344
12919
  payload: {
13345
- episodeCount: countOf("past_episodes"),
13346
- referenceCount: countOf("reference"),
12920
+ ...episodeCount === undefined ? {} : { episodeCount },
12921
+ referenceCount: countOf("reference") ?? 0,
13347
12922
  ...failures.length > 0 ? { recallFailures: failures } : {}
13348
12923
  }
13349
12924
  });
@@ -13364,7 +12939,7 @@ ${prompt}`;
13364
12939
  const measured = measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha);
13365
12940
  if (measured !== "none") {
13366
12941
  if (measured === "unknown") {
13367
- log35.debug(this.tag, `no-commit check could not attribute this run's commits — staying quiet on ${this.branchName ?? "this branch"}`);
12942
+ log34.debug(this.tag, `no-commit check could not attribute this run's commits — staying quiet on ${this.branchName ?? "this branch"}`);
13368
12943
  }
13369
12944
  return;
13370
12945
  }
@@ -13373,7 +12948,7 @@ ${prompt}`;
13373
12948
  recordNoCommitsYet(trigger, numTurns) {
13374
12949
  const turnBudget = this.effectiveMaxTurns;
13375
12950
  const threshold = noCommitNoticeThreshold(turnBudget);
13376
- log35.warn(this.tag, `No commits yet on ${this.branchName ?? "this run's branch"} — ${this.runToolCalls} tool calls into a ${turnBudget}-turn budget (${trigger})`);
12951
+ log34.warn(this.tag, `No commits yet on ${this.branchName ?? "this run's branch"} — ${this.runToolCalls} tool calls into a ${turnBudget}-turn budget (${trigger})`);
13377
12952
  this.cliRunner?.record({
13378
12953
  kind: "no_commits_yet",
13379
12954
  source: "system",
@@ -13425,9 +13000,9 @@ ${prompt}`;
13425
13000
  agentSessionId: this.sessionId ?? undefined
13426
13001
  });
13427
13002
  giveUpCommentId = res?.comment?.id ?? null;
13428
- log35.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13003
+ log34.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13429
13004
  } catch (err) {
13430
- log35.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13005
+ log34.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13431
13006
  }
13432
13007
  if (this.config.budget.pause.enabled) {
13433
13008
  const waitHours = this.config.budget.pause.waitHours;
@@ -13441,7 +13016,7 @@ ${prompt}`;
13441
13016
  awaitingDecisionUntil: new Date(until).toISOString()
13442
13017
  });
13443
13018
  } catch (err) {
13444
- log35.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13019
+ log34.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13445
13020
  }
13446
13021
  try {
13447
13022
  await this.stateStore.markAwaitingDecision(cardId, {
@@ -13450,19 +13025,19 @@ ${prompt}`;
13450
13025
  agentIdentifier: this.sessionIdentifier
13451
13026
  });
13452
13027
  } catch (err) {
13453
- log35.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13028
+ log34.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13454
13029
  }
13455
13030
  }
13456
13031
  }
13457
13032
  }
13458
13033
  } catch (err) {
13459
- log35.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13034
+ log34.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13460
13035
  }
13461
13036
  }
13462
13037
  async pause() {
13463
13038
  if (!this.isActive || !this.process || this.process.killed)
13464
13039
  return;
13465
- log35.info(this.tag, `Pausing work on ${this.cardId}`);
13040
+ log34.info(this.tag, `Pausing work on ${this.cardId}`);
13466
13041
  signalGroup2(this.process, "SIGSTOP");
13467
13042
  if (this.timeoutTimer) {
13468
13043
  clearTimeout(this.timeoutTimer);
@@ -13476,17 +13051,17 @@ ${prompt}`;
13476
13051
  status: "paused"
13477
13052
  });
13478
13053
  } catch {
13479
- log35.warn(this.tag, "Failed to update agent session to paused");
13054
+ log34.warn(this.tag, "Failed to update agent session to paused");
13480
13055
  }
13481
13056
  }
13482
13057
  }
13483
13058
  async resume() {
13484
13059
  if (!this.isActive || !this.process || this.process.killed)
13485
13060
  return;
13486
- log35.info(this.tag, `Resuming work on ${this.cardId}`);
13061
+ log34.info(this.tag, `Resuming work on ${this.cardId}`);
13487
13062
  signalGroup2(this.process, "SIGCONT");
13488
13063
  this.timeoutTimer = setTimeout(() => {
13489
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13064
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13490
13065
  this.timedOut = true;
13491
13066
  this.cancel("timeout");
13492
13067
  }, this.config.maxTimeout);
@@ -13498,7 +13073,7 @@ ${prompt}`;
13498
13073
  status: "working"
13499
13074
  });
13500
13075
  } catch {
13501
- log35.warn(this.tag, "Failed to update agent session to working");
13076
+ log34.warn(this.tag, "Failed to update agent session to working");
13502
13077
  }
13503
13078
  }
13504
13079
  }
@@ -13507,7 +13082,7 @@ ${prompt}`;
13507
13082
  return;
13508
13083
  this.aborted = true;
13509
13084
  this.state = "cancelling";
13510
- log35.info(this.tag, `Cancelling work on ${this.cardId}`);
13085
+ log34.info(this.tag, `Cancelling work on ${this.cardId}`);
13511
13086
  this.motorAbort?.abort();
13512
13087
  if (this.sdkRunner) {
13513
13088
  await this.sdkRunner.stop(this.timedOut ? "timeout" : "user_requested");
@@ -13525,14 +13100,14 @@ ${prompt}`;
13525
13100
  ...buildTokenPayload(stats)
13526
13101
  });
13527
13102
  } catch (err) {
13528
- log35.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13103
+ log34.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13529
13104
  }
13530
13105
  }
13531
13106
  }
13532
13107
  async runPlanningPhase(enriched) {
13533
13108
  const planning = this.config.planning;
13534
13109
  const { card } = enriched;
13535
- log35.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13110
+ log34.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13536
13111
  await this.client.updateAgentProgress(card.id, {
13537
13112
  agentIdentifier: this.sessionIdentifier,
13538
13113
  agentName: AGENT_NAME,
@@ -13545,7 +13120,7 @@ ${prompt}`;
13545
13120
  let planTimedOut = false;
13546
13121
  const planTimeout = setTimeout(() => {
13547
13122
  planTimedOut = true;
13548
- log35.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13123
+ log34.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13549
13124
  if (this.sdkRunner) {
13550
13125
  this.sdkRunner.stop("timeout").catch(() => {});
13551
13126
  } else if (this.process && !this.process.killed) {
@@ -13563,7 +13138,7 @@ ${prompt}`;
13563
13138
  initialPhase: "planning"
13564
13139
  });
13565
13140
  } catch (err) {
13566
- log35.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13141
+ log34.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13567
13142
  return false;
13568
13143
  } finally {
13569
13144
  clearTimeout(planTimeout);
@@ -13574,7 +13149,7 @@ ${prompt}`;
13574
13149
  await this.chargeDailyLedger(card.id, card.short_id);
13575
13150
  const planText = stats?.lastAssistantText ?? "";
13576
13151
  if (!planText.trim()) {
13577
- log35.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13152
+ log34.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13578
13153
  return false;
13579
13154
  }
13580
13155
  const artifact = extractPlanArtifact(planText, card.title);
@@ -13595,9 +13170,9 @@ ${prompt}`;
13595
13170
  });
13596
13171
  planId = createdId;
13597
13172
  }
13598
- log35.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13173
+ log34.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13599
13174
  } catch (err) {
13600
- log35.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13175
+ log34.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13601
13176
  }
13602
13177
  if (planning.mode === "gated" && planId) {
13603
13178
  try {
@@ -13616,11 +13191,11 @@ ${prompt}`;
13616
13191
  ...buildTokenPayload(stats)
13617
13192
  }
13618
13193
  }, { store: this.stateStore, runId: this.runId ?? undefined });
13619
- log35.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13194
+ log34.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13620
13195
  this.lastSessionStats = undefined;
13621
13196
  return true;
13622
13197
  } catch (err) {
13623
- log35.warn(this.tag, `Gated park failed for #${card.short_id} (non-fatal, implementing directly): ${err instanceof TransitionError ? err.detail : err instanceof Error ? err.message : err}`);
13198
+ log34.warn(this.tag, `Gated park failed for #${card.short_id} (non-fatal, implementing directly): ${err instanceof TransitionError ? err.detail : err instanceof Error ? err.message : err}`);
13624
13199
  }
13625
13200
  }
13626
13201
  if (planId && planning.postComment) {
@@ -13630,7 +13205,7 @@ ${prompt}`;
13630
13205
  agentSessionId: this.sessionId ?? undefined
13631
13206
  });
13632
13207
  } catch (err) {
13633
- log35.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13208
+ log34.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13634
13209
  }
13635
13210
  }
13636
13211
  return false;
@@ -13640,10 +13215,10 @@ ${prompt}`;
13640
13215
  const { card } = enriched;
13641
13216
  const existing = await this.loadPinnedContract(card.id);
13642
13217
  if (existing) {
13643
- log35.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13218
+ log34.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13644
13219
  return;
13645
13220
  }
13646
- log35.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13221
+ log34.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13647
13222
  await this.client.updateAgentProgress(card.id, {
13648
13223
  agentIdentifier: this.sessionIdentifier,
13649
13224
  agentName: AGENT_NAME,
@@ -13656,7 +13231,7 @@ ${prompt}`;
13656
13231
  let contractTimedOut = false;
13657
13232
  const contractTimeout = setTimeout(() => {
13658
13233
  contractTimedOut = true;
13659
- log35.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13234
+ log34.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13660
13235
  if (this.sdkRunner) {
13661
13236
  this.sdkRunner.stop("timeout").catch(() => {});
13662
13237
  } else if (this.process && !this.process.killed) {
@@ -13674,7 +13249,7 @@ ${prompt}`;
13674
13249
  initialPhase: "planning"
13675
13250
  });
13676
13251
  } catch (err) {
13677
- log35.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13252
+ log34.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13678
13253
  return;
13679
13254
  } finally {
13680
13255
  clearTimeout(contractTimeout);
@@ -13685,12 +13260,12 @@ ${prompt}`;
13685
13260
  await this.chargeDailyLedger(card.id, card.short_id);
13686
13261
  const contractText = stats?.lastAssistantText ?? "";
13687
13262
  if (!contractText.trim()) {
13688
- log35.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13263
+ log34.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13689
13264
  return;
13690
13265
  }
13691
13266
  const contract = extractContract(contractText, card);
13692
13267
  if (contract.assertions.length < contractCfg.minAssertions) {
13693
- log35.warn(this.tag, `Contract for #${card.short_id} had ${contract.assertions.length} assertion(s) (< ${contractCfg.minAssertions}) — not pinning, implementing directly`);
13268
+ log34.warn(this.tag, `Contract for #${card.short_id} had ${contract.assertions.length} assertion(s) (< ${contractCfg.minAssertions}) — not pinning, implementing directly`);
13694
13269
  return;
13695
13270
  }
13696
13271
  try {
@@ -13698,9 +13273,9 @@ ${prompt}`;
13698
13273
  commentType: "decision",
13699
13274
  agentSessionId: this.sessionId ?? undefined
13700
13275
  });
13701
- log35.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13276
+ log34.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13702
13277
  } catch (err) {
13703
- log35.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13278
+ log34.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13704
13279
  }
13705
13280
  }
13706
13281
  async loadPinnedContract(cardId) {
@@ -13710,7 +13285,7 @@ ${prompt}`;
13710
13285
  return null;
13711
13286
  return extractPinnedContract(comments, this.identity);
13712
13287
  } catch (err) {
13713
- log35.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13288
+ log34.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13714
13289
  return null;
13715
13290
  }
13716
13291
  }
@@ -13723,13 +13298,13 @@ ${prompt}`;
13723
13298
  const res = await this.client.getPendingUserMessages(this.cardId, this.sessionId, this.lastDrainedSeq);
13724
13299
  messages = res.messages ?? [];
13725
13300
  } catch (err) {
13726
- log35.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13301
+ log34.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13727
13302
  return;
13728
13303
  }
13729
13304
  if (messages.length === 0)
13730
13305
  return;
13731
13306
  this.lastDrainedSeq = Math.max(this.lastDrainedSeq, ...messages.map((m) => m.seq));
13732
- log35.info(this.tag, `Steering #${card.short_id}: resuming with ${messages.length} queued message(s)`);
13307
+ log34.info(this.tag, `Steering #${card.short_id}: resuming with ${messages.length} queued message(s)`);
13733
13308
  this.state = "running";
13734
13309
  await this.recordPhase("running");
13735
13310
  try {
@@ -13741,7 +13316,7 @@ ${prompt}`;
13741
13316
  ...this.activeRunSpawnOpts ?? {}
13742
13317
  });
13743
13318
  } catch (err) {
13744
- log35.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13319
+ log34.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13745
13320
  return;
13746
13321
  }
13747
13322
  }
@@ -13776,10 +13351,10 @@ ${prompt}`;
13776
13351
  "--",
13777
13352
  prompt
13778
13353
  ];
13779
- log35.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13354
+ log34.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13780
13355
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13781
13356
  if (runLog) {
13782
- log35.info(this.tag, `Run log: ${runLog.path}`);
13357
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13783
13358
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} started=${new Date().toISOString()}
13784
13359
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
13785
13360
 
@@ -13816,7 +13391,7 @@ ${prompt}`;
13816
13391
  });
13817
13392
  }
13818
13393
  parser.on("parse_error", (msg) => {
13819
- log35.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13394
+ log34.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13820
13395
  runLog?.stream.write(`
13821
13396
  [parse_error] ${msg}
13822
13397
  `);
@@ -13889,10 +13464,10 @@ ${prompt}`;
13889
13464
  const disallowedTools = opts.disallowedTools ? opts.disallowedTools.split(",").map((t) => t.trim()).filter(Boolean) : undefined;
13890
13465
  const initialPhase = opts.initialPhase ?? "exploring";
13891
13466
  const maxBudgetUsd = this.effectiveMaxBudgetUsd;
13892
- log35.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13467
+ log34.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13893
13468
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13894
13469
  if (runLog) {
13895
- log35.info(this.tag, `Run log: ${runLog.path}`);
13470
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13896
13471
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} runner=sdk started=${new Date().toISOString()}
13897
13472
  ` + `# model=${model} maxTurns=${maxTurns} <prompt:${prompt.length} chars>
13898
13473
 
@@ -14027,7 +13602,7 @@ ${prompt}`;
14027
13602
  try {
14028
13603
  await teardownWorktree2(this.client, this.cardId, this.worktreePath, this.branchName ?? undefined, this.sessionId);
14029
13604
  } catch {
14030
- log35.warn(this.tag, "Failed to cleanup worktree");
13605
+ log34.warn(this.tag, "Failed to cleanup worktree");
14031
13606
  }
14032
13607
  }
14033
13608
  this.process = null;
@@ -14046,7 +13621,7 @@ ${prompt}`;
14046
13621
  this.chargedTokens = emptyTokens();
14047
13622
  }
14048
13623
  }
14049
- var TAG32 = "worker", CANCEL_SIGINT_TIMEOUT2 = 30000, CANCEL_SIGTERM_TIMEOUT2 = 1e4, MOTOR_SESSION_HEARTBEAT_MS = 60000, MOTOR_RUN_PROGRESS_PERCENT = 10, STEERING_MAX_TURNS = 15, MAX_STEERING_ITERATIONS = 10, PLAN_ALLOWED_TOOLS = "Read,Grep,Glob,mcp__harmony__*", IMPLEMENT_ALLOWED_TOOLS = "Bash,Read,Write,Edit,Glob,Grep,Agent,mcp__harmony__*", PLAN_PHASE_TIMEOUT, MAX_STAGE_NAME_CHARS = 80, MAX_HANDOFF_CHARS = 400;
13624
+ var TAG31 = "worker", CANCEL_SIGINT_TIMEOUT2 = 30000, CANCEL_SIGTERM_TIMEOUT2 = 1e4, MOTOR_SESSION_HEARTBEAT_MS = 60000, MOTOR_RUN_PROGRESS_PERCENT = 10, STEERING_MAX_TURNS = 15, MAX_STEERING_ITERATIONS = 10, PLAN_ALLOWED_TOOLS = "Read,Grep,Glob,mcp__harmony__*", IMPLEMENT_ALLOWED_TOOLS = "Bash,Read,Write,Edit,Glob,Grep,Agent,mcp__harmony__*", PLAN_PHASE_TIMEOUT, MAX_STAGE_NAME_CHARS = 80, MAX_HANDOFF_CHARS = 400;
14050
13625
  var init_worker = __esm(() => {
14051
13626
  init_dist();
14052
13627
  init_board_helpers();
@@ -14077,7 +13652,7 @@ var init_worker = __esm(() => {
14077
13652
  });
14078
13653
 
14079
13654
  // src/workspace-model-cache.ts
14080
- import { log as log36 } from "@gethmy/harness";
13655
+ import { log as log35 } from "@gethmy/harness";
14081
13656
 
14082
13657
  class WorkspaceModelCache {
14083
13658
  fetcher;
@@ -14112,7 +13687,7 @@ class WorkspaceModelCache {
14112
13687
  this.stale = false;
14113
13688
  } catch (err) {
14114
13689
  this.stale = true;
14115
- log36.warn("config", `Could not refresh a pickup-cached value, using ${this.everFetched ? "the last known value" : "local config only"}: ${err instanceof Error ? err.message : String(err)}`);
13690
+ log35.warn("config", `Could not refresh a pickup-cached value, using ${this.everFetched ? "the last known value" : "local config only"}: ${err instanceof Error ? err.message : String(err)}`);
14116
13691
  }
14117
13692
  return this.value;
14118
13693
  }
@@ -14123,7 +13698,7 @@ var init_workspace_model_cache = () => {};
14123
13698
  import {
14124
13699
  cooldownMsFor,
14125
13700
  describeApiError as describeApiError3,
14126
- log as log37
13701
+ log as log36
14127
13702
  } from "@gethmy/harness";
14128
13703
  async function routeBudgetDecision(d, run, actions, cardId) {
14129
13704
  if (!run) {
@@ -14219,11 +13794,11 @@ class Pool {
14219
13794
  }
14220
13795
  async enqueue(card, column, labels, subtasks, mode = "implement") {
14221
13796
  if (card.done || card.archived_at) {
14222
- log37.debug(TAG33, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
13797
+ log36.debug(TAG32, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
14223
13798
  return;
14224
13799
  }
14225
13800
  if (this.isCardKnown(card.id) || this.reservations.has(card.id)) {
14226
- log37.debug(TAG33, `Card ${card.id} already queued, active, or reserved, skipping`);
13801
+ log36.debug(TAG32, `Card ${card.id} already queued, active, or reserved, skipping`);
14227
13802
  return;
14228
13803
  }
14229
13804
  this.reservations.add(card.id);
@@ -14231,19 +13806,19 @@ class Pool {
14231
13806
  try {
14232
13807
  const account = this.accountGuard?.check();
14233
13808
  if (account && !account.running) {
14234
- log37.debug(TAG33, `#${card.short_id} held — ${account.detail}`);
13809
+ log36.debug(TAG32, `#${card.short_id} held — ${account.detail}`);
14235
13810
  await this.emitWaiting(card.id, account.detail);
14236
13811
  return;
14237
13812
  }
14238
13813
  if (mode === "implement") {
14239
13814
  if (this.authPaused) {
14240
- log37.debug(TAG33, `#${card.short_id} held — agent paused (auth error)`);
13815
+ log36.debug(TAG32, `#${card.short_id} held — agent paused (auth error)`);
14241
13816
  await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
14242
13817
  return;
14243
13818
  }
14244
13819
  const cooldownMs = this.apiCooldownRemainingMs();
14245
13820
  if (cooldownMs > 0) {
14246
- log37.debug(TAG33, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
13821
+ log36.debug(TAG32, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
14247
13822
  await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
14248
13823
  return;
14249
13824
  }
@@ -14252,19 +13827,19 @@ class Pool {
14252
13827
  if (decision.reason === "daily_budget") {
14253
13828
  await this.denyDailyBudget(card, decision.detail);
14254
13829
  } else {
14255
- log37.debug(TAG33, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
13830
+ log36.debug(TAG32, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
14256
13831
  }
14257
13832
  return;
14258
13833
  }
14259
13834
  const { blockers, successors } = await getChainSignals(this.client, card, this.projectId);
14260
13835
  chainSuccessors = successors;
14261
13836
  if (blockers === null) {
14262
- log37.warn(TAG33, `#${card.short_id} blocker check failed — deferring to next tick`);
13837
+ log36.warn(TAG32, `#${card.short_id} blocker check failed — deferring to next tick`);
14263
13838
  return;
14264
13839
  }
14265
13840
  if (blockers.length > 0) {
14266
13841
  const list = blockers.map((b) => `#${b.shortId}`).join(", ");
14267
- log37.info(TAG33, `#${card.short_id} blocked by ${list} — waiting`);
13842
+ log36.info(TAG32, `#${card.short_id} blocked by ${list} — waiting`);
14268
13843
  await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
14269
13844
  return;
14270
13845
  }
@@ -14296,9 +13871,9 @@ class Pool {
14296
13871
  const reason = `Daily budget reached — waiting for reset (${detail})`;
14297
13872
  const line = `#${card.short_id} skipped (daily_budget): ${detail}`;
14298
13873
  if (this.lastWaitingEmit.get(card.id) === reason)
14299
- log37.debug(TAG33, line);
13874
+ log36.debug(TAG32, line);
14300
13875
  else
14301
- log37.warn(TAG33, line);
13876
+ log36.warn(TAG32, line);
14302
13877
  await this.emitWaiting(card.id, reason);
14303
13878
  }
14304
13879
  lastWaitingEmit = new Map;
@@ -14315,7 +13890,7 @@ class Pool {
14315
13890
  });
14316
13891
  this.lastWaitingEmit.set(cardId, currentTask);
14317
13892
  } catch (err) {
14318
- log37.debug(TAG33, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13893
+ log36.debug(TAG32, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
14319
13894
  }
14320
13895
  }
14321
13896
  noteApiError(err) {
@@ -14323,13 +13898,13 @@ class Pool {
14323
13898
  return;
14324
13899
  if (err.kind === "spend_limit") {
14325
13900
  this.accountGuard?.halt("spend_limit").catch((hErr) => {
14326
- log37.error(TAG33, `Failed to latch the account halt: ${hErr}`);
13901
+ log36.error(TAG32, `Failed to latch the account halt: ${hErr}`);
14327
13902
  });
14328
13903
  return;
14329
13904
  }
14330
13905
  if (err.kind === "auth") {
14331
13906
  if (!this.authPaused) {
14332
- log37.error(TAG33, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
13907
+ log36.error(TAG32, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
14333
13908
  }
14334
13909
  this.authPaused = true;
14335
13910
  return;
@@ -14338,7 +13913,7 @@ class Pool {
14338
13913
  const until = Date.now() + cooldownMs;
14339
13914
  if (until > this.apiCooldownUntil) {
14340
13915
  this.apiCooldownUntil = until;
14341
- log37.warn(TAG33, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
13916
+ log36.warn(TAG32, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
14342
13917
  }
14343
13918
  }
14344
13919
  apiCooldownRemainingMs() {
@@ -14352,13 +13927,13 @@ class Pool {
14352
13927
  const removed = queue.remove(cardId);
14353
13928
  if (removed) {
14354
13929
  this.cardDataCache.delete(cardId);
14355
- log37.info(TAG33, `Removed #${removed.shortId} from ${removed.mode} queue`);
13930
+ log36.info(TAG32, `Removed #${removed.shortId} from ${removed.mode} queue`);
14356
13931
  return;
14357
13932
  }
14358
13933
  }
14359
13934
  const worker = this.implWorkers.find((w) => w.cardId === cardId) ?? this.reviewWorkers.find((w) => w.cardId === cardId);
14360
13935
  if (worker) {
14361
- log37.info(TAG33, `Cancelling worker ${worker.id} for card ${cardId}`);
13936
+ log36.info(TAG32, `Cancelling worker ${worker.id} for card ${cardId}`);
14362
13937
  await worker.cancel("unassigned");
14363
13938
  }
14364
13939
  }
@@ -14415,10 +13990,10 @@ class Pool {
14415
13990
  }
14416
13991
  const worker = this.implWorkers.find((w) => w.cardId === cardId && w.isActive) ?? this.reviewWorkers.find((w) => w.cardId === cardId && w.isActive);
14417
13992
  if (!worker) {
14418
- log37.debug(TAG33, `No active worker for card ${cardId}, ignoring ${command}`);
13993
+ log36.debug(TAG32, `No active worker for card ${cardId}, ignoring ${command}`);
14419
13994
  return;
14420
13995
  }
14421
- log37.info(TAG33, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
13996
+ log36.info(TAG32, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
14422
13997
  switch (command) {
14423
13998
  case "pause":
14424
13999
  await worker.pause();
@@ -14466,7 +14041,7 @@ class Pool {
14466
14041
  };
14467
14042
  }
14468
14043
  async shutdown() {
14469
- log37.info(TAG33, "Shutting down pool...");
14044
+ log36.info(TAG32, "Shutting down pool...");
14470
14045
  this.shuttingDown = true;
14471
14046
  const active = [
14472
14047
  ...this.implWorkers.filter((w) => w.isActive),
@@ -14474,7 +14049,7 @@ class Pool {
14474
14049
  ];
14475
14050
  await Promise.all(active.map((w) => w.cancel("shutdown")));
14476
14051
  this.sleepGuard.stop();
14477
- log37.info(TAG33, "Pool shutdown complete");
14052
+ log36.info(TAG32, "Pool shutdown complete");
14478
14053
  }
14479
14054
  async drainBudgetDecisions(cardId) {
14480
14055
  const targets = cardId ? [cardId] : [
@@ -14505,7 +14080,7 @@ class Pool {
14505
14080
  try {
14506
14081
  ({ decisions } = await this.client.getBudgetDecisions(cardId, new Date(sinceMs).toISOString()));
14507
14082
  } catch (err) {
14508
- log37.warn(TAG33, `getBudgetDecisions failed for ${cardId}: ${err}`);
14083
+ log36.warn(TAG32, `getBudgetDecisions failed for ${cardId}: ${err}`);
14509
14084
  return;
14510
14085
  }
14511
14086
  if (decisions.length > 0) {
@@ -14540,7 +14115,7 @@ class Pool {
14540
14115
  ...run.blockerCommentId ? { replyToId: run.blockerCommentId } : {}
14541
14116
  });
14542
14117
  } catch (err) {
14543
- log37.warn(TAG33, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14118
+ log36.warn(TAG32, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14544
14119
  }
14545
14120
  try {
14546
14121
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14554,14 +14129,14 @@ class Pool {
14554
14129
  });
14555
14130
  }
14556
14131
  } catch (err) {
14557
- log37.error(TAG33, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14132
+ log36.error(TAG32, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14558
14133
  }
14559
14134
  try {
14560
14135
  await this.stateStore.endRun(run.runId, "failed", {
14561
14136
  errorMessage: "budget decision expired"
14562
14137
  });
14563
14138
  } catch (err) {
14564
- log37.warn(TAG33, `Failed to release the expired park for ${run.cardId}: ${err}`);
14139
+ log36.warn(TAG32, `Failed to release the expired park for ${run.cardId}: ${err}`);
14565
14140
  }
14566
14141
  }
14567
14142
  async releaseExpiredAttemptCap(cardId, blockerCommentId) {
@@ -14571,7 +14146,7 @@ class Pool {
14571
14146
  ...blockerCommentId ? { replyToId: blockerCommentId } : {}
14572
14147
  });
14573
14148
  } catch (err) {
14574
- log37.warn(TAG33, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14149
+ log36.warn(TAG32, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14575
14150
  }
14576
14151
  try {
14577
14152
  await this.client.endAgentSession(cardId, {
@@ -14580,7 +14155,7 @@ class Pool {
14580
14155
  failureSummary: "The attempt-budget decision expired with no answer. Reassign the card to grant a fresh attempt."
14581
14156
  });
14582
14157
  } catch (err) {
14583
- log37.warn(TAG33, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14158
+ log36.warn(TAG32, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14584
14159
  }
14585
14160
  await this.stateStore.clearAwaitingDecision(cardId);
14586
14161
  }
@@ -14591,16 +14166,16 @@ class Pool {
14591
14166
  }
14592
14167
  const account = this.accountGuard?.check();
14593
14168
  if (account && !account.running) {
14594
- log37.debug(TAG33, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14169
+ log36.debug(TAG32, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14595
14170
  return;
14596
14171
  }
14597
14172
  const first = !this.adoptAnnounced.has(run.runId);
14598
14173
  this.adoptAnnounced.add(run.runId);
14599
14174
  const line = `#${run.cardShortId}: granted continue never reached a worker — re-enqueueing (${run.pipeline})`;
14600
14175
  if (first)
14601
- log37.warn(TAG33, line);
14176
+ log36.warn(TAG32, line);
14602
14177
  else
14603
- log37.debug(TAG33, line);
14178
+ log36.debug(TAG32, line);
14604
14179
  await this.enqueueCard(run.cardId, run.pipeline);
14605
14180
  }
14606
14181
  adoptAnnounced = new Set;
@@ -14619,7 +14194,7 @@ class Pool {
14619
14194
  async continueRun(run, opts) {
14620
14195
  const turns = this.budget.checkCardTurns(run.cardId);
14621
14196
  if (!turns.allow) {
14622
- log37.warn(TAG33, `Refusing a Continue on ${run.cardId} — ${turns.detail}. Handing the card back: reassign it to clear the count, or raise budget.maxTurnsPerCard.`);
14197
+ log36.warn(TAG32, `Refusing a Continue on ${run.cardId} — ${turns.detail}. Handing the card back: reassign it to clear the count, or raise budget.maxTurnsPerCard.`);
14623
14198
  try {
14624
14199
  await this.client.addComment(run.cardId, `**That Continue cannot be granted.** ${turns.detail}, which is this card's ceiling (\`budget.maxTurnsPerCard\`), so the implement pipeline would refuse it again the moment it was dispatched.
14625
14200
 
@@ -14628,14 +14203,14 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14628
14203
  agentSessionId: run.sessionId ?? undefined
14629
14204
  });
14630
14205
  } catch (err) {
14631
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14206
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14632
14207
  }
14633
14208
  await this.stopRun(run, "Continue refused: the card is at its per-card turn cap.");
14634
14209
  return;
14635
14210
  }
14636
14211
  const runsSpent = this.budget.checkCardRuns(run.cardId);
14637
14212
  if (!runsSpent.allow) {
14638
- log37.warn(TAG33, `Refusing a Continue on ${run.cardId} — ${runsSpent.detail}. Handing the card back: reassign it to clear the count, or raise budget.maxRunsPerCard.`);
14213
+ log36.warn(TAG32, `Refusing a Continue on ${run.cardId} — ${runsSpent.detail}. Handing the card back: reassign it to clear the count, or raise budget.maxRunsPerCard.`);
14639
14214
  try {
14640
14215
  await this.client.addComment(run.cardId, `**That Continue cannot be granted.** ${runsSpent.detail}, which is this card's run backstop (\`budget.maxRunsPerCard\`), so the implement pipeline would refuse it again the moment it was dispatched.
14641
14216
 
@@ -14644,7 +14219,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14644
14219
  agentSessionId: run.sessionId ?? undefined
14645
14220
  });
14646
14221
  } catch (err) {
14647
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14222
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14648
14223
  }
14649
14224
  await this.stopRun(run, "Continue refused: the card is at its per-card run backstop.");
14650
14225
  return;
@@ -14668,7 +14243,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14668
14243
  awaitingDecisionUntil: null
14669
14244
  });
14670
14245
  } catch (err) {
14671
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14246
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14672
14247
  }
14673
14248
  if (run.blockerCommentId) {
14674
14249
  try {
@@ -14676,7 +14251,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14676
14251
  resolve: true
14677
14252
  });
14678
14253
  } catch (err) {
14679
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14254
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14680
14255
  }
14681
14256
  }
14682
14257
  await this.enqueueCard(run.cardId, run.pipeline);
@@ -14700,7 +14275,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14700
14275
  awaitingDecisionUntil: null
14701
14276
  });
14702
14277
  } catch (err) {
14703
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14278
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14704
14279
  }
14705
14280
  if (run.blockerCommentId) {
14706
14281
  try {
@@ -14708,13 +14283,13 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14708
14283
  resolve: true
14709
14284
  });
14710
14285
  } catch (err) {
14711
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14286
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14712
14287
  }
14713
14288
  }
14714
14289
  await this.enqueueCard(run.cardId, run.pipeline);
14715
14290
  released += 1;
14716
14291
  } catch (err) {
14717
- log37.error(TAG33, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14292
+ log36.error(TAG32, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14718
14293
  }
14719
14294
  }
14720
14295
  return released;
@@ -14726,7 +14301,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14726
14301
  resolve: true
14727
14302
  });
14728
14303
  } catch (err) {
14729
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14304
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14730
14305
  }
14731
14306
  }
14732
14307
  try {
@@ -14735,7 +14310,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14735
14310
  awaitingDecisionUntil: null
14736
14311
  });
14737
14312
  } catch (err) {
14738
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14313
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14739
14314
  }
14740
14315
  try {
14741
14316
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14757,26 +14332,26 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14757
14332
  await this.client.endAgentSession(run.cardId, endSession);
14758
14333
  }
14759
14334
  } catch (err) {
14760
- log37.error(TAG33, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14335
+ log36.error(TAG32, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14761
14336
  }
14762
14337
  try {
14763
14338
  await this.stateStore.endRun(run.runId, "failed", {
14764
14339
  errorMessage: "budget_decision_stop"
14765
14340
  });
14766
14341
  } catch (err) {
14767
- log37.warn(TAG33, `Failed to end the local run record for ${run.cardId}: ${err}`);
14342
+ log36.warn(TAG32, `Failed to end the local run record for ${run.cardId}: ${err}`);
14768
14343
  }
14769
14344
  }
14770
14345
  async grantAttempt(cardId) {
14771
14346
  const turns = this.budget.checkCardTurns(cardId);
14772
14347
  if (!turns.allow) {
14773
- log37.warn(TAG33, `Attempt grant on ${cardId} cannot start a run — ${turns.detail}. Clearing the attempt budget anyway; reassign the card to clear the turn count, or raise budget.maxTurnsPerCard.`);
14348
+ log36.warn(TAG32, `Attempt grant on ${cardId} cannot start a run — ${turns.detail}. Clearing the attempt budget anyway; reassign the card to clear the turn count, or raise budget.maxTurnsPerCard.`);
14774
14349
  try {
14775
14350
  await this.client.addComment(cardId, `**Attempt budget cleared, but this card is at its turn cap.** ${turns.detail}, which is its ceiling (\`budget.maxTurnsPerCard\`), so I will not pick it up even with attempts restored.
14776
14351
 
14777
14352
  Reassign the card — that clears the turn count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14778
14353
  } catch (err) {
14779
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14354
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14780
14355
  }
14781
14356
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14782
14357
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card turn cap.");
@@ -14784,13 +14359,13 @@ Reassign the card — that clears the turn count and starts it fresh — or rais
14784
14359
  }
14785
14360
  const runsSpent = this.budget.checkCardRuns(cardId);
14786
14361
  if (!runsSpent.allow) {
14787
- log37.warn(TAG33, `Attempt grant on ${cardId} cannot start a run — ${runsSpent.detail}. Clearing the attempt budget anyway; reassign the card to clear the run count, or raise budget.maxRunsPerCard.`);
14362
+ log36.warn(TAG32, `Attempt grant on ${cardId} cannot start a run — ${runsSpent.detail}. Clearing the attempt budget anyway; reassign the card to clear the run count, or raise budget.maxRunsPerCard.`);
14788
14363
  try {
14789
14364
  await this.client.addComment(cardId, `**Attempt budget cleared, but this card is at its run backstop.** ${runsSpent.detail}, which is its ceiling (\`budget.maxRunsPerCard\`), so I will not pick it up even with attempts restored.
14790
14365
 
14791
14366
  Reassign the card — that clears the run count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14792
14367
  } catch (err) {
14793
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14368
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14794
14369
  }
14795
14370
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14796
14371
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card run backstop.");
@@ -14805,7 +14380,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14805
14380
  awaitingDecisionUntil: null
14806
14381
  });
14807
14382
  } catch (err) {
14808
- log37.warn(TAG33, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14383
+ log36.warn(TAG32, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14809
14384
  }
14810
14385
  await this.enqueueCard(cardId, "implement");
14811
14386
  }
@@ -14816,7 +14391,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14816
14391
  try {
14817
14392
  await this.client.updateComment(blockerCommentId, { resolve: true });
14818
14393
  } catch (err) {
14819
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14394
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14820
14395
  }
14821
14396
  }
14822
14397
  try {
@@ -14825,7 +14400,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14825
14400
  awaitingDecisionUntil: null
14826
14401
  });
14827
14402
  } catch (err) {
14828
- log37.warn(TAG33, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14403
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14829
14404
  }
14830
14405
  try {
14831
14406
  await this.client.endAgentSession(cardId, {
@@ -14834,7 +14409,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14834
14409
  failureSummary
14835
14410
  });
14836
14411
  } catch (err) {
14837
- log37.warn(TAG33, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14412
+ log36.warn(TAG32, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14838
14413
  }
14839
14414
  await this.stateStore.clearAwaitingDecision(cardId);
14840
14415
  }
@@ -14865,12 +14440,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14865
14440
  const subtasks = card.subtasks ?? [];
14866
14441
  await this.enqueue(card, column, cardLabels, subtasks, mode);
14867
14442
  } catch (err) {
14868
- log37.error(TAG33, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14443
+ log36.error(TAG32, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14869
14444
  }
14870
14445
  }
14871
14446
  async retireUnroutableRuns(shortId, cardId, reason = "column not found on this board") {
14872
14447
  const unended = this.stateStore.getRunsForCard(cardId).filter((r) => r.endedAt === null);
14873
- log37.warn(TAG33, `#${shortId}: ${reason} — retiring ${unended.length} run record(s) instead of re-enqueueing`);
14448
+ log36.warn(TAG32, `#${shortId}: ${reason} — retiring ${unended.length} run record(s) instead of re-enqueueing`);
14874
14449
  for (const run of unended) {
14875
14450
  await this.stateStore.endRun(run.runId, "orphaned", {
14876
14451
  errorMessage: `${reason} at re-enqueue — retired as unroutable (#1057/#1102)`
@@ -14883,12 +14458,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14883
14458
  if (this.shuttingDown)
14884
14459
  return false;
14885
14460
  if (this.accountGuard && !this.accountGuard.check().running) {
14886
- log37.debug(TAG33, `${label} dispatch held — the account is halted`);
14461
+ log36.debug(TAG32, `${label} dispatch held — the account is halted`);
14887
14462
  return false;
14888
14463
  }
14889
14464
  const idle = workers.find((w) => w.isIdle);
14890
14465
  if (!idle) {
14891
- log37.debug(TAG33, `No idle ${label} workers (queue: ${queue.length})`);
14466
+ log36.debug(TAG32, `No idle ${label} workers (queue: ${queue.length})`);
14892
14467
  return false;
14893
14468
  }
14894
14469
  const next = queue.dequeue();
@@ -14896,18 +14471,18 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14896
14471
  return false;
14897
14472
  const data = this.cardDataCache.get(next.cardId);
14898
14473
  if (!data) {
14899
- log37.warn(TAG33, `No cached data for card ${next.cardId}, skipping`);
14474
+ log36.warn(TAG32, `No cached data for card ${next.cardId}, skipping`);
14900
14475
  return false;
14901
14476
  }
14902
14477
  this.cardDataCache.delete(next.cardId);
14903
14478
  this.lastWaitingEmit.delete(next.cardId);
14904
- log37.info(TAG33, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14479
+ log36.info(TAG32, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14905
14480
  this.sleepGuard.acquire();
14906
14481
  idle.run(data.card, data.column, data.labels, data.subtasks);
14907
14482
  return true;
14908
14483
  }
14909
14484
  }
14910
- var TAG33 = "pool";
14485
+ var TAG32 = "pool";
14911
14486
  var init_pool = __esm(() => {
14912
14487
  init_dist();
14913
14488
  init_board_helpers();
@@ -14941,7 +14516,7 @@ import {
14941
14516
  writeFileSync as writeFileSync4
14942
14517
  } from "node:fs";
14943
14518
  import { dirname as dirname5 } from "node:path";
14944
- import { log as log38 } from "@gethmy/harness";
14519
+ import { log as log37 } from "@gethmy/harness";
14945
14520
  function defaultRegistryPath() {
14946
14521
  return portRegistryPath();
14947
14522
  }
@@ -14956,7 +14531,7 @@ function load(path) {
14956
14531
  }
14957
14532
  return emptyRegistry();
14958
14533
  } catch (err) {
14959
- log38.warn(TAG34, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14534
+ log37.warn(TAG33, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14960
14535
  return emptyRegistry();
14961
14536
  }
14962
14537
  }
@@ -14977,7 +14552,7 @@ function recordDaemonPort(projectId, entry, path = defaultRegistryPath()) {
14977
14552
  registry[projectId] = { ...entry, updatedAt: Date.now() };
14978
14553
  save(path, registry);
14979
14554
  } catch (err) {
14980
- log38.warn(TAG34, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14555
+ log37.warn(TAG33, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14981
14556
  }
14982
14557
  }
14983
14558
  function daemonBaseUrl(bindAddr, port) {
@@ -14997,17 +14572,17 @@ function clearDaemonPort(projectId, pid, path = defaultRegistryPath()) {
14997
14572
  delete registry[projectId];
14998
14573
  save(path, registry);
14999
14574
  } catch (err) {
15000
- log38.warn(TAG34, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14575
+ log37.warn(TAG33, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
15001
14576
  }
15002
14577
  }
15003
- var TAG34 = "port-registry";
14578
+ var TAG33 = "port-registry";
15004
14579
  var init_port_registry = __esm(() => {
15005
14580
  init_dist();
15006
14581
  init_paths();
15007
14582
  });
15008
14583
 
15009
14584
  // src/recovery.ts
15010
- import { log as log39, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
14585
+ import { log as log38, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
15011
14586
  function isProcessAlive(pid, currentPid) {
15012
14587
  if (pid === currentPid)
15013
14588
  return true;
@@ -15023,7 +14598,7 @@ async function fetchCardSafely(client, cardId) {
15023
14598
  const { card } = await client.getCard(cardId);
15024
14599
  return card;
15025
14600
  } catch (err) {
15026
- log39.warn(TAG35, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
14601
+ log38.warn(TAG34, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
15027
14602
  return null;
15028
14603
  }
15029
14604
  }
@@ -15033,7 +14608,7 @@ async function recoverOrphans(store, client, config, opts = {}) {
15033
14608
  return [];
15034
14609
  }
15035
14610
  const outcomes = [];
15036
- log39.info(TAG35, `recovering ${active.length} orphan run(s) from prior daemon`);
14611
+ log38.info(TAG34, `recovering ${active.length} orphan run(s) from prior daemon`);
15037
14612
  for (const run of active) {
15038
14613
  const outcome = {
15039
14614
  runId: run.runId,
@@ -15045,16 +14620,16 @@ async function recoverOrphans(store, client, config, opts = {}) {
15045
14620
  };
15046
14621
  outcomes.push(outcome);
15047
14622
  if (isBudgetHeldRun(run)) {
15048
- log39.info(TAG35, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
14623
+ log38.info(TAG34, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15049
14624
  outcome.actions.push("skipped: held for a human budget decision");
15050
14625
  continue;
15051
14626
  }
15052
14627
  if (isProcessAlive(run.daemonPid, process.pid)) {
15053
- log39.warn(TAG35, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
14628
+ log38.warn(TAG34, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
15054
14629
  outcome.actions.push("skipped: daemon pid still alive");
15055
14630
  continue;
15056
14631
  }
15057
- log39.info(TAG35, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
14632
+ log38.info(TAG34, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
15058
14633
  await recoverRun(run, store, client, config, outcome, {
15059
14634
  rollbackAttempt: true,
15060
14635
  agentId: opts.agentId
@@ -15075,7 +14650,7 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15075
14650
  } catch (err) {
15076
14651
  const msg = err instanceof Error ? err.message : String(err);
15077
14652
  outcome.errors.push(`endAgentSession: ${msg}`);
15078
- log39.warn(TAG35, `endAgentSession failed for ${run.cardId}: ${msg}`);
14653
+ log38.warn(TAG34, `endAgentSession failed for ${run.cardId}: ${msg}`);
15079
14654
  }
15080
14655
  const card = await fetchCardSafely(client, run.cardId);
15081
14656
  if (card) {
@@ -15135,9 +14710,9 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15135
14710
  outcome.errors.push(`decrementAttempt: ${msg}`);
15136
14711
  }
15137
14712
  }
15138
- log39.info(TAG35, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
14713
+ log38.info(TAG34, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
15139
14714
  }
15140
- var TAG35 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
14715
+ var TAG34 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
15141
14716
  var init_recovery = __esm(() => {
15142
14717
  init_board_helpers();
15143
14718
  init_handback();
@@ -15159,18 +14734,18 @@ var init_repo_dirs = __esm(() => {
15159
14734
  });
15160
14735
 
15161
14736
  // src/claim.ts
15162
- import { log as log40 } from "@gethmy/harness";
14737
+ import { log as log39 } from "@gethmy/harness";
15163
14738
  async function claimUnassignedCard(client, cardId, agentId, opts) {
15164
14739
  try {
15165
14740
  const { claimed } = opts ? await client.claimCard(cardId, agentId, opts) : await client.claimCard(cardId, agentId);
15166
- log40.debug(TAG36, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
14741
+ log39.debug(TAG35, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
15167
14742
  return claimed;
15168
14743
  } catch (err) {
15169
- log40.error(TAG36, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
14744
+ log39.error(TAG35, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
15170
14745
  return false;
15171
14746
  }
15172
14747
  }
15173
- var TAG36 = "claim";
14748
+ var TAG35 = "claim";
15174
14749
  var init_claim = () => {};
15175
14750
 
15176
14751
  // src/strand-recovery.ts
@@ -15178,7 +14753,7 @@ var exports_strand_recovery = {};
15178
14753
  __export(exports_strand_recovery, {
15179
14754
  reclaimPreReviewStrands: () => reclaimPreReviewStrands
15180
14755
  });
15181
- import { log as log41, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
14756
+ import { log as log40, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
15182
14757
  async function reclaimPreReviewStrands(opts) {
15183
14758
  const {
15184
14759
  client,
@@ -15222,22 +14797,22 @@ async function reclaimPreReviewStrands(opts) {
15222
14797
  continue;
15223
14798
  const won = await claimUnassignedCard(client, card.id, agentId);
15224
14799
  if (!won) {
15225
- log41.debug(TAG37, `#${card.short_id} — lost the review claim race, skipping`);
14800
+ log40.debug(TAG36, `#${card.short_id} — lost the review claim race, skipping`);
15226
14801
  continue;
15227
14802
  }
15228
- log41.warn(TAG37, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
14803
+ log40.warn(TAG36, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
15229
14804
  reclaimed.push(card.id);
15230
14805
  if (opts.onClaimed) {
15231
14806
  try {
15232
14807
  await opts.onClaimed(card);
15233
14808
  } catch (err) {
15234
- log41.error(TAG37, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
14809
+ log40.error(TAG36, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
15235
14810
  }
15236
14811
  }
15237
14812
  }
15238
14813
  return reclaimed;
15239
14814
  }
15240
- var TAG37 = "strand-recovery";
14815
+ var TAG36 = "strand-recovery";
15241
14816
  var init_strand_recovery = __esm(() => {
15242
14817
  init_board_helpers();
15243
14818
  init_claim();
@@ -15403,7 +14978,7 @@ var init_scope = __esm(() => {
15403
14978
  });
15404
14979
 
15405
14980
  // src/sweep.ts
15406
- import { log as log42 } from "@gethmy/harness";
14981
+ import { log as log41 } from "@gethmy/harness";
15407
14982
  function rankSweepCandidates(opts) {
15408
14983
  const {
15409
14984
  agentId,
@@ -15522,10 +15097,10 @@ async function sweepForCard(opts) {
15522
15097
  let { candidates, skipped, scope } = rankSweepCandidates(opts);
15523
15098
  const cohesionCounts = opts.ranking.cohesionWeight !== 0;
15524
15099
  if (cohesionCounts) {
15525
- log42.debug(TAG38, describeActiveScope(scope.active));
15100
+ log41.debug(TAG37, describeActiveScope(scope.active));
15526
15101
  }
15527
15102
  if (candidates.length === 0) {
15528
- log42.debug(TAG38, `no claimable card (${skipped.length} skipped in a pickup column)`);
15103
+ log41.debug(TAG37, `no claimable card (${skipped.length} skipped in a pickup column)`);
15529
15104
  return { claimed: null, skipped, probed: 0 };
15530
15105
  }
15531
15106
  const probeWindow = candidates.slice(0, maxProbes);
@@ -15541,12 +15116,12 @@ async function sweepForCard(opts) {
15541
15116
  chainNeighbors: chainNeighbors(chain2)
15542
15117
  }));
15543
15118
  } else if (chainTermsCount && candidates.length > 1) {
15544
- log42.debug(TAG38, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15119
+ log41.debug(TAG37, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15545
15120
  }
15546
15121
  let probed = 0;
15547
15122
  for (const candidate of candidates) {
15548
15123
  if (probed >= maxProbes) {
15549
- log42.debug(TAG38, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15124
+ log41.debug(TAG37, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15550
15125
  break;
15551
15126
  }
15552
15127
  probed++;
@@ -15624,10 +15199,10 @@ async function sweepForCard(opts) {
15624
15199
  continue;
15625
15200
  }
15626
15201
  verified.card.assigned_agent_id = agentId;
15627
- log42.info(TAG38, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15202
+ log41.info(TAG37, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15628
15203
  return { claimed: verified, skipped, probed };
15629
15204
  }
15630
- log42.debug(TAG38, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15205
+ log41.debug(TAG37, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15631
15206
  return { claimed: null, skipped, probed };
15632
15207
  }
15633
15208
  function claimLine(claimed, rank, candidates, skipped, scope) {
@@ -15648,7 +15223,7 @@ async function refetchCard(client, cardId) {
15648
15223
  const { card } = await client.getCard(cardId);
15649
15224
  return card ?? null;
15650
15225
  } catch (err) {
15651
- log42.warn(TAG38, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15226
+ log41.warn(TAG37, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15652
15227
  return null;
15653
15228
  }
15654
15229
  }
@@ -15657,11 +15232,11 @@ async function hasLiveSession(client, cardId) {
15657
15232
  const { session } = await client.getAgentSession(cardId);
15658
15233
  return session != null;
15659
15234
  } catch (err) {
15660
- log42.warn(TAG38, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15235
+ log41.warn(TAG37, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15661
15236
  return true;
15662
15237
  }
15663
15238
  }
15664
- var TAG38 = "sweep";
15239
+ var TAG37 = "sweep";
15665
15240
  var init_sweep = __esm(() => {
15666
15241
  init_board_helpers();
15667
15242
  init_claim();
@@ -15672,7 +15247,7 @@ var init_sweep = __esm(() => {
15672
15247
  });
15673
15248
 
15674
15249
  // src/sweep-commands.ts
15675
- import { log as log43 } from "@gethmy/harness";
15250
+ import { log as log42 } from "@gethmy/harness";
15676
15251
  function parseSweepCommands(payload) {
15677
15252
  if (!payload || typeof payload !== "object")
15678
15253
  return [];
@@ -15699,14 +15274,14 @@ function parseSweepCommands(payload) {
15699
15274
  async function claimSweepCommands(client, agentId, projectId, daemonId) {
15700
15275
  const request = client.request?.bind(client);
15701
15276
  if (typeof request !== "function") {
15702
- log43.warn(TAG39, "installed @gethmy/mcp has no generic request method — board sweep commands cannot be claimed; use `harmony-agent sweep stop|resume` until it is upgraded");
15277
+ log42.warn(TAG38, "installed @gethmy/mcp has no generic request method — board sweep commands cannot be claimed; use `harmony-agent sweep stop|resume` until it is upgraded");
15703
15278
  return [];
15704
15279
  }
15705
15280
  try {
15706
15281
  const res = await request("POST", `/agents/${encodeURIComponent(agentId)}/sweep-commands/claim`, { projectId, daemonId });
15707
15282
  return parseSweepCommands(res);
15708
15283
  } catch (err) {
15709
- log43.warn(TAG39, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15284
+ log42.warn(TAG38, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15710
15285
  return [];
15711
15286
  }
15712
15287
  }
@@ -15719,15 +15294,15 @@ async function applySweepCommands(commands, actions) {
15719
15294
  await actions.resume();
15720
15295
  }
15721
15296
  applied = command.verb;
15722
- log43.info(TAG39, `applied "${command.verb}" from the board (${command.id})`);
15297
+ log42.info(TAG38, `applied "${command.verb}" from the board (${command.id})`);
15723
15298
  }
15724
15299
  return applied;
15725
15300
  }
15726
- var TAG39 = "sweep-cmd";
15301
+ var TAG38 = "sweep-cmd";
15727
15302
  var init_sweep_commands = () => {};
15728
15303
 
15729
15304
  // src/sweep-guard.ts
15730
- import { log as log44 } from "@gethmy/harness";
15305
+ import { log as log43 } from "@gethmy/harness";
15731
15306
 
15732
15307
  class SweepGuard {
15733
15308
  config;
@@ -15783,7 +15358,7 @@ class SweepGuard {
15783
15358
  await this.store.haltSweep(reason);
15784
15359
  if (!already) {
15785
15360
  const claimed = this.store.getSweep().claimed;
15786
- log44.info(TAG40, `claiming stopped (${reason}) after ${claimed} claimed`);
15361
+ log43.info(TAG39, `claiming stopped (${reason}) after ${claimed} claimed`);
15787
15362
  }
15788
15363
  return this.snapshot();
15789
15364
  }
@@ -15792,7 +15367,7 @@ class SweepGuard {
15792
15367
  const was = before.haltReason ? this.describeStop(before.haltReason) : null;
15793
15368
  await this.store.resumeSweep();
15794
15369
  if (was)
15795
- log44.info(TAG40, `claiming resumed by the operator — was stopped: ${was}`);
15370
+ log43.info(TAG39, `claiming resumed by the operator — was stopped: ${was}`);
15796
15371
  return this.snapshot();
15797
15372
  }
15798
15373
  snapshot() {
@@ -15854,11 +15429,11 @@ function sweepBannerLine(config) {
15854
15429
  const authors = extra ? `you + ${extra} trusted author${extra === 1 ? "" : "s"}` : "you only";
15855
15430
  return `Sweep ON — claims ${scope} in ${config.pickupColumns.join(", ")}, ` + `authored by ${authors}; caps: ${describeCaps(sweep, config.budget.dailyBudgetCents)}; ` + `${sweep.maxProbesPerTick} probes/tick`;
15856
15431
  }
15857
- var TAG40 = "sweep";
15432
+ var TAG39 = "sweep";
15858
15433
  var init_sweep_guard = () => {};
15859
15434
 
15860
15435
  // src/reconcile.ts
15861
- import { detectGitProvider as detectGitProvider5, log as log45 } from "@gethmy/harness";
15436
+ import { detectGitProvider as detectGitProvider5, log as log44 } from "@gethmy/harness";
15862
15437
  function daemonProcessLabels(approvedLabel) {
15863
15438
  const names = ["agent", "agent-recovered", NEED_REVIEW_LABEL, approvedLabel];
15864
15439
  return new Set(names.filter(Boolean).map((n) => n.toLowerCase()));
@@ -15921,7 +15496,7 @@ class Reconciler {
15921
15496
  clearInterval(this.timer);
15922
15497
  this.timer = null;
15923
15498
  }
15924
- log45.info(TAG41, "Heartbeat stopped");
15499
+ log44.info(TAG40, "Heartbeat stopped");
15925
15500
  }
15926
15501
  async recoverStaleRuns() {
15927
15502
  if (!this.stateStore || !this.agentConfig)
@@ -15932,7 +15507,7 @@ class Reconciler {
15932
15507
  const pool = this.pool;
15933
15508
  for (const run of active) {
15934
15509
  if (isBudgetHeldRun(run)) {
15935
- log45.info(TAG41, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15510
+ log44.info(TAG40, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15936
15511
  continue;
15937
15512
  }
15938
15513
  const foreignDaemon = run.daemonPid !== process.pid;
@@ -15942,7 +15517,7 @@ class Reconciler {
15942
15517
  if (!daemonDead && !(heartbeatStale && ourZombie))
15943
15518
  continue;
15944
15519
  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`;
15945
- log45.warn(TAG41, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
15520
+ log44.warn(TAG40, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
15946
15521
  await recoverRun(run, this.stateStore, this.client, this.agentConfig, {
15947
15522
  runId: run.runId,
15948
15523
  cardId: run.cardId,
@@ -15969,11 +15544,11 @@ class Reconciler {
15969
15544
  const stalledAt = Date.parse(card.updated_at ?? "");
15970
15545
  if (!Number.isFinite(stalledAt) || now - stalledAt < graceMs)
15971
15546
  continue;
15972
- log45.warn(TAG41, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15547
+ log44.warn(TAG40, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15973
15548
  try {
15974
15549
  await this.client.moveCard(card.id, pickupCol.id);
15975
15550
  } catch (err) {
15976
- log45.error(TAG41, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15551
+ log44.error(TAG40, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15977
15552
  }
15978
15553
  }
15979
15554
  }
@@ -16005,7 +15580,7 @@ class Reconciler {
16005
15580
  return;
16006
15581
  const cardLabels = resolveCardLabels(card, labelMap);
16007
15582
  const subtasks = card.subtasks ?? [];
16008
- log45.info(TAG41, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
15583
+ log44.info(TAG40, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
16009
15584
  await this.pool.enqueue(card, column, cardLabels, subtasks, "review");
16010
15585
  }
16011
15586
  });
@@ -16029,11 +15604,11 @@ class Reconciler {
16029
15604
  const parkedAt = Date.parse(card.updated_at ?? "");
16030
15605
  if (!Number.isFinite(parkedAt) || now - parkedAt < ttlMs)
16031
15606
  continue;
16032
- log45.warn(TAG41, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
15607
+ log44.warn(TAG40, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
16033
15608
  try {
16034
15609
  await this.client.moveCard(card.id, pickupCol.id);
16035
15610
  } catch (err) {
16036
- log45.error(TAG41, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15611
+ log44.error(TAG40, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
16037
15612
  }
16038
15613
  }
16039
15614
  }
@@ -16068,7 +15643,7 @@ class Reconciler {
16068
15643
  }
16069
15644
  this.lastSweepStopReported = null;
16070
15645
  if (!this.pool.hasFreeImplementSlot()) {
16071
- log45.debug(TAG41, "sweep skipped — no free implement slot");
15646
+ log44.debug(TAG40, "sweep skipped — no free implement slot");
16072
15647
  return;
16073
15648
  }
16074
15649
  const { claimed } = await sweepForCard({
@@ -16087,9 +15662,9 @@ class Reconciler {
16087
15662
  reportSweepStopped(reason, detail) {
16088
15663
  const line = `sweep stopped claiming — ${detail}`;
16089
15664
  if (this.lastSweepStopReported === reason)
16090
- log45.debug(TAG41, line);
15665
+ log44.debug(TAG40, line);
16091
15666
  else
16092
- log45.warn(TAG41, line);
15667
+ log44.warn(TAG40, line);
16093
15668
  this.lastSweepStopReported = reason;
16094
15669
  }
16095
15670
  setSweepPresenceSink(sink) {
@@ -16127,7 +15702,7 @@ class Reconciler {
16127
15702
  return;
16128
15703
  this.lastSweepNudgeAt = now;
16129
15704
  this.drainSweepCommands().catch((err) => {
16130
- log45.error(TAG41, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
15705
+ log44.error(TAG40, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
16131
15706
  });
16132
15707
  }
16133
15708
  resolveRepoDirectories() {
@@ -16136,9 +15711,9 @@ class Reconciler {
16136
15711
  const dirs = readRepoDirectories(process.cwd());
16137
15712
  this.repoDirectories = dirs;
16138
15713
  if (dirs.size === 0) {
16139
- log45.warn(TAG41, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
15714
+ log44.warn(TAG40, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
16140
15715
  } else {
16141
- log45.debug(TAG41, `Path signal allows ${dirs.size} top-level directories`);
15716
+ log44.debug(TAG40, `Path signal allows ${dirs.size} top-level directories`);
16142
15717
  }
16143
15718
  return dirs;
16144
15719
  }
@@ -16174,7 +15749,7 @@ class Reconciler {
16174
15749
  if (accountHalt !== this.lastAccountHoldReported) {
16175
15750
  if (accountHalt) {
16176
15751
  const unqueued = assignedCards.filter((c) => !knownCardIds.has(c.id)).length;
16177
- log45.warn(TAG41, `Account halted (${accountHalt}) — ${unqueued} assigned card(s) not queued; nothing is dispatched until \`harmony-agent resume\``);
15752
+ log44.warn(TAG40, `Account halted (${accountHalt}) — ${unqueued} assigned card(s) not queued; nothing is dispatched until \`harmony-agent resume\``);
16178
15753
  }
16179
15754
  this.lastAccountHoldReported = accountHalt;
16180
15755
  }
@@ -16190,24 +15765,24 @@ class Reconciler {
16190
15765
  const subtasks = card.subtasks ?? [];
16191
15766
  const mode = route.mode;
16192
15767
  if (route.stage) {
16193
- log45.info(TAG41, `Stage card #${card.short_id} (stage "${card.current_stage}") in "${column.name}" — routing to the stage executor (implement) regardless of column`);
15768
+ log44.info(TAG40, `Stage card #${card.short_id} (stage "${card.current_stage}") in "${column.name}" — routing to the stage executor (implement) regardless of column`);
16194
15769
  }
16195
15770
  if (mode === "review" && this.approvedLabel && hasLabel(cardLabels, this.approvedLabel)) {
16196
- log45.debug(TAG41, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
15771
+ log44.debug(TAG40, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
16197
15772
  continue;
16198
15773
  }
16199
15774
  if (mode === "review" && hasLabel(cardLabels, NEED_REVIEW_LABEL)) {
16200
- log45.debug(TAG41, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
15775
+ log44.debug(TAG40, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
16201
15776
  continue;
16202
15777
  }
16203
15778
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
16204
- log45.debug(TAG41, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
15779
+ log44.debug(TAG40, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
16205
15780
  continue;
16206
15781
  }
16207
15782
  if (accountHalt) {
16208
- log45.debug(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
15783
+ log44.debug(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
16209
15784
  } else {
16210
- log45.info(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
15785
+ log44.info(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
16211
15786
  }
16212
15787
  await this.pool.enqueue(card, column, cardLabels, subtasks, mode);
16213
15788
  }
@@ -16218,13 +15793,13 @@ class Reconciler {
16218
15793
  try {
16219
15794
  await this.pool.drainBudgetDecisions();
16220
15795
  } catch (err) {
16221
- log45.error(TAG41, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
15796
+ log44.error(TAG40, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
16222
15797
  }
16223
15798
  await this.recoverStrandedInProgress(cards, columns, knownCardIds);
16224
15799
  await this.recoverStrandedReview(cards, columns, labelMap, knownCardIds);
16225
15800
  for (const knownId of knownCardIds) {
16226
15801
  if (!allAgentCardIds.has(knownId)) {
16227
- log45.info(TAG41, `Missed unassign: ${knownId} — removing`);
15802
+ log44.info(TAG40, `Missed unassign: ${knownId} — removing`);
16228
15803
  await this.pool.removeCard(knownId);
16229
15804
  }
16230
15805
  }
@@ -16232,20 +15807,20 @@ class Reconciler {
16232
15807
  try {
16233
15808
  await this.drainSweepCommands();
16234
15809
  } catch (err) {
16235
- log45.error(TAG41, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
15810
+ log44.error(TAG40, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
16236
15811
  }
16237
15812
  try {
16238
15813
  await this.sweepForWork(cards, columns, labelMap, pickupConfig);
16239
15814
  } catch (err) {
16240
- log45.error(TAG41, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
15815
+ log44.error(TAG40, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
16241
15816
  }
16242
- log45.debug(TAG41, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
15817
+ log44.debug(TAG40, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
16243
15818
  } catch (err) {
16244
- log45.error(TAG41, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
15819
+ log44.error(TAG40, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
16245
15820
  }
16246
15821
  }
16247
15822
  }
16248
- var TAG41 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
15823
+ var TAG40 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
16249
15824
  var init_reconcile = __esm(() => {
16250
15825
  init_board_helpers();
16251
15826
  init_recovery();
@@ -16265,7 +15840,7 @@ __export(exports_startup_banner, {
16265
15840
  createStartupBanner: () => createStartupBanner,
16266
15841
  contextSourceLine: () => contextSourceLine
16267
15842
  });
16268
- import { isPretty, log as log46 } from "@gethmy/harness";
15843
+ import { isPretty, log as log45 } from "@gethmy/harness";
16269
15844
  function createStartupBanner(config, version) {
16270
15845
  return isPretty() ? prettyBanner(config, version) : jsonBanner(config, version);
16271
15846
  }
@@ -16290,7 +15865,7 @@ function prettyBanner(config, version) {
16290
15865
  checks.push({ kind: "ok", message });
16291
15866
  },
16292
15867
  warn(message) {
16293
- log46.warn(TAG42, message);
15868
+ log45.warn(TAG41, message);
16294
15869
  checks.push({ kind: "warn", message: message.split(`
16295
15870
  `, 1)[0] });
16296
15871
  },
@@ -16315,26 +15890,26 @@ function prettyBanner(config, version) {
16315
15890
  };
16316
15891
  }
16317
15892
  function jsonBanner(config, version) {
16318
- log46.info(TAG42, `Harmony Agent Daemon v${version} starting...`);
16319
- log46.info(TAG42, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
16320
- log46.info(TAG42, `Config: ${contextSourceLine(config)}`);
15893
+ log45.info(TAG41, `Harmony Agent Daemon v${version} starting...`);
15894
+ log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
15895
+ log45.info(TAG41, `Config: ${contextSourceLine(config)}`);
16321
15896
  if (config.agent.review.enabled) {
16322
- log46.info(TAG42, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
15897
+ log45.info(TAG41, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
16323
15898
  }
16324
15899
  let failed = false;
16325
15900
  return {
16326
15901
  setProjectName(_name) {},
16327
15902
  setGitProvider(provider) {
16328
- log46.info(TAG42, `Git provider: ${provider}`);
15903
+ log45.info(TAG41, `Git provider: ${provider}`);
16329
15904
  },
16330
15905
  setHttpPort(port) {
16331
- log46.info(TAG42, `HTTP server on port ${port}`);
15906
+ log45.info(TAG41, `HTTP server on port ${port}`);
16332
15907
  },
16333
15908
  check(message) {
16334
- log46.info(TAG42, message);
15909
+ log45.info(TAG41, message);
16335
15910
  },
16336
15911
  warn(message) {
16337
- log46.warn(TAG42, message);
15912
+ log45.warn(TAG41, message);
16338
15913
  },
16339
15914
  fail() {
16340
15915
  failed = true;
@@ -16342,7 +15917,7 @@ function jsonBanner(config, version) {
16342
15917
  async ready(message) {
16343
15918
  if (failed)
16344
15919
  return;
16345
- log46.info(TAG42, message);
15920
+ log45.info(TAG41, message);
16346
15921
  }
16347
15922
  };
16348
15923
  }
@@ -16435,7 +16010,7 @@ function cyan(s) {
16435
16010
  function yellow(s) {
16436
16011
  return `${ANSI.yellow}${s}${ANSI.reset}`;
16437
16012
  }
16438
- var TAG42 = "daemon", RULE_WIDTH = 70, ANSI;
16013
+ var TAG41 = "daemon", RULE_WIDTH = 70, ANSI;
16439
16014
  var init_startup_banner = __esm(() => {
16440
16015
  init_port_registry();
16441
16016
  ANSI = {
@@ -16456,7 +16031,7 @@ import {
16456
16031
  writeFileSync as writeFileSync5
16457
16032
  } from "node:fs";
16458
16033
  import { dirname as dirname6, resolve as resolve2, sep as sep2 } from "node:path";
16459
- import { log as log47 } from "@gethmy/harness";
16034
+ import { log as log46 } from "@gethmy/harness";
16460
16035
  function migrationMarkerPath(targetPath) {
16461
16036
  return `${targetPath}.migrated`;
16462
16037
  }
@@ -16530,7 +16105,7 @@ function migrateLegacyStateFile(opts) {
16530
16105
  throw new Error("not an object");
16531
16106
  legacy = parsed;
16532
16107
  } catch (err) {
16533
- log47.warn(TAG43, `legacy state file unreadable — skipping the split this start; it retries on the next (${err instanceof Error ? err.message : err})`);
16108
+ log46.warn(TAG42, `legacy state file unreadable — skipping the split this start; it retries on the next (${err instanceof Error ? err.message : err})`);
16534
16109
  return NO_MIGRATION;
16535
16110
  }
16536
16111
  const runs = Array.isArray(legacy.runs) ? legacy.runs : [];
@@ -16552,13 +16127,13 @@ function migrateLegacyStateFile(opts) {
16552
16127
  const legacyVersion = typeof legacy.version === "number" ? legacy.version : SCHEMA_VERSION;
16553
16128
  const existing = existsSync5(targetPath) ? readTargetFile(targetPath) : null;
16554
16129
  if (existsSync5(targetPath) && !existing) {
16555
- log47.warn(TAG43, "existing project state file unreadable — the split overwrites it");
16130
+ log46.warn(TAG42, "existing project state file unreadable — the split overwrites it");
16556
16131
  }
16557
16132
  let target;
16558
16133
  if (existing) {
16559
16134
  const existingVersion = typeof existing.version === "number" ? existing.version : SCHEMA_VERSION;
16560
16135
  if (existingVersion !== legacyVersion) {
16561
- log47.warn(TAG43, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16136
+ log46.warn(TAG42, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16562
16137
  return NO_MIGRATION;
16563
16138
  }
16564
16139
  const existingRuns = Array.isArray(existing.runs) ? existing.runs : [];
@@ -16604,7 +16179,7 @@ function migrateLegacyStateFile(opts) {
16604
16179
  if (!existsSync5(backupPath))
16605
16180
  copyFileSync(legacyPath, backupPath);
16606
16181
  } catch (err) {
16607
- log47.warn(TAG43, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16182
+ log46.warn(TAG42, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16608
16183
  }
16609
16184
  const remainingRuns = runs.filter((r) => !ownRunIds.has(r.runId));
16610
16185
  const remainingCards = cards.filter((c) => !ownCardIds.has(c.cardId));
@@ -16628,10 +16203,10 @@ function migrateLegacyStateFile(opts) {
16628
16203
  copiedIndeterminateCards: indeterminateCards.length,
16629
16204
  foreignUnendedRuns: remainingRuns.filter((r) => r.endedAt === null).length
16630
16205
  };
16631
- log47.info(TAG43, `split legacy state into ${targetPath}: moved ${result.movedRuns} run(s) ` + `(${result.movedUnendedRuns} unended) and ${result.movedCards} card record(s), ` + `copied ${result.copiedIndeterminateCards} unattributable card record(s); ` + `left ${remainingRuns.length} run(s) (${result.foreignUnendedRuns} unended) for other projects`);
16206
+ log46.info(TAG42, `split legacy state into ${targetPath}: moved ${result.movedRuns} run(s) ` + `(${result.movedUnendedRuns} unended) and ${result.movedCards} card record(s), ` + `copied ${result.copiedIndeterminateCards} unattributable card record(s); ` + `left ${remainingRuns.length} run(s) (${result.foreignUnendedRuns} unended) for other projects`);
16632
16207
  return result;
16633
16208
  }
16634
- var TAG43 = "state-migration", NO_MIGRATION;
16209
+ var TAG42 = "state-migration", NO_MIGRATION;
16635
16210
  var init_state_migration = __esm(() => {
16636
16211
  init_dist();
16637
16212
  init_state_store();
@@ -16738,7 +16313,7 @@ var init_stream_parser_selftest = __esm(() => {
16738
16313
 
16739
16314
  // src/watcher.ts
16740
16315
  import { randomUUID as randomUUID3 } from "node:crypto";
16741
- import { isPretty as isPretty2, log as log48 } from "@gethmy/harness";
16316
+ import { isPretty as isPretty2, log as log47 } from "@gethmy/harness";
16742
16317
  import { createClient } from "@supabase/supabase-js";
16743
16318
  function toPresenceColumns(names) {
16744
16319
  return names.map((n) => n.trim()).filter((n) => n.length > 0).slice(0, MAX_PRESENCE_COLUMNS).map((n) => n.slice(0, MAX_PRESENCE_COLUMN_LENGTH));
@@ -16799,7 +16374,7 @@ class Watcher {
16799
16374
  const stillHeld = this.supabase?.getChannels().some((c) => c.topic === old.topic) ?? false;
16800
16375
  if (!stillHeld)
16801
16376
  return true;
16802
- log48.warn(TAG44, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16377
+ log47.warn(TAG43, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16803
16378
  return false;
16804
16379
  }
16805
16380
  constructor(credentials, projectId, identity, routing, onCardBroadcast, onAgentCommand, onSweepCommandNudge) {
@@ -16813,7 +16388,7 @@ class Watcher {
16813
16388
  }
16814
16389
  async start() {
16815
16390
  if (!isPretty2()) {
16816
- log48.info(TAG44, "Connecting to Supabase realtime (broadcast)...");
16391
+ log47.info(TAG43, "Connecting to Supabase realtime (broadcast)...");
16817
16392
  }
16818
16393
  this.supabase = createClient(this.credentials.supabaseUrl, this.credentials.supabaseAnonKey);
16819
16394
  this.subscribeBroadcast();
@@ -16851,7 +16426,7 @@ class Watcher {
16851
16426
  status = `threw (${String(err)})`;
16852
16427
  }
16853
16428
  if (status !== "ok") {
16854
- log48.debug(TAG44, `Presence sweep update returned "${status}"`);
16429
+ log47.debug(TAG43, `Presence sweep update returned "${status}"`);
16855
16430
  }
16856
16431
  })();
16857
16432
  }
@@ -16862,7 +16437,7 @@ class Watcher {
16862
16437
  const presenceChannel = this.supabase.channel(`board-presence-${this.projectId}`);
16863
16438
  this.presenceChannel = presenceChannel;
16864
16439
  presenceChannel.on("presence", { event: "sync" }, () => {
16865
- log48.debug(TAG44, "Presence sync");
16440
+ log47.debug(TAG43, "Presence sync");
16866
16441
  }).subscribe(async (status) => {
16867
16442
  if (gen !== this.presenceGen)
16868
16443
  return;
@@ -16878,13 +16453,13 @@ class Watcher {
16878
16453
  if (trackStatus !== "ok") {
16879
16454
  this.presenceTracked = false;
16880
16455
  if (!this.stopping) {
16881
- log48.warn(TAG44, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16456
+ log47.warn(TAG43, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16882
16457
  this.schedulePresenceReconnect();
16883
16458
  }
16884
16459
  return;
16885
16460
  }
16886
16461
  if (!isPretty2() || !this.suppressStartupLogs) {
16887
- log48.info(TAG44, "Presence tracked on board-presence channel");
16462
+ log47.info(TAG43, "Presence tracked on board-presence channel");
16888
16463
  }
16889
16464
  this.presenceTracked = true;
16890
16465
  this.presenceReconnectAttempts = 0;
@@ -16892,7 +16467,7 @@ class Watcher {
16892
16467
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16893
16468
  this.presenceTracked = false;
16894
16469
  if (!this.stopping) {
16895
- log48.warn(TAG44, `Presence subscription ${status} — scheduling reconnect`);
16470
+ log47.warn(TAG43, `Presence subscription ${status} — scheduling reconnect`);
16896
16471
  this.schedulePresenceReconnect();
16897
16472
  }
16898
16473
  }
@@ -16911,7 +16486,7 @@ class Watcher {
16911
16486
  async reconnectPresence() {
16912
16487
  if (this.stopping || !this.supabase)
16913
16488
  return;
16914
- log48.warn(TAG44, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16489
+ log47.warn(TAG43, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16915
16490
  if (this.presenceChannel) {
16916
16491
  const old = this.presenceChannel;
16917
16492
  this.presenceChannel = null;
@@ -16934,13 +16509,13 @@ class Watcher {
16934
16509
  return;
16935
16510
  const gen = ++this.broadcastGen;
16936
16511
  this.channel = this.supabase.channel(`board-${this.projectId}`).on("broadcast", { event: "card_update" }, (msg) => {
16937
- log48.debug(TAG44, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
16512
+ log47.debug(TAG43, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
16938
16513
  this.onCardBroadcast({
16939
16514
  event: "card_update",
16940
16515
  payload: msg.payload ?? {}
16941
16516
  });
16942
16517
  }).on("broadcast", { event: "card_created" }, (msg) => {
16943
- log48.debug(TAG44, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16518
+ log47.debug(TAG43, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16944
16519
  this.onCardBroadcast({
16945
16520
  event: "card_created",
16946
16521
  payload: msg.payload ?? {}
@@ -16950,11 +16525,11 @@ class Watcher {
16950
16525
  const cardId = payload.card_id;
16951
16526
  const command = payload.command;
16952
16527
  if (cardId && command) {
16953
- log48.info(TAG44, `Broadcast: agent_command ${command} for ${cardId}`);
16528
+ log47.info(TAG43, `Broadcast: agent_command ${command} for ${cardId}`);
16954
16529
  this.onAgentCommand?.({ cardId, command });
16955
16530
  }
16956
16531
  }).on("broadcast", { event: "sweep_command" }, () => {
16957
- log48.debug(TAG44, "Broadcast: sweep_command — draining");
16532
+ log47.debug(TAG43, "Broadcast: sweep_command — draining");
16958
16533
  this.onSweepCommandNudge?.();
16959
16534
  }).subscribe((status) => {
16960
16535
  if (gen !== this.broadcastGen)
@@ -16963,13 +16538,13 @@ class Watcher {
16963
16538
  this.connected = true;
16964
16539
  this.reconnectAttempts = 0;
16965
16540
  if (!isPretty2() || !this.suppressStartupLogs) {
16966
- log48.info(TAG44, "Broadcast subscription active");
16541
+ log47.info(TAG43, "Broadcast subscription active");
16967
16542
  }
16968
16543
  this.maybeResolveReady();
16969
16544
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16970
16545
  this.connected = false;
16971
16546
  if (!this.stopping) {
16972
- log48.warn(TAG44, `Broadcast subscription ${status} — scheduling reconnect`);
16547
+ log47.warn(TAG43, `Broadcast subscription ${status} — scheduling reconnect`);
16973
16548
  this.scheduleReconnect();
16974
16549
  }
16975
16550
  }
@@ -16988,7 +16563,7 @@ class Watcher {
16988
16563
  async reconnectBroadcast() {
16989
16564
  if (this.stopping || !this.supabase)
16990
16565
  return;
16991
- log48.warn(TAG44, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16566
+ log47.warn(TAG43, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16992
16567
  if (this.channel) {
16993
16568
  const old = this.channel;
16994
16569
  this.channel = null;
@@ -17030,10 +16605,10 @@ class Watcher {
17030
16605
  }
17031
16606
  this.connected = false;
17032
16607
  this.presenceTracked = false;
17033
- log48.info(TAG44, "Broadcast subscription stopped");
16608
+ log47.info(TAG43, "Broadcast subscription stopped");
17034
16609
  }
17035
16610
  }
17036
- var TAG44 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
16611
+ var TAG43 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
17037
16612
  var init_watcher = __esm(() => {
17038
16613
  init_sweep_guard();
17039
16614
  });
@@ -17307,7 +16882,7 @@ __export(exports_run_gc, {
17307
16882
  pruneRunLogs: () => pruneRunLogs
17308
16883
  });
17309
16884
  import { unlinkSync as unlinkSync2 } from "node:fs";
17310
- import { log as log49 } from "@gethmy/harness";
16885
+ import { log as log48 } from "@gethmy/harness";
17311
16886
  function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17312
16887
  let deleted = 0;
17313
16888
  let bytesFreed = 0;
@@ -17321,7 +16896,7 @@ function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17321
16896
  deleted++;
17322
16897
  bytesFreed += file.sizeBytes;
17323
16898
  } catch (err) {
17324
- log49.debug(TAG45, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
16899
+ log48.debug(TAG44, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
17325
16900
  }
17326
16901
  }
17327
16902
  return { deleted, bytesFreed };
@@ -17344,7 +16919,7 @@ async function runRetentionGc(store, opts) {
17344
16919
  logs = pruneRunLogs(opts.runsDirectory ?? runsDir(), now - opts.runLogDays * DAY_MS2, openRunIds);
17345
16920
  }
17346
16921
  if (runRecordsPurged > 0 || logs.deleted > 0) {
17347
- log49.info(TAG45, `Retention sweep: trimmed ${runRecordsPurged} run record(s), removed ${logs.deleted} run log(s) (${Math.round(logs.bytesFreed / 1024)} KB)`);
16922
+ log48.info(TAG44, `Retention sweep: trimmed ${runRecordsPurged} run record(s), removed ${logs.deleted} run log(s) (${Math.round(logs.bytesFreed / 1024)} KB)`);
17348
16923
  }
17349
16924
  return {
17350
16925
  runRecordsPurged,
@@ -17352,7 +16927,7 @@ async function runRetentionGc(store, opts) {
17352
16927
  logBytesFreed: logs.bytesFreed
17353
16928
  };
17354
16929
  }
17355
- var TAG45 = "gc", DAY_MS2 = 86400000;
16930
+ var TAG44 = "gc", DAY_MS2 = 86400000;
17356
16931
  var init_run_gc = __esm(() => {
17357
16932
  init_paths();
17358
16933
  init_run_stats();
@@ -17369,7 +16944,7 @@ __export(exports_worktree_gc, {
17369
16944
  import { execFileSync as execFileSync8 } from "node:child_process";
17370
16945
  import { existsSync as existsSync6, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
17371
16946
  import { resolve as resolve3 } from "node:path";
17372
- import { cleanupWorktree as cleanupWorktree5, GIT_NO_HOOKS as GIT_NO_HOOKS9, log as log50 } from "@gethmy/harness";
16947
+ import { cleanupWorktree as cleanupWorktree5, GIT_NO_HOOKS as GIT_NO_HOOKS9, log as log49 } from "@gethmy/harness";
17373
16948
  function isTransientGitNetworkError(message) {
17374
16949
  return TRANSIENT_GIT_NETWORK_ERROR.test(message);
17375
16950
  }
@@ -17482,10 +17057,10 @@ function runWorktreeGc(basePath, store, opts = {}) {
17482
17057
  });
17483
17058
  } catch {}
17484
17059
  if (result.removed.length > 0) {
17485
- log50.info(TAG46, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
17060
+ log49.info(TAG45, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
17486
17061
  }
17487
17062
  if (result.errors.length > 0) {
17488
- log50.warn(TAG46, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
17063
+ log49.warn(TAG45, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
17489
17064
  }
17490
17065
  return result;
17491
17066
  }
@@ -17515,7 +17090,7 @@ function pruneFailedRemoteBranches(opts) {
17515
17090
  } catch (err) {
17516
17091
  const detail = gitErrorDetail2(err);
17517
17092
  if (isTransientGitNetworkError(detail)) {
17518
- log50.debug(TAG46, `Remote branch GC skipped — remote unreachable: ${detail}`);
17093
+ log49.debug(TAG45, `Remote branch GC skipped — remote unreachable: ${detail}`);
17519
17094
  return result;
17520
17095
  }
17521
17096
  result.errors.push({ ref: "fetch", error: detail });
@@ -17555,7 +17130,7 @@ function pruneFailedRemoteBranches(opts) {
17555
17130
  continue;
17556
17131
  }
17557
17132
  if (clock() > sweepDeadline) {
17558
- log50.debug(TAG46, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17133
+ log49.debug(TAG45, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17559
17134
  break;
17560
17135
  }
17561
17136
  try {
@@ -17568,17 +17143,17 @@ function pruneFailedRemoteBranches(opts) {
17568
17143
  } catch (err) {
17569
17144
  const detail = gitErrorDetail2(err);
17570
17145
  if (isTransientGitNetworkError(detail)) {
17571
- log50.debug(TAG46, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17146
+ log49.debug(TAG45, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17572
17147
  break;
17573
17148
  }
17574
17149
  result.errors.push({ ref, error: detail });
17575
17150
  }
17576
17151
  }
17577
17152
  if (result.removed.length > 0) {
17578
- log50.info(TAG46, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17153
+ log49.info(TAG45, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17579
17154
  }
17580
17155
  if (result.errors.length > 0) {
17581
- log50.warn(TAG46, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
17156
+ log49.warn(TAG45, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
17582
17157
  }
17583
17158
  return result;
17584
17159
  }
@@ -17611,18 +17186,18 @@ class WorktreeGc {
17611
17186
  try {
17612
17187
  runWorktreeGc(this.basePath, this.store);
17613
17188
  } catch (err) {
17614
- log50.warn(TAG46, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17189
+ log49.warn(TAG45, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17615
17190
  }
17616
17191
  if (this.remoteOpts) {
17617
17192
  try {
17618
17193
  pruneFailedRemoteBranches(this.remoteOpts);
17619
17194
  } catch (err) {
17620
- log50.warn(TAG46, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17195
+ log49.warn(TAG45, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17621
17196
  }
17622
17197
  }
17623
17198
  if (this.retentionOpts) {
17624
17199
  runRetentionGc(this.store, this.retentionOpts).catch((err) => {
17625
- log50.warn(TAG46, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17200
+ log49.warn(TAG45, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17626
17201
  });
17627
17202
  }
17628
17203
  }
@@ -17636,7 +17211,7 @@ function getRepoRoot2() {
17636
17211
  return null;
17637
17212
  }
17638
17213
  }
17639
- var TAG46 = "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;
17214
+ var TAG45 = "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;
17640
17215
  var init_worktree_gc = __esm(() => {
17641
17216
  init_run_gc();
17642
17217
  GIT_NETWORK_EXEC = {
@@ -17677,7 +17252,7 @@ import { resolve as resolve4 } from "node:path";
17677
17252
  import {
17678
17253
  detectGitProvider as detectGitProvider6,
17679
17254
  GIT_NO_HOOKS as GIT_NO_HOOKS10,
17680
- log as log51,
17255
+ log as log50,
17681
17256
  validateGitProviderCli
17682
17257
  } from "@gethmy/harness";
17683
17258
  async function validatePrerequisites(config, banner) {
@@ -17754,7 +17329,7 @@ async function main() {
17754
17329
  } catch (err) {
17755
17330
  if (err instanceof ConfigValidationError) {
17756
17331
  banner.fail();
17757
- log51.error(TAG47, err.message);
17332
+ log50.error(TAG46, err.message);
17758
17333
  process.exit(1);
17759
17334
  }
17760
17335
  throw err;
@@ -17772,7 +17347,7 @@ async function main() {
17772
17347
  } catch (err) {
17773
17348
  if (err instanceof ConfigValidationError) {
17774
17349
  banner.fail();
17775
- log51.error(TAG47, err.message);
17350
+ log50.error(TAG46, err.message);
17776
17351
  process.exit(1);
17777
17352
  }
17778
17353
  throw err;
@@ -17796,7 +17371,7 @@ async function main() {
17796
17371
  try {
17797
17372
  await client.reportAgentConfig(config.workspaceId, agentId, effectiveModelReport(config.agent));
17798
17373
  } catch (err) {
17799
- log51.warn(TAG47, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17374
+ log50.warn(TAG46, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17800
17375
  }
17801
17376
  migrateConfigDir();
17802
17377
  try {
@@ -17806,7 +17381,7 @@ async function main() {
17806
17381
  worktreePrefix: resolve4(config.repoRoot, config.agent.worktree.basePath)
17807
17382
  });
17808
17383
  } catch (err) {
17809
- log51.error(TAG47, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17384
+ log50.error(TAG46, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17810
17385
  }
17811
17386
  const stateStore = StateStore.open({ projectId: config.projectId });
17812
17387
  const daemonId = randomUUID4();
@@ -17957,7 +17532,7 @@ async function main() {
17957
17532
  if (shuttingDown)
17958
17533
  return;
17959
17534
  shuttingDown = true;
17960
- log51.info(TAG47, `Received ${signal}, shutting down gracefully...`);
17535
+ log50.info(TAG46, `Received ${signal}, shutting down gracefully...`);
17961
17536
  reconciler.stop();
17962
17537
  mergeMonitor?.stop();
17963
17538
  worktreeGc.stop();
@@ -17968,19 +17543,19 @@ async function main() {
17968
17543
  }
17969
17544
  await watcher.stop();
17970
17545
  await pool.shutdown();
17971
- log51.info(TAG47, "Daemon stopped.");
17546
+ log50.info(TAG46, "Daemon stopped.");
17972
17547
  process.exit(exitCode);
17973
17548
  };
17974
17549
  process.on("SIGINT", () => shutdown("SIGINT"));
17975
17550
  process.on("SIGTERM", () => shutdown("SIGTERM"));
17976
17551
  process.on("SIGHUP", () => shutdown("SIGHUP"));
17977
17552
  process.on("uncaughtException", (err) => {
17978
- log51.error(TAG47, `Uncaught exception: ${err.message}`);
17553
+ log50.error(TAG46, `Uncaught exception: ${err.message}`);
17979
17554
  exitCode = 1;
17980
17555
  shutdown("uncaughtException");
17981
17556
  });
17982
17557
  process.on("unhandledRejection", (reason) => {
17983
- log51.error(TAG47, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17558
+ log50.error(TAG46, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17984
17559
  exitCode = 1;
17985
17560
  shutdown("unhandledRejection");
17986
17561
  });
@@ -18040,33 +17615,33 @@ async function handleBroadcast(event, client, pool, config, agentId) {
18040
17615
  if (assignedAgentId === undefined)
18041
17616
  return;
18042
17617
  if (assignedAgentId === agentId) {
18043
- log51.info(TAG47, `Broadcast: card ${cardId} assigned to agent`);
17618
+ log50.info(TAG46, `Broadcast: card ${cardId} assigned to agent`);
18044
17619
  try {
18045
17620
  await pool.resetAttemptsForReassign(cardId);
18046
17621
  await tryEnqueueCard(cardId, client, pool, config, agentId);
18047
17622
  } catch (err) {
18048
- log51.error(TAG47, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
17623
+ log50.error(TAG46, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
18049
17624
  }
18050
17625
  } else if (pool.isCardKnown(cardId)) {
18051
- log51.info(TAG47, `Broadcast: card ${cardId} unassigned from agent`);
17626
+ log50.info(TAG46, `Broadcast: card ${cardId} unassigned from agent`);
18052
17627
  await pool.removeCard(cardId);
18053
17628
  }
18054
17629
  }
18055
17630
  async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18056
17631
  const { card } = await client.getCard(cardId);
18057
17632
  if (card.assigned_agent_id !== agentId) {
18058
- log51.debug(TAG47, `Card ${cardId} no longer assigned to agent — skipping`);
17633
+ log50.debug(TAG46, `Card ${cardId} no longer assigned to agent — skipping`);
18059
17634
  return;
18060
17635
  }
18061
17636
  if (card.done || card.archived_at) {
18062
- log51.debug(TAG47, `Card ${cardId} is finished — skipping`);
17637
+ log50.debug(TAG46, `Card ${cardId} is finished — skipping`);
18063
17638
  return;
18064
17639
  }
18065
17640
  const board = await client.getBoard(config.projectId, { summary: true });
18066
17641
  const columns = board.columns;
18067
17642
  const column = columns.find((c) => c.id === card.column_id);
18068
17643
  if (!column) {
18069
- log51.warn(TAG47, `Column not found for card ${cardId}`);
17644
+ log50.warn(TAG46, `Column not found for card ${cardId}`);
18070
17645
  return;
18071
17646
  }
18072
17647
  const route = classifyPickup(card, column.name, {
@@ -18075,31 +17650,31 @@ async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18075
17650
  playbooks: config.agent.playbooks
18076
17651
  });
18077
17652
  if (!route) {
18078
- log51.info(TAG47, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
17653
+ log50.info(TAG46, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
18079
17654
  return;
18080
17655
  }
18081
17656
  if (route.stage) {
18082
- log51.info(TAG47, `Card #${card.short_id} is a playbook stage card (stage "${card.current_stage}") in "${column.name}" — routing to the stage executor (implement pool) regardless of column`);
17657
+ log50.info(TAG46, `Card #${card.short_id} is a playbook stage card (stage "${card.current_stage}") in "${column.name}" — routing to the stage executor (implement pool) regardless of column`);
18083
17658
  }
18084
17659
  const mode = route.mode;
18085
17660
  const labelMap = buildLabelMap(board.labels ?? []);
18086
17661
  const cardLabels = resolveCardLabels(card, labelMap);
18087
17662
  const subtasks = card.subtasks ?? [];
18088
17663
  if (mode === "review" && config.agent.review.approvedLabel && hasLabel(cardLabels, config.agent.review.approvedLabel)) {
18089
- log51.debug(TAG47, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
17664
+ log50.debug(TAG46, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
18090
17665
  return;
18091
17666
  }
18092
17667
  if (mode === "review" && hasLabel(cardLabels, NEED_REVIEW_LABEL)) {
18093
- log51.debug(TAG47, `Card #${card.short_id} has "${NEED_REVIEW_LABEL}" label (needs human) — skipping review`);
17668
+ log50.debug(TAG46, `Card #${card.short_id} has "${NEED_REVIEW_LABEL}" label (needs human) — skipping review`);
18094
17669
  return;
18095
17670
  }
18096
17671
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
18097
- log51.info(TAG47, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
17672
+ log50.info(TAG46, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
18098
17673
  return;
18099
17674
  }
18100
17675
  await pool.enqueue(card, column, cardLabels, subtasks, mode);
18101
17676
  }
18102
- var TAG47 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
17677
+ var TAG46 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
18103
17678
  var init_src = __esm(() => {
18104
17679
  init_account_guard();
18105
17680
  init_account_probe();