@gethmy/agent 1.41.0 → 1.42.0

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