@gethmy/agent 1.41.0 → 1.43.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 +676 -997
  2. package/dist/index.js +578 -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
  }
@@ -9037,6 +8611,14 @@ class StateStore {
9037
8611
  getCard(cardId) {
9038
8612
  return this.state.cards.find((c) => c.cardId === cardId) ?? null;
9039
8613
  }
8614
+ async forgetCard(cardId) {
8615
+ const before = this.state.cards.length;
8616
+ this.state.cards = this.state.cards.filter((c) => c.cardId !== cardId);
8617
+ if (this.state.cards.length === before)
8618
+ return false;
8619
+ await this.persist();
8620
+ return true;
8621
+ }
9040
8622
  async incrementAttempt(cardId) {
9041
8623
  const rec = this.ensureCard(cardId);
9042
8624
  rec.attempts += 1;
@@ -9273,7 +8855,7 @@ class StateStore {
9273
8855
  return this.state.daily.find((d) => d.date === key)?.costCents ?? 0;
9274
8856
  }
9275
8857
  }
9276
- var TAG23 = "state-store", SCHEMA_VERSION = 1;
8858
+ var TAG22 = "state-store", SCHEMA_VERSION = 1;
9277
8859
  var init_state_store = __esm(() => {
9278
8860
  init_dist();
9279
8861
  init_paths();
@@ -9281,7 +8863,7 @@ var init_state_store = __esm(() => {
9281
8863
 
9282
8864
  // src/stream-parser.ts
9283
8865
  import { EventEmitter } from "node:events";
9284
- import { log as log27 } from "@gethmy/harness";
8866
+ import { log as log26 } from "@gethmy/harness";
9285
8867
  function normalizeToolResultContent(raw) {
9286
8868
  if (raw == null)
9287
8869
  return;
@@ -9302,7 +8884,7 @@ function normalizeToolResultContent(raw) {
9302
8884
  return String(raw);
9303
8885
  }
9304
8886
  }
9305
- var TAG24 = "stream-parser", StreamParser;
8887
+ var TAG23 = "stream-parser", StreamParser;
9306
8888
  var init_stream_parser = __esm(() => {
9307
8889
  StreamParser = class StreamParser extends EventEmitter {
9308
8890
  buffer = "";
@@ -9349,14 +8931,14 @@ var init_stream_parser = __esm(() => {
9349
8931
  try {
9350
8932
  msg = JSON.parse(line);
9351
8933
  } catch {
9352
- log27.debug(TAG24, `Non-JSON line: ${line.slice(0, 100)}`);
8934
+ log26.debug(TAG23, `Non-JSON line: ${line.slice(0, 100)}`);
9353
8935
  return;
9354
8936
  }
9355
8937
  try {
9356
8938
  this.handleMessage(msg);
9357
8939
  } catch (err) {
9358
8940
  const errMsg = err instanceof Error ? err.message : String(err);
9359
- log27.warn(TAG24, `Error handling stream event: ${errMsg}`);
8941
+ log26.warn(TAG23, `Error handling stream event: ${errMsg}`);
9360
8942
  this.emit("parse_error", errMsg);
9361
8943
  }
9362
8944
  }
@@ -9432,7 +9014,7 @@ var init_stream_parser = __esm(() => {
9432
9014
  });
9433
9015
 
9434
9016
  // src/transitions.ts
9435
- import { log as log28 } from "@gethmy/harness";
9017
+ import { log as log27 } from "@gethmy/harness";
9436
9018
  async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9437
9019
  let lastErr;
9438
9020
  for (let i = 0;i < attempts; i++) {
@@ -9443,7 +9025,7 @@ async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9443
9025
  const msg2 = err instanceof Error ? err.message : String(err);
9444
9026
  if (i < attempts - 1) {
9445
9027
  const wait = backoffMs * 2 ** i;
9446
- log28.warn(TAG25, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9028
+ log27.warn(TAG24, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9447
9029
  await new Promise((r) => setTimeout(r, wait));
9448
9030
  }
9449
9031
  }
@@ -9467,10 +9049,10 @@ async function runTransition(client, card, plan, opts = {}) {
9467
9049
  if (opts.strictColumn) {
9468
9050
  throw new TransitionError("move", 1, msg);
9469
9051
  }
9470
- log28.warn(TAG25, `#${shortId}: ${msg} — skipping move`);
9052
+ log27.warn(TAG24, `#${shortId}: ${msg} — skipping move`);
9471
9053
  } else if (card.column_id !== target.id) {
9472
9054
  await withRetry("move", shortId, () => client.moveCard(card.id, target.id), attempts, backoffMs);
9473
- log28.info(TAG25, `#${shortId} → "${target.name}"`);
9055
+ log27.info(TAG24, `#${shortId} → "${target.name}"`);
9474
9056
  card.column_id = target.id;
9475
9057
  moveLanded = true;
9476
9058
  } else {
@@ -9489,7 +9071,7 @@ async function runTransition(client, card, plan, opts = {}) {
9489
9071
  continue;
9490
9072
  await withRetry("addLabel", shortId, () => client.addLabelToCard(card.id, labelId), attempts, backoffMs);
9491
9073
  existing.add(labelId);
9492
- log28.info(TAG25, `#${shortId} +label "${name}"`);
9074
+ log27.info(TAG24, `#${shortId} +label "${name}"`);
9493
9075
  }
9494
9076
  card.labelIds = Array.from(existing);
9495
9077
  }
@@ -9501,23 +9083,23 @@ async function runTransition(client, card, plan, opts = {}) {
9501
9083
  continue;
9502
9084
  await withRetry("removeLabel", shortId, () => client.removeLabelFromCard(card.id, match.id), attempts, backoffMs);
9503
9085
  existing.delete(match.id);
9504
- log28.info(TAG25, `#${shortId} -label "${name}"`);
9086
+ log27.info(TAG24, `#${shortId} -label "${name}"`);
9505
9087
  }
9506
9088
  card.labelIds = Array.from(existing);
9507
9089
  }
9508
9090
  if (plan.updateCard) {
9509
9091
  await withRetry("updateCard", shortId, () => client.updateCard(card.id, plan.updateCard), attempts, backoffMs);
9510
- log28.info(TAG25, `#${shortId} updated`);
9092
+ log27.info(TAG24, `#${shortId} updated`);
9511
9093
  }
9512
9094
  if (plan.endSession) {
9513
9095
  const endResult = await withRetry("endSession", shortId, () => client.endAgentSession(card.id, plan.endSession), attempts, backoffMs);
9514
9096
  result.endSession = endResult;
9515
- log28.info(TAG25, `#${shortId} session ended (${plan.endSession.status})`);
9097
+ log27.info(TAG24, `#${shortId} session ended (${plan.endSession.status})`);
9516
9098
  }
9517
9099
  if (plan.assignAgent !== undefined) {
9518
9100
  const assignedAgentId = plan.assignAgent;
9519
9101
  await withRetry("assignAgent", shortId, () => client.updateCard(card.id, { assignedAgentId }), attempts, backoffMs);
9520
- log28.info(TAG25, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9102
+ log27.info(TAG24, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9521
9103
  }
9522
9104
  if (opts.store && opts.runId) {
9523
9105
  try {
@@ -9531,11 +9113,11 @@ async function ensureLabel(client, projectId, name, color, attempts, backoffMs)
9531
9113
  const result = await withRetry("addLabel", 0, () => client.createLabel(projectId, { name, color: color ?? "#8b5cf6" }), attempts, backoffMs);
9532
9114
  return result?.label?.id ?? null;
9533
9115
  } catch (err) {
9534
- log28.warn(TAG25, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9116
+ log27.warn(TAG24, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9535
9117
  return null;
9536
9118
  }
9537
9119
  }
9538
- var TAG25 = "transition", TransitionError;
9120
+ var TAG24 = "transition", TransitionError;
9539
9121
  var init_transitions = __esm(() => {
9540
9122
  TransitionError = class TransitionError extends Error {
9541
9123
  step;
@@ -9565,7 +9147,7 @@ import {
9565
9147
  formatDiffSummary,
9566
9148
  GIT_NO_HOOKS as GIT_NO_HOOKS7,
9567
9149
  implementRunContainmentCliArgs,
9568
- log as log29,
9150
+ log as log28,
9569
9151
  probeDevServer,
9570
9152
  removeSandboxContainer,
9571
9153
  resolveStageGate,
@@ -9661,11 +9243,11 @@ class ReviewWorker {
9661
9243
  cliSessionId: this.cliSessionId
9662
9244
  });
9663
9245
  } catch (err) {
9664
- log29.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9246
+ log28.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9665
9247
  }
9666
9248
  }
9667
9249
  get tag() {
9668
- return `${TAG26}:${this.id}`;
9250
+ return `${TAG25}:${this.id}`;
9669
9251
  }
9670
9252
  get isIdle() {
9671
9253
  return this.state === "idle";
@@ -9703,7 +9285,7 @@ class ReviewWorker {
9703
9285
  try {
9704
9286
  const after = await this.stateStore.addTurns(cardId, numTurns);
9705
9287
  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.`);
9288
+ 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
9289
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
9708
9290
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), {
9709
9291
  commentType: "blocker",
@@ -9745,12 +9327,12 @@ class ReviewWorker {
9745
9327
  resumeMessage: null
9746
9328
  });
9747
9329
  } catch (err) {
9748
- log29.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9330
+ log28.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9749
9331
  }
9750
9332
  }
9751
9333
  try {
9752
9334
  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}"`);
9335
+ 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
9336
  this.startHeartbeat();
9755
9337
  if (!resuming) {
9756
9338
  await this.stateStore.insertRun({
@@ -9778,7 +9360,7 @@ class ReviewWorker {
9778
9360
  const resolution = await resolveReviewBranch(card.description, repoRoot);
9779
9361
  if (resolution.kind !== "branch") {
9780
9362
  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)`);
9363
+ log28.info(this.tag, `#${card.short_id} not auto-reviewable (${why}) — marking for human review (staying in Review)`);
9782
9364
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9783
9365
  return;
9784
9366
  }
@@ -9789,13 +9371,13 @@ class ReviewWorker {
9789
9371
  reviewedSha: extractReviewedSha2(card.description ?? null)
9790
9372
  });
9791
9373
  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)`);
9374
+ log28.warn(this.tag, `#${card.short_id} refusing the PR-derived re-review (${continuity.reason}) — marking for human review (staying in Review)`);
9793
9375
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9794
9376
  return;
9795
9377
  }
9796
9378
  }
9797
9379
  this.branchName = resolution.branch;
9798
- log29.info(this.tag, `Review branch: ${this.branchName}`);
9380
+ log28.info(this.tag, `Review branch: ${this.branchName}`);
9799
9381
  let reviewSession;
9800
9382
  try {
9801
9383
  const startSession = () => this.client.startAgentSession(card.id, {
@@ -9811,14 +9393,14 @@ class ReviewWorker {
9811
9393
  awaitingDecisionUntil: null
9812
9394
  });
9813
9395
  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)
9396
+ info: (message) => log28.info(this.tag, message),
9397
+ warn: (message) => log28.warn(this.tag, message)
9816
9398
  });
9817
9399
  reviewSession = started.session;
9818
9400
  } catch (err) {
9819
9401
  if (isSessionConflict(err)) {
9820
9402
  this.sessionConflict = true;
9821
- log29.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9403
+ log28.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9822
9404
  return;
9823
9405
  }
9824
9406
  throw err;
@@ -9839,7 +9421,7 @@ class ReviewWorker {
9839
9421
  const cwd = this.worktreePath;
9840
9422
  const devServer = await this.startDevServer(card, cwd, port);
9841
9423
  if (devServer.skipReason) {
9842
- log29.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9424
+ log28.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9843
9425
  }
9844
9426
  await this.client.updateAgentProgress(card.id, {
9845
9427
  agentIdentifier: this.sessionIdentifier,
@@ -9877,10 +9459,10 @@ class ReviewWorker {
9877
9459
  pinnedContract = extractPinnedContract(comments, this.identity);
9878
9460
  }
9879
9461
  } catch (err) {
9880
- log29.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9462
+ log28.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9881
9463
  }
9882
9464
  if (pinnedContract) {
9883
- log29.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9465
+ log28.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9884
9466
  }
9885
9467
  }
9886
9468
  const systemPrompt = buildReviewSystemPrompt();
@@ -9895,7 +9477,7 @@ class ReviewWorker {
9895
9477
  } else {
9896
9478
  const planCriteria2 = await fetchAcceptanceCriteria(this.client, this.tag, card);
9897
9479
  if (planCriteria2.length > 0) {
9898
- log29.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9480
+ log28.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9899
9481
  }
9900
9482
  userPrompt = buildReviewUserPrompt(enriched, this.branchName, cwd, previewUrl, diffSummary, this.config.worktree.baseBranch, undefined, pinnedContract, planCriteria2, devServer.skipReason);
9901
9483
  if (resuming && this.resumeMessage) {
@@ -9912,7 +9494,7 @@ ${userPrompt}`;
9912
9494
  contextIncluded: { source: "review-knowledge", mode: "review" }
9913
9495
  });
9914
9496
  } catch (err) {
9915
- log29.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9497
+ log28.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9916
9498
  }
9917
9499
  await this.client.updateAgentProgress(card.id, {
9918
9500
  agentIdentifier: this.sessionIdentifier,
@@ -9922,7 +9504,7 @@ ${userPrompt}`;
9922
9504
  progressPercent: 20
9923
9505
  });
9924
9506
  this.timeoutTimer = setTimeout(() => {
9925
- log29.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9507
+ log28.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9926
9508
  this.timedOut = true;
9927
9509
  this.cancel("timeout");
9928
9510
  }, this.config.review.maxTimeout);
@@ -9944,10 +9526,10 @@ ${userPrompt}`;
9944
9526
  }
9945
9527
  this.state = "completing";
9946
9528
  await this.recordPhase("completing");
9947
- log29.info(this.tag, `Claude review finished for #${card.short_id}`);
9529
+ log28.info(this.tag, `Claude review finished for #${card.short_id}`);
9948
9530
  this.killDevServer();
9949
9531
  const result = parseReviewOutput(stdout);
9950
- log29.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9532
+ log28.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9951
9533
  await this.client.updateAgentProgress(card.id, {
9952
9534
  agentIdentifier: this.sessionIdentifier,
9953
9535
  agentName: `${AGENT_NAME} (Review)`,
@@ -9955,7 +9537,7 @@ ${userPrompt}`;
9955
9537
  currentTask: `Processing ${result.verdict} verdict`,
9956
9538
  progressPercent: 80
9957
9539
  });
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);
9540
+ 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
9541
  await this.collectReviewGate(card, result);
9960
9542
  } catch (err) {
9961
9543
  if (err instanceof BudgetPauseError) {
@@ -9969,7 +9551,7 @@ ${userPrompt}`;
9969
9551
  this.state = "error";
9970
9552
  const msg = err instanceof Error ? err.message : String(err);
9971
9553
  this.lastErrorMessage = msg;
9972
- log29.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9554
+ log28.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9973
9555
  this.lastRunLogPath = appendRunLog(this.tag, this.runId, card.short_id, `[${new Date().toISOString()}] review failed before completion: ${msg}`) ?? this.lastRunLogPath;
9974
9556
  const reviewHandback = await guardedHandback(this.client, card.id, {
9975
9557
  agentId: this.identity.agentId,
@@ -9985,7 +9567,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9985
9567
  agentSessionId: this.sessionId ?? undefined
9986
9568
  });
9987
9569
  } catch (cErr) {
9988
- log29.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9570
+ log28.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9989
9571
  }
9990
9572
  }
9991
9573
  try {
@@ -9997,21 +9579,21 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9997
9579
  }
9998
9580
  });
9999
9581
  } catch (tErr) {
10000
- log29.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
9582
+ log28.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
10001
9583
  }
10002
9584
  if (reviewHandback.verdict.proceed) {
10003
9585
  try {
10004
9586
  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`);
9587
+ log28.info(this.tag, `Moved #${card.short_id} to "${this.config.review.failColumn}" after error`);
10006
9588
  } catch {
10007
- log29.warn(this.tag, "Failed to move card to fail column after error");
9589
+ log28.warn(this.tag, "Failed to move card to fail column after error");
10008
9590
  }
10009
9591
  } else if (reviewHandback.verdict.reason === "unreadable" || reviewHandback.verdict.reason === "released" || reviewHandback.verdict.reason === "done") {
10010
9592
  try {
10011
9593
  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`);
9594
+ log28.warn(this.tag, `#${card.short_id} could not be re-read — labelled "${NEED_REVIEW_LABEL}" so reconcile stops re-enqueueing the review`);
10013
9595
  } catch {
10014
- log29.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
9596
+ log28.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
10015
9597
  }
10016
9598
  }
10017
9599
  if (this.runId) {
@@ -10055,7 +9637,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10055
9637
  const holderMessage = err instanceof Error ? err.message : String(err);
10056
9638
  const waitHours = this.config.budget.pause.waitHours;
10057
9639
  const until = computeDecisionDeadline(waitHours);
10058
- log29.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
9640
+ log28.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
10059
9641
  try {
10060
9642
  await this.client.addComment(card.id, formatResumeConflictComment({
10061
9643
  holderMessage,
@@ -10067,7 +9649,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10067
9649
  agentSessionId: this.sessionId ?? undefined
10068
9650
  });
10069
9651
  } catch (commentErr) {
10070
- log29.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
9652
+ log28.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
10071
9653
  }
10072
9654
  if (this.runId) {
10073
9655
  const run = this.stateStore.getRun(this.runId);
@@ -10078,7 +9660,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10078
9660
  awaitingDecisionUntil: until
10079
9661
  });
10080
9662
  } 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}`);
9663
+ 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
9664
  }
10083
9665
  }
10084
9666
  }
@@ -10091,7 +9673,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10091
9673
  this.progressTracker = null;
10092
9674
  const waitHours = this.config.budget.pause.waitHours;
10093
9675
  const until = computeDecisionDeadline(waitHours);
10094
- log29.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
9676
+ log28.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
10095
9677
  const body = formatBudgetComment({
10096
9678
  trigger,
10097
9679
  numTurns: stats?.cost?.numTurns ?? 0,
@@ -10113,7 +9695,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10113
9695
  });
10114
9696
  commentId = res?.comment?.id ?? null;
10115
9697
  } catch (err) {
10116
- log29.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
9698
+ log28.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
10117
9699
  }
10118
9700
  try {
10119
9701
  await this.client.updateAgentProgress(card.id, {
@@ -10124,7 +9706,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10124
9706
  awaitingDecisionUntil: new Date(until).toISOString()
10125
9707
  });
10126
9708
  } catch (err) {
10127
- log29.warn(this.tag, `Failed to mark the session blocked: ${err}`);
9709
+ log28.warn(this.tag, `Failed to mark the session blocked: ${err}`);
10128
9710
  }
10129
9711
  if (this.runId) {
10130
9712
  try {
@@ -10135,14 +9717,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10135
9717
  ...this.endLedger()
10136
9718
  });
10137
9719
  } 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}`);
9720
+ 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
9721
  }
10140
9722
  }
10141
9723
  }
10142
9724
  async pause() {
10143
9725
  if (!this.isActive || !this.process || this.process.killed)
10144
9726
  return;
10145
- log29.info(this.tag, `Pausing review on ${this.cardId}`);
9727
+ log28.info(this.tag, `Pausing review on ${this.cardId}`);
10146
9728
  signalGroup(this.process, "SIGSTOP");
10147
9729
  if (this.timeoutTimer) {
10148
9730
  clearTimeout(this.timeoutTimer);
@@ -10156,17 +9738,17 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10156
9738
  status: "paused"
10157
9739
  });
10158
9740
  } catch {
10159
- log29.warn(this.tag, "Failed to update agent session to paused");
9741
+ log28.warn(this.tag, "Failed to update agent session to paused");
10160
9742
  }
10161
9743
  }
10162
9744
  }
10163
9745
  async resume() {
10164
9746
  if (!this.isActive || !this.process || this.process.killed)
10165
9747
  return;
10166
- log29.info(this.tag, `Resuming review on ${this.cardId}`);
9748
+ log28.info(this.tag, `Resuming review on ${this.cardId}`);
10167
9749
  signalGroup(this.process, "SIGCONT");
10168
9750
  this.timeoutTimer = setTimeout(() => {
10169
- log29.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9751
+ log28.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
10170
9752
  this.timedOut = true;
10171
9753
  this.cancel("timeout");
10172
9754
  }, this.config.review.maxTimeout);
@@ -10178,7 +9760,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10178
9760
  status: "working"
10179
9761
  });
10180
9762
  } catch {
10181
- log29.warn(this.tag, "Failed to update agent session to working");
9763
+ log28.warn(this.tag, "Failed to update agent session to working");
10182
9764
  }
10183
9765
  }
10184
9766
  }
@@ -10187,7 +9769,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10187
9769
  return;
10188
9770
  this.aborted = true;
10189
9771
  this.state = "cancelling";
10190
- log29.info(this.tag, `Cancelling review on ${this.cardId}`);
9772
+ log28.info(this.tag, `Cancelling review on ${this.cardId}`);
10191
9773
  const snapshotStats = this.lastSessionStats ?? this.progressTracker?.stats;
10192
9774
  if (this.progressTracker) {
10193
9775
  this.progressTracker?.stop();
@@ -10240,11 +9822,11 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10240
9822
  "--",
10241
9823
  prompt
10242
9824
  ];
10243
- log29.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
9825
+ log28.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
10244
9826
  const runLog = openRunLog(this.tag, this.runId, shortId);
10245
9827
  this.lastRunLogPath = runLog?.path ?? null;
10246
9828
  if (runLog) {
10247
- log29.info(this.tag, `Run log: ${runLog.path}`);
9829
+ log28.info(this.tag, `Run log: ${runLog.path}`);
10248
9830
  runLog.stream.write(`# run=${this.runId} card=#${shortId} pipeline=review started=${new Date().toISOString()}
10249
9831
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
10250
9832
 
@@ -10263,7 +9845,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10263
9845
  this.captureCliSessionId(parser.sessionId);
10264
9846
  });
10265
9847
  parser.on("parse_error", (msg) => {
10266
- log29.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
9848
+ log28.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
10267
9849
  runLog?.stream.write(`
10268
9850
  [parse_error] ${msg}
10269
9851
  `);
@@ -10342,16 +9924,16 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10342
9924
  const evidence = await collectGateEvidence(registry, context);
10343
9925
  const evaluation = gateEvaluate(resolved.gate, evidence);
10344
9926
  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}`);
9927
+ log28.info(this.tag, `Recorded review_passed gate evidence for #${card.short_id} stage "${resolved.stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
10346
9928
  } catch (err) {
10347
- log29.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9929
+ log28.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10348
9930
  }
10349
9931
  }
10350
9932
  async startDevServer(card, cwd, port) {
10351
9933
  const declined = devServerSkipReason(cwd, this.config.commands);
10352
9934
  if (declined)
10353
9935
  return { previewUrl: null, skipReason: declined };
10354
- log29.info(this.tag, `Starting dev server on port ${port}...`);
9936
+ log28.info(this.tag, `Starting dev server on port ${port}...`);
10355
9937
  const launch = devServerLaunch({
10356
9938
  worktreePath: cwd,
10357
9939
  port,
@@ -10392,14 +9974,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10392
9974
  skipReason: launch.origin ? `${launch.origin}, and ${failure}` : failure
10393
9975
  };
10394
9976
  }
10395
- log29.info(this.tag, `Dev server ready on port ${port}`);
9977
+ log28.info(this.tag, `Dev server ready on port ${port}`);
10396
9978
  return { previewUrl: `http://localhost:${port}`, skipReason: null };
10397
9979
  }
10398
9980
  killDevServer() {
10399
9981
  if (this.devServerProcess && !this.devServerProcess.killed) {
10400
9982
  signalGroup(this.devServerProcess, "SIGTERM");
10401
9983
  this.devServerProcess = null;
10402
- log29.debug(this.tag, "Killed dev server group");
9984
+ log28.debug(this.tag, "Killed dev server group");
10403
9985
  }
10404
9986
  if (this.devServerContainer) {
10405
9987
  const name = this.devServerContainer;
@@ -10422,7 +10004,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10422
10004
  try {
10423
10005
  cleanupWorktree4(this.worktreePath);
10424
10006
  } catch {
10425
- log29.warn(this.tag, "Failed to cleanup review worktree");
10007
+ log28.warn(this.tag, "Failed to cleanup review worktree");
10426
10008
  }
10427
10009
  }
10428
10010
  this.process = null;
@@ -10434,7 +10016,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10434
10016
  this.lastSessionStats = null;
10435
10017
  }
10436
10018
  }
10437
- var TAG26 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10019
+ var TAG25 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10438
10020
  var init_review_worker = __esm(() => {
10439
10021
  init_dist();
10440
10022
  init_board_helpers();
@@ -10458,7 +10040,7 @@ var init_review_worker = __esm(() => {
10458
10040
 
10459
10041
  // src/sleep-guard.ts
10460
10042
  import { spawn } from "node:child_process";
10461
- import { log as log30 } from "@gethmy/harness";
10043
+ import { log as log29 } from "@gethmy/harness";
10462
10044
 
10463
10045
  class SleepGuard {
10464
10046
  platform;
@@ -10486,7 +10068,7 @@ class SleepGuard {
10486
10068
  if (!this.child.killed)
10487
10069
  this.child.kill("SIGTERM");
10488
10070
  this.child = null;
10489
- log30.info(TAG27, "sleep assertion released");
10071
+ log29.info(TAG26, "sleep assertion released");
10490
10072
  }
10491
10073
  }
10492
10074
  start() {
@@ -10501,7 +10083,7 @@ class SleepGuard {
10501
10083
  spawned = true;
10502
10084
  });
10503
10085
  child.on("error", (err) => {
10504
- log30.warn(TAG27, `caffeinate unavailable: ${err.message}`);
10086
+ log29.warn(TAG26, `caffeinate unavailable: ${err.message}`);
10505
10087
  if (this.child === child)
10506
10088
  this.child = null;
10507
10089
  });
@@ -10514,23 +10096,23 @@ class SleepGuard {
10514
10096
  });
10515
10097
  child.unref();
10516
10098
  this.child = child;
10517
- log30.info(TAG27, "sleep assertion acquired (caffeinate -i)");
10099
+ log29.info(TAG26, "sleep assertion acquired (caffeinate -i)");
10518
10100
  } catch (err) {
10519
- log30.warn(TAG27, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10101
+ log29.warn(TAG26, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10520
10102
  }
10521
10103
  }
10522
10104
  }
10523
- var TAG27 = "sleep-guard";
10105
+ var TAG26 = "sleep-guard";
10524
10106
  var init_sleep_guard = () => {};
10525
10107
 
10526
10108
  // src/unblock.ts
10527
- import { log as log31 } from "@gethmy/harness";
10109
+ import { log as log30 } from "@gethmy/harness";
10528
10110
  async function fetchBlocksLinks(client, cardId) {
10529
10111
  try {
10530
10112
  const { links } = await client.getCardLinks(cardId);
10531
10113
  return links.filter((l) => l.link_type === "blocks");
10532
10114
  } catch (err) {
10533
- log31.warn(TAG28, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10115
+ log30.warn(TAG27, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10534
10116
  return null;
10535
10117
  }
10536
10118
  }
@@ -10564,31 +10146,31 @@ async function promoteUnblockedSuccessors(completedCard, deps) {
10564
10146
  const successors = links.filter((l) => l.direction === "outgoing" && !l.target_card.done);
10565
10147
  if (successors.length === 0)
10566
10148
  return;
10567
- log31.info(TAG28, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10149
+ log30.info(TAG27, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10568
10150
  for (const link of successors) {
10569
10151
  const successorId = link.target_card.id;
10570
10152
  try {
10571
10153
  const { card } = await deps.client.getCard(successorId);
10572
10154
  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`);
10155
+ log30.info(TAG27, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
10574
10156
  await deps.client.updateCard(successorId, {
10575
10157
  assignedAgentId: deps.agentId
10576
10158
  });
10577
10159
  } else {
10578
- log31.debug(TAG28, `successor #${card.short_id} assigned to different entity — skipping`);
10160
+ log30.debug(TAG27, `successor #${card.short_id} assigned to different entity — skipping`);
10579
10161
  continue;
10580
10162
  }
10581
10163
  await deps.enqueue(successorId);
10582
10164
  } catch (err) {
10583
- log31.warn(TAG28, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10165
+ log30.warn(TAG27, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10584
10166
  }
10585
10167
  }
10586
10168
  }
10587
- var TAG28 = "unblock";
10169
+ var TAG27 = "unblock";
10588
10170
  var init_unblock = () => {};
10589
10171
 
10590
10172
  // src/cli-agent-runner.ts
10591
- import { log as log32 } from "@gethmy/harness";
10173
+ import { log as log31 } from "@gethmy/harness";
10592
10174
  function truncateOutput(value) {
10593
10175
  return value === undefined ? undefined : value.slice(0, MAX_OUTPUT_CHARS);
10594
10176
  }
@@ -10753,7 +10335,7 @@ class CliAgentRunner {
10753
10335
  return;
10754
10336
  const draft = sanitizeRunEventDraft(body);
10755
10337
  if (runEventPayloadExceedsLimit(draft.payload)) {
10756
- log32.warn(TAG29, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10338
+ log31.warn(TAG28, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10757
10339
  return;
10758
10340
  }
10759
10341
  this.buffer.push({ ...draft, createdAt: new Date().toISOString() });
@@ -10785,15 +10367,15 @@ class CliAgentRunner {
10785
10367
  this.requeue(batch);
10786
10368
  if (batch.length > 1) {
10787
10369
  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}`);
10370
+ log31.warn(TAG28, `Flush of ${batch.length} run event(s) failed ${MAX_BATCH_ATTEMPTS}×; bisecting to ${this.nextBatchSize}: ${err}`);
10789
10371
  return;
10790
10372
  }
10791
10373
  const dropped = this.buffer.shift();
10792
10374
  this.nextBatchSize = MAX_BUFFER;
10793
- log32.warn(TAG29, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10375
+ log31.warn(TAG28, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10794
10376
  return;
10795
10377
  }
10796
- log32.warn(TAG29, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10378
+ log31.warn(TAG28, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10797
10379
  this.requeue(batch);
10798
10380
  } finally {
10799
10381
  this.flushing = false;
@@ -10836,26 +10418,26 @@ function mapCost(cost) {
10836
10418
  durationMs: cost.durationMs
10837
10419
  };
10838
10420
  }
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;
10421
+ 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
10422
  var init_cli_agent_runner = __esm(() => {
10841
10423
  init_dist();
10842
10424
  });
10843
10425
 
10844
10426
  // src/fanout.ts
10845
- import { log as log33 } from "@gethmy/harness";
10427
+ import { log as log32 } from "@gethmy/harness";
10846
10428
  async function fetchLinks(client, cardId) {
10847
10429
  try {
10848
10430
  const { links } = await client.getCardLinks(cardId);
10849
10431
  return links;
10850
10432
  } catch (err) {
10851
- log33.warn(TAG30, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10433
+ log32.warn(TAG29, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10852
10434
  return null;
10853
10435
  }
10854
10436
  }
10855
10437
  async function isFanoutChildOf(card, stage, client) {
10856
10438
  const links = await fetchLinks(client, card.id);
10857
10439
  if (links === null) {
10858
- log33.warn(TAG30, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10440
+ log32.warn(TAG29, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10859
10441
  return true;
10860
10442
  }
10861
10443
  const parents = links.filter((l) => l.direction === "outgoing" && l.link_type === "is_part_of");
@@ -10942,7 +10524,7 @@ async function readStageHandoff(card, fromStage, deps) {
10942
10524
  }
10943
10525
  return null;
10944
10526
  } catch (err) {
10945
- log33.warn(TAG30, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10527
+ log32.warn(TAG29, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10946
10528
  return null;
10947
10529
  }
10948
10530
  }
@@ -11043,7 +10625,7 @@ async function dispatchWave(parent, stage, plan, items, deps) {
11043
10625
  });
11044
10626
  spawned = res.children ?? [];
11045
10627
  } catch (err) {
11046
- log33.warn(TAG30, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
10628
+ log32.warn(TAG29, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
11047
10629
  return 0;
11048
10630
  }
11049
10631
  let created = 0;
@@ -11098,10 +10680,10 @@ async function seedChildHandoff(parent, stage, item, total, childId, deps) {
11098
10680
  try {
11099
10681
  await deps.client.addComment(childId, body, { commentType: "decision" });
11100
10682
  } catch (err) {
11101
- log33.warn(TAG30, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
10683
+ log32.warn(TAG29, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
11102
10684
  }
11103
10685
  }
11104
- var TAG30 = "fanout";
10686
+ var TAG29 = "fanout";
11105
10687
  var init_fanout = __esm(() => {
11106
10688
  init_dist();
11107
10689
  });
@@ -11336,7 +10918,7 @@ function runSizedPayload(input) {
11336
10918
  }
11337
10919
 
11338
10920
  // src/stage-advance.ts
11339
- import { gateConfigErrorReason, log as log34 } from "@gethmy/harness";
10921
+ import { gateConfigErrorReason, log as log33 } from "@gethmy/harness";
11340
10922
  function endDispositionFor(outcome) {
11341
10923
  return "endDisposition" in outcome && outcome.endDisposition ? outcome.endDisposition : { status: "completed" };
11342
10924
  }
@@ -11367,7 +10949,7 @@ async function resolveStageColumnName(client, card, stage) {
11367
10949
  const match = board.columns.find((c) => c.id === target || c.name.toLowerCase() === target.toLowerCase());
11368
10950
  return match ? match.name : null;
11369
10951
  } catch (err) {
11370
- log34.warn(TAG31, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10952
+ log33.warn(TAG30, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11371
10953
  return null;
11372
10954
  }
11373
10955
  }
@@ -11406,7 +10988,7 @@ async function holdGateMisconfigured(card, stage, detail, deps) {
11406
10988
  });
11407
10989
  } catch {}
11408
10990
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, { agentSessionId: deps.agentSessionId });
11409
- log34.info(TAG31, `#${card.short_id} GateMisconfigured: ${reason}`);
10991
+ log33.info(TAG30, `#${card.short_id} GateMisconfigured: ${reason}`);
11410
10992
  return { kind: "held_misconfigured", reason, endDisposition };
11411
10993
  }
11412
10994
  function firstErrorMessage(evaluation) {
@@ -11437,7 +11019,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11437
11019
  evidence,
11438
11020
  summary
11439
11021
  });
11440
- log34.info(TAG31, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11022
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11441
11023
  if (decision === "exit") {
11442
11024
  await deps.stateStore.resetLoopIterations(card.id).catch(() => {});
11443
11025
  deps.sink?.recordLoopCompleted?.({
@@ -11482,7 +11064,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11482
11064
  blockers: [reason],
11483
11065
  agentSessionId: deps.agentSessionId
11484
11066
  });
11485
- log34.info(TAG31, `#${card.short_id} LoopExhausted: ${reason}`);
11067
+ log33.info(TAG30, `#${card.short_id} LoopExhausted: ${reason}`);
11486
11068
  return { kind: "held_gate_unmet", reason, endDisposition };
11487
11069
  }
11488
11070
  const guard = await guardStageReclaim(card, `converge-loop iteration of "${stage.name}"`, deps);
@@ -11507,7 +11089,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11507
11089
  addLabels: [{ name: AGENT_LABEL }],
11508
11090
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11509
11091
  }, { 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}`);
11092
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}" — requeued to "${toColumn}" for iteration ${iteration + 1}/${maxIterations}`);
11511
11093
  return { kind: "requeued_gate_unmet", toColumn };
11512
11094
  }
11513
11095
  async function writeIterationHandoff(card, stage, iteration, maxIterations, evaluation, deps) {
@@ -11529,7 +11111,7 @@ ${findings.map((f) => `- [${f.level}] ${f.message}`).join(`
11529
11111
  agentSessionId: deps.agentSessionId ?? undefined
11530
11112
  });
11531
11113
  } catch (err) {
11532
- log34.warn(TAG31, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11114
+ log33.warn(TAG30, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11533
11115
  }
11534
11116
  }
11535
11117
  async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps) {
@@ -11557,7 +11139,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11557
11139
  reason: "Playbook complete — final stage gate passed."
11558
11140
  });
11559
11141
  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)`);
11142
+ log33.info(TAG30, `#${card.short_id} terminal stage "${stage.name}" passed — playbook complete (done left to the column)`);
11561
11143
  return { kind: "completed_terminal" };
11562
11144
  }
11563
11145
  if (next.kind === "out_of_range") {
@@ -11589,7 +11171,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11589
11171
  ...isAgentRunnableOwner(next.stage.owner) ? { assignAgent: deps.agentId } : {}
11590
11172
  }, { store: deps.stateStore, runId: deps.runId });
11591
11173
  deps.stateStore.recordOutcome(card.id, "success").catch(() => {});
11592
- log34.info(TAG31, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11174
+ log33.info(TAG30, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11593
11175
  if (next.stage.owner === "human") {
11594
11176
  const reason = `Stage "${next.stage.name}" is yours: ${handoffText(next.stage)}`;
11595
11177
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, {
@@ -11626,7 +11208,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11626
11208
  blockers: [reason],
11627
11209
  agentSessionId: deps.agentSessionId
11628
11210
  });
11629
- log34.info(TAG31, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11211
+ log33.info(TAG30, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11630
11212
  return { kind: "held_gate_unmet", reason, endDisposition };
11631
11213
  }
11632
11214
  const guard = await guardStageReclaim(card, `gate-unmet re-run of "${stage.name}"`, deps);
@@ -11649,7 +11231,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11649
11231
  addLabels: [{ name: AGENT_LABEL }],
11650
11232
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11651
11233
  }, { 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})`);
11234
+ log33.info(TAG30, `#${card.short_id} gate unmet for "${stage.name}" — requeued to "${toColumn}" for re-run (attempt ${attempts}/${deps.maxAttempts})`);
11653
11235
  return { kind: "requeued_gate_unmet", toColumn };
11654
11236
  }
11655
11237
  async function guardStageReclaim(card, what, deps) {
@@ -11675,10 +11257,10 @@ async function guardStageReclaim(card, what, deps) {
11675
11257
  }, { store: deps.stateStore, runId: deps.runId });
11676
11258
  released = stillOurs;
11677
11259
  } 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" : ""}`);
11260
+ 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
11261
  }
11680
11262
  }
11681
- log34.info(TAG31, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11263
+ log33.info(TAG30, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11682
11264
  try {
11683
11265
  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
11266
  commentType: "decision",
@@ -11700,7 +11282,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11700
11282
  try {
11701
11283
  await runTransition(client, card, { removeLabels: [AGENT_LABEL] }, { store: stateStore, runId });
11702
11284
  } catch (err) {
11703
- log34.warn(TAG31, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11285
+ log33.warn(TAG30, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11704
11286
  }
11705
11287
  return {
11706
11288
  status: opts.endStatus ?? "paused",
@@ -11709,7 +11291,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11709
11291
  failureSummary: reason.slice(0, 300)
11710
11292
  };
11711
11293
  }
11712
- var TAG31 = "stage-advance", AGENT_LABEL = "agent";
11294
+ var TAG30 = "stage-advance", AGENT_LABEL = "agent";
11713
11295
  var init_stage_advance = __esm(() => {
11714
11296
  init_dist();
11715
11297
  init_handback();
@@ -11785,7 +11367,7 @@ import {
11785
11367
  GIT_NO_HOOKS as GIT_NO_HOOKS8,
11786
11368
  implementRunContainment,
11787
11369
  implementRunContainmentCliArgs as implementRunContainmentCliArgs2,
11788
- log as log35,
11370
+ log as log34,
11789
11371
  makeBranchName,
11790
11372
  normalizeGateSpec,
11791
11373
  pushBranch as pushBranch3,
@@ -11991,11 +11573,11 @@ class Worker {
11991
11573
  sessionId: this.sessionId
11992
11574
  });
11993
11575
  } catch (err) {
11994
- log35.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11576
+ log34.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11995
11577
  }
11996
11578
  }
11997
11579
  get tag() {
11998
- return `${TAG32}:${this.id}`;
11580
+ return `${TAG31}:${this.id}`;
11999
11581
  }
12000
11582
  get isIdle() {
12001
11583
  return this.state === "idle";
@@ -12057,12 +11639,12 @@ class Worker {
12057
11639
  }
12058
11640
  if (!crossedTurnCap(before, after, cap))
12059
11641
  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.`);
11642
+ 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
11643
  try {
12062
11644
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
12063
11645
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), { commentType: "blocker", agentSessionId: this.sessionId ?? undefined });
12064
11646
  } catch (err) {
12065
- log35.warn(TAG32, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
11647
+ log34.warn(TAG31, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
12066
11648
  }
12067
11649
  }
12068
11650
  async run(card, column, labels, subtasks) {
@@ -12117,7 +11699,7 @@ class Worker {
12117
11699
  resumeReason: null
12118
11700
  });
12119
11701
  } catch (err) {
12120
- log35.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
11702
+ log34.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
12121
11703
  }
12122
11704
  }
12123
11705
  try {
@@ -12125,20 +11707,20 @@ class Worker {
12125
11707
  if (!resuming) {
12126
11708
  this.branchName = makeBranchName(card.short_id, card.title, this.config.worktree.failedBranchPrefix);
12127
11709
  }
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}"`);
11710
+ 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
11711
  const attemptCount = await this.stateStore.incrementAttempt(card.id);
12130
11712
  const isRework = attemptCount > 1;
12131
11713
  const runStarts = this.stateStore.getCardRunStarts(card.id);
12132
11714
  const runCap = this.config.budget.maxRunsPerCard;
12133
11715
  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.`);
11716
+ 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
11717
  try {
12136
11718
  await this.client.addComment(card.id, buildRunCapComment(runStarts, runCap), {
12137
11719
  commentType: "blocker",
12138
11720
  agentSessionId: this.sessionId ?? undefined
12139
11721
  });
12140
11722
  } catch (err) {
12141
- log35.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
11723
+ log34.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
12142
11724
  }
12143
11725
  }
12144
11726
  const recordedBranch = recordedBranchForCard(card.description, card.short_id, [
@@ -12148,10 +11730,10 @@ class Worker {
12148
11730
  const continuesPushedWork = isRework || recordedBranch !== null;
12149
11731
  if (!resuming && recordedBranch) {
12150
11732
  if (recordedBranch !== this.branchName) {
12151
- log35.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
11733
+ log34.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
12152
11734
  this.branchName = recordedBranch;
12153
11735
  } 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}`);
11736
+ log34.info(this.tag, `Card records pushed work on ${this.branchName} — continuing that branch instead of rebuilding from ${this.config.worktree.baseBranch}`);
12155
11737
  }
12156
11738
  }
12157
11739
  this.startHeartbeat();
@@ -12193,14 +11775,14 @@ class Worker {
12193
11775
  awaitingDecisionUntil: null
12194
11776
  });
12195
11777
  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)
11778
+ info: (message) => log34.info(this.tag, message),
11779
+ warn: (message) => log34.warn(this.tag, message)
12198
11780
  });
12199
11781
  session = started.session;
12200
11782
  } catch (err) {
12201
11783
  if (isSessionConflict(err)) {
12202
11784
  this.sessionConflict = true;
12203
- log35.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
11785
+ log34.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
12204
11786
  await this.stateStore.decrementAttempt(card.id);
12205
11787
  return;
12206
11788
  }
@@ -12208,7 +11790,7 @@ class Worker {
12208
11790
  }
12209
11791
  const sid = session && typeof session === "object" && "id" in session ? session.id : null;
12210
11792
  if (!sid) {
12211
- log35.warn(TAG32, "startAgentSession returned no session id");
11793
+ log34.warn(TAG31, "startAgentSession returned no session id");
12212
11794
  }
12213
11795
  this.sessionId = sid;
12214
11796
  }
@@ -12226,7 +11808,7 @@ class Worker {
12226
11808
  if (!resuming) {
12227
11809
  const moved = await moveCardAndAddLabel(this.client, card, IN_PROGRESS_COLUMN, "agent");
12228
11810
  if (!moved) {
12229
- log35.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
11811
+ log34.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
12230
11812
  }
12231
11813
  }
12232
11814
  if (this.aborted)
@@ -12253,10 +11835,10 @@ class Worker {
12253
11835
  }).trim();
12254
11836
  const target = resolveContinuationTarget(this.branchName, continueRequested, this.config.worktree.failedBranchPrefix, this.config.worktree.approvedBranchPrefix, (ref) => fetchExistingBranch(repoRoot, ref));
12255
11837
  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`);
11838
+ log34.info(this.tag, `Branch ${this.branchName} is gone from origin but its approved rename ${target.branchName} exists — continuing that branch`);
12257
11839
  this.branchName = target.branchName;
12258
11840
  } 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`);
11841
+ log34.info(this.tag, `Branch ${this.branchName} exists on origin with no card record — continuing it rather than resetting it`);
12260
11842
  }
12261
11843
  this.worktreePath = createWorktree(this.config.worktree.basePath, this.config.worktree.baseBranch, this.branchName, {
12262
11844
  continueExisting: target.continueExisting,
@@ -12290,7 +11872,7 @@ class Worker {
12290
11872
  if (this.aborted)
12291
11873
  return;
12292
11874
  if (parked) {
12293
- log35.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
11875
+ log34.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
12294
11876
  return;
12295
11877
  }
12296
11878
  }
@@ -12311,7 +11893,7 @@ class Worker {
12311
11893
  progressPercent: 10
12312
11894
  });
12313
11895
  this.timeoutTimer = setTimeout(() => {
12314
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
11896
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
12315
11897
  this.timedOut = true;
12316
11898
  this.cancel("timeout");
12317
11899
  }, this.config.maxTimeout);
@@ -12338,7 +11920,7 @@ class Worker {
12338
11920
  }
12339
11921
  this.state = "verifying";
12340
11922
  await this.recordPhase("verifying");
12341
- log35.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
11923
+ log34.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
12342
11924
  await this.client.updateAgentProgress(card.id, {
12343
11925
  agentIdentifier: this.sessionIdentifier,
12344
11926
  agentName: AGENT_NAME,
@@ -12354,7 +11936,7 @@ class Worker {
12354
11936
  const onBeforeWorktreeCleanup = stageRun ? async (worktreePath) => {
12355
11937
  stageGateEvaluation = await this.collectStageGateEvidence(card, stageRun.stage, worktreePath, subtasks);
12356
11938
  } : 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);
11939
+ 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
11940
  if (completed === "park") {
12359
11941
  await this.parkForDecision(card, "max_turns");
12360
11942
  return;
@@ -12373,7 +11955,7 @@ class Worker {
12373
11955
  break;
12374
11956
  case "reclaim_refused":
12375
11957
  this.held = true;
12376
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
11958
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12377
11959
  break;
12378
11960
  case "advanced":
12379
11961
  case "completed_terminal":
@@ -12411,7 +11993,7 @@ class Worker {
12411
11993
  return;
12412
11994
  }
12413
11995
  this.state = "error";
12414
- log35.error(this.tag, `Error on #${card.short_id}: ${msg}`);
11996
+ log34.error(this.tag, `Error on #${card.short_id}: ${msg}`);
12415
11997
  const apiError = errClass.kind !== null;
12416
11998
  const baseError = err instanceof WorktreeBaseError;
12417
11999
  const noBudgetBurn = apiError || baseError;
@@ -12429,7 +12011,7 @@ class Worker {
12429
12011
  try {
12430
12012
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12431
12013
  } catch {
12432
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12014
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12433
12015
  }
12434
12016
  this.worktreePath = null;
12435
12017
  }
@@ -12454,7 +12036,7 @@ class Worker {
12454
12036
  }
12455
12037
  });
12456
12038
  } catch (tErr) {
12457
- log35.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12039
+ log34.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12458
12040
  }
12459
12041
  if (this.runId) {
12460
12042
  try {
@@ -12490,7 +12072,7 @@ class Worker {
12490
12072
  try {
12491
12073
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12492
12074
  } catch {
12493
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12075
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12494
12076
  }
12495
12077
  this.worktreePath = null;
12496
12078
  }
@@ -12513,7 +12095,7 @@ class Worker {
12513
12095
  }
12514
12096
  });
12515
12097
  } catch (tErr) {
12516
- log35.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12098
+ log34.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12517
12099
  }
12518
12100
  try {
12519
12101
  await this.stateStore.endRun(this.runId, "failed", {
@@ -12527,15 +12109,15 @@ class Worker {
12527
12109
  try {
12528
12110
  await this.client.updateCard(card.id, { assignedAgentId: null });
12529
12111
  } catch (err) {
12530
- log35.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12112
+ log34.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12531
12113
  }
12532
12114
  try {
12533
12115
  await runTransition(this.client, card, { removeLabels: ["agent"] });
12534
12116
  } catch (tErr) {
12535
- log35.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12117
+ log34.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12536
12118
  }
12537
12119
  } else {
12538
- log35.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12120
+ log34.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12539
12121
  }
12540
12122
  try {
12541
12123
  await this.stateStore.endRun(this.runId, "paused", {
@@ -12599,28 +12181,28 @@ class Worker {
12599
12181
  };
12600
12182
  const { pick, reason } = selectAutoPlaybook(subject, playbooks ?? []);
12601
12183
  if (!pick) {
12602
- log35.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12184
+ log34.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12603
12185
  return card;
12604
12186
  }
12605
12187
  const undeclared = undeclaredGateMetricsIn(pick, declaredMetricSet(this.config));
12606
12188
  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.");
12189
+ 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
12190
  return card;
12609
12191
  }
12610
12192
  const applyResult = await this.client.request("POST", `/cards/${card.id}/apply-playbook`, {
12611
12193
  playbookId: pick.id
12612
12194
  });
12613
- log35.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12195
+ log34.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12614
12196
  try {
12615
12197
  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
12198
  } catch (commentErr) {
12617
- log35.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12199
+ log34.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12618
12200
  }
12619
12201
  try {
12620
12202
  const { card: fresh } = await this.client.getCard(card.id);
12621
12203
  return fresh;
12622
12204
  } 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)}`);
12205
+ 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
12206
  return {
12625
12207
  ...card,
12626
12208
  playbook_id: applyResult.card.playbook_id,
@@ -12629,7 +12211,7 @@ class Worker {
12629
12211
  };
12630
12212
  }
12631
12213
  } 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)}`);
12214
+ log34.warn(this.tag, `Auto-bind playbook check failed for #${card.short_id}, continuing unbound: ${err instanceof Error ? err.message : String(err)}`);
12633
12215
  return card;
12634
12216
  }
12635
12217
  }
@@ -12741,7 +12323,7 @@ class Worker {
12741
12323
  });
12742
12324
  } catch (err) {
12743
12325
  const detail = err instanceof Error ? err.message : String(err);
12744
- log35.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12326
+ log34.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12745
12327
  await this.holdStageCard(card, `Fan-out stage "${ctx.stage.name}" could not run: ${detail}`);
12746
12328
  return;
12747
12329
  }
@@ -12750,7 +12332,7 @@ class Worker {
12750
12332
  case "waiting": {
12751
12333
  const total = outcome.kind === "dispatched" ? outcome.total : outcome.total;
12752
12334
  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}`);
12335
+ log34.info(this.tag, `#${card.short_id} ${note}`);
12754
12336
  await this.client.updateAgentProgress(card.id, {
12755
12337
  agentIdentifier: "claude-code-stage",
12756
12338
  agentName: "Harmony Agent",
@@ -12778,7 +12360,7 @@ class Worker {
12778
12360
  if (advance.kind === "advanced" || advance.kind === "completed_terminal") {
12779
12361
  this.held = false;
12780
12362
  }
12781
- log35.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12363
+ log34.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12782
12364
  return;
12783
12365
  }
12784
12366
  case "halted": {
@@ -12798,7 +12380,7 @@ class Worker {
12798
12380
  }
12799
12381
  }
12800
12382
  async holdStageCard(card, reason, wait = false) {
12801
- log35.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12383
+ log34.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12802
12384
  await this.stateStore.decrementAttempt(card.id);
12803
12385
  try {
12804
12386
  await this.client.addComment(card.id, reason, {
@@ -12817,7 +12399,7 @@ class Worker {
12817
12399
  }
12818
12400
  });
12819
12401
  } catch (tErr) {
12820
- log35.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12402
+ log34.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12821
12403
  }
12822
12404
  if (this.runId) {
12823
12405
  try {
@@ -12835,7 +12417,7 @@ class Worker {
12835
12417
  const holderMessage = err instanceof Error ? err.message : String(err);
12836
12418
  const waitHours = this.config.budget.pause.waitHours;
12837
12419
  const until = computeDecisionDeadline(waitHours);
12838
- log35.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12420
+ log34.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12839
12421
  try {
12840
12422
  await this.client.addComment(card.id, formatResumeConflictComment({
12841
12423
  holderMessage,
@@ -12847,7 +12429,7 @@ class Worker {
12847
12429
  agentSessionId: this.sessionId ?? undefined
12848
12430
  });
12849
12431
  } catch (commentErr) {
12850
- log35.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12432
+ log34.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12851
12433
  }
12852
12434
  if (this.runId) {
12853
12435
  const run = this.stateStore.getRun(this.runId);
@@ -12858,7 +12440,7 @@ class Worker {
12858
12440
  awaitingDecisionUntil: until
12859
12441
  });
12860
12442
  } 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}`);
12443
+ 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
12444
  }
12863
12445
  }
12864
12446
  }
@@ -12870,7 +12452,7 @@ class Worker {
12870
12452
  this.progressTracker = null;
12871
12453
  const waitHours = this.config.budget.pause.waitHours;
12872
12454
  const until = computeDecisionDeadline(waitHours);
12873
- log35.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12455
+ log34.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12874
12456
  const measured = this.worktreePath && this.runExpectsCommits ? measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha) : "unknown";
12875
12457
  const hasCommits = measured === "unknown" ? undefined : measured === "committed";
12876
12458
  if (hasCommits === false && !this.noCommitNoticeSettled) {
@@ -12900,7 +12482,7 @@ class Worker {
12900
12482
  });
12901
12483
  commentId = res?.comment?.id ?? null;
12902
12484
  } catch (err) {
12903
- log35.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12485
+ log34.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12904
12486
  }
12905
12487
  const cardCostCents = this.stateStore.getCardCostCents(card.id) + Math.max(0, this.runCostCents - this.chargedCents);
12906
12488
  const readout = [
@@ -12921,7 +12503,7 @@ class Worker {
12921
12503
  awaitingDecisionUntil: new Date(until).toISOString()
12922
12504
  });
12923
12505
  } catch (err) {
12924
- log35.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12506
+ log34.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12925
12507
  }
12926
12508
  if (this.runId) {
12927
12509
  try {
@@ -12932,7 +12514,7 @@ class Worker {
12932
12514
  ...this.runLedger()
12933
12515
  });
12934
12516
  } 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}`);
12517
+ 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
12518
  }
12937
12519
  }
12938
12520
  }
@@ -12963,11 +12545,11 @@ class Worker {
12963
12545
  });
12964
12546
  const gate = normalizeGateSpec(ctx.stage.gate);
12965
12547
  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`);
12548
+ log34.info(this.tag, `Running stage "${ctx.stage.name}" (role ${ctx.role}) for #${card.short_id} under the harness motor`);
12967
12549
  const motorAbort = new AbortController;
12968
12550
  this.motorAbort = motorAbort;
12969
12551
  this.timeoutTimer = setTimeout(() => {
12970
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12552
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12971
12553
  this.timedOut = true;
12972
12554
  this.cancel("timeout");
12973
12555
  }, this.config.maxTimeout);
@@ -12978,12 +12560,12 @@ class Worker {
12978
12560
  let motorRunSettled = false;
12979
12561
  const onMotorLine = (line) => {
12980
12562
  if (line.type !== "agent_event") {
12981
- log35.info(this.tag, `motor: ${line.type}`);
12563
+ log34.info(this.tag, `motor: ${line.type}`);
12982
12564
  return;
12983
12565
  }
12984
12566
  if (motorRunSettled)
12985
12567
  return;
12986
- log35.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12568
+ log34.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12987
12569
  if (line.event.kind === "tool_started" && STAGE_DAEMON_OWNED_TOOLS.includes(line.event.payload.toolName)) {
12988
12570
  return;
12989
12571
  }
@@ -13003,7 +12585,7 @@ class Worker {
13003
12585
  currentTask: motorTask,
13004
12586
  progressPercent: MOTOR_RUN_PROGRESS_PERCENT
13005
12587
  }).catch((err) => {
13006
- log35.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12588
+ log34.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13007
12589
  });
13008
12590
  }, MOTOR_SESSION_HEARTBEAT_MS);
13009
12591
  heartbeat.unref?.();
@@ -13077,7 +12659,7 @@ class Worker {
13077
12659
  break;
13078
12660
  case "reclaim_refused":
13079
12661
  this.held = true;
13080
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12662
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
13081
12663
  break;
13082
12664
  case "advanced":
13083
12665
  case "completed_terminal":
@@ -13099,7 +12681,7 @@ class Worker {
13099
12681
  try {
13100
12682
  pushBranch3(this.branchName, worktreePath);
13101
12683
  } 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}`);
12684
+ log34.error(this.tag, `push after the motor stage "${ctx.stage.name}" failed for ${this.branchName}: ${err instanceof Error ? err.message : err}`);
13103
12685
  }
13104
12686
  }
13105
12687
  }
@@ -13107,7 +12689,7 @@ class Worker {
13107
12689
  if (completionColumn) {
13108
12690
  await transferCardToCompletion({ client: this.client, tag: this.tag }, card, completionColumn, this.onCardCompleted);
13109
12691
  } else {
13110
- log35.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
12692
+ log34.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
13111
12693
  }
13112
12694
  await this.closeoutMotorWorktree(card);
13113
12695
  }
@@ -13118,7 +12700,7 @@ class Worker {
13118
12700
  try {
13119
12701
  await teardownWorktree2(this.client, card.id, worktreePath, this.branchName ?? undefined, this.sessionId);
13120
12702
  } catch {
13121
- log35.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
12703
+ log34.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
13122
12704
  }
13123
12705
  this.worktreePath = null;
13124
12706
  }
@@ -13175,7 +12757,7 @@ ${prompt}`;
13175
12757
  });
13176
12758
  return handoff ? renderInheritedHandoffSection(handoff) : "";
13177
12759
  } catch (err) {
13178
- log35.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
12760
+ log34.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13179
12761
  return "";
13180
12762
  }
13181
12763
  }
@@ -13195,9 +12777,9 @@ ${prompt}`;
13195
12777
  commentType: "decision",
13196
12778
  agentSessionId: this.sessionId ?? undefined
13197
12779
  });
13198
- log35.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
12780
+ log34.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
13199
12781
  } catch (err) {
13200
- log35.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12782
+ log34.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13201
12783
  }
13202
12784
  }
13203
12785
  async collectStageGateEvidence(card, stage, worktreePath, subtasks) {
@@ -13209,12 +12791,12 @@ ${prompt}`;
13209
12791
  return null;
13210
12792
  }
13211
12793
  if (gate.pendingEngine === true) {
13212
- log35.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
12794
+ log34.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
13213
12795
  return null;
13214
12796
  }
13215
12797
  const review = gate.kind === "review_passed" ? parseReviewOutput(this.lastRunText) : undefined;
13216
12798
  if (review) {
13217
- log35.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
12799
+ log34.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
13218
12800
  }
13219
12801
  const registry = buildGateCollectorRegistry2({
13220
12802
  build: {
@@ -13231,7 +12813,7 @@ ${prompt}`;
13231
12813
  return [];
13232
12814
  const criteria = await fetchAcceptanceCriteria(this.client, this.tag, card);
13233
12815
  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`);
12816
+ 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
12817
  }
13236
12818
  return criteria;
13237
12819
  })()
@@ -13253,10 +12835,10 @@ ${prompt}`;
13253
12835
  const evaluation = gateEvaluate(gate, evidence);
13254
12836
  const insert = toStageGateEvidenceInsert(context, evidence);
13255
12837
  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}`);
12838
+ log34.info(this.tag, `Recorded ${gate.kind} gate evidence for #${card.short_id} stage "${stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
13257
12839
  return evaluation;
13258
12840
  } catch (err) {
13259
- log35.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12841
+ log34.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13260
12842
  return null;
13261
12843
  }
13262
12844
  }
@@ -13274,7 +12856,7 @@ ${prompt}`;
13274
12856
  agentSessionId: this.sessionId
13275
12857
  });
13276
12858
  } catch (err) {
13277
- log35.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12859
+ log34.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13278
12860
  return { kind: "no_advance" };
13279
12861
  }
13280
12862
  }
@@ -13300,7 +12882,7 @@ ${prompt}`;
13300
12882
  this.modelChoice = choice;
13301
12883
  const { model, escalated, source } = choice;
13302
12884
  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"})`);
12885
+ log34.info(this.tag, `Implement model "${model}" (source=${source}, escalated=${escalated}, attempts=${attempts}, priority=${card.priority ?? "none"}, tier=${this.sizing?.tier ?? "none"})`);
13304
12886
  }
13305
12887
  return model;
13306
12888
  }
@@ -13315,7 +12897,7 @@ ${prompt}`;
13315
12897
  encoding: "utf-8"
13316
12898
  }).trim();
13317
12899
  } 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`);
12900
+ 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
12901
  return { status: "failed", reason: "spawn" };
13320
12902
  }
13321
12903
  const outcome = await sizeRun({
@@ -13329,21 +12911,22 @@ ${prompt}`;
13329
12911
  scoreBands: claude.scoreBands
13330
12912
  });
13331
12913
  if (outcome.status === "sized") {
13332
- log35.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
12914
+ log34.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
13333
12915
  } else if (outcome.status === "failed") {
13334
- log35.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
12916
+ log34.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
13335
12917
  }
13336
12918
  return outcome;
13337
12919
  }
13338
12920
  recordPromptAssembled(outcomes) {
13339
- const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count ?? 0;
12921
+ const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count;
13340
12922
  const failures = outcomes.flatMap((o) => o.failure ? [{ flavour: o.flavour, message: o.failure.slice(0, 300) }] : []);
12923
+ const episodeCount = countOf("past_episodes");
13341
12924
  this.cliRunner?.record({
13342
12925
  kind: "prompt_assembled",
13343
12926
  source: "system",
13344
12927
  payload: {
13345
- episodeCount: countOf("past_episodes"),
13346
- referenceCount: countOf("reference"),
12928
+ ...episodeCount === undefined ? {} : { episodeCount },
12929
+ referenceCount: countOf("reference") ?? 0,
13347
12930
  ...failures.length > 0 ? { recallFailures: failures } : {}
13348
12931
  }
13349
12932
  });
@@ -13364,7 +12947,7 @@ ${prompt}`;
13364
12947
  const measured = measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha);
13365
12948
  if (measured !== "none") {
13366
12949
  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"}`);
12950
+ log34.debug(this.tag, `no-commit check could not attribute this run's commits — staying quiet on ${this.branchName ?? "this branch"}`);
13368
12951
  }
13369
12952
  return;
13370
12953
  }
@@ -13373,7 +12956,7 @@ ${prompt}`;
13373
12956
  recordNoCommitsYet(trigger, numTurns) {
13374
12957
  const turnBudget = this.effectiveMaxTurns;
13375
12958
  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})`);
12959
+ 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
12960
  this.cliRunner?.record({
13378
12961
  kind: "no_commits_yet",
13379
12962
  source: "system",
@@ -13425,9 +13008,9 @@ ${prompt}`;
13425
13008
  agentSessionId: this.sessionId ?? undefined
13426
13009
  });
13427
13010
  giveUpCommentId = res?.comment?.id ?? null;
13428
- log35.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13011
+ log34.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13429
13012
  } catch (err) {
13430
- log35.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13013
+ log34.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13431
13014
  }
13432
13015
  if (this.config.budget.pause.enabled) {
13433
13016
  const waitHours = this.config.budget.pause.waitHours;
@@ -13441,7 +13024,7 @@ ${prompt}`;
13441
13024
  awaitingDecisionUntil: new Date(until).toISOString()
13442
13025
  });
13443
13026
  } catch (err) {
13444
- log35.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13027
+ log34.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13445
13028
  }
13446
13029
  try {
13447
13030
  await this.stateStore.markAwaitingDecision(cardId, {
@@ -13450,19 +13033,19 @@ ${prompt}`;
13450
13033
  agentIdentifier: this.sessionIdentifier
13451
13034
  });
13452
13035
  } catch (err) {
13453
- log35.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13036
+ log34.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13454
13037
  }
13455
13038
  }
13456
13039
  }
13457
13040
  }
13458
13041
  } catch (err) {
13459
- log35.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13042
+ log34.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13460
13043
  }
13461
13044
  }
13462
13045
  async pause() {
13463
13046
  if (!this.isActive || !this.process || this.process.killed)
13464
13047
  return;
13465
- log35.info(this.tag, `Pausing work on ${this.cardId}`);
13048
+ log34.info(this.tag, `Pausing work on ${this.cardId}`);
13466
13049
  signalGroup2(this.process, "SIGSTOP");
13467
13050
  if (this.timeoutTimer) {
13468
13051
  clearTimeout(this.timeoutTimer);
@@ -13476,17 +13059,17 @@ ${prompt}`;
13476
13059
  status: "paused"
13477
13060
  });
13478
13061
  } catch {
13479
- log35.warn(this.tag, "Failed to update agent session to paused");
13062
+ log34.warn(this.tag, "Failed to update agent session to paused");
13480
13063
  }
13481
13064
  }
13482
13065
  }
13483
13066
  async resume() {
13484
13067
  if (!this.isActive || !this.process || this.process.killed)
13485
13068
  return;
13486
- log35.info(this.tag, `Resuming work on ${this.cardId}`);
13069
+ log34.info(this.tag, `Resuming work on ${this.cardId}`);
13487
13070
  signalGroup2(this.process, "SIGCONT");
13488
13071
  this.timeoutTimer = setTimeout(() => {
13489
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13072
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13490
13073
  this.timedOut = true;
13491
13074
  this.cancel("timeout");
13492
13075
  }, this.config.maxTimeout);
@@ -13498,7 +13081,7 @@ ${prompt}`;
13498
13081
  status: "working"
13499
13082
  });
13500
13083
  } catch {
13501
- log35.warn(this.tag, "Failed to update agent session to working");
13084
+ log34.warn(this.tag, "Failed to update agent session to working");
13502
13085
  }
13503
13086
  }
13504
13087
  }
@@ -13507,7 +13090,7 @@ ${prompt}`;
13507
13090
  return;
13508
13091
  this.aborted = true;
13509
13092
  this.state = "cancelling";
13510
- log35.info(this.tag, `Cancelling work on ${this.cardId}`);
13093
+ log34.info(this.tag, `Cancelling work on ${this.cardId}`);
13511
13094
  this.motorAbort?.abort();
13512
13095
  if (this.sdkRunner) {
13513
13096
  await this.sdkRunner.stop(this.timedOut ? "timeout" : "user_requested");
@@ -13525,14 +13108,14 @@ ${prompt}`;
13525
13108
  ...buildTokenPayload(stats)
13526
13109
  });
13527
13110
  } catch (err) {
13528
- log35.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13111
+ log34.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13529
13112
  }
13530
13113
  }
13531
13114
  }
13532
13115
  async runPlanningPhase(enriched) {
13533
13116
  const planning = this.config.planning;
13534
13117
  const { card } = enriched;
13535
- log35.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13118
+ log34.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13536
13119
  await this.client.updateAgentProgress(card.id, {
13537
13120
  agentIdentifier: this.sessionIdentifier,
13538
13121
  agentName: AGENT_NAME,
@@ -13545,7 +13128,7 @@ ${prompt}`;
13545
13128
  let planTimedOut = false;
13546
13129
  const planTimeout = setTimeout(() => {
13547
13130
  planTimedOut = true;
13548
- log35.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13131
+ log34.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13549
13132
  if (this.sdkRunner) {
13550
13133
  this.sdkRunner.stop("timeout").catch(() => {});
13551
13134
  } else if (this.process && !this.process.killed) {
@@ -13563,7 +13146,7 @@ ${prompt}`;
13563
13146
  initialPhase: "planning"
13564
13147
  });
13565
13148
  } catch (err) {
13566
- log35.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13149
+ log34.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13567
13150
  return false;
13568
13151
  } finally {
13569
13152
  clearTimeout(planTimeout);
@@ -13574,7 +13157,7 @@ ${prompt}`;
13574
13157
  await this.chargeDailyLedger(card.id, card.short_id);
13575
13158
  const planText = stats?.lastAssistantText ?? "";
13576
13159
  if (!planText.trim()) {
13577
- log35.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13160
+ log34.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13578
13161
  return false;
13579
13162
  }
13580
13163
  const artifact = extractPlanArtifact(planText, card.title);
@@ -13595,9 +13178,9 @@ ${prompt}`;
13595
13178
  });
13596
13179
  planId = createdId;
13597
13180
  }
13598
- log35.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13181
+ log34.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13599
13182
  } catch (err) {
13600
- log35.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13183
+ log34.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13601
13184
  }
13602
13185
  if (planning.mode === "gated" && planId) {
13603
13186
  try {
@@ -13616,11 +13199,11 @@ ${prompt}`;
13616
13199
  ...buildTokenPayload(stats)
13617
13200
  }
13618
13201
  }, { store: this.stateStore, runId: this.runId ?? undefined });
13619
- log35.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13202
+ log34.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13620
13203
  this.lastSessionStats = undefined;
13621
13204
  return true;
13622
13205
  } 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}`);
13206
+ 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
13207
  }
13625
13208
  }
13626
13209
  if (planId && planning.postComment) {
@@ -13630,7 +13213,7 @@ ${prompt}`;
13630
13213
  agentSessionId: this.sessionId ?? undefined
13631
13214
  });
13632
13215
  } catch (err) {
13633
- log35.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13216
+ log34.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13634
13217
  }
13635
13218
  }
13636
13219
  return false;
@@ -13640,10 +13223,10 @@ ${prompt}`;
13640
13223
  const { card } = enriched;
13641
13224
  const existing = await this.loadPinnedContract(card.id);
13642
13225
  if (existing) {
13643
- log35.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13226
+ log34.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13644
13227
  return;
13645
13228
  }
13646
- log35.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13229
+ log34.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13647
13230
  await this.client.updateAgentProgress(card.id, {
13648
13231
  agentIdentifier: this.sessionIdentifier,
13649
13232
  agentName: AGENT_NAME,
@@ -13656,7 +13239,7 @@ ${prompt}`;
13656
13239
  let contractTimedOut = false;
13657
13240
  const contractTimeout = setTimeout(() => {
13658
13241
  contractTimedOut = true;
13659
- log35.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13242
+ log34.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13660
13243
  if (this.sdkRunner) {
13661
13244
  this.sdkRunner.stop("timeout").catch(() => {});
13662
13245
  } else if (this.process && !this.process.killed) {
@@ -13674,7 +13257,7 @@ ${prompt}`;
13674
13257
  initialPhase: "planning"
13675
13258
  });
13676
13259
  } catch (err) {
13677
- log35.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13260
+ log34.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13678
13261
  return;
13679
13262
  } finally {
13680
13263
  clearTimeout(contractTimeout);
@@ -13685,12 +13268,12 @@ ${prompt}`;
13685
13268
  await this.chargeDailyLedger(card.id, card.short_id);
13686
13269
  const contractText = stats?.lastAssistantText ?? "";
13687
13270
  if (!contractText.trim()) {
13688
- log35.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13271
+ log34.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13689
13272
  return;
13690
13273
  }
13691
13274
  const contract = extractContract(contractText, card);
13692
13275
  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`);
13276
+ log34.warn(this.tag, `Contract for #${card.short_id} had ${contract.assertions.length} assertion(s) (< ${contractCfg.minAssertions}) — not pinning, implementing directly`);
13694
13277
  return;
13695
13278
  }
13696
13279
  try {
@@ -13698,9 +13281,9 @@ ${prompt}`;
13698
13281
  commentType: "decision",
13699
13282
  agentSessionId: this.sessionId ?? undefined
13700
13283
  });
13701
- log35.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13284
+ log34.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13702
13285
  } catch (err) {
13703
- log35.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13286
+ log34.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13704
13287
  }
13705
13288
  }
13706
13289
  async loadPinnedContract(cardId) {
@@ -13710,7 +13293,7 @@ ${prompt}`;
13710
13293
  return null;
13711
13294
  return extractPinnedContract(comments, this.identity);
13712
13295
  } catch (err) {
13713
- log35.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13296
+ log34.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13714
13297
  return null;
13715
13298
  }
13716
13299
  }
@@ -13723,13 +13306,13 @@ ${prompt}`;
13723
13306
  const res = await this.client.getPendingUserMessages(this.cardId, this.sessionId, this.lastDrainedSeq);
13724
13307
  messages = res.messages ?? [];
13725
13308
  } catch (err) {
13726
- log35.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13309
+ log34.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13727
13310
  return;
13728
13311
  }
13729
13312
  if (messages.length === 0)
13730
13313
  return;
13731
13314
  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)`);
13315
+ log34.info(this.tag, `Steering #${card.short_id}: resuming with ${messages.length} queued message(s)`);
13733
13316
  this.state = "running";
13734
13317
  await this.recordPhase("running");
13735
13318
  try {
@@ -13741,7 +13324,7 @@ ${prompt}`;
13741
13324
  ...this.activeRunSpawnOpts ?? {}
13742
13325
  });
13743
13326
  } catch (err) {
13744
- log35.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13327
+ log34.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13745
13328
  return;
13746
13329
  }
13747
13330
  }
@@ -13776,10 +13359,10 @@ ${prompt}`;
13776
13359
  "--",
13777
13360
  prompt
13778
13361
  ];
13779
- log35.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13362
+ log34.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13780
13363
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13781
13364
  if (runLog) {
13782
- log35.info(this.tag, `Run log: ${runLog.path}`);
13365
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13783
13366
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} started=${new Date().toISOString()}
13784
13367
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
13785
13368
 
@@ -13816,7 +13399,7 @@ ${prompt}`;
13816
13399
  });
13817
13400
  }
13818
13401
  parser.on("parse_error", (msg) => {
13819
- log35.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13402
+ log34.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13820
13403
  runLog?.stream.write(`
13821
13404
  [parse_error] ${msg}
13822
13405
  `);
@@ -13889,10 +13472,10 @@ ${prompt}`;
13889
13472
  const disallowedTools = opts.disallowedTools ? opts.disallowedTools.split(",").map((t) => t.trim()).filter(Boolean) : undefined;
13890
13473
  const initialPhase = opts.initialPhase ?? "exploring";
13891
13474
  const maxBudgetUsd = this.effectiveMaxBudgetUsd;
13892
- log35.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13475
+ log34.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13893
13476
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13894
13477
  if (runLog) {
13895
- log35.info(this.tag, `Run log: ${runLog.path}`);
13478
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13896
13479
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} runner=sdk started=${new Date().toISOString()}
13897
13480
  ` + `# model=${model} maxTurns=${maxTurns} <prompt:${prompt.length} chars>
13898
13481
 
@@ -14027,7 +13610,7 @@ ${prompt}`;
14027
13610
  try {
14028
13611
  await teardownWorktree2(this.client, this.cardId, this.worktreePath, this.branchName ?? undefined, this.sessionId);
14029
13612
  } catch {
14030
- log35.warn(this.tag, "Failed to cleanup worktree");
13613
+ log34.warn(this.tag, "Failed to cleanup worktree");
14031
13614
  }
14032
13615
  }
14033
13616
  this.process = null;
@@ -14046,7 +13629,7 @@ ${prompt}`;
14046
13629
  this.chargedTokens = emptyTokens();
14047
13630
  }
14048
13631
  }
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;
13632
+ 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
13633
  var init_worker = __esm(() => {
14051
13634
  init_dist();
14052
13635
  init_board_helpers();
@@ -14077,7 +13660,7 @@ var init_worker = __esm(() => {
14077
13660
  });
14078
13661
 
14079
13662
  // src/workspace-model-cache.ts
14080
- import { log as log36 } from "@gethmy/harness";
13663
+ import { log as log35 } from "@gethmy/harness";
14081
13664
 
14082
13665
  class WorkspaceModelCache {
14083
13666
  fetcher;
@@ -14112,7 +13695,7 @@ class WorkspaceModelCache {
14112
13695
  this.stale = false;
14113
13696
  } catch (err) {
14114
13697
  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)}`);
13698
+ 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
13699
  }
14117
13700
  return this.value;
14118
13701
  }
@@ -14123,8 +13706,14 @@ var init_workspace_model_cache = () => {};
14123
13706
  import {
14124
13707
  cooldownMsFor,
14125
13708
  describeApiError as describeApiError3,
14126
- log as log37
13709
+ log as log36
14127
13710
  } from "@gethmy/harness";
13711
+ function httpStatusOf(err) {
13712
+ if (typeof err !== "object" || err === null)
13713
+ return;
13714
+ const status = own(err, "status");
13715
+ return typeof status === "number" ? status : undefined;
13716
+ }
14128
13717
  async function routeBudgetDecision(d, run, actions, cardId) {
14129
13718
  if (!run) {
14130
13719
  if (!cardId)
@@ -14219,11 +13808,11 @@ class Pool {
14219
13808
  }
14220
13809
  async enqueue(card, column, labels, subtasks, mode = "implement") {
14221
13810
  if (card.done || card.archived_at) {
14222
- log37.debug(TAG33, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
13811
+ log36.debug(TAG32, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
14223
13812
  return;
14224
13813
  }
14225
13814
  if (this.isCardKnown(card.id) || this.reservations.has(card.id)) {
14226
- log37.debug(TAG33, `Card ${card.id} already queued, active, or reserved, skipping`);
13815
+ log36.debug(TAG32, `Card ${card.id} already queued, active, or reserved, skipping`);
14227
13816
  return;
14228
13817
  }
14229
13818
  this.reservations.add(card.id);
@@ -14231,19 +13820,19 @@ class Pool {
14231
13820
  try {
14232
13821
  const account = this.accountGuard?.check();
14233
13822
  if (account && !account.running) {
14234
- log37.debug(TAG33, `#${card.short_id} held — ${account.detail}`);
13823
+ log36.debug(TAG32, `#${card.short_id} held — ${account.detail}`);
14235
13824
  await this.emitWaiting(card.id, account.detail);
14236
13825
  return;
14237
13826
  }
14238
13827
  if (mode === "implement") {
14239
13828
  if (this.authPaused) {
14240
- log37.debug(TAG33, `#${card.short_id} held — agent paused (auth error)`);
13829
+ log36.debug(TAG32, `#${card.short_id} held — agent paused (auth error)`);
14241
13830
  await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
14242
13831
  return;
14243
13832
  }
14244
13833
  const cooldownMs = this.apiCooldownRemainingMs();
14245
13834
  if (cooldownMs > 0) {
14246
- log37.debug(TAG33, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
13835
+ log36.debug(TAG32, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
14247
13836
  await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
14248
13837
  return;
14249
13838
  }
@@ -14252,19 +13841,19 @@ class Pool {
14252
13841
  if (decision.reason === "daily_budget") {
14253
13842
  await this.denyDailyBudget(card, decision.detail);
14254
13843
  } else {
14255
- log37.debug(TAG33, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
13844
+ log36.debug(TAG32, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
14256
13845
  }
14257
13846
  return;
14258
13847
  }
14259
13848
  const { blockers, successors } = await getChainSignals(this.client, card, this.projectId);
14260
13849
  chainSuccessors = successors;
14261
13850
  if (blockers === null) {
14262
- log37.warn(TAG33, `#${card.short_id} blocker check failed — deferring to next tick`);
13851
+ log36.warn(TAG32, `#${card.short_id} blocker check failed — deferring to next tick`);
14263
13852
  return;
14264
13853
  }
14265
13854
  if (blockers.length > 0) {
14266
13855
  const list = blockers.map((b) => `#${b.shortId}`).join(", ");
14267
- log37.info(TAG33, `#${card.short_id} blocked by ${list} — waiting`);
13856
+ log36.info(TAG32, `#${card.short_id} blocked by ${list} — waiting`);
14268
13857
  await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
14269
13858
  return;
14270
13859
  }
@@ -14296,9 +13885,9 @@ class Pool {
14296
13885
  const reason = `Daily budget reached — waiting for reset (${detail})`;
14297
13886
  const line = `#${card.short_id} skipped (daily_budget): ${detail}`;
14298
13887
  if (this.lastWaitingEmit.get(card.id) === reason)
14299
- log37.debug(TAG33, line);
13888
+ log36.debug(TAG32, line);
14300
13889
  else
14301
- log37.warn(TAG33, line);
13890
+ log36.warn(TAG32, line);
14302
13891
  await this.emitWaiting(card.id, reason);
14303
13892
  }
14304
13893
  lastWaitingEmit = new Map;
@@ -14315,7 +13904,7 @@ class Pool {
14315
13904
  });
14316
13905
  this.lastWaitingEmit.set(cardId, currentTask);
14317
13906
  } catch (err) {
14318
- log37.debug(TAG33, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13907
+ log36.debug(TAG32, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
14319
13908
  }
14320
13909
  }
14321
13910
  noteApiError(err) {
@@ -14323,13 +13912,13 @@ class Pool {
14323
13912
  return;
14324
13913
  if (err.kind === "spend_limit") {
14325
13914
  this.accountGuard?.halt("spend_limit").catch((hErr) => {
14326
- log37.error(TAG33, `Failed to latch the account halt: ${hErr}`);
13915
+ log36.error(TAG32, `Failed to latch the account halt: ${hErr}`);
14327
13916
  });
14328
13917
  return;
14329
13918
  }
14330
13919
  if (err.kind === "auth") {
14331
13920
  if (!this.authPaused) {
14332
- log37.error(TAG33, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
13921
+ log36.error(TAG32, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
14333
13922
  }
14334
13923
  this.authPaused = true;
14335
13924
  return;
@@ -14338,7 +13927,7 @@ class Pool {
14338
13927
  const until = Date.now() + cooldownMs;
14339
13928
  if (until > this.apiCooldownUntil) {
14340
13929
  this.apiCooldownUntil = until;
14341
- log37.warn(TAG33, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
13930
+ log36.warn(TAG32, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
14342
13931
  }
14343
13932
  }
14344
13933
  apiCooldownRemainingMs() {
@@ -14352,13 +13941,13 @@ class Pool {
14352
13941
  const removed = queue.remove(cardId);
14353
13942
  if (removed) {
14354
13943
  this.cardDataCache.delete(cardId);
14355
- log37.info(TAG33, `Removed #${removed.shortId} from ${removed.mode} queue`);
13944
+ log36.info(TAG32, `Removed #${removed.shortId} from ${removed.mode} queue`);
14356
13945
  return;
14357
13946
  }
14358
13947
  }
14359
13948
  const worker = this.implWorkers.find((w) => w.cardId === cardId) ?? this.reviewWorkers.find((w) => w.cardId === cardId);
14360
13949
  if (worker) {
14361
- log37.info(TAG33, `Cancelling worker ${worker.id} for card ${cardId}`);
13950
+ log36.info(TAG32, `Cancelling worker ${worker.id} for card ${cardId}`);
14362
13951
  await worker.cancel("unassigned");
14363
13952
  }
14364
13953
  }
@@ -14415,10 +14004,10 @@ class Pool {
14415
14004
  }
14416
14005
  const worker = this.implWorkers.find((w) => w.cardId === cardId && w.isActive) ?? this.reviewWorkers.find((w) => w.cardId === cardId && w.isActive);
14417
14006
  if (!worker) {
14418
- log37.debug(TAG33, `No active worker for card ${cardId}, ignoring ${command}`);
14007
+ log36.debug(TAG32, `No active worker for card ${cardId}, ignoring ${command}`);
14419
14008
  return;
14420
14009
  }
14421
- log37.info(TAG33, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
14010
+ log36.info(TAG32, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
14422
14011
  switch (command) {
14423
14012
  case "pause":
14424
14013
  await worker.pause();
@@ -14466,7 +14055,7 @@ class Pool {
14466
14055
  };
14467
14056
  }
14468
14057
  async shutdown() {
14469
- log37.info(TAG33, "Shutting down pool...");
14058
+ log36.info(TAG32, "Shutting down pool...");
14470
14059
  this.shuttingDown = true;
14471
14060
  const active = [
14472
14061
  ...this.implWorkers.filter((w) => w.isActive),
@@ -14474,7 +14063,7 @@ class Pool {
14474
14063
  ];
14475
14064
  await Promise.all(active.map((w) => w.cancel("shutdown")));
14476
14065
  this.sleepGuard.stop();
14477
- log37.info(TAG33, "Pool shutdown complete");
14066
+ log36.info(TAG32, "Pool shutdown complete");
14478
14067
  }
14479
14068
  async drainBudgetDecisions(cardId) {
14480
14069
  const targets = cardId ? [cardId] : [
@@ -14505,7 +14094,11 @@ class Pool {
14505
14094
  try {
14506
14095
  ({ decisions } = await this.client.getBudgetDecisions(cardId, new Date(sinceMs).toISOString()));
14507
14096
  } catch (err) {
14508
- log37.warn(TAG33, `getBudgetDecisions failed for ${cardId}: ${err}`);
14097
+ if (httpStatusOf(err) === 404) {
14098
+ await this.forgetDeletedCard(cardId, run);
14099
+ return;
14100
+ }
14101
+ log36.warn(TAG32, `getBudgetDecisions failed for ${cardId}: ${err}`);
14509
14102
  return;
14510
14103
  }
14511
14104
  if (decisions.length > 0) {
@@ -14529,6 +14122,25 @@ class Pool {
14529
14122
  this.draining.delete(cardId);
14530
14123
  }
14531
14124
  }
14125
+ async forgetDeletedCard(cardId, run) {
14126
+ if (run) {
14127
+ try {
14128
+ await this.stateStore.endRun(run.runId, "failed", {
14129
+ errorMessage: "card deleted"
14130
+ });
14131
+ } catch (err) {
14132
+ log36.warn(TAG32, `Failed to end the parked run for the deleted card ${cardId}: ${err}`);
14133
+ }
14134
+ }
14135
+ try {
14136
+ const dropped = await this.stateStore.forgetCard(cardId);
14137
+ if (dropped) {
14138
+ log36.info(TAG32, `Card ${cardId} no longer exists on the server — dropped from the local ledger; its budget question can never be answered`);
14139
+ }
14140
+ } catch (err) {
14141
+ log36.warn(TAG32, `Failed to drop the deleted card ${cardId}: ${err}`);
14142
+ }
14143
+ }
14532
14144
  async releaseExpiredPark(run) {
14533
14145
  try {
14534
14146
  await this.client.addComment(run.cardId, formatExpiredParkComment({
@@ -14540,7 +14152,7 @@ class Pool {
14540
14152
  ...run.blockerCommentId ? { replyToId: run.blockerCommentId } : {}
14541
14153
  });
14542
14154
  } catch (err) {
14543
- log37.warn(TAG33, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14155
+ log36.warn(TAG32, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14544
14156
  }
14545
14157
  try {
14546
14158
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14554,14 +14166,14 @@ class Pool {
14554
14166
  });
14555
14167
  }
14556
14168
  } catch (err) {
14557
- log37.error(TAG33, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14169
+ log36.error(TAG32, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14558
14170
  }
14559
14171
  try {
14560
14172
  await this.stateStore.endRun(run.runId, "failed", {
14561
14173
  errorMessage: "budget decision expired"
14562
14174
  });
14563
14175
  } catch (err) {
14564
- log37.warn(TAG33, `Failed to release the expired park for ${run.cardId}: ${err}`);
14176
+ log36.warn(TAG32, `Failed to release the expired park for ${run.cardId}: ${err}`);
14565
14177
  }
14566
14178
  }
14567
14179
  async releaseExpiredAttemptCap(cardId, blockerCommentId) {
@@ -14571,7 +14183,7 @@ class Pool {
14571
14183
  ...blockerCommentId ? { replyToId: blockerCommentId } : {}
14572
14184
  });
14573
14185
  } catch (err) {
14574
- log37.warn(TAG33, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14186
+ log36.warn(TAG32, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14575
14187
  }
14576
14188
  try {
14577
14189
  await this.client.endAgentSession(cardId, {
@@ -14580,7 +14192,7 @@ class Pool {
14580
14192
  failureSummary: "The attempt-budget decision expired with no answer. Reassign the card to grant a fresh attempt."
14581
14193
  });
14582
14194
  } catch (err) {
14583
- log37.warn(TAG33, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14195
+ log36.warn(TAG32, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14584
14196
  }
14585
14197
  await this.stateStore.clearAwaitingDecision(cardId);
14586
14198
  }
@@ -14591,16 +14203,16 @@ class Pool {
14591
14203
  }
14592
14204
  const account = this.accountGuard?.check();
14593
14205
  if (account && !account.running) {
14594
- log37.debug(TAG33, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14206
+ log36.debug(TAG32, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14595
14207
  return;
14596
14208
  }
14597
14209
  const first = !this.adoptAnnounced.has(run.runId);
14598
14210
  this.adoptAnnounced.add(run.runId);
14599
14211
  const line = `#${run.cardShortId}: granted continue never reached a worker — re-enqueueing (${run.pipeline})`;
14600
14212
  if (first)
14601
- log37.warn(TAG33, line);
14213
+ log36.warn(TAG32, line);
14602
14214
  else
14603
- log37.debug(TAG33, line);
14215
+ log36.debug(TAG32, line);
14604
14216
  await this.enqueueCard(run.cardId, run.pipeline);
14605
14217
  }
14606
14218
  adoptAnnounced = new Set;
@@ -14619,7 +14231,7 @@ class Pool {
14619
14231
  async continueRun(run, opts) {
14620
14232
  const turns = this.budget.checkCardTurns(run.cardId);
14621
14233
  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.`);
14234
+ 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
14235
  try {
14624
14236
  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
14237
 
@@ -14628,14 +14240,14 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14628
14240
  agentSessionId: run.sessionId ?? undefined
14629
14241
  });
14630
14242
  } catch (err) {
14631
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14243
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14632
14244
  }
14633
14245
  await this.stopRun(run, "Continue refused: the card is at its per-card turn cap.");
14634
14246
  return;
14635
14247
  }
14636
14248
  const runsSpent = this.budget.checkCardRuns(run.cardId);
14637
14249
  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.`);
14250
+ 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
14251
  try {
14640
14252
  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
14253
 
@@ -14644,7 +14256,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14644
14256
  agentSessionId: run.sessionId ?? undefined
14645
14257
  });
14646
14258
  } catch (err) {
14647
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14259
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14648
14260
  }
14649
14261
  await this.stopRun(run, "Continue refused: the card is at its per-card run backstop.");
14650
14262
  return;
@@ -14668,7 +14280,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14668
14280
  awaitingDecisionUntil: null
14669
14281
  });
14670
14282
  } catch (err) {
14671
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14283
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14672
14284
  }
14673
14285
  if (run.blockerCommentId) {
14674
14286
  try {
@@ -14676,7 +14288,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14676
14288
  resolve: true
14677
14289
  });
14678
14290
  } catch (err) {
14679
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14291
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14680
14292
  }
14681
14293
  }
14682
14294
  await this.enqueueCard(run.cardId, run.pipeline);
@@ -14700,7 +14312,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14700
14312
  awaitingDecisionUntil: null
14701
14313
  });
14702
14314
  } catch (err) {
14703
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14315
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14704
14316
  }
14705
14317
  if (run.blockerCommentId) {
14706
14318
  try {
@@ -14708,13 +14320,13 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14708
14320
  resolve: true
14709
14321
  });
14710
14322
  } catch (err) {
14711
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14323
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14712
14324
  }
14713
14325
  }
14714
14326
  await this.enqueueCard(run.cardId, run.pipeline);
14715
14327
  released += 1;
14716
14328
  } catch (err) {
14717
- log37.error(TAG33, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14329
+ log36.error(TAG32, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14718
14330
  }
14719
14331
  }
14720
14332
  return released;
@@ -14726,7 +14338,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14726
14338
  resolve: true
14727
14339
  });
14728
14340
  } catch (err) {
14729
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14341
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14730
14342
  }
14731
14343
  }
14732
14344
  try {
@@ -14735,7 +14347,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14735
14347
  awaitingDecisionUntil: null
14736
14348
  });
14737
14349
  } catch (err) {
14738
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14350
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14739
14351
  }
14740
14352
  try {
14741
14353
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14757,26 +14369,26 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14757
14369
  await this.client.endAgentSession(run.cardId, endSession);
14758
14370
  }
14759
14371
  } catch (err) {
14760
- log37.error(TAG33, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14372
+ log36.error(TAG32, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14761
14373
  }
14762
14374
  try {
14763
14375
  await this.stateStore.endRun(run.runId, "failed", {
14764
14376
  errorMessage: "budget_decision_stop"
14765
14377
  });
14766
14378
  } catch (err) {
14767
- log37.warn(TAG33, `Failed to end the local run record for ${run.cardId}: ${err}`);
14379
+ log36.warn(TAG32, `Failed to end the local run record for ${run.cardId}: ${err}`);
14768
14380
  }
14769
14381
  }
14770
14382
  async grantAttempt(cardId) {
14771
14383
  const turns = this.budget.checkCardTurns(cardId);
14772
14384
  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.`);
14385
+ 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
14386
  try {
14775
14387
  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
14388
 
14777
14389
  Reassign the card — that clears the turn count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14778
14390
  } catch (err) {
14779
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14391
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14780
14392
  }
14781
14393
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14782
14394
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card turn cap.");
@@ -14784,13 +14396,13 @@ Reassign the card — that clears the turn count and starts it fresh — or rais
14784
14396
  }
14785
14397
  const runsSpent = this.budget.checkCardRuns(cardId);
14786
14398
  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.`);
14399
+ 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
14400
  try {
14789
14401
  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
14402
 
14791
14403
  Reassign the card — that clears the run count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14792
14404
  } catch (err) {
14793
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14405
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14794
14406
  }
14795
14407
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14796
14408
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card run backstop.");
@@ -14805,7 +14417,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14805
14417
  awaitingDecisionUntil: null
14806
14418
  });
14807
14419
  } catch (err) {
14808
- log37.warn(TAG33, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14420
+ log36.warn(TAG32, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14809
14421
  }
14810
14422
  await this.enqueueCard(cardId, "implement");
14811
14423
  }
@@ -14816,7 +14428,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14816
14428
  try {
14817
14429
  await this.client.updateComment(blockerCommentId, { resolve: true });
14818
14430
  } catch (err) {
14819
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14431
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14820
14432
  }
14821
14433
  }
14822
14434
  try {
@@ -14825,7 +14437,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14825
14437
  awaitingDecisionUntil: null
14826
14438
  });
14827
14439
  } catch (err) {
14828
- log37.warn(TAG33, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14440
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14829
14441
  }
14830
14442
  try {
14831
14443
  await this.client.endAgentSession(cardId, {
@@ -14834,7 +14446,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14834
14446
  failureSummary
14835
14447
  });
14836
14448
  } catch (err) {
14837
- log37.warn(TAG33, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14449
+ log36.warn(TAG32, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14838
14450
  }
14839
14451
  await this.stateStore.clearAwaitingDecision(cardId);
14840
14452
  }
@@ -14865,12 +14477,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14865
14477
  const subtasks = card.subtasks ?? [];
14866
14478
  await this.enqueue(card, column, cardLabels, subtasks, mode);
14867
14479
  } catch (err) {
14868
- log37.error(TAG33, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14480
+ log36.error(TAG32, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14869
14481
  }
14870
14482
  }
14871
14483
  async retireUnroutableRuns(shortId, cardId, reason = "column not found on this board") {
14872
14484
  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`);
14485
+ log36.warn(TAG32, `#${shortId}: ${reason} — retiring ${unended.length} run record(s) instead of re-enqueueing`);
14874
14486
  for (const run of unended) {
14875
14487
  await this.stateStore.endRun(run.runId, "orphaned", {
14876
14488
  errorMessage: `${reason} at re-enqueue — retired as unroutable (#1057/#1102)`
@@ -14883,12 +14495,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14883
14495
  if (this.shuttingDown)
14884
14496
  return false;
14885
14497
  if (this.accountGuard && !this.accountGuard.check().running) {
14886
- log37.debug(TAG33, `${label} dispatch held — the account is halted`);
14498
+ log36.debug(TAG32, `${label} dispatch held — the account is halted`);
14887
14499
  return false;
14888
14500
  }
14889
14501
  const idle = workers.find((w) => w.isIdle);
14890
14502
  if (!idle) {
14891
- log37.debug(TAG33, `No idle ${label} workers (queue: ${queue.length})`);
14503
+ log36.debug(TAG32, `No idle ${label} workers (queue: ${queue.length})`);
14892
14504
  return false;
14893
14505
  }
14894
14506
  const next = queue.dequeue();
@@ -14896,18 +14508,18 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14896
14508
  return false;
14897
14509
  const data = this.cardDataCache.get(next.cardId);
14898
14510
  if (!data) {
14899
- log37.warn(TAG33, `No cached data for card ${next.cardId}, skipping`);
14511
+ log36.warn(TAG32, `No cached data for card ${next.cardId}, skipping`);
14900
14512
  return false;
14901
14513
  }
14902
14514
  this.cardDataCache.delete(next.cardId);
14903
14515
  this.lastWaitingEmit.delete(next.cardId);
14904
- log37.info(TAG33, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14516
+ log36.info(TAG32, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14905
14517
  this.sleepGuard.acquire();
14906
14518
  idle.run(data.card, data.column, data.labels, data.subtasks);
14907
14519
  return true;
14908
14520
  }
14909
14521
  }
14910
- var TAG33 = "pool";
14522
+ var TAG32 = "pool";
14911
14523
  var init_pool = __esm(() => {
14912
14524
  init_dist();
14913
14525
  init_board_helpers();
@@ -14941,7 +14553,7 @@ import {
14941
14553
  writeFileSync as writeFileSync4
14942
14554
  } from "node:fs";
14943
14555
  import { dirname as dirname5 } from "node:path";
14944
- import { log as log38 } from "@gethmy/harness";
14556
+ import { log as log37 } from "@gethmy/harness";
14945
14557
  function defaultRegistryPath() {
14946
14558
  return portRegistryPath();
14947
14559
  }
@@ -14956,7 +14568,7 @@ function load(path) {
14956
14568
  }
14957
14569
  return emptyRegistry();
14958
14570
  } catch (err) {
14959
- log38.warn(TAG34, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14571
+ log37.warn(TAG33, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14960
14572
  return emptyRegistry();
14961
14573
  }
14962
14574
  }
@@ -14977,7 +14589,7 @@ function recordDaemonPort(projectId, entry, path = defaultRegistryPath()) {
14977
14589
  registry[projectId] = { ...entry, updatedAt: Date.now() };
14978
14590
  save(path, registry);
14979
14591
  } catch (err) {
14980
- log38.warn(TAG34, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14592
+ log37.warn(TAG33, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14981
14593
  }
14982
14594
  }
14983
14595
  function daemonBaseUrl(bindAddr, port) {
@@ -14997,17 +14609,17 @@ function clearDaemonPort(projectId, pid, path = defaultRegistryPath()) {
14997
14609
  delete registry[projectId];
14998
14610
  save(path, registry);
14999
14611
  } catch (err) {
15000
- log38.warn(TAG34, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14612
+ log37.warn(TAG33, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
15001
14613
  }
15002
14614
  }
15003
- var TAG34 = "port-registry";
14615
+ var TAG33 = "port-registry";
15004
14616
  var init_port_registry = __esm(() => {
15005
14617
  init_dist();
15006
14618
  init_paths();
15007
14619
  });
15008
14620
 
15009
14621
  // src/recovery.ts
15010
- import { log as log39, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
14622
+ import { log as log38, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
15011
14623
  function isProcessAlive(pid, currentPid) {
15012
14624
  if (pid === currentPid)
15013
14625
  return true;
@@ -15023,7 +14635,7 @@ async function fetchCardSafely(client, cardId) {
15023
14635
  const { card } = await client.getCard(cardId);
15024
14636
  return card;
15025
14637
  } catch (err) {
15026
- log39.warn(TAG35, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
14638
+ log38.warn(TAG34, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
15027
14639
  return null;
15028
14640
  }
15029
14641
  }
@@ -15033,7 +14645,7 @@ async function recoverOrphans(store, client, config, opts = {}) {
15033
14645
  return [];
15034
14646
  }
15035
14647
  const outcomes = [];
15036
- log39.info(TAG35, `recovering ${active.length} orphan run(s) from prior daemon`);
14648
+ log38.info(TAG34, `recovering ${active.length} orphan run(s) from prior daemon`);
15037
14649
  for (const run of active) {
15038
14650
  const outcome = {
15039
14651
  runId: run.runId,
@@ -15045,16 +14657,16 @@ async function recoverOrphans(store, client, config, opts = {}) {
15045
14657
  };
15046
14658
  outcomes.push(outcome);
15047
14659
  if (isBudgetHeldRun(run)) {
15048
- log39.info(TAG35, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
14660
+ log38.info(TAG34, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15049
14661
  outcome.actions.push("skipped: held for a human budget decision");
15050
14662
  continue;
15051
14663
  }
15052
14664
  if (isProcessAlive(run.daemonPid, process.pid)) {
15053
- log39.warn(TAG35, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
14665
+ log38.warn(TAG34, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
15054
14666
  outcome.actions.push("skipped: daemon pid still alive");
15055
14667
  continue;
15056
14668
  }
15057
- log39.info(TAG35, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
14669
+ log38.info(TAG34, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
15058
14670
  await recoverRun(run, store, client, config, outcome, {
15059
14671
  rollbackAttempt: true,
15060
14672
  agentId: opts.agentId
@@ -15075,7 +14687,7 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15075
14687
  } catch (err) {
15076
14688
  const msg = err instanceof Error ? err.message : String(err);
15077
14689
  outcome.errors.push(`endAgentSession: ${msg}`);
15078
- log39.warn(TAG35, `endAgentSession failed for ${run.cardId}: ${msg}`);
14690
+ log38.warn(TAG34, `endAgentSession failed for ${run.cardId}: ${msg}`);
15079
14691
  }
15080
14692
  const card = await fetchCardSafely(client, run.cardId);
15081
14693
  if (card) {
@@ -15135,9 +14747,9 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15135
14747
  outcome.errors.push(`decrementAttempt: ${msg}`);
15136
14748
  }
15137
14749
  }
15138
- log39.info(TAG35, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
14750
+ log38.info(TAG34, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
15139
14751
  }
15140
- var TAG35 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
14752
+ var TAG34 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
15141
14753
  var init_recovery = __esm(() => {
15142
14754
  init_board_helpers();
15143
14755
  init_handback();
@@ -15159,18 +14771,18 @@ var init_repo_dirs = __esm(() => {
15159
14771
  });
15160
14772
 
15161
14773
  // src/claim.ts
15162
- import { log as log40 } from "@gethmy/harness";
14774
+ import { log as log39 } from "@gethmy/harness";
15163
14775
  async function claimUnassignedCard(client, cardId, agentId, opts) {
15164
14776
  try {
15165
14777
  const { claimed } = opts ? await client.claimCard(cardId, agentId, opts) : await client.claimCard(cardId, agentId);
15166
- log40.debug(TAG36, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
14778
+ log39.debug(TAG35, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
15167
14779
  return claimed;
15168
14780
  } catch (err) {
15169
- log40.error(TAG36, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
14781
+ log39.error(TAG35, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
15170
14782
  return false;
15171
14783
  }
15172
14784
  }
15173
- var TAG36 = "claim";
14785
+ var TAG35 = "claim";
15174
14786
  var init_claim = () => {};
15175
14787
 
15176
14788
  // src/strand-recovery.ts
@@ -15178,7 +14790,7 @@ var exports_strand_recovery = {};
15178
14790
  __export(exports_strand_recovery, {
15179
14791
  reclaimPreReviewStrands: () => reclaimPreReviewStrands
15180
14792
  });
15181
- import { log as log41, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
14793
+ import { log as log40, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
15182
14794
  async function reclaimPreReviewStrands(opts) {
15183
14795
  const {
15184
14796
  client,
@@ -15222,22 +14834,22 @@ async function reclaimPreReviewStrands(opts) {
15222
14834
  continue;
15223
14835
  const won = await claimUnassignedCard(client, card.id, agentId);
15224
14836
  if (!won) {
15225
- log41.debug(TAG37, `#${card.short_id} — lost the review claim race, skipping`);
14837
+ log40.debug(TAG36, `#${card.short_id} — lost the review claim race, skipping`);
15226
14838
  continue;
15227
14839
  }
15228
- log41.warn(TAG37, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
14840
+ log40.warn(TAG36, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
15229
14841
  reclaimed.push(card.id);
15230
14842
  if (opts.onClaimed) {
15231
14843
  try {
15232
14844
  await opts.onClaimed(card);
15233
14845
  } catch (err) {
15234
- log41.error(TAG37, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
14846
+ log40.error(TAG36, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
15235
14847
  }
15236
14848
  }
15237
14849
  }
15238
14850
  return reclaimed;
15239
14851
  }
15240
- var TAG37 = "strand-recovery";
14852
+ var TAG36 = "strand-recovery";
15241
14853
  var init_strand_recovery = __esm(() => {
15242
14854
  init_board_helpers();
15243
14855
  init_claim();
@@ -15403,7 +15015,7 @@ var init_scope = __esm(() => {
15403
15015
  });
15404
15016
 
15405
15017
  // src/sweep.ts
15406
- import { log as log42 } from "@gethmy/harness";
15018
+ import { log as log41 } from "@gethmy/harness";
15407
15019
  function rankSweepCandidates(opts) {
15408
15020
  const {
15409
15021
  agentId,
@@ -15522,10 +15134,10 @@ async function sweepForCard(opts) {
15522
15134
  let { candidates, skipped, scope } = rankSweepCandidates(opts);
15523
15135
  const cohesionCounts = opts.ranking.cohesionWeight !== 0;
15524
15136
  if (cohesionCounts) {
15525
- log42.debug(TAG38, describeActiveScope(scope.active));
15137
+ log41.debug(TAG37, describeActiveScope(scope.active));
15526
15138
  }
15527
15139
  if (candidates.length === 0) {
15528
- log42.debug(TAG38, `no claimable card (${skipped.length} skipped in a pickup column)`);
15140
+ log41.debug(TAG37, `no claimable card (${skipped.length} skipped in a pickup column)`);
15529
15141
  return { claimed: null, skipped, probed: 0 };
15530
15142
  }
15531
15143
  const probeWindow = candidates.slice(0, maxProbes);
@@ -15541,12 +15153,12 @@ async function sweepForCard(opts) {
15541
15153
  chainNeighbors: chainNeighbors(chain2)
15542
15154
  }));
15543
15155
  } else if (chainTermsCount && candidates.length > 1) {
15544
- log42.debug(TAG38, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15156
+ log41.debug(TAG37, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15545
15157
  }
15546
15158
  let probed = 0;
15547
15159
  for (const candidate of candidates) {
15548
15160
  if (probed >= maxProbes) {
15549
- log42.debug(TAG38, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15161
+ log41.debug(TAG37, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15550
15162
  break;
15551
15163
  }
15552
15164
  probed++;
@@ -15624,10 +15236,10 @@ async function sweepForCard(opts) {
15624
15236
  continue;
15625
15237
  }
15626
15238
  verified.card.assigned_agent_id = agentId;
15627
- log42.info(TAG38, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15239
+ log41.info(TAG37, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15628
15240
  return { claimed: verified, skipped, probed };
15629
15241
  }
15630
- log42.debug(TAG38, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15242
+ log41.debug(TAG37, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15631
15243
  return { claimed: null, skipped, probed };
15632
15244
  }
15633
15245
  function claimLine(claimed, rank, candidates, skipped, scope) {
@@ -15648,7 +15260,7 @@ async function refetchCard(client, cardId) {
15648
15260
  const { card } = await client.getCard(cardId);
15649
15261
  return card ?? null;
15650
15262
  } catch (err) {
15651
- log42.warn(TAG38, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15263
+ log41.warn(TAG37, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15652
15264
  return null;
15653
15265
  }
15654
15266
  }
@@ -15657,11 +15269,11 @@ async function hasLiveSession(client, cardId) {
15657
15269
  const { session } = await client.getAgentSession(cardId);
15658
15270
  return session != null;
15659
15271
  } catch (err) {
15660
- log42.warn(TAG38, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15272
+ log41.warn(TAG37, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15661
15273
  return true;
15662
15274
  }
15663
15275
  }
15664
- var TAG38 = "sweep";
15276
+ var TAG37 = "sweep";
15665
15277
  var init_sweep = __esm(() => {
15666
15278
  init_board_helpers();
15667
15279
  init_claim();
@@ -15672,7 +15284,7 @@ var init_sweep = __esm(() => {
15672
15284
  });
15673
15285
 
15674
15286
  // src/sweep-commands.ts
15675
- import { log as log43 } from "@gethmy/harness";
15287
+ import { log as log42 } from "@gethmy/harness";
15676
15288
  function parseSweepCommands(payload) {
15677
15289
  if (!payload || typeof payload !== "object")
15678
15290
  return [];
@@ -15699,14 +15311,14 @@ function parseSweepCommands(payload) {
15699
15311
  async function claimSweepCommands(client, agentId, projectId, daemonId) {
15700
15312
  const request = client.request?.bind(client);
15701
15313
  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");
15314
+ 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
15315
  return [];
15704
15316
  }
15705
15317
  try {
15706
15318
  const res = await request("POST", `/agents/${encodeURIComponent(agentId)}/sweep-commands/claim`, { projectId, daemonId });
15707
15319
  return parseSweepCommands(res);
15708
15320
  } catch (err) {
15709
- log43.warn(TAG39, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15321
+ log42.warn(TAG38, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15710
15322
  return [];
15711
15323
  }
15712
15324
  }
@@ -15719,15 +15331,15 @@ async function applySweepCommands(commands, actions) {
15719
15331
  await actions.resume();
15720
15332
  }
15721
15333
  applied = command.verb;
15722
- log43.info(TAG39, `applied "${command.verb}" from the board (${command.id})`);
15334
+ log42.info(TAG38, `applied "${command.verb}" from the board (${command.id})`);
15723
15335
  }
15724
15336
  return applied;
15725
15337
  }
15726
- var TAG39 = "sweep-cmd";
15338
+ var TAG38 = "sweep-cmd";
15727
15339
  var init_sweep_commands = () => {};
15728
15340
 
15729
15341
  // src/sweep-guard.ts
15730
- import { log as log44 } from "@gethmy/harness";
15342
+ import { log as log43 } from "@gethmy/harness";
15731
15343
 
15732
15344
  class SweepGuard {
15733
15345
  config;
@@ -15783,7 +15395,7 @@ class SweepGuard {
15783
15395
  await this.store.haltSweep(reason);
15784
15396
  if (!already) {
15785
15397
  const claimed = this.store.getSweep().claimed;
15786
- log44.info(TAG40, `claiming stopped (${reason}) after ${claimed} claimed`);
15398
+ log43.info(TAG39, `claiming stopped (${reason}) after ${claimed} claimed`);
15787
15399
  }
15788
15400
  return this.snapshot();
15789
15401
  }
@@ -15792,7 +15404,7 @@ class SweepGuard {
15792
15404
  const was = before.haltReason ? this.describeStop(before.haltReason) : null;
15793
15405
  await this.store.resumeSweep();
15794
15406
  if (was)
15795
- log44.info(TAG40, `claiming resumed by the operator — was stopped: ${was}`);
15407
+ log43.info(TAG39, `claiming resumed by the operator — was stopped: ${was}`);
15796
15408
  return this.snapshot();
15797
15409
  }
15798
15410
  snapshot() {
@@ -15854,11 +15466,11 @@ function sweepBannerLine(config) {
15854
15466
  const authors = extra ? `you + ${extra} trusted author${extra === 1 ? "" : "s"}` : "you only";
15855
15467
  return `Sweep ON — claims ${scope} in ${config.pickupColumns.join(", ")}, ` + `authored by ${authors}; caps: ${describeCaps(sweep, config.budget.dailyBudgetCents)}; ` + `${sweep.maxProbesPerTick} probes/tick`;
15856
15468
  }
15857
- var TAG40 = "sweep";
15469
+ var TAG39 = "sweep";
15858
15470
  var init_sweep_guard = () => {};
15859
15471
 
15860
15472
  // src/reconcile.ts
15861
- import { detectGitProvider as detectGitProvider5, log as log45 } from "@gethmy/harness";
15473
+ import { detectGitProvider as detectGitProvider5, log as log44 } from "@gethmy/harness";
15862
15474
  function daemonProcessLabels(approvedLabel) {
15863
15475
  const names = ["agent", "agent-recovered", NEED_REVIEW_LABEL, approvedLabel];
15864
15476
  return new Set(names.filter(Boolean).map((n) => n.toLowerCase()));
@@ -15921,7 +15533,7 @@ class Reconciler {
15921
15533
  clearInterval(this.timer);
15922
15534
  this.timer = null;
15923
15535
  }
15924
- log45.info(TAG41, "Heartbeat stopped");
15536
+ log44.info(TAG40, "Heartbeat stopped");
15925
15537
  }
15926
15538
  async recoverStaleRuns() {
15927
15539
  if (!this.stateStore || !this.agentConfig)
@@ -15932,7 +15544,7 @@ class Reconciler {
15932
15544
  const pool = this.pool;
15933
15545
  for (const run of active) {
15934
15546
  if (isBudgetHeldRun(run)) {
15935
- log45.info(TAG41, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15547
+ log44.info(TAG40, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15936
15548
  continue;
15937
15549
  }
15938
15550
  const foreignDaemon = run.daemonPid !== process.pid;
@@ -15942,7 +15554,7 @@ class Reconciler {
15942
15554
  if (!daemonDead && !(heartbeatStale && ourZombie))
15943
15555
  continue;
15944
15556
  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`);
15557
+ log44.warn(TAG40, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
15946
15558
  await recoverRun(run, this.stateStore, this.client, this.agentConfig, {
15947
15559
  runId: run.runId,
15948
15560
  cardId: run.cardId,
@@ -15969,11 +15581,11 @@ class Reconciler {
15969
15581
  const stalledAt = Date.parse(card.updated_at ?? "");
15970
15582
  if (!Number.isFinite(stalledAt) || now - stalledAt < graceMs)
15971
15583
  continue;
15972
- log45.warn(TAG41, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15584
+ log44.warn(TAG40, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15973
15585
  try {
15974
15586
  await this.client.moveCard(card.id, pickupCol.id);
15975
15587
  } catch (err) {
15976
- log45.error(TAG41, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15588
+ log44.error(TAG40, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15977
15589
  }
15978
15590
  }
15979
15591
  }
@@ -16005,7 +15617,7 @@ class Reconciler {
16005
15617
  return;
16006
15618
  const cardLabels = resolveCardLabels(card, labelMap);
16007
15619
  const subtasks = card.subtasks ?? [];
16008
- log45.info(TAG41, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
15620
+ log44.info(TAG40, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
16009
15621
  await this.pool.enqueue(card, column, cardLabels, subtasks, "review");
16010
15622
  }
16011
15623
  });
@@ -16029,11 +15641,11 @@ class Reconciler {
16029
15641
  const parkedAt = Date.parse(card.updated_at ?? "");
16030
15642
  if (!Number.isFinite(parkedAt) || now - parkedAt < ttlMs)
16031
15643
  continue;
16032
- log45.warn(TAG41, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
15644
+ log44.warn(TAG40, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
16033
15645
  try {
16034
15646
  await this.client.moveCard(card.id, pickupCol.id);
16035
15647
  } catch (err) {
16036
- log45.error(TAG41, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15648
+ log44.error(TAG40, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
16037
15649
  }
16038
15650
  }
16039
15651
  }
@@ -16068,7 +15680,7 @@ class Reconciler {
16068
15680
  }
16069
15681
  this.lastSweepStopReported = null;
16070
15682
  if (!this.pool.hasFreeImplementSlot()) {
16071
- log45.debug(TAG41, "sweep skipped — no free implement slot");
15683
+ log44.debug(TAG40, "sweep skipped — no free implement slot");
16072
15684
  return;
16073
15685
  }
16074
15686
  const { claimed } = await sweepForCard({
@@ -16087,9 +15699,9 @@ class Reconciler {
16087
15699
  reportSweepStopped(reason, detail) {
16088
15700
  const line = `sweep stopped claiming — ${detail}`;
16089
15701
  if (this.lastSweepStopReported === reason)
16090
- log45.debug(TAG41, line);
15702
+ log44.debug(TAG40, line);
16091
15703
  else
16092
- log45.warn(TAG41, line);
15704
+ log44.warn(TAG40, line);
16093
15705
  this.lastSweepStopReported = reason;
16094
15706
  }
16095
15707
  setSweepPresenceSink(sink) {
@@ -16127,7 +15739,7 @@ class Reconciler {
16127
15739
  return;
16128
15740
  this.lastSweepNudgeAt = now;
16129
15741
  this.drainSweepCommands().catch((err) => {
16130
- log45.error(TAG41, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
15742
+ log44.error(TAG40, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
16131
15743
  });
16132
15744
  }
16133
15745
  resolveRepoDirectories() {
@@ -16136,9 +15748,9 @@ class Reconciler {
16136
15748
  const dirs = readRepoDirectories(process.cwd());
16137
15749
  this.repoDirectories = dirs;
16138
15750
  if (dirs.size === 0) {
16139
- log45.warn(TAG41, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
15751
+ log44.warn(TAG40, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
16140
15752
  } else {
16141
- log45.debug(TAG41, `Path signal allows ${dirs.size} top-level directories`);
15753
+ log44.debug(TAG40, `Path signal allows ${dirs.size} top-level directories`);
16142
15754
  }
16143
15755
  return dirs;
16144
15756
  }
@@ -16174,7 +15786,7 @@ class Reconciler {
16174
15786
  if (accountHalt !== this.lastAccountHoldReported) {
16175
15787
  if (accountHalt) {
16176
15788
  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\``);
15789
+ log44.warn(TAG40, `Account halted (${accountHalt}) — ${unqueued} assigned card(s) not queued; nothing is dispatched until \`harmony-agent resume\``);
16178
15790
  }
16179
15791
  this.lastAccountHoldReported = accountHalt;
16180
15792
  }
@@ -16190,24 +15802,24 @@ class Reconciler {
16190
15802
  const subtasks = card.subtasks ?? [];
16191
15803
  const mode = route.mode;
16192
15804
  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`);
15805
+ 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
15806
  }
16195
15807
  if (mode === "review" && this.approvedLabel && hasLabel(cardLabels, this.approvedLabel)) {
16196
- log45.debug(TAG41, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
15808
+ log44.debug(TAG40, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
16197
15809
  continue;
16198
15810
  }
16199
15811
  if (mode === "review" && hasLabel(cardLabels, NEED_REVIEW_LABEL)) {
16200
- log45.debug(TAG41, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
15812
+ log44.debug(TAG40, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
16201
15813
  continue;
16202
15814
  }
16203
15815
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
16204
- log45.debug(TAG41, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
15816
+ log44.debug(TAG40, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
16205
15817
  continue;
16206
15818
  }
16207
15819
  if (accountHalt) {
16208
- log45.debug(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
15820
+ log44.debug(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
16209
15821
  } else {
16210
- log45.info(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
15822
+ log44.info(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
16211
15823
  }
16212
15824
  await this.pool.enqueue(card, column, cardLabels, subtasks, mode);
16213
15825
  }
@@ -16218,13 +15830,13 @@ class Reconciler {
16218
15830
  try {
16219
15831
  await this.pool.drainBudgetDecisions();
16220
15832
  } catch (err) {
16221
- log45.error(TAG41, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
15833
+ log44.error(TAG40, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
16222
15834
  }
16223
15835
  await this.recoverStrandedInProgress(cards, columns, knownCardIds);
16224
15836
  await this.recoverStrandedReview(cards, columns, labelMap, knownCardIds);
16225
15837
  for (const knownId of knownCardIds) {
16226
15838
  if (!allAgentCardIds.has(knownId)) {
16227
- log45.info(TAG41, `Missed unassign: ${knownId} — removing`);
15839
+ log44.info(TAG40, `Missed unassign: ${knownId} — removing`);
16228
15840
  await this.pool.removeCard(knownId);
16229
15841
  }
16230
15842
  }
@@ -16232,20 +15844,20 @@ class Reconciler {
16232
15844
  try {
16233
15845
  await this.drainSweepCommands();
16234
15846
  } catch (err) {
16235
- log45.error(TAG41, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
15847
+ log44.error(TAG40, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
16236
15848
  }
16237
15849
  try {
16238
15850
  await this.sweepForWork(cards, columns, labelMap, pickupConfig);
16239
15851
  } catch (err) {
16240
- log45.error(TAG41, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
15852
+ log44.error(TAG40, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
16241
15853
  }
16242
- log45.debug(TAG41, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
15854
+ log44.debug(TAG40, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
16243
15855
  } catch (err) {
16244
- log45.error(TAG41, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
15856
+ log44.error(TAG40, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
16245
15857
  }
16246
15858
  }
16247
15859
  }
16248
- var TAG41 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
15860
+ var TAG40 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
16249
15861
  var init_reconcile = __esm(() => {
16250
15862
  init_board_helpers();
16251
15863
  init_recovery();
@@ -16265,7 +15877,7 @@ __export(exports_startup_banner, {
16265
15877
  createStartupBanner: () => createStartupBanner,
16266
15878
  contextSourceLine: () => contextSourceLine
16267
15879
  });
16268
- import { isPretty, log as log46 } from "@gethmy/harness";
15880
+ import { isPretty, log as log45 } from "@gethmy/harness";
16269
15881
  function createStartupBanner(config, version) {
16270
15882
  return isPretty() ? prettyBanner(config, version) : jsonBanner(config, version);
16271
15883
  }
@@ -16290,7 +15902,7 @@ function prettyBanner(config, version) {
16290
15902
  checks.push({ kind: "ok", message });
16291
15903
  },
16292
15904
  warn(message) {
16293
- log46.warn(TAG42, message);
15905
+ log45.warn(TAG41, message);
16294
15906
  checks.push({ kind: "warn", message: message.split(`
16295
15907
  `, 1)[0] });
16296
15908
  },
@@ -16315,26 +15927,26 @@ function prettyBanner(config, version) {
16315
15927
  };
16316
15928
  }
16317
15929
  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)}`);
15930
+ log45.info(TAG41, `Harmony Agent Daemon v${version} starting...`);
15931
+ log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
15932
+ log45.info(TAG41, `Config: ${contextSourceLine(config)}`);
16321
15933
  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}`);
15934
+ log45.info(TAG41, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
16323
15935
  }
16324
15936
  let failed = false;
16325
15937
  return {
16326
15938
  setProjectName(_name) {},
16327
15939
  setGitProvider(provider) {
16328
- log46.info(TAG42, `Git provider: ${provider}`);
15940
+ log45.info(TAG41, `Git provider: ${provider}`);
16329
15941
  },
16330
15942
  setHttpPort(port) {
16331
- log46.info(TAG42, `HTTP server on port ${port}`);
15943
+ log45.info(TAG41, `HTTP server on port ${port}`);
16332
15944
  },
16333
15945
  check(message) {
16334
- log46.info(TAG42, message);
15946
+ log45.info(TAG41, message);
16335
15947
  },
16336
15948
  warn(message) {
16337
- log46.warn(TAG42, message);
15949
+ log45.warn(TAG41, message);
16338
15950
  },
16339
15951
  fail() {
16340
15952
  failed = true;
@@ -16342,7 +15954,7 @@ function jsonBanner(config, version) {
16342
15954
  async ready(message) {
16343
15955
  if (failed)
16344
15956
  return;
16345
- log46.info(TAG42, message);
15957
+ log45.info(TAG41, message);
16346
15958
  }
16347
15959
  };
16348
15960
  }
@@ -16435,7 +16047,7 @@ function cyan(s) {
16435
16047
  function yellow(s) {
16436
16048
  return `${ANSI.yellow}${s}${ANSI.reset}`;
16437
16049
  }
16438
- var TAG42 = "daemon", RULE_WIDTH = 70, ANSI;
16050
+ var TAG41 = "daemon", RULE_WIDTH = 70, ANSI;
16439
16051
  var init_startup_banner = __esm(() => {
16440
16052
  init_port_registry();
16441
16053
  ANSI = {
@@ -16456,7 +16068,7 @@ import {
16456
16068
  writeFileSync as writeFileSync5
16457
16069
  } from "node:fs";
16458
16070
  import { dirname as dirname6, resolve as resolve2, sep as sep2 } from "node:path";
16459
- import { log as log47 } from "@gethmy/harness";
16071
+ import { log as log46 } from "@gethmy/harness";
16460
16072
  function migrationMarkerPath(targetPath) {
16461
16073
  return `${targetPath}.migrated`;
16462
16074
  }
@@ -16530,7 +16142,7 @@ function migrateLegacyStateFile(opts) {
16530
16142
  throw new Error("not an object");
16531
16143
  legacy = parsed;
16532
16144
  } 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})`);
16145
+ log46.warn(TAG42, `legacy state file unreadable — skipping the split this start; it retries on the next (${err instanceof Error ? err.message : err})`);
16534
16146
  return NO_MIGRATION;
16535
16147
  }
16536
16148
  const runs = Array.isArray(legacy.runs) ? legacy.runs : [];
@@ -16552,13 +16164,13 @@ function migrateLegacyStateFile(opts) {
16552
16164
  const legacyVersion = typeof legacy.version === "number" ? legacy.version : SCHEMA_VERSION;
16553
16165
  const existing = existsSync5(targetPath) ? readTargetFile(targetPath) : null;
16554
16166
  if (existsSync5(targetPath) && !existing) {
16555
- log47.warn(TAG43, "existing project state file unreadable — the split overwrites it");
16167
+ log46.warn(TAG42, "existing project state file unreadable — the split overwrites it");
16556
16168
  }
16557
16169
  let target;
16558
16170
  if (existing) {
16559
16171
  const existingVersion = typeof existing.version === "number" ? existing.version : SCHEMA_VERSION;
16560
16172
  if (existingVersion !== legacyVersion) {
16561
- log47.warn(TAG43, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16173
+ log46.warn(TAG42, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16562
16174
  return NO_MIGRATION;
16563
16175
  }
16564
16176
  const existingRuns = Array.isArray(existing.runs) ? existing.runs : [];
@@ -16604,7 +16216,7 @@ function migrateLegacyStateFile(opts) {
16604
16216
  if (!existsSync5(backupPath))
16605
16217
  copyFileSync(legacyPath, backupPath);
16606
16218
  } catch (err) {
16607
- log47.warn(TAG43, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16219
+ log46.warn(TAG42, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16608
16220
  }
16609
16221
  const remainingRuns = runs.filter((r) => !ownRunIds.has(r.runId));
16610
16222
  const remainingCards = cards.filter((c) => !ownCardIds.has(c.cardId));
@@ -16628,10 +16240,10 @@ function migrateLegacyStateFile(opts) {
16628
16240
  copiedIndeterminateCards: indeterminateCards.length,
16629
16241
  foreignUnendedRuns: remainingRuns.filter((r) => r.endedAt === null).length
16630
16242
  };
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`);
16243
+ 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
16244
  return result;
16633
16245
  }
16634
- var TAG43 = "state-migration", NO_MIGRATION;
16246
+ var TAG42 = "state-migration", NO_MIGRATION;
16635
16247
  var init_state_migration = __esm(() => {
16636
16248
  init_dist();
16637
16249
  init_state_store();
@@ -16738,7 +16350,7 @@ var init_stream_parser_selftest = __esm(() => {
16738
16350
 
16739
16351
  // src/watcher.ts
16740
16352
  import { randomUUID as randomUUID3 } from "node:crypto";
16741
- import { isPretty as isPretty2, log as log48 } from "@gethmy/harness";
16353
+ import { isPretty as isPretty2, log as log47 } from "@gethmy/harness";
16742
16354
  import { createClient } from "@supabase/supabase-js";
16743
16355
  function toPresenceColumns(names) {
16744
16356
  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 +16411,7 @@ class Watcher {
16799
16411
  const stillHeld = this.supabase?.getChannels().some((c) => c.topic === old.topic) ?? false;
16800
16412
  if (!stillHeld)
16801
16413
  return true;
16802
- log48.warn(TAG44, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16414
+ log47.warn(TAG43, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16803
16415
  return false;
16804
16416
  }
16805
16417
  constructor(credentials, projectId, identity, routing, onCardBroadcast, onAgentCommand, onSweepCommandNudge) {
@@ -16813,7 +16425,7 @@ class Watcher {
16813
16425
  }
16814
16426
  async start() {
16815
16427
  if (!isPretty2()) {
16816
- log48.info(TAG44, "Connecting to Supabase realtime (broadcast)...");
16428
+ log47.info(TAG43, "Connecting to Supabase realtime (broadcast)...");
16817
16429
  }
16818
16430
  this.supabase = createClient(this.credentials.supabaseUrl, this.credentials.supabaseAnonKey);
16819
16431
  this.subscribeBroadcast();
@@ -16851,7 +16463,7 @@ class Watcher {
16851
16463
  status = `threw (${String(err)})`;
16852
16464
  }
16853
16465
  if (status !== "ok") {
16854
- log48.debug(TAG44, `Presence sweep update returned "${status}"`);
16466
+ log47.debug(TAG43, `Presence sweep update returned "${status}"`);
16855
16467
  }
16856
16468
  })();
16857
16469
  }
@@ -16862,7 +16474,7 @@ class Watcher {
16862
16474
  const presenceChannel = this.supabase.channel(`board-presence-${this.projectId}`);
16863
16475
  this.presenceChannel = presenceChannel;
16864
16476
  presenceChannel.on("presence", { event: "sync" }, () => {
16865
- log48.debug(TAG44, "Presence sync");
16477
+ log47.debug(TAG43, "Presence sync");
16866
16478
  }).subscribe(async (status) => {
16867
16479
  if (gen !== this.presenceGen)
16868
16480
  return;
@@ -16878,13 +16490,13 @@ class Watcher {
16878
16490
  if (trackStatus !== "ok") {
16879
16491
  this.presenceTracked = false;
16880
16492
  if (!this.stopping) {
16881
- log48.warn(TAG44, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16493
+ log47.warn(TAG43, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16882
16494
  this.schedulePresenceReconnect();
16883
16495
  }
16884
16496
  return;
16885
16497
  }
16886
16498
  if (!isPretty2() || !this.suppressStartupLogs) {
16887
- log48.info(TAG44, "Presence tracked on board-presence channel");
16499
+ log47.info(TAG43, "Presence tracked on board-presence channel");
16888
16500
  }
16889
16501
  this.presenceTracked = true;
16890
16502
  this.presenceReconnectAttempts = 0;
@@ -16892,7 +16504,7 @@ class Watcher {
16892
16504
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16893
16505
  this.presenceTracked = false;
16894
16506
  if (!this.stopping) {
16895
- log48.warn(TAG44, `Presence subscription ${status} — scheduling reconnect`);
16507
+ log47.warn(TAG43, `Presence subscription ${status} — scheduling reconnect`);
16896
16508
  this.schedulePresenceReconnect();
16897
16509
  }
16898
16510
  }
@@ -16911,7 +16523,7 @@ class Watcher {
16911
16523
  async reconnectPresence() {
16912
16524
  if (this.stopping || !this.supabase)
16913
16525
  return;
16914
- log48.warn(TAG44, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16526
+ log47.warn(TAG43, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16915
16527
  if (this.presenceChannel) {
16916
16528
  const old = this.presenceChannel;
16917
16529
  this.presenceChannel = null;
@@ -16934,13 +16546,13 @@ class Watcher {
16934
16546
  return;
16935
16547
  const gen = ++this.broadcastGen;
16936
16548
  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)}`);
16549
+ log47.debug(TAG43, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
16938
16550
  this.onCardBroadcast({
16939
16551
  event: "card_update",
16940
16552
  payload: msg.payload ?? {}
16941
16553
  });
16942
16554
  }).on("broadcast", { event: "card_created" }, (msg) => {
16943
- log48.debug(TAG44, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16555
+ log47.debug(TAG43, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16944
16556
  this.onCardBroadcast({
16945
16557
  event: "card_created",
16946
16558
  payload: msg.payload ?? {}
@@ -16950,11 +16562,11 @@ class Watcher {
16950
16562
  const cardId = payload.card_id;
16951
16563
  const command = payload.command;
16952
16564
  if (cardId && command) {
16953
- log48.info(TAG44, `Broadcast: agent_command ${command} for ${cardId}`);
16565
+ log47.info(TAG43, `Broadcast: agent_command ${command} for ${cardId}`);
16954
16566
  this.onAgentCommand?.({ cardId, command });
16955
16567
  }
16956
16568
  }).on("broadcast", { event: "sweep_command" }, () => {
16957
- log48.debug(TAG44, "Broadcast: sweep_command — draining");
16569
+ log47.debug(TAG43, "Broadcast: sweep_command — draining");
16958
16570
  this.onSweepCommandNudge?.();
16959
16571
  }).subscribe((status) => {
16960
16572
  if (gen !== this.broadcastGen)
@@ -16963,13 +16575,13 @@ class Watcher {
16963
16575
  this.connected = true;
16964
16576
  this.reconnectAttempts = 0;
16965
16577
  if (!isPretty2() || !this.suppressStartupLogs) {
16966
- log48.info(TAG44, "Broadcast subscription active");
16578
+ log47.info(TAG43, "Broadcast subscription active");
16967
16579
  }
16968
16580
  this.maybeResolveReady();
16969
16581
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16970
16582
  this.connected = false;
16971
16583
  if (!this.stopping) {
16972
- log48.warn(TAG44, `Broadcast subscription ${status} — scheduling reconnect`);
16584
+ log47.warn(TAG43, `Broadcast subscription ${status} — scheduling reconnect`);
16973
16585
  this.scheduleReconnect();
16974
16586
  }
16975
16587
  }
@@ -16988,7 +16600,7 @@ class Watcher {
16988
16600
  async reconnectBroadcast() {
16989
16601
  if (this.stopping || !this.supabase)
16990
16602
  return;
16991
- log48.warn(TAG44, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16603
+ log47.warn(TAG43, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16992
16604
  if (this.channel) {
16993
16605
  const old = this.channel;
16994
16606
  this.channel = null;
@@ -17030,10 +16642,10 @@ class Watcher {
17030
16642
  }
17031
16643
  this.connected = false;
17032
16644
  this.presenceTracked = false;
17033
- log48.info(TAG44, "Broadcast subscription stopped");
16645
+ log47.info(TAG43, "Broadcast subscription stopped");
17034
16646
  }
17035
16647
  }
17036
- var TAG44 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
16648
+ var TAG43 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
17037
16649
  var init_watcher = __esm(() => {
17038
16650
  init_sweep_guard();
17039
16651
  });
@@ -17307,7 +16919,7 @@ __export(exports_run_gc, {
17307
16919
  pruneRunLogs: () => pruneRunLogs
17308
16920
  });
17309
16921
  import { unlinkSync as unlinkSync2 } from "node:fs";
17310
- import { log as log49 } from "@gethmy/harness";
16922
+ import { log as log48 } from "@gethmy/harness";
17311
16923
  function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17312
16924
  let deleted = 0;
17313
16925
  let bytesFreed = 0;
@@ -17321,7 +16933,7 @@ function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17321
16933
  deleted++;
17322
16934
  bytesFreed += file.sizeBytes;
17323
16935
  } catch (err) {
17324
- log49.debug(TAG45, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
16936
+ log48.debug(TAG44, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
17325
16937
  }
17326
16938
  }
17327
16939
  return { deleted, bytesFreed };
@@ -17344,7 +16956,7 @@ async function runRetentionGc(store, opts) {
17344
16956
  logs = pruneRunLogs(opts.runsDirectory ?? runsDir(), now - opts.runLogDays * DAY_MS2, openRunIds);
17345
16957
  }
17346
16958
  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)`);
16959
+ log48.info(TAG44, `Retention sweep: trimmed ${runRecordsPurged} run record(s), removed ${logs.deleted} run log(s) (${Math.round(logs.bytesFreed / 1024)} KB)`);
17348
16960
  }
17349
16961
  return {
17350
16962
  runRecordsPurged,
@@ -17352,7 +16964,7 @@ async function runRetentionGc(store, opts) {
17352
16964
  logBytesFreed: logs.bytesFreed
17353
16965
  };
17354
16966
  }
17355
- var TAG45 = "gc", DAY_MS2 = 86400000;
16967
+ var TAG44 = "gc", DAY_MS2 = 86400000;
17356
16968
  var init_run_gc = __esm(() => {
17357
16969
  init_paths();
17358
16970
  init_run_stats();
@@ -17369,7 +16981,7 @@ __export(exports_worktree_gc, {
17369
16981
  import { execFileSync as execFileSync8 } from "node:child_process";
17370
16982
  import { existsSync as existsSync6, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
17371
16983
  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";
16984
+ import { cleanupWorktree as cleanupWorktree5, GIT_NO_HOOKS as GIT_NO_HOOKS9, log as log49 } from "@gethmy/harness";
17373
16985
  function isTransientGitNetworkError(message) {
17374
16986
  return TRANSIENT_GIT_NETWORK_ERROR.test(message);
17375
16987
  }
@@ -17482,10 +17094,10 @@ function runWorktreeGc(basePath, store, opts = {}) {
17482
17094
  });
17483
17095
  } catch {}
17484
17096
  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(", ")}`);
17097
+ log49.info(TAG45, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
17486
17098
  }
17487
17099
  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("; ")}`);
17100
+ log49.warn(TAG45, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
17489
17101
  }
17490
17102
  return result;
17491
17103
  }
@@ -17515,7 +17127,7 @@ function pruneFailedRemoteBranches(opts) {
17515
17127
  } catch (err) {
17516
17128
  const detail = gitErrorDetail2(err);
17517
17129
  if (isTransientGitNetworkError(detail)) {
17518
- log50.debug(TAG46, `Remote branch GC skipped — remote unreachable: ${detail}`);
17130
+ log49.debug(TAG45, `Remote branch GC skipped — remote unreachable: ${detail}`);
17519
17131
  return result;
17520
17132
  }
17521
17133
  result.errors.push({ ref: "fetch", error: detail });
@@ -17555,7 +17167,7 @@ function pruneFailedRemoteBranches(opts) {
17555
17167
  continue;
17556
17168
  }
17557
17169
  if (clock() > sweepDeadline) {
17558
- log50.debug(TAG46, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17170
+ log49.debug(TAG45, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17559
17171
  break;
17560
17172
  }
17561
17173
  try {
@@ -17568,17 +17180,17 @@ function pruneFailedRemoteBranches(opts) {
17568
17180
  } catch (err) {
17569
17181
  const detail = gitErrorDetail2(err);
17570
17182
  if (isTransientGitNetworkError(detail)) {
17571
- log50.debug(TAG46, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17183
+ log49.debug(TAG45, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17572
17184
  break;
17573
17185
  }
17574
17186
  result.errors.push({ ref, error: detail });
17575
17187
  }
17576
17188
  }
17577
17189
  if (result.removed.length > 0) {
17578
- log50.info(TAG46, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17190
+ log49.info(TAG45, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17579
17191
  }
17580
17192
  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("; ")}`);
17193
+ log49.warn(TAG45, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
17582
17194
  }
17583
17195
  return result;
17584
17196
  }
@@ -17611,18 +17223,18 @@ class WorktreeGc {
17611
17223
  try {
17612
17224
  runWorktreeGc(this.basePath, this.store);
17613
17225
  } catch (err) {
17614
- log50.warn(TAG46, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17226
+ log49.warn(TAG45, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17615
17227
  }
17616
17228
  if (this.remoteOpts) {
17617
17229
  try {
17618
17230
  pruneFailedRemoteBranches(this.remoteOpts);
17619
17231
  } catch (err) {
17620
- log50.warn(TAG46, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17232
+ log49.warn(TAG45, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17621
17233
  }
17622
17234
  }
17623
17235
  if (this.retentionOpts) {
17624
17236
  runRetentionGc(this.store, this.retentionOpts).catch((err) => {
17625
- log50.warn(TAG46, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17237
+ log49.warn(TAG45, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17626
17238
  });
17627
17239
  }
17628
17240
  }
@@ -17636,7 +17248,7 @@ function getRepoRoot2() {
17636
17248
  return null;
17637
17249
  }
17638
17250
  }
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;
17251
+ 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
17252
  var init_worktree_gc = __esm(() => {
17641
17253
  init_run_gc();
17642
17254
  GIT_NETWORK_EXEC = {
@@ -17677,7 +17289,7 @@ import { resolve as resolve4 } from "node:path";
17677
17289
  import {
17678
17290
  detectGitProvider as detectGitProvider6,
17679
17291
  GIT_NO_HOOKS as GIT_NO_HOOKS10,
17680
- log as log51,
17292
+ log as log50,
17681
17293
  validateGitProviderCli
17682
17294
  } from "@gethmy/harness";
17683
17295
  async function validatePrerequisites(config, banner) {
@@ -17754,7 +17366,7 @@ async function main() {
17754
17366
  } catch (err) {
17755
17367
  if (err instanceof ConfigValidationError) {
17756
17368
  banner.fail();
17757
- log51.error(TAG47, err.message);
17369
+ log50.error(TAG46, err.message);
17758
17370
  process.exit(1);
17759
17371
  }
17760
17372
  throw err;
@@ -17772,7 +17384,7 @@ async function main() {
17772
17384
  } catch (err) {
17773
17385
  if (err instanceof ConfigValidationError) {
17774
17386
  banner.fail();
17775
- log51.error(TAG47, err.message);
17387
+ log50.error(TAG46, err.message);
17776
17388
  process.exit(1);
17777
17389
  }
17778
17390
  throw err;
@@ -17796,7 +17408,7 @@ async function main() {
17796
17408
  try {
17797
17409
  await client.reportAgentConfig(config.workspaceId, agentId, effectiveModelReport(config.agent));
17798
17410
  } catch (err) {
17799
- log51.warn(TAG47, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17411
+ log50.warn(TAG46, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17800
17412
  }
17801
17413
  migrateConfigDir();
17802
17414
  try {
@@ -17806,7 +17418,7 @@ async function main() {
17806
17418
  worktreePrefix: resolve4(config.repoRoot, config.agent.worktree.basePath)
17807
17419
  });
17808
17420
  } catch (err) {
17809
- log51.error(TAG47, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17421
+ log50.error(TAG46, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17810
17422
  }
17811
17423
  const stateStore = StateStore.open({ projectId: config.projectId });
17812
17424
  const daemonId = randomUUID4();
@@ -17957,7 +17569,7 @@ async function main() {
17957
17569
  if (shuttingDown)
17958
17570
  return;
17959
17571
  shuttingDown = true;
17960
- log51.info(TAG47, `Received ${signal}, shutting down gracefully...`);
17572
+ log50.info(TAG46, `Received ${signal}, shutting down gracefully...`);
17961
17573
  reconciler.stop();
17962
17574
  mergeMonitor?.stop();
17963
17575
  worktreeGc.stop();
@@ -17968,19 +17580,19 @@ async function main() {
17968
17580
  }
17969
17581
  await watcher.stop();
17970
17582
  await pool.shutdown();
17971
- log51.info(TAG47, "Daemon stopped.");
17583
+ log50.info(TAG46, "Daemon stopped.");
17972
17584
  process.exit(exitCode);
17973
17585
  };
17974
17586
  process.on("SIGINT", () => shutdown("SIGINT"));
17975
17587
  process.on("SIGTERM", () => shutdown("SIGTERM"));
17976
17588
  process.on("SIGHUP", () => shutdown("SIGHUP"));
17977
17589
  process.on("uncaughtException", (err) => {
17978
- log51.error(TAG47, `Uncaught exception: ${err.message}`);
17590
+ log50.error(TAG46, `Uncaught exception: ${err.message}`);
17979
17591
  exitCode = 1;
17980
17592
  shutdown("uncaughtException");
17981
17593
  });
17982
17594
  process.on("unhandledRejection", (reason) => {
17983
- log51.error(TAG47, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17595
+ log50.error(TAG46, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17984
17596
  exitCode = 1;
17985
17597
  shutdown("unhandledRejection");
17986
17598
  });
@@ -18040,33 +17652,33 @@ async function handleBroadcast(event, client, pool, config, agentId) {
18040
17652
  if (assignedAgentId === undefined)
18041
17653
  return;
18042
17654
  if (assignedAgentId === agentId) {
18043
- log51.info(TAG47, `Broadcast: card ${cardId} assigned to agent`);
17655
+ log50.info(TAG46, `Broadcast: card ${cardId} assigned to agent`);
18044
17656
  try {
18045
17657
  await pool.resetAttemptsForReassign(cardId);
18046
17658
  await tryEnqueueCard(cardId, client, pool, config, agentId);
18047
17659
  } catch (err) {
18048
- log51.error(TAG47, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
17660
+ log50.error(TAG46, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
18049
17661
  }
18050
17662
  } else if (pool.isCardKnown(cardId)) {
18051
- log51.info(TAG47, `Broadcast: card ${cardId} unassigned from agent`);
17663
+ log50.info(TAG46, `Broadcast: card ${cardId} unassigned from agent`);
18052
17664
  await pool.removeCard(cardId);
18053
17665
  }
18054
17666
  }
18055
17667
  async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18056
17668
  const { card } = await client.getCard(cardId);
18057
17669
  if (card.assigned_agent_id !== agentId) {
18058
- log51.debug(TAG47, `Card ${cardId} no longer assigned to agent — skipping`);
17670
+ log50.debug(TAG46, `Card ${cardId} no longer assigned to agent — skipping`);
18059
17671
  return;
18060
17672
  }
18061
17673
  if (card.done || card.archived_at) {
18062
- log51.debug(TAG47, `Card ${cardId} is finished — skipping`);
17674
+ log50.debug(TAG46, `Card ${cardId} is finished — skipping`);
18063
17675
  return;
18064
17676
  }
18065
17677
  const board = await client.getBoard(config.projectId, { summary: true });
18066
17678
  const columns = board.columns;
18067
17679
  const column = columns.find((c) => c.id === card.column_id);
18068
17680
  if (!column) {
18069
- log51.warn(TAG47, `Column not found for card ${cardId}`);
17681
+ log50.warn(TAG46, `Column not found for card ${cardId}`);
18070
17682
  return;
18071
17683
  }
18072
17684
  const route = classifyPickup(card, column.name, {
@@ -18075,31 +17687,31 @@ async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18075
17687
  playbooks: config.agent.playbooks
18076
17688
  });
18077
17689
  if (!route) {
18078
- log51.info(TAG47, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
17690
+ log50.info(TAG46, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
18079
17691
  return;
18080
17692
  }
18081
17693
  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`);
17694
+ 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
17695
  }
18084
17696
  const mode = route.mode;
18085
17697
  const labelMap = buildLabelMap(board.labels ?? []);
18086
17698
  const cardLabels = resolveCardLabels(card, labelMap);
18087
17699
  const subtasks = card.subtasks ?? [];
18088
17700
  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`);
17701
+ log50.debug(TAG46, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
18090
17702
  return;
18091
17703
  }
18092
17704
  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`);
17705
+ log50.debug(TAG46, `Card #${card.short_id} has "${NEED_REVIEW_LABEL}" label (needs human) — skipping review`);
18094
17706
  return;
18095
17707
  }
18096
17708
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
18097
- log51.info(TAG47, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
17709
+ log50.info(TAG46, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
18098
17710
  return;
18099
17711
  }
18100
17712
  await pool.enqueue(card, column, cardLabels, subtasks, mode);
18101
17713
  }
18102
- var TAG47 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
17714
+ var TAG46 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
18103
17715
  var init_src = __esm(() => {
18104
17716
  init_account_guard();
18105
17717
  init_account_probe();