@gethmy/agent 1.41.0 → 1.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +676 -997
  2. package/dist/index.js +578 -966
  3. package/package.json +3 -3
package/dist/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
  }
@@ -9038,6 +8612,14 @@ class StateStore {
9038
8612
  getCard(cardId) {
9039
8613
  return this.state.cards.find((c) => c.cardId === cardId) ?? null;
9040
8614
  }
8615
+ async forgetCard(cardId) {
8616
+ const before = this.state.cards.length;
8617
+ this.state.cards = this.state.cards.filter((c) => c.cardId !== cardId);
8618
+ if (this.state.cards.length === before)
8619
+ return false;
8620
+ await this.persist();
8621
+ return true;
8622
+ }
9041
8623
  async incrementAttempt(cardId) {
9042
8624
  const rec = this.ensureCard(cardId);
9043
8625
  rec.attempts += 1;
@@ -9274,7 +8856,7 @@ class StateStore {
9274
8856
  return this.state.daily.find((d) => d.date === key)?.costCents ?? 0;
9275
8857
  }
9276
8858
  }
9277
- var TAG23 = "state-store", SCHEMA_VERSION = 1;
8859
+ var TAG22 = "state-store", SCHEMA_VERSION = 1;
9278
8860
  var init_state_store = __esm(() => {
9279
8861
  init_dist();
9280
8862
  init_paths();
@@ -9282,7 +8864,7 @@ var init_state_store = __esm(() => {
9282
8864
 
9283
8865
  // src/stream-parser.ts
9284
8866
  import { EventEmitter } from "node:events";
9285
- import { log as log27 } from "@gethmy/harness";
8867
+ import { log as log26 } from "@gethmy/harness";
9286
8868
  function normalizeToolResultContent(raw) {
9287
8869
  if (raw == null)
9288
8870
  return;
@@ -9303,7 +8885,7 @@ function normalizeToolResultContent(raw) {
9303
8885
  return String(raw);
9304
8886
  }
9305
8887
  }
9306
- var TAG24 = "stream-parser", StreamParser;
8888
+ var TAG23 = "stream-parser", StreamParser;
9307
8889
  var init_stream_parser = __esm(() => {
9308
8890
  StreamParser = class StreamParser extends EventEmitter {
9309
8891
  buffer = "";
@@ -9350,14 +8932,14 @@ var init_stream_parser = __esm(() => {
9350
8932
  try {
9351
8933
  msg = JSON.parse(line);
9352
8934
  } catch {
9353
- log27.debug(TAG24, `Non-JSON line: ${line.slice(0, 100)}`);
8935
+ log26.debug(TAG23, `Non-JSON line: ${line.slice(0, 100)}`);
9354
8936
  return;
9355
8937
  }
9356
8938
  try {
9357
8939
  this.handleMessage(msg);
9358
8940
  } catch (err) {
9359
8941
  const errMsg = err instanceof Error ? err.message : String(err);
9360
- log27.warn(TAG24, `Error handling stream event: ${errMsg}`);
8942
+ log26.warn(TAG23, `Error handling stream event: ${errMsg}`);
9361
8943
  this.emit("parse_error", errMsg);
9362
8944
  }
9363
8945
  }
@@ -9433,7 +9015,7 @@ var init_stream_parser = __esm(() => {
9433
9015
  });
9434
9016
 
9435
9017
  // src/transitions.ts
9436
- import { log as log28 } from "@gethmy/harness";
9018
+ import { log as log27 } from "@gethmy/harness";
9437
9019
  async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9438
9020
  let lastErr;
9439
9021
  for (let i = 0;i < attempts; i++) {
@@ -9444,7 +9026,7 @@ async function withRetry(step, cardShortId, op, attempts, backoffMs) {
9444
9026
  const msg2 = err instanceof Error ? err.message : String(err);
9445
9027
  if (i < attempts - 1) {
9446
9028
  const wait = backoffMs * 2 ** i;
9447
- log28.warn(TAG25, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9029
+ log27.warn(TAG24, `${step} failed for #${cardShortId} (attempt ${i + 1}/${attempts}): ${msg2} — retrying in ${wait}ms`);
9448
9030
  await new Promise((r) => setTimeout(r, wait));
9449
9031
  }
9450
9032
  }
@@ -9468,10 +9050,10 @@ async function runTransition(client, card, plan, opts = {}) {
9468
9050
  if (opts.strictColumn) {
9469
9051
  throw new TransitionError("move", 1, msg);
9470
9052
  }
9471
- log28.warn(TAG25, `#${shortId}: ${msg} — skipping move`);
9053
+ log27.warn(TAG24, `#${shortId}: ${msg} — skipping move`);
9472
9054
  } else if (card.column_id !== target.id) {
9473
9055
  await withRetry("move", shortId, () => client.moveCard(card.id, target.id), attempts, backoffMs);
9474
- log28.info(TAG25, `#${shortId} → "${target.name}"`);
9056
+ log27.info(TAG24, `#${shortId} → "${target.name}"`);
9475
9057
  card.column_id = target.id;
9476
9058
  moveLanded = true;
9477
9059
  } else {
@@ -9490,7 +9072,7 @@ async function runTransition(client, card, plan, opts = {}) {
9490
9072
  continue;
9491
9073
  await withRetry("addLabel", shortId, () => client.addLabelToCard(card.id, labelId), attempts, backoffMs);
9492
9074
  existing.add(labelId);
9493
- log28.info(TAG25, `#${shortId} +label "${name}"`);
9075
+ log27.info(TAG24, `#${shortId} +label "${name}"`);
9494
9076
  }
9495
9077
  card.labelIds = Array.from(existing);
9496
9078
  }
@@ -9502,23 +9084,23 @@ async function runTransition(client, card, plan, opts = {}) {
9502
9084
  continue;
9503
9085
  await withRetry("removeLabel", shortId, () => client.removeLabelFromCard(card.id, match.id), attempts, backoffMs);
9504
9086
  existing.delete(match.id);
9505
- log28.info(TAG25, `#${shortId} -label "${name}"`);
9087
+ log27.info(TAG24, `#${shortId} -label "${name}"`);
9506
9088
  }
9507
9089
  card.labelIds = Array.from(existing);
9508
9090
  }
9509
9091
  if (plan.updateCard) {
9510
9092
  await withRetry("updateCard", shortId, () => client.updateCard(card.id, plan.updateCard), attempts, backoffMs);
9511
- log28.info(TAG25, `#${shortId} updated`);
9093
+ log27.info(TAG24, `#${shortId} updated`);
9512
9094
  }
9513
9095
  if (plan.endSession) {
9514
9096
  const endResult = await withRetry("endSession", shortId, () => client.endAgentSession(card.id, plan.endSession), attempts, backoffMs);
9515
9097
  result.endSession = endResult;
9516
- log28.info(TAG25, `#${shortId} session ended (${plan.endSession.status})`);
9098
+ log27.info(TAG24, `#${shortId} session ended (${plan.endSession.status})`);
9517
9099
  }
9518
9100
  if (plan.assignAgent !== undefined) {
9519
9101
  const assignedAgentId = plan.assignAgent;
9520
9102
  await withRetry("assignAgent", shortId, () => client.updateCard(card.id, { assignedAgentId }), attempts, backoffMs);
9521
- log28.info(TAG25, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9103
+ log27.info(TAG24, assignedAgentId ? `#${shortId} assigned → agent ${assignedAgentId}` : `#${shortId} unassigned`);
9522
9104
  }
9523
9105
  if (opts.store && opts.runId) {
9524
9106
  try {
@@ -9532,11 +9114,11 @@ async function ensureLabel(client, projectId, name, color, attempts, backoffMs)
9532
9114
  const result = await withRetry("addLabel", 0, () => client.createLabel(projectId, { name, color: color ?? "#8b5cf6" }), attempts, backoffMs);
9533
9115
  return result?.label?.id ?? null;
9534
9116
  } catch (err) {
9535
- log28.warn(TAG25, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9117
+ log27.warn(TAG24, `ensureLabel "${name}" failed: ${err instanceof Error ? err.message : err}`);
9536
9118
  return null;
9537
9119
  }
9538
9120
  }
9539
- var TAG25 = "transition", TransitionError;
9121
+ var TAG24 = "transition", TransitionError;
9540
9122
  var init_transitions = __esm(() => {
9541
9123
  TransitionError = class TransitionError extends Error {
9542
9124
  step;
@@ -9566,7 +9148,7 @@ import {
9566
9148
  formatDiffSummary,
9567
9149
  GIT_NO_HOOKS as GIT_NO_HOOKS7,
9568
9150
  implementRunContainmentCliArgs,
9569
- log as log29,
9151
+ log as log28,
9570
9152
  probeDevServer,
9571
9153
  removeSandboxContainer,
9572
9154
  resolveStageGate,
@@ -9662,11 +9244,11 @@ class ReviewWorker {
9662
9244
  cliSessionId: this.cliSessionId
9663
9245
  });
9664
9246
  } catch (err) {
9665
- log29.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9247
+ log28.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
9666
9248
  }
9667
9249
  }
9668
9250
  get tag() {
9669
- return `${TAG26}:${this.id}`;
9251
+ return `${TAG25}:${this.id}`;
9670
9252
  }
9671
9253
  get isIdle() {
9672
9254
  return this.state === "idle";
@@ -9704,7 +9286,7 @@ class ReviewWorker {
9704
9286
  try {
9705
9287
  const after = await this.stateStore.addTurns(cardId, numTurns);
9706
9288
  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.`);
9289
+ 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
9290
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
9709
9291
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), {
9710
9292
  commentType: "blocker",
@@ -9746,12 +9328,12 @@ class ReviewWorker {
9746
9328
  resumeMessage: null
9747
9329
  });
9748
9330
  } catch (err) {
9749
- log29.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9331
+ log28.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
9750
9332
  }
9751
9333
  }
9752
9334
  try {
9753
9335
  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}"`);
9336
+ 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
9337
  this.startHeartbeat();
9756
9338
  if (!resuming) {
9757
9339
  await this.stateStore.insertRun({
@@ -9779,7 +9361,7 @@ class ReviewWorker {
9779
9361
  const resolution = await resolveReviewBranch(card.description, repoRoot);
9780
9362
  if (resolution.kind !== "branch") {
9781
9363
  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)`);
9364
+ log28.info(this.tag, `#${card.short_id} not auto-reviewable (${why}) — marking for human review (staying in Review)`);
9783
9365
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9784
9366
  return;
9785
9367
  }
@@ -9790,13 +9372,13 @@ class ReviewWorker {
9790
9372
  reviewedSha: extractReviewedSha2(card.description ?? null)
9791
9373
  });
9792
9374
  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)`);
9375
+ log28.warn(this.tag, `#${card.short_id} refusing the PR-derived re-review (${continuity.reason}) — marking for human review (staying in Review)`);
9794
9376
  await addLabelByName(this.client, card, NEED_REVIEW_LABEL, NEED_REVIEW_LABEL_COLOR);
9795
9377
  return;
9796
9378
  }
9797
9379
  }
9798
9380
  this.branchName = resolution.branch;
9799
- log29.info(this.tag, `Review branch: ${this.branchName}`);
9381
+ log28.info(this.tag, `Review branch: ${this.branchName}`);
9800
9382
  let reviewSession;
9801
9383
  try {
9802
9384
  const startSession = () => this.client.startAgentSession(card.id, {
@@ -9812,14 +9394,14 @@ class ReviewWorker {
9812
9394
  awaitingDecisionUntil: null
9813
9395
  });
9814
9396
  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)
9397
+ info: (message) => log28.info(this.tag, message),
9398
+ warn: (message) => log28.warn(this.tag, message)
9817
9399
  });
9818
9400
  reviewSession = started.session;
9819
9401
  } catch (err) {
9820
9402
  if (isSessionConflict(err)) {
9821
9403
  this.sessionConflict = true;
9822
- log29.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9404
+ log28.info(this.tag, `Skipping review of #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
9823
9405
  return;
9824
9406
  }
9825
9407
  throw err;
@@ -9840,7 +9422,7 @@ class ReviewWorker {
9840
9422
  const cwd = this.worktreePath;
9841
9423
  const devServer = await this.startDevServer(card, cwd, port);
9842
9424
  if (devServer.skipReason) {
9843
- log29.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9425
+ log28.warn(this.tag, `Reviewing #${card.short_id} without the visual lens — ${devServer.skipReason}`);
9844
9426
  }
9845
9427
  await this.client.updateAgentProgress(card.id, {
9846
9428
  agentIdentifier: this.sessionIdentifier,
@@ -9878,10 +9460,10 @@ class ReviewWorker {
9878
9460
  pinnedContract = extractPinnedContract(comments, this.identity);
9879
9461
  }
9880
9462
  } catch (err) {
9881
- log29.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9463
+ log28.warn(this.tag, `pinned-contract fetch failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9882
9464
  }
9883
9465
  if (pinnedContract) {
9884
- log29.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9466
+ log28.info(this.tag, `Grading pinned contract for #${card.short_id} (${pinnedContract.assertions.length} criteria)`);
9885
9467
  }
9886
9468
  }
9887
9469
  const systemPrompt = buildReviewSystemPrompt();
@@ -9896,7 +9478,7 @@ class ReviewWorker {
9896
9478
  } else {
9897
9479
  const planCriteria2 = await fetchAcceptanceCriteria(this.client, this.tag, card);
9898
9480
  if (planCriteria2.length > 0) {
9899
- log29.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9481
+ log28.info(this.tag, `Grading ${planCriteria2.length} plan criteria for #${card.short_id}`);
9900
9482
  }
9901
9483
  userPrompt = buildReviewUserPrompt(enriched, this.branchName, cwd, previewUrl, diffSummary, this.config.worktree.baseBranch, undefined, pinnedContract, planCriteria2, devServer.skipReason);
9902
9484
  if (resuming && this.resumeMessage) {
@@ -9913,7 +9495,7 @@ ${userPrompt}`;
9913
9495
  contextIncluded: { source: "review-knowledge", mode: "review" }
9914
9496
  });
9915
9497
  } catch (err) {
9916
- log29.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9498
+ log28.warn(this.tag, `prompt_history persistence skipped: ${err instanceof Error ? err.message : String(err)}`);
9917
9499
  }
9918
9500
  await this.client.updateAgentProgress(card.id, {
9919
9501
  agentIdentifier: this.sessionIdentifier,
@@ -9923,7 +9505,7 @@ ${userPrompt}`;
9923
9505
  progressPercent: 20
9924
9506
  });
9925
9507
  this.timeoutTimer = setTimeout(() => {
9926
- log29.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9508
+ log28.warn(this.tag, `Review timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9927
9509
  this.timedOut = true;
9928
9510
  this.cancel("timeout");
9929
9511
  }, this.config.review.maxTimeout);
@@ -9945,10 +9527,10 @@ ${userPrompt}`;
9945
9527
  }
9946
9528
  this.state = "completing";
9947
9529
  await this.recordPhase("completing");
9948
- log29.info(this.tag, `Claude review finished for #${card.short_id}`);
9530
+ log28.info(this.tag, `Claude review finished for #${card.short_id}`);
9949
9531
  this.killDevServer();
9950
9532
  const result = parseReviewOutput(stdout);
9951
- log29.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9533
+ log28.info(this.tag, `Review verdict: ${result.verdict} (${result.findings.length} finding(s))`);
9952
9534
  await this.client.updateAgentProgress(card.id, {
9953
9535
  agentIdentifier: this.sessionIdentifier,
9954
9536
  agentName: `${AGENT_NAME} (Review)`,
@@ -9956,7 +9538,7 @@ ${userPrompt}`;
9956
9538
  currentTask: `Processing ${result.verdict} verdict`,
9957
9539
  progressPercent: 80
9958
9540
  });
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);
9541
+ 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
9542
  await this.collectReviewGate(card, result);
9961
9543
  } catch (err) {
9962
9544
  if (err instanceof BudgetPauseError) {
@@ -9970,7 +9552,7 @@ ${userPrompt}`;
9970
9552
  this.state = "error";
9971
9553
  const msg = err instanceof Error ? err.message : String(err);
9972
9554
  this.lastErrorMessage = msg;
9973
- log29.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9555
+ log28.error(this.tag, `Error reviewing #${card.short_id}: ${msg}`);
9974
9556
  this.lastRunLogPath = appendRunLog(this.tag, this.runId, card.short_id, `[${new Date().toISOString()}] review failed before completion: ${msg}`) ?? this.lastRunLogPath;
9975
9557
  const reviewHandback = await guardedHandback(this.client, card.id, {
9976
9558
  agentId: this.identity.agentId,
@@ -9986,7 +9568,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9986
9568
  agentSessionId: this.sessionId ?? undefined
9987
9569
  });
9988
9570
  } catch (cErr) {
9989
- log29.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9571
+ log28.warn(this.tag, `Failed to post the failure reason to #${card.short_id}: ${cErr instanceof Error ? cErr.message : cErr}`);
9990
9572
  }
9991
9573
  }
9992
9574
  try {
@@ -9998,21 +9580,21 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
9998
9580
  }
9999
9581
  });
10000
9582
  } catch (tErr) {
10001
- log29.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
9583
+ log28.error(this.tag, `endAgentSession unrecoverable on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
10002
9584
  }
10003
9585
  if (reviewHandback.verdict.proceed) {
10004
9586
  try {
10005
9587
  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`);
9588
+ log28.info(this.tag, `Moved #${card.short_id} to "${this.config.review.failColumn}" after error`);
10007
9589
  } catch {
10008
- log29.warn(this.tag, "Failed to move card to fail column after error");
9590
+ log28.warn(this.tag, "Failed to move card to fail column after error");
10009
9591
  }
10010
9592
  } else if (reviewHandback.verdict.reason === "unreadable" || reviewHandback.verdict.reason === "released" || reviewHandback.verdict.reason === "done") {
10011
9593
  try {
10012
9594
  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`);
9595
+ log28.warn(this.tag, `#${card.short_id} could not be re-read — labelled "${NEED_REVIEW_LABEL}" so reconcile stops re-enqueueing the review`);
10014
9596
  } catch {
10015
- log29.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
9597
+ log28.warn(this.tag, `Failed to add "${NEED_REVIEW_LABEL}" label after an unreadable card`);
10016
9598
  }
10017
9599
  }
10018
9600
  if (this.runId) {
@@ -10056,7 +9638,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10056
9638
  const holderMessage = err instanceof Error ? err.message : String(err);
10057
9639
  const waitHours = this.config.budget.pause.waitHours;
10058
9640
  const until = computeDecisionDeadline(waitHours);
10059
- log29.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
9641
+ log28.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
10060
9642
  try {
10061
9643
  await this.client.addComment(card.id, formatResumeConflictComment({
10062
9644
  holderMessage,
@@ -10068,7 +9650,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10068
9650
  agentSessionId: this.sessionId ?? undefined
10069
9651
  });
10070
9652
  } catch (commentErr) {
10071
- log29.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
9653
+ log28.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
10072
9654
  }
10073
9655
  if (this.runId) {
10074
9656
  const run = this.stateStore.getRun(this.runId);
@@ -10079,7 +9661,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10079
9661
  awaitingDecisionUntil: until
10080
9662
  });
10081
9663
  } 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}`);
9664
+ 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
9665
  }
10084
9666
  }
10085
9667
  }
@@ -10092,7 +9674,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10092
9674
  this.progressTracker = null;
10093
9675
  const waitHours = this.config.budget.pause.waitHours;
10094
9676
  const until = computeDecisionDeadline(waitHours);
10095
- log29.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
9677
+ log28.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
10096
9678
  const body = formatBudgetComment({
10097
9679
  trigger,
10098
9680
  numTurns: stats?.cost?.numTurns ?? 0,
@@ -10114,7 +9696,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10114
9696
  });
10115
9697
  commentId = res?.comment?.id ?? null;
10116
9698
  } catch (err) {
10117
- log29.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
9699
+ log28.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
10118
9700
  }
10119
9701
  try {
10120
9702
  await this.client.updateAgentProgress(card.id, {
@@ -10125,7 +9707,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10125
9707
  awaitingDecisionUntil: new Date(until).toISOString()
10126
9708
  });
10127
9709
  } catch (err) {
10128
- log29.warn(this.tag, `Failed to mark the session blocked: ${err}`);
9710
+ log28.warn(this.tag, `Failed to mark the session blocked: ${err}`);
10129
9711
  }
10130
9712
  if (this.runId) {
10131
9713
  try {
@@ -10136,14 +9718,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10136
9718
  ...this.endLedger()
10137
9719
  });
10138
9720
  } 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}`);
9721
+ 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
9722
  }
10141
9723
  }
10142
9724
  }
10143
9725
  async pause() {
10144
9726
  if (!this.isActive || !this.process || this.process.killed)
10145
9727
  return;
10146
- log29.info(this.tag, `Pausing review on ${this.cardId}`);
9728
+ log28.info(this.tag, `Pausing review on ${this.cardId}`);
10147
9729
  signalGroup(this.process, "SIGSTOP");
10148
9730
  if (this.timeoutTimer) {
10149
9731
  clearTimeout(this.timeoutTimer);
@@ -10157,17 +9739,17 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10157
9739
  status: "paused"
10158
9740
  });
10159
9741
  } catch {
10160
- log29.warn(this.tag, "Failed to update agent session to paused");
9742
+ log28.warn(this.tag, "Failed to update agent session to paused");
10161
9743
  }
10162
9744
  }
10163
9745
  }
10164
9746
  async resume() {
10165
9747
  if (!this.isActive || !this.process || this.process.killed)
10166
9748
  return;
10167
- log29.info(this.tag, `Resuming review on ${this.cardId}`);
9749
+ log28.info(this.tag, `Resuming review on ${this.cardId}`);
10168
9750
  signalGroup(this.process, "SIGCONT");
10169
9751
  this.timeoutTimer = setTimeout(() => {
10170
- log29.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
9752
+ log28.warn(this.tag, `Timeout reached (${this.config.review.maxTimeout}ms), cancelling`);
10171
9753
  this.timedOut = true;
10172
9754
  this.cancel("timeout");
10173
9755
  }, this.config.review.maxTimeout);
@@ -10179,7 +9761,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10179
9761
  status: "working"
10180
9762
  });
10181
9763
  } catch {
10182
- log29.warn(this.tag, "Failed to update agent session to working");
9764
+ log28.warn(this.tag, "Failed to update agent session to working");
10183
9765
  }
10184
9766
  }
10185
9767
  }
@@ -10188,7 +9770,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10188
9770
  return;
10189
9771
  this.aborted = true;
10190
9772
  this.state = "cancelling";
10191
- log29.info(this.tag, `Cancelling review on ${this.cardId}`);
9773
+ log28.info(this.tag, `Cancelling review on ${this.cardId}`);
10192
9774
  const snapshotStats = this.lastSessionStats ?? this.progressTracker?.stats;
10193
9775
  if (this.progressTracker) {
10194
9776
  this.progressTracker?.stop();
@@ -10241,11 +9823,11 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10241
9823
  "--",
10242
9824
  prompt
10243
9825
  ];
10244
- log29.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
9826
+ log28.info(this.tag, `Spawning review: claude ${args.slice(0, 5).join(" ")} ...`);
10245
9827
  const runLog = openRunLog(this.tag, this.runId, shortId);
10246
9828
  this.lastRunLogPath = runLog?.path ?? null;
10247
9829
  if (runLog) {
10248
- log29.info(this.tag, `Run log: ${runLog.path}`);
9830
+ log28.info(this.tag, `Run log: ${runLog.path}`);
10249
9831
  runLog.stream.write(`# run=${this.runId} card=#${shortId} pipeline=review started=${new Date().toISOString()}
10250
9832
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
10251
9833
 
@@ -10264,7 +9846,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10264
9846
  this.captureCliSessionId(parser.sessionId);
10265
9847
  });
10266
9848
  parser.on("parse_error", (msg) => {
10267
- log29.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
9849
+ log28.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
10268
9850
  runLog?.stream.write(`
10269
9851
  [parse_error] ${msg}
10270
9852
  `);
@@ -10343,16 +9925,16 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10343
9925
  const evidence = await collectGateEvidence(registry, context);
10344
9926
  const evaluation = gateEvaluate(resolved.gate, evidence);
10345
9927
  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}`);
9928
+ log28.info(this.tag, `Recorded review_passed gate evidence for #${card.short_id} stage "${resolved.stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
10347
9929
  } catch (err) {
10348
- log29.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
9930
+ log28.warn(this.tag, `review gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10349
9931
  }
10350
9932
  }
10351
9933
  async startDevServer(card, cwd, port) {
10352
9934
  const declined = devServerSkipReason(cwd, this.config.commands);
10353
9935
  if (declined)
10354
9936
  return { previewUrl: null, skipReason: declined };
10355
- log29.info(this.tag, `Starting dev server on port ${port}...`);
9937
+ log28.info(this.tag, `Starting dev server on port ${port}...`);
10356
9938
  const launch = devServerLaunch({
10357
9939
  worktreePath: cwd,
10358
9940
  port,
@@ -10393,14 +9975,14 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10393
9975
  skipReason: launch.origin ? `${launch.origin}, and ${failure}` : failure
10394
9976
  };
10395
9977
  }
10396
- log29.info(this.tag, `Dev server ready on port ${port}`);
9978
+ log28.info(this.tag, `Dev server ready on port ${port}`);
10397
9979
  return { previewUrl: `http://localhost:${port}`, skipReason: null };
10398
9980
  }
10399
9981
  killDevServer() {
10400
9982
  if (this.devServerProcess && !this.devServerProcess.killed) {
10401
9983
  signalGroup(this.devServerProcess, "SIGTERM");
10402
9984
  this.devServerProcess = null;
10403
- log29.debug(this.tag, "Killed dev server group");
9985
+ log28.debug(this.tag, "Killed dev server group");
10404
9986
  }
10405
9987
  if (this.devServerContainer) {
10406
9988
  const name = this.devServerContainer;
@@ -10423,7 +10005,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10423
10005
  try {
10424
10006
  cleanupWorktree4(this.worktreePath);
10425
10007
  } catch {
10426
- log29.warn(this.tag, "Failed to cleanup review worktree");
10008
+ log28.warn(this.tag, "Failed to cleanup review worktree");
10427
10009
  }
10428
10010
  }
10429
10011
  this.process = null;
@@ -10435,7 +10017,7 @@ No verdict was produced, so this card has not been reviewed. The run's log is at
10435
10017
  this.lastSessionStats = null;
10436
10018
  }
10437
10019
  }
10438
- var TAG26 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10020
+ var TAG25 = "review-worker", CANCEL_SIGINT_TIMEOUT = 30000, CANCEL_SIGTERM_TIMEOUT = 1e4;
10439
10021
  var init_review_worker = __esm(() => {
10440
10022
  init_dist();
10441
10023
  init_board_helpers();
@@ -10459,7 +10041,7 @@ var init_review_worker = __esm(() => {
10459
10041
 
10460
10042
  // src/sleep-guard.ts
10461
10043
  import { spawn } from "node:child_process";
10462
- import { log as log30 } from "@gethmy/harness";
10044
+ import { log as log29 } from "@gethmy/harness";
10463
10045
 
10464
10046
  class SleepGuard {
10465
10047
  platform;
@@ -10487,7 +10069,7 @@ class SleepGuard {
10487
10069
  if (!this.child.killed)
10488
10070
  this.child.kill("SIGTERM");
10489
10071
  this.child = null;
10490
- log30.info(TAG27, "sleep assertion released");
10072
+ log29.info(TAG26, "sleep assertion released");
10491
10073
  }
10492
10074
  }
10493
10075
  start() {
@@ -10502,7 +10084,7 @@ class SleepGuard {
10502
10084
  spawned = true;
10503
10085
  });
10504
10086
  child.on("error", (err) => {
10505
- log30.warn(TAG27, `caffeinate unavailable: ${err.message}`);
10087
+ log29.warn(TAG26, `caffeinate unavailable: ${err.message}`);
10506
10088
  if (this.child === child)
10507
10089
  this.child = null;
10508
10090
  });
@@ -10515,23 +10097,23 @@ class SleepGuard {
10515
10097
  });
10516
10098
  child.unref();
10517
10099
  this.child = child;
10518
- log30.info(TAG27, "sleep assertion acquired (caffeinate -i)");
10100
+ log29.info(TAG26, "sleep assertion acquired (caffeinate -i)");
10519
10101
  } catch (err) {
10520
- log30.warn(TAG27, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10102
+ log29.warn(TAG26, `failed to spawn caffeinate: ${err instanceof Error ? err.message : err}`);
10521
10103
  }
10522
10104
  }
10523
10105
  }
10524
- var TAG27 = "sleep-guard";
10106
+ var TAG26 = "sleep-guard";
10525
10107
  var init_sleep_guard = () => {};
10526
10108
 
10527
10109
  // src/unblock.ts
10528
- import { log as log31 } from "@gethmy/harness";
10110
+ import { log as log30 } from "@gethmy/harness";
10529
10111
  async function fetchBlocksLinks(client, cardId) {
10530
10112
  try {
10531
10113
  const { links } = await client.getCardLinks(cardId);
10532
10114
  return links.filter((l) => l.link_type === "blocks");
10533
10115
  } catch (err) {
10534
- log31.warn(TAG28, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10116
+ log30.warn(TAG27, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10535
10117
  return null;
10536
10118
  }
10537
10119
  }
@@ -10565,31 +10147,31 @@ async function promoteUnblockedSuccessors(completedCard, deps) {
10565
10147
  const successors = links.filter((l) => l.direction === "outgoing" && !l.target_card.done);
10566
10148
  if (successors.length === 0)
10567
10149
  return;
10568
- log31.info(TAG28, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10150
+ log30.info(TAG27, `#${completedCard.short_id} completed — checking ${successors.length} chained successor(s)`);
10569
10151
  for (const link of successors) {
10570
10152
  const successorId = link.target_card.id;
10571
10153
  try {
10572
10154
  const { card } = await deps.client.getCard(successorId);
10573
10155
  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`);
10156
+ log30.info(TAG27, `successor #${card.short_id} unassigned — auto-assigning to continue chain`);
10575
10157
  await deps.client.updateCard(successorId, {
10576
10158
  assignedAgentId: deps.agentId
10577
10159
  });
10578
10160
  } else {
10579
- log31.debug(TAG28, `successor #${card.short_id} assigned to different entity — skipping`);
10161
+ log30.debug(TAG27, `successor #${card.short_id} assigned to different entity — skipping`);
10580
10162
  continue;
10581
10163
  }
10582
10164
  await deps.enqueue(successorId);
10583
10165
  } catch (err) {
10584
- log31.warn(TAG28, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10166
+ log30.warn(TAG27, `promotion failed for successor ${successorId}: ${err instanceof Error ? err.message : err}`);
10585
10167
  }
10586
10168
  }
10587
10169
  }
10588
- var TAG28 = "unblock";
10170
+ var TAG27 = "unblock";
10589
10171
  var init_unblock = () => {};
10590
10172
 
10591
10173
  // src/cli-agent-runner.ts
10592
- import { log as log32 } from "@gethmy/harness";
10174
+ import { log as log31 } from "@gethmy/harness";
10593
10175
  function truncateOutput(value) {
10594
10176
  return value === undefined ? undefined : value.slice(0, MAX_OUTPUT_CHARS);
10595
10177
  }
@@ -10754,7 +10336,7 @@ class CliAgentRunner {
10754
10336
  return;
10755
10337
  const draft = sanitizeRunEventDraft(body);
10756
10338
  if (runEventPayloadExceedsLimit(draft.payload)) {
10757
- log32.warn(TAG29, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10339
+ log31.warn(TAG28, `Dropping ${body.kind} event: payload exceeds ${MAX_RUN_EVENT_PAYLOAD_BYTES} bytes, or cannot be serialized`);
10758
10340
  return;
10759
10341
  }
10760
10342
  this.buffer.push({ ...draft, createdAt: new Date().toISOString() });
@@ -10786,15 +10368,15 @@ class CliAgentRunner {
10786
10368
  this.requeue(batch);
10787
10369
  if (batch.length > 1) {
10788
10370
  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}`);
10371
+ log31.warn(TAG28, `Flush of ${batch.length} run event(s) failed ${MAX_BATCH_ATTEMPTS}×; bisecting to ${this.nextBatchSize}: ${err}`);
10790
10372
  return;
10791
10373
  }
10792
10374
  const dropped = this.buffer.shift();
10793
10375
  this.nextBatchSize = MAX_BUFFER;
10794
- log32.warn(TAG29, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10376
+ log31.warn(TAG28, `Dropping one ${dropped?.kind} event the API refused ${MAX_BATCH_ATTEMPTS}×: ${err}`);
10795
10377
  return;
10796
10378
  }
10797
- log32.warn(TAG29, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10379
+ log31.warn(TAG28, `Failed to flush run events (attempt ${this.batchAttempts}/${MAX_BATCH_ATTEMPTS}): ${err}`);
10798
10380
  this.requeue(batch);
10799
10381
  } finally {
10800
10382
  this.flushing = false;
@@ -10837,26 +10419,26 @@ function mapCost(cost) {
10837
10419
  durationMs: cost.durationMs
10838
10420
  };
10839
10421
  }
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;
10422
+ 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
10423
  var init_cli_agent_runner = __esm(() => {
10842
10424
  init_dist();
10843
10425
  });
10844
10426
 
10845
10427
  // src/fanout.ts
10846
- import { log as log33 } from "@gethmy/harness";
10428
+ import { log as log32 } from "@gethmy/harness";
10847
10429
  async function fetchLinks(client, cardId) {
10848
10430
  try {
10849
10431
  const { links } = await client.getCardLinks(cardId);
10850
10432
  return links;
10851
10433
  } catch (err) {
10852
- log33.warn(TAG30, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10434
+ log32.warn(TAG29, `link fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
10853
10435
  return null;
10854
10436
  }
10855
10437
  }
10856
10438
  async function isFanoutChildOf(card, stage, client) {
10857
10439
  const links = await fetchLinks(client, card.id);
10858
10440
  if (links === null) {
10859
- log33.warn(TAG30, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10441
+ log32.warn(TAG29, `#${card.short_id}: link read failed — treating as a fan-out child (fail closed, no recursive dispatch)`);
10860
10442
  return true;
10861
10443
  }
10862
10444
  const parents = links.filter((l) => l.direction === "outgoing" && l.link_type === "is_part_of");
@@ -10943,7 +10525,7 @@ async function readStageHandoff(card, fromStage, deps) {
10943
10525
  }
10944
10526
  return null;
10945
10527
  } catch (err) {
10946
- log33.warn(TAG30, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10528
+ log32.warn(TAG29, `handoff read failed for #${card.short_id} stage "${fromStage}": ${err instanceof Error ? err.message : err}`);
10947
10529
  return null;
10948
10530
  }
10949
10531
  }
@@ -11044,7 +10626,7 @@ async function dispatchWave(parent, stage, plan, items, deps) {
11044
10626
  });
11045
10627
  spawned = res.children ?? [];
11046
10628
  } catch (err) {
11047
- log33.warn(TAG30, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
10629
+ log32.warn(TAG29, `child spawn failed for #${parent.short_id} stage "${stage.id}": ${err instanceof Error ? err.message : err}`);
11048
10630
  return 0;
11049
10631
  }
11050
10632
  let created = 0;
@@ -11099,10 +10681,10 @@ async function seedChildHandoff(parent, stage, item, total, childId, deps) {
11099
10681
  try {
11100
10682
  await deps.client.addComment(childId, body, { commentType: "decision" });
11101
10683
  } catch (err) {
11102
- log33.warn(TAG30, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
10684
+ log32.warn(TAG29, `seed handoff failed for child ${childId}: ${err instanceof Error ? err.message : err}`);
11103
10685
  }
11104
10686
  }
11105
- var TAG30 = "fanout";
10687
+ var TAG29 = "fanout";
11106
10688
  var init_fanout = __esm(() => {
11107
10689
  init_dist();
11108
10690
  });
@@ -11337,7 +10919,7 @@ function runSizedPayload(input) {
11337
10919
  }
11338
10920
 
11339
10921
  // src/stage-advance.ts
11340
- import { gateConfigErrorReason, log as log34 } from "@gethmy/harness";
10922
+ import { gateConfigErrorReason, log as log33 } from "@gethmy/harness";
11341
10923
  function endDispositionFor(outcome) {
11342
10924
  return "endDisposition" in outcome && outcome.endDisposition ? outcome.endDisposition : { status: "completed" };
11343
10925
  }
@@ -11368,7 +10950,7 @@ async function resolveStageColumnName(client, card, stage) {
11368
10950
  const match = board.columns.find((c) => c.id === target || c.name.toLowerCase() === target.toLowerCase());
11369
10951
  return match ? match.name : null;
11370
10952
  } catch (err) {
11371
- log34.warn(TAG31, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
10953
+ log33.warn(TAG30, `board fetch failed resolving stage column for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11372
10954
  return null;
11373
10955
  }
11374
10956
  }
@@ -11407,7 +10989,7 @@ async function holdGateMisconfigured(card, stage, detail, deps) {
11407
10989
  });
11408
10990
  } catch {}
11409
10991
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, { agentSessionId: deps.agentSessionId });
11410
- log34.info(TAG31, `#${card.short_id} GateMisconfigured: ${reason}`);
10992
+ log33.info(TAG30, `#${card.short_id} GateMisconfigured: ${reason}`);
11411
10993
  return { kind: "held_misconfigured", reason, endDisposition };
11412
10994
  }
11413
10995
  function firstErrorMessage(evaluation) {
@@ -11438,7 +11020,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11438
11020
  evidence,
11439
11021
  summary
11440
11022
  });
11441
- log34.info(TAG31, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11023
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}": ${summary} → ${decision}`);
11442
11024
  if (decision === "exit") {
11443
11025
  await deps.stateStore.resetLoopIterations(card.id).catch(() => {});
11444
11026
  deps.sink?.recordLoopCompleted?.({
@@ -11483,7 +11065,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11483
11065
  blockers: [reason],
11484
11066
  agentSessionId: deps.agentSessionId
11485
11067
  });
11486
- log34.info(TAG31, `#${card.short_id} LoopExhausted: ${reason}`);
11068
+ log33.info(TAG30, `#${card.short_id} LoopExhausted: ${reason}`);
11487
11069
  return { kind: "held_gate_unmet", reason, endDisposition };
11488
11070
  }
11489
11071
  const guard = await guardStageReclaim(card, `converge-loop iteration of "${stage.name}"`, deps);
@@ -11508,7 +11090,7 @@ async function advanceConvergeLoop(card, stage, stageIndex, def, evaluation, loo
11508
11090
  addLabels: [{ name: AGENT_LABEL }],
11509
11091
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11510
11092
  }, { 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}`);
11093
+ log33.info(TAG30, `#${card.short_id} converge loop "${stage.name}" — requeued to "${toColumn}" for iteration ${iteration + 1}/${maxIterations}`);
11512
11094
  return { kind: "requeued_gate_unmet", toColumn };
11513
11095
  }
11514
11096
  async function writeIterationHandoff(card, stage, iteration, maxIterations, evaluation, deps) {
@@ -11530,7 +11112,7 @@ ${findings.map((f) => `- [${f.level}] ${f.message}`).join(`
11530
11112
  agentSessionId: deps.agentSessionId ?? undefined
11531
11113
  });
11532
11114
  } catch (err) {
11533
- log34.warn(TAG31, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11115
+ log33.warn(TAG30, `iteration-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11534
11116
  }
11535
11117
  }
11536
11118
  async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps) {
@@ -11558,7 +11140,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11558
11140
  reason: "Playbook complete — final stage gate passed."
11559
11141
  });
11560
11142
  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)`);
11143
+ log33.info(TAG30, `#${card.short_id} terminal stage "${stage.name}" passed — playbook complete (done left to the column)`);
11562
11144
  return { kind: "completed_terminal" };
11563
11145
  }
11564
11146
  if (next.kind === "out_of_range") {
@@ -11590,7 +11172,7 @@ async function advanceStageOnGate(card, stage, stageIndex, def, evaluation, deps
11590
11172
  ...isAgentRunnableOwner(next.stage.owner) ? { assignAgent: deps.agentId } : {}
11591
11173
  }, { store: deps.stateStore, runId: deps.runId });
11592
11174
  deps.stateStore.recordOutcome(card.id, "success").catch(() => {});
11593
- log34.info(TAG31, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11175
+ log33.info(TAG30, `#${card.short_id} advanced "${stage.name}" → "${next.stage.name}" (column "${toColumn}")`);
11594
11176
  if (next.stage.owner === "human") {
11595
11177
  const reason = `Stage "${next.stage.name}" is yours: ${handoffText(next.stage)}`;
11596
11178
  const endDisposition = await holdForHuman(deps.client, card, reason, deps.runId, deps.stateStore, {
@@ -11627,7 +11209,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11627
11209
  blockers: [reason],
11628
11210
  agentSessionId: deps.agentSessionId
11629
11211
  });
11630
- log34.info(TAG31, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11212
+ log33.info(TAG30, `#${card.short_id} GateUnmetExhausted: ${reason}`);
11631
11213
  return { kind: "held_gate_unmet", reason, endDisposition };
11632
11214
  }
11633
11215
  const guard = await guardStageReclaim(card, `gate-unmet re-run of "${stage.name}"`, deps);
@@ -11650,7 +11232,7 @@ async function handleGateUnmet(card, stage, summary, deps) {
11650
11232
  addLabels: [{ name: AGENT_LABEL }],
11651
11233
  ...isAgentRunnableOwner(stage.owner) ? { assignAgent: deps.agentId } : {}
11652
11234
  }, { 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})`);
11235
+ log33.info(TAG30, `#${card.short_id} gate unmet for "${stage.name}" — requeued to "${toColumn}" for re-run (attempt ${attempts}/${deps.maxAttempts})`);
11654
11236
  return { kind: "requeued_gate_unmet", toColumn };
11655
11237
  }
11656
11238
  async function guardStageReclaim(card, what, deps) {
@@ -11676,10 +11258,10 @@ async function guardStageReclaim(card, what, deps) {
11676
11258
  }, { store: deps.stateStore, runId: deps.runId });
11677
11259
  released = stillOurs;
11678
11260
  } 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" : ""}`);
11261
+ 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
11262
  }
11681
11263
  }
11682
- log34.info(TAG31, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11264
+ log33.info(TAG30, `#${card.short_id} ${what} refused — ${detail} (${reason})${released ? "; released the daemon's claim so the stage router stops here" : ""}`);
11683
11265
  try {
11684
11266
  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
11267
  commentType: "decision",
@@ -11701,7 +11283,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11701
11283
  try {
11702
11284
  await runTransition(client, card, { removeLabels: [AGENT_LABEL] }, { store: stateStore, runId });
11703
11285
  } catch (err) {
11704
- log34.warn(TAG31, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11286
+ log33.warn(TAG30, `hold transition failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
11705
11287
  }
11706
11288
  return {
11707
11289
  status: opts.endStatus ?? "paused",
@@ -11710,7 +11292,7 @@ async function holdForHuman(client, card, reason, runId, stateStore, opts = {})
11710
11292
  failureSummary: reason.slice(0, 300)
11711
11293
  };
11712
11294
  }
11713
- var TAG31 = "stage-advance", AGENT_LABEL = "agent";
11295
+ var TAG30 = "stage-advance", AGENT_LABEL = "agent";
11714
11296
  var init_stage_advance = __esm(() => {
11715
11297
  init_dist();
11716
11298
  init_handback();
@@ -11786,7 +11368,7 @@ import {
11786
11368
  GIT_NO_HOOKS as GIT_NO_HOOKS8,
11787
11369
  implementRunContainment,
11788
11370
  implementRunContainmentCliArgs as implementRunContainmentCliArgs2,
11789
- log as log35,
11371
+ log as log34,
11790
11372
  makeBranchName,
11791
11373
  normalizeGateSpec,
11792
11374
  pushBranch as pushBranch3,
@@ -11992,11 +11574,11 @@ class Worker {
11992
11574
  sessionId: this.sessionId
11993
11575
  });
11994
11576
  } catch (err) {
11995
- log35.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11577
+ log34.warn(this.tag, `state store updateRun failed: ${err instanceof Error ? err.message : err}`);
11996
11578
  }
11997
11579
  }
11998
11580
  get tag() {
11999
- return `${TAG32}:${this.id}`;
11581
+ return `${TAG31}:${this.id}`;
12000
11582
  }
12001
11583
  get isIdle() {
12002
11584
  return this.state === "idle";
@@ -12058,12 +11640,12 @@ class Worker {
12058
11640
  }
12059
11641
  if (!crossedTurnCap(before, after, cap))
12060
11642
  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.`);
11643
+ 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
11644
  try {
12063
11645
  const legs = this.stateStore.getRun(this.runId ?? "")?.legs?.length || 1;
12064
11646
  await this.client.addComment(cardId, buildTurnCapComment(after, cap, legs), { commentType: "blocker", agentSessionId: this.sessionId ?? undefined });
12065
11647
  } catch (err) {
12066
- log35.warn(TAG32, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
11648
+ log34.warn(TAG31, `Could not post the turn-cap notice for ${cardId}: ${err instanceof Error ? err.message : err}`);
12067
11649
  }
12068
11650
  }
12069
11651
  async run(card, column, labels, subtasks) {
@@ -12118,7 +11700,7 @@ class Worker {
12118
11700
  resumeReason: null
12119
11701
  });
12120
11702
  } catch (err) {
12121
- log35.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
11703
+ log34.warn(this.tag, `Failed to clear the consumed grant: ${err}`);
12122
11704
  }
12123
11705
  }
12124
11706
  try {
@@ -12126,20 +11708,20 @@ class Worker {
12126
11708
  if (!resuming) {
12127
11709
  this.branchName = makeBranchName(card.short_id, card.title, this.config.worktree.failedBranchPrefix);
12128
11710
  }
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}"`);
11711
+ 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
11712
  const attemptCount = await this.stateStore.incrementAttempt(card.id);
12131
11713
  const isRework = attemptCount > 1;
12132
11714
  const runStarts = this.stateStore.getCardRunStarts(card.id);
12133
11715
  const runCap = this.config.budget.maxRunsPerCard;
12134
11716
  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.`);
11717
+ 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
11718
  try {
12137
11719
  await this.client.addComment(card.id, buildRunCapComment(runStarts, runCap), {
12138
11720
  commentType: "blocker",
12139
11721
  agentSessionId: this.sessionId ?? undefined
12140
11722
  });
12141
11723
  } catch (err) {
12142
- log35.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
11724
+ log34.warn(this.tag, `Could not post the run-backstop notice for ${card.id}: ${err instanceof Error ? err.message : err}`);
12143
11725
  }
12144
11726
  }
12145
11727
  const recordedBranch = recordedBranchForCard(card.description, card.short_id, [
@@ -12149,10 +11731,10 @@ class Worker {
12149
11731
  const continuesPushedWork = isRework || recordedBranch !== null;
12150
11732
  if (!resuming && recordedBranch) {
12151
11733
  if (recordedBranch !== this.branchName) {
12152
- log35.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
11734
+ log34.info(this.tag, `Card records pushed work on ${recordedBranch} — continuing that branch instead of ${this.branchName}`);
12153
11735
  this.branchName = recordedBranch;
12154
11736
  } 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}`);
11737
+ log34.info(this.tag, `Card records pushed work on ${this.branchName} — continuing that branch instead of rebuilding from ${this.config.worktree.baseBranch}`);
12156
11738
  }
12157
11739
  }
12158
11740
  this.startHeartbeat();
@@ -12194,14 +11776,14 @@ class Worker {
12194
11776
  awaitingDecisionUntil: null
12195
11777
  });
12196
11778
  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)
11779
+ info: (message) => log34.info(this.tag, message),
11780
+ warn: (message) => log34.warn(this.tag, message)
12199
11781
  });
12200
11782
  session = started.session;
12201
11783
  } catch (err) {
12202
11784
  if (isSessionConflict(err)) {
12203
11785
  this.sessionConflict = true;
12204
- log35.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
11786
+ log34.info(this.tag, `Skipping #${card.short_id}: ${err instanceof Error ? err.message : String(err)}`);
12205
11787
  await this.stateStore.decrementAttempt(card.id);
12206
11788
  return;
12207
11789
  }
@@ -12209,7 +11791,7 @@ class Worker {
12209
11791
  }
12210
11792
  const sid = session && typeof session === "object" && "id" in session ? session.id : null;
12211
11793
  if (!sid) {
12212
- log35.warn(TAG32, "startAgentSession returned no session id");
11794
+ log34.warn(TAG31, "startAgentSession returned no session id");
12213
11795
  }
12214
11796
  this.sessionId = sid;
12215
11797
  }
@@ -12227,7 +11809,7 @@ class Worker {
12227
11809
  if (!resuming) {
12228
11810
  const moved = await moveCardAndAddLabel(this.client, card, IN_PROGRESS_COLUMN, "agent");
12229
11811
  if (!moved) {
12230
- log35.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
11812
+ log34.warn(this.tag, `Card #${card.short_id} was NOT moved to "In Progress" — check API logs`);
12231
11813
  }
12232
11814
  }
12233
11815
  if (this.aborted)
@@ -12254,10 +11836,10 @@ class Worker {
12254
11836
  }).trim();
12255
11837
  const target = resolveContinuationTarget(this.branchName, continueRequested, this.config.worktree.failedBranchPrefix, this.config.worktree.approvedBranchPrefix, (ref) => fetchExistingBranch(repoRoot, ref));
12256
11838
  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`);
11839
+ log34.info(this.tag, `Branch ${this.branchName} is gone from origin but its approved rename ${target.branchName} exists — continuing that branch`);
12258
11840
  this.branchName = target.branchName;
12259
11841
  } 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`);
11842
+ log34.info(this.tag, `Branch ${this.branchName} exists on origin with no card record — continuing it rather than resetting it`);
12261
11843
  }
12262
11844
  this.worktreePath = createWorktree(this.config.worktree.basePath, this.config.worktree.baseBranch, this.branchName, {
12263
11845
  continueExisting: target.continueExisting,
@@ -12291,7 +11873,7 @@ class Worker {
12291
11873
  if (this.aborted)
12292
11874
  return;
12293
11875
  if (parked) {
12294
- log35.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
11876
+ log34.info(this.tag, `#${card.short_id} parked for plan approval — ending run`);
12295
11877
  return;
12296
11878
  }
12297
11879
  }
@@ -12312,7 +11894,7 @@ class Worker {
12312
11894
  progressPercent: 10
12313
11895
  });
12314
11896
  this.timeoutTimer = setTimeout(() => {
12315
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
11897
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
12316
11898
  this.timedOut = true;
12317
11899
  this.cancel("timeout");
12318
11900
  }, this.config.maxTimeout);
@@ -12339,7 +11921,7 @@ class Worker {
12339
11921
  }
12340
11922
  this.state = "verifying";
12341
11923
  await this.recordPhase("verifying");
12342
- log35.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
11924
+ log34.info(this.tag, `Claude finished for #${card.short_id}, running verification & completion`);
12343
11925
  await this.client.updateAgentProgress(card.id, {
12344
11926
  agentIdentifier: this.sessionIdentifier,
12345
11927
  agentName: AGENT_NAME,
@@ -12355,7 +11937,7 @@ class Worker {
12355
11937
  const onBeforeWorktreeCleanup = stageRun ? async (worktreePath) => {
12356
11938
  stageGateEvaluation = await this.collectStageGateEvidence(card, stageRun.stage, worktreePath, subtasks);
12357
11939
  } : 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);
11940
+ 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
11941
  if (completed === "park") {
12360
11942
  await this.parkForDecision(card, "max_turns");
12361
11943
  return;
@@ -12374,7 +11956,7 @@ class Worker {
12374
11956
  break;
12375
11957
  case "reclaim_refused":
12376
11958
  this.held = true;
12377
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
11959
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12378
11960
  break;
12379
11961
  case "advanced":
12380
11962
  case "completed_terminal":
@@ -12412,7 +11994,7 @@ class Worker {
12412
11994
  return;
12413
11995
  }
12414
11996
  this.state = "error";
12415
- log35.error(this.tag, `Error on #${card.short_id}: ${msg}`);
11997
+ log34.error(this.tag, `Error on #${card.short_id}: ${msg}`);
12416
11998
  const apiError = errClass.kind !== null;
12417
11999
  const baseError = err instanceof WorktreeBaseError;
12418
12000
  const noBudgetBurn = apiError || baseError;
@@ -12430,7 +12012,7 @@ class Worker {
12430
12012
  try {
12431
12013
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12432
12014
  } catch {
12433
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12015
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12434
12016
  }
12435
12017
  this.worktreePath = null;
12436
12018
  }
@@ -12455,7 +12037,7 @@ class Worker {
12455
12037
  }
12456
12038
  });
12457
12039
  } catch (tErr) {
12458
- log35.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12040
+ log34.error(this.tag, `error transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12459
12041
  }
12460
12042
  if (this.runId) {
12461
12043
  try {
@@ -12491,7 +12073,7 @@ class Worker {
12491
12073
  try {
12492
12074
  await teardownWorktree2(this.client, card.id, this.worktreePath, this.branchName ?? undefined, this.sessionId);
12493
12075
  } catch {
12494
- log35.warn(this.tag, "Failed to cleanup worktree before requeue");
12076
+ log34.warn(this.tag, "Failed to cleanup worktree before requeue");
12495
12077
  }
12496
12078
  this.worktreePath = null;
12497
12079
  }
@@ -12514,7 +12096,7 @@ class Worker {
12514
12096
  }
12515
12097
  });
12516
12098
  } catch (tErr) {
12517
- log35.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12099
+ log34.error(this.tag, `timeout transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12518
12100
  }
12519
12101
  try {
12520
12102
  await this.stateStore.endRun(this.runId, "failed", {
@@ -12528,15 +12110,15 @@ class Worker {
12528
12110
  try {
12529
12111
  await this.client.updateCard(card.id, { assignedAgentId: null });
12530
12112
  } catch (err) {
12531
- log35.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12113
+ log34.warn(this.tag, `failed to release card after stop: ${err instanceof Error ? err.message : err}`);
12532
12114
  }
12533
12115
  try {
12534
12116
  await runTransition(this.client, card, { removeLabels: ["agent"] });
12535
12117
  } catch (tErr) {
12536
- log35.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12118
+ log34.warn(this.tag, `stop label cleanup failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12537
12119
  }
12538
12120
  } else {
12539
- log35.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12121
+ log34.info(this.tag, `cancel arrived after completion on #${card.short_id} — keeping assignment so review picks it up (#585)`);
12540
12122
  }
12541
12123
  try {
12542
12124
  await this.stateStore.endRun(this.runId, "paused", {
@@ -12600,28 +12182,28 @@ class Worker {
12600
12182
  };
12601
12183
  const { pick, reason } = selectAutoPlaybook(subject, playbooks ?? []);
12602
12184
  if (!pick) {
12603
- log35.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12185
+ log34.info(this.tag, `No playbook auto-bound to #${card.short_id}: ${reason}`);
12604
12186
  return card;
12605
12187
  }
12606
12188
  const undeclared = undeclaredGateMetricsIn(pick, declaredMetricSet(this.config));
12607
12189
  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.");
12190
+ 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
12191
  return card;
12610
12192
  }
12611
12193
  const applyResult = await this.client.request("POST", `/cards/${card.id}/apply-playbook`, {
12612
12194
  playbookId: pick.id
12613
12195
  });
12614
- log35.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12196
+ log34.info(this.tag, `Auto-bound #${card.short_id} to playbook "${pick.name}": ${reason}`);
12615
12197
  try {
12616
12198
  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
12199
  } catch (commentErr) {
12618
- log35.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12200
+ log34.warn(this.tag, `Auto-bind comment failed for #${card.short_id}: ${commentErr instanceof Error ? commentErr.message : String(commentErr)}`);
12619
12201
  }
12620
12202
  try {
12621
12203
  const { card: fresh } = await this.client.getCard(card.id);
12622
12204
  return fresh;
12623
12205
  } 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)}`);
12206
+ 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
12207
  return {
12626
12208
  ...card,
12627
12209
  playbook_id: applyResult.card.playbook_id,
@@ -12630,7 +12212,7 @@ class Worker {
12630
12212
  };
12631
12213
  }
12632
12214
  } 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)}`);
12215
+ log34.warn(this.tag, `Auto-bind playbook check failed for #${card.short_id}, continuing unbound: ${err instanceof Error ? err.message : String(err)}`);
12634
12216
  return card;
12635
12217
  }
12636
12218
  }
@@ -12742,7 +12324,7 @@ class Worker {
12742
12324
  });
12743
12325
  } catch (err) {
12744
12326
  const detail = err instanceof Error ? err.message : String(err);
12745
- log35.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12327
+ log34.warn(this.tag, `fan-out tick failed on #${card.short_id}: ${detail}`);
12746
12328
  await this.holdStageCard(card, `Fan-out stage "${ctx.stage.name}" could not run: ${detail}`);
12747
12329
  return;
12748
12330
  }
@@ -12751,7 +12333,7 @@ class Worker {
12751
12333
  case "waiting": {
12752
12334
  const total = outcome.kind === "dispatched" ? outcome.total : outcome.total;
12753
12335
  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}`);
12336
+ log34.info(this.tag, `#${card.short_id} ${note}`);
12755
12337
  await this.client.updateAgentProgress(card.id, {
12756
12338
  agentIdentifier: "claude-code-stage",
12757
12339
  agentName: "Harmony Agent",
@@ -12779,7 +12361,7 @@ class Worker {
12779
12361
  if (advance.kind === "advanced" || advance.kind === "completed_terminal") {
12780
12362
  this.held = false;
12781
12363
  }
12782
- log35.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12364
+ log34.info(this.tag, `#${card.short_id} ${summary} → ${advance.kind}`);
12783
12365
  return;
12784
12366
  }
12785
12367
  case "halted": {
@@ -12799,7 +12381,7 @@ class Worker {
12799
12381
  }
12800
12382
  }
12801
12383
  async holdStageCard(card, reason, wait = false) {
12802
- log35.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12384
+ log34.info(this.tag, `Holding #${card.short_id}: ${reason}`);
12803
12385
  await this.stateStore.decrementAttempt(card.id);
12804
12386
  try {
12805
12387
  await this.client.addComment(card.id, reason, {
@@ -12818,7 +12400,7 @@ class Worker {
12818
12400
  }
12819
12401
  });
12820
12402
  } catch (tErr) {
12821
- log35.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12403
+ log34.warn(this.tag, `hold transition failed on #${card.short_id}: ${tErr instanceof TransitionError ? tErr.detail : tErr}`);
12822
12404
  }
12823
12405
  if (this.runId) {
12824
12406
  try {
@@ -12836,7 +12418,7 @@ class Worker {
12836
12418
  const holderMessage = err instanceof Error ? err.message : String(err);
12837
12419
  const waitHours = this.config.budget.pause.waitHours;
12838
12420
  const until = computeDecisionDeadline(waitHours);
12839
- log35.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12421
+ log34.warn(this.tag, `#${card.short_id} stays parked — the resume could not reclaim its session: ${holderMessage}`);
12840
12422
  try {
12841
12423
  await this.client.addComment(card.id, formatResumeConflictComment({
12842
12424
  holderMessage,
@@ -12848,7 +12430,7 @@ class Worker {
12848
12430
  agentSessionId: this.sessionId ?? undefined
12849
12431
  });
12850
12432
  } catch (commentErr) {
12851
- log35.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12433
+ log34.warn(this.tag, `Failed to post the resume-conflict note for #${card.short_id}: ${commentErr}`);
12852
12434
  }
12853
12435
  if (this.runId) {
12854
12436
  const run = this.stateStore.getRun(this.runId);
@@ -12859,7 +12441,7 @@ class Worker {
12859
12441
  awaitingDecisionUntil: until
12860
12442
  });
12861
12443
  } 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}`);
12444
+ 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
12445
  }
12864
12446
  }
12865
12447
  }
@@ -12871,7 +12453,7 @@ class Worker {
12871
12453
  this.progressTracker = null;
12872
12454
  const waitHours = this.config.budget.pause.waitHours;
12873
12455
  const until = computeDecisionDeadline(waitHours);
12874
- log35.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12456
+ log34.warn(this.tag, `#${card.short_id} parked (${trigger}) — awaiting a human decision for ${waitHours}h`);
12875
12457
  const measured = this.worktreePath && this.runExpectsCommits ? measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha) : "unknown";
12876
12458
  const hasCommits = measured === "unknown" ? undefined : measured === "committed";
12877
12459
  if (hasCommits === false && !this.noCommitNoticeSettled) {
@@ -12901,7 +12483,7 @@ class Worker {
12901
12483
  });
12902
12484
  commentId = res?.comment?.id ?? null;
12903
12485
  } catch (err) {
12904
- log35.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12486
+ log34.warn(this.tag, `Failed to post the budget-pause comment: ${err}`);
12905
12487
  }
12906
12488
  const cardCostCents = this.stateStore.getCardCostCents(card.id) + Math.max(0, this.runCostCents - this.chargedCents);
12907
12489
  const readout = [
@@ -12922,7 +12504,7 @@ class Worker {
12922
12504
  awaitingDecisionUntil: new Date(until).toISOString()
12923
12505
  });
12924
12506
  } catch (err) {
12925
- log35.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12507
+ log34.warn(this.tag, `Failed to mark the session blocked: ${err}`);
12926
12508
  }
12927
12509
  if (this.runId) {
12928
12510
  try {
@@ -12933,7 +12515,7 @@ class Worker {
12933
12515
  ...this.runLedger()
12934
12516
  });
12935
12517
  } 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}`);
12518
+ 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
12519
  }
12938
12520
  }
12939
12521
  }
@@ -12964,11 +12546,11 @@ class Worker {
12964
12546
  });
12965
12547
  const gate = normalizeGateSpec(ctx.stage.gate);
12966
12548
  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`);
12549
+ log34.info(this.tag, `Running stage "${ctx.stage.name}" (role ${ctx.role}) for #${card.short_id} under the harness motor`);
12968
12550
  const motorAbort = new AbortController;
12969
12551
  this.motorAbort = motorAbort;
12970
12552
  this.timeoutTimer = setTimeout(() => {
12971
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12553
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms) during the motor stage run, cancelling`);
12972
12554
  this.timedOut = true;
12973
12555
  this.cancel("timeout");
12974
12556
  }, this.config.maxTimeout);
@@ -12979,12 +12561,12 @@ class Worker {
12979
12561
  let motorRunSettled = false;
12980
12562
  const onMotorLine = (line) => {
12981
12563
  if (line.type !== "agent_event") {
12982
- log35.info(this.tag, `motor: ${line.type}`);
12564
+ log34.info(this.tag, `motor: ${line.type}`);
12983
12565
  return;
12984
12566
  }
12985
12567
  if (motorRunSettled)
12986
12568
  return;
12987
- log35.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12569
+ log34.debug(this.tag, `motor: agent_event ${line.event.kind}`);
12988
12570
  if (line.event.kind === "tool_started" && STAGE_DAEMON_OWNED_TOOLS.includes(line.event.payload.toolName)) {
12989
12571
  return;
12990
12572
  }
@@ -13004,7 +12586,7 @@ class Worker {
13004
12586
  currentTask: motorTask,
13005
12587
  progressPercent: MOTOR_RUN_PROGRESS_PERCENT
13006
12588
  }).catch((err) => {
13007
- log35.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12589
+ log34.warn(this.tag, `motor session heartbeat failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13008
12590
  });
13009
12591
  }, MOTOR_SESSION_HEARTBEAT_MS);
13010
12592
  heartbeat.unref?.();
@@ -13078,7 +12660,7 @@ class Worker {
13078
12660
  break;
13079
12661
  case "reclaim_refused":
13080
12662
  this.held = true;
13081
- log35.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
12663
+ log34.info(this.tag, `#${card.short_id} stage reclaim refused (${outcome.reason})${outcome.released ? " — released the daemon's claim" : ""}`);
13082
12664
  break;
13083
12665
  case "advanced":
13084
12666
  case "completed_terminal":
@@ -13100,7 +12682,7 @@ class Worker {
13100
12682
  try {
13101
12683
  pushBranch3(this.branchName, worktreePath);
13102
12684
  } 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}`);
12685
+ log34.error(this.tag, `push after the motor stage "${ctx.stage.name}" failed for ${this.branchName}: ${err instanceof Error ? err.message : err}`);
13104
12686
  }
13105
12687
  }
13106
12688
  }
@@ -13108,7 +12690,7 @@ class Worker {
13108
12690
  if (completionColumn) {
13109
12691
  await transferCardToCompletion({ client: this.client, tag: this.tag }, card, completionColumn, this.onCardCompleted);
13110
12692
  } else {
13111
- log35.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
12693
+ log34.warn(this.tag, `completion.moveToColumn is empty — #${card.short_id} stays in its current column after the motor stage run`);
13112
12694
  }
13113
12695
  await this.closeoutMotorWorktree(card);
13114
12696
  }
@@ -13119,7 +12701,7 @@ class Worker {
13119
12701
  try {
13120
12702
  await teardownWorktree2(this.client, card.id, worktreePath, this.branchName ?? undefined, this.sessionId);
13121
12703
  } catch {
13122
- log35.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
12704
+ log34.warn(this.tag, "Failed to cleanup worktree after the motor stage run");
13123
12705
  }
13124
12706
  this.worktreePath = null;
13125
12707
  }
@@ -13176,7 +12758,7 @@ ${prompt}`;
13176
12758
  });
13177
12759
  return handoff ? renderInheritedHandoffSection(handoff) : "";
13178
12760
  } catch (err) {
13179
- log35.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
12761
+ log34.warn(this.tag, `inherited-handoff fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13180
12762
  return "";
13181
12763
  }
13182
12764
  }
@@ -13196,9 +12778,9 @@ ${prompt}`;
13196
12778
  commentType: "decision",
13197
12779
  agentSessionId: this.sessionId ?? undefined
13198
12780
  });
13199
- log35.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
12781
+ log34.info(this.tag, `Wrote stage handoff for #${card.short_id} (stage "${stage.name}")`);
13200
12782
  } catch (err) {
13201
- log35.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12783
+ log34.warn(this.tag, `stage-handoff write failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13202
12784
  }
13203
12785
  }
13204
12786
  async collectStageGateEvidence(card, stage, worktreePath, subtasks) {
@@ -13210,12 +12792,12 @@ ${prompt}`;
13210
12792
  return null;
13211
12793
  }
13212
12794
  if (gate.pendingEngine === true) {
13213
- log35.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
12795
+ log34.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
13214
12796
  return null;
13215
12797
  }
13216
12798
  const review = gate.kind === "review_passed" ? parseReviewOutput(this.lastRunText) : undefined;
13217
12799
  if (review) {
13218
- log35.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
12800
+ log34.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
13219
12801
  }
13220
12802
  const registry = buildGateCollectorRegistry2({
13221
12803
  build: {
@@ -13232,7 +12814,7 @@ ${prompt}`;
13232
12814
  return [];
13233
12815
  const criteria = await fetchAcceptanceCriteria(this.client, this.tag, card);
13234
12816
  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`);
12817
+ 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
12818
  }
13237
12819
  return criteria;
13238
12820
  })()
@@ -13254,10 +12836,10 @@ ${prompt}`;
13254
12836
  const evaluation = gateEvaluate(gate, evidence);
13255
12837
  const insert = toStageGateEvidenceInsert(context, evidence);
13256
12838
  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}`);
12839
+ log34.info(this.tag, `Recorded ${gate.kind} gate evidence for #${card.short_id} stage "${stage.name}": result=${evidence.result} passed=${evaluation.passed}`);
13258
12840
  return evaluation;
13259
12841
  } catch (err) {
13260
- log35.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12842
+ log34.warn(this.tag, `stage-gate evidence collection failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13261
12843
  return null;
13262
12844
  }
13263
12845
  }
@@ -13275,7 +12857,7 @@ ${prompt}`;
13275
12857
  agentSessionId: this.sessionId
13276
12858
  });
13277
12859
  } catch (err) {
13278
- log35.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
12860
+ log34.warn(this.tag, `stage advancement failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
13279
12861
  return { kind: "no_advance" };
13280
12862
  }
13281
12863
  }
@@ -13301,7 +12883,7 @@ ${prompt}`;
13301
12883
  this.modelChoice = choice;
13302
12884
  const { model, escalated, source } = choice;
13303
12885
  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"})`);
12886
+ log34.info(this.tag, `Implement model "${model}" (source=${source}, escalated=${escalated}, attempts=${attempts}, priority=${card.priority ?? "none"}, tier=${this.sizing?.tier ?? "none"})`);
13305
12887
  }
13306
12888
  return model;
13307
12889
  }
@@ -13316,7 +12898,7 @@ ${prompt}`;
13316
12898
  encoding: "utf-8"
13317
12899
  }).trim();
13318
12900
  } 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`);
12901
+ 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
12902
  return { status: "failed", reason: "spawn" };
13321
12903
  }
13322
12904
  const outcome = await sizeRun({
@@ -13330,21 +12912,22 @@ ${prompt}`;
13330
12912
  scoreBands: claude.scoreBands
13331
12913
  });
13332
12914
  if (outcome.status === "sized") {
13333
- log35.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
12915
+ log34.info(this.tag, `Sized #${card.short_id}: complexity ${outcome.sizing.complexity}/10 -> ${outcome.sizing.tier}`);
13334
12916
  } else if (outcome.status === "failed") {
13335
- log35.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
12917
+ log34.warn(this.tag, `Sizing #${card.short_id} failed (${outcome.reason}) — using the policy fallback`);
13336
12918
  }
13337
12919
  return outcome;
13338
12920
  }
13339
12921
  recordPromptAssembled(outcomes) {
13340
- const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count ?? 0;
12922
+ const countOf = (flavour) => outcomes.find((o) => o.flavour === flavour)?.count;
13341
12923
  const failures = outcomes.flatMap((o) => o.failure ? [{ flavour: o.flavour, message: o.failure.slice(0, 300) }] : []);
12924
+ const episodeCount = countOf("past_episodes");
13342
12925
  this.cliRunner?.record({
13343
12926
  kind: "prompt_assembled",
13344
12927
  source: "system",
13345
12928
  payload: {
13346
- episodeCount: countOf("past_episodes"),
13347
- referenceCount: countOf("reference"),
12929
+ ...episodeCount === undefined ? {} : { episodeCount },
12930
+ referenceCount: countOf("reference") ?? 0,
13348
12931
  ...failures.length > 0 ? { recallFailures: failures } : {}
13349
12932
  }
13350
12933
  });
@@ -13365,7 +12948,7 @@ ${prompt}`;
13365
12948
  const measured = measureRunCommits(this.worktreePath, this.config.worktree.baseBranch, this.runBaselineSha);
13366
12949
  if (measured !== "none") {
13367
12950
  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"}`);
12951
+ log34.debug(this.tag, `no-commit check could not attribute this run's commits — staying quiet on ${this.branchName ?? "this branch"}`);
13369
12952
  }
13370
12953
  return;
13371
12954
  }
@@ -13374,7 +12957,7 @@ ${prompt}`;
13374
12957
  recordNoCommitsYet(trigger, numTurns) {
13375
12958
  const turnBudget = this.effectiveMaxTurns;
13376
12959
  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})`);
12960
+ 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
12961
  this.cliRunner?.record({
13379
12962
  kind: "no_commits_yet",
13380
12963
  source: "system",
@@ -13426,9 +13009,9 @@ ${prompt}`;
13426
13009
  agentSessionId: this.sessionId ?? undefined
13427
13010
  });
13428
13011
  giveUpCommentId = res?.comment?.id ?? null;
13429
- log35.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13012
+ log34.warn(this.tag, `gave up on ${cardId} after ${attempts} attempts`);
13430
13013
  } catch (err) {
13431
- log35.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13014
+ log34.warn(this.tag, `failed to post give-up comment for ${cardId}: ${err instanceof Error ? err.message : err}`);
13432
13015
  }
13433
13016
  if (this.config.budget.pause.enabled) {
13434
13017
  const waitHours = this.config.budget.pause.waitHours;
@@ -13442,7 +13025,7 @@ ${prompt}`;
13442
13025
  awaitingDecisionUntil: new Date(until).toISOString()
13443
13026
  });
13444
13027
  } catch (err) {
13445
- log35.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13028
+ log34.warn(this.tag, `Failed to mark the attempt cap pending for ${cardId}: ${err}`);
13446
13029
  }
13447
13030
  try {
13448
13031
  await this.stateStore.markAwaitingDecision(cardId, {
@@ -13451,19 +13034,19 @@ ${prompt}`;
13451
13034
  agentIdentifier: this.sessionIdentifier
13452
13035
  });
13453
13036
  } catch (err) {
13454
- log35.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13037
+ log34.warn(this.tag, `Failed to record the attempt-cap decision locally for ${cardId}: ${err}`);
13455
13038
  }
13456
13039
  }
13457
13040
  }
13458
13041
  }
13459
13042
  } catch (err) {
13460
- log35.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13043
+ log34.warn(this.tag, `recordOutcome(${outcome}) failed: ${err instanceof Error ? err.message : err}`);
13461
13044
  }
13462
13045
  }
13463
13046
  async pause() {
13464
13047
  if (!this.isActive || !this.process || this.process.killed)
13465
13048
  return;
13466
- log35.info(this.tag, `Pausing work on ${this.cardId}`);
13049
+ log34.info(this.tag, `Pausing work on ${this.cardId}`);
13467
13050
  signalGroup2(this.process, "SIGSTOP");
13468
13051
  if (this.timeoutTimer) {
13469
13052
  clearTimeout(this.timeoutTimer);
@@ -13477,17 +13060,17 @@ ${prompt}`;
13477
13060
  status: "paused"
13478
13061
  });
13479
13062
  } catch {
13480
- log35.warn(this.tag, "Failed to update agent session to paused");
13063
+ log34.warn(this.tag, "Failed to update agent session to paused");
13481
13064
  }
13482
13065
  }
13483
13066
  }
13484
13067
  async resume() {
13485
13068
  if (!this.isActive || !this.process || this.process.killed)
13486
13069
  return;
13487
- log35.info(this.tag, `Resuming work on ${this.cardId}`);
13070
+ log34.info(this.tag, `Resuming work on ${this.cardId}`);
13488
13071
  signalGroup2(this.process, "SIGCONT");
13489
13072
  this.timeoutTimer = setTimeout(() => {
13490
- log35.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13073
+ log34.warn(this.tag, `Timeout reached (${this.config.maxTimeout}ms), cancelling`);
13491
13074
  this.timedOut = true;
13492
13075
  this.cancel("timeout");
13493
13076
  }, this.config.maxTimeout);
@@ -13499,7 +13082,7 @@ ${prompt}`;
13499
13082
  status: "working"
13500
13083
  });
13501
13084
  } catch {
13502
- log35.warn(this.tag, "Failed to update agent session to working");
13085
+ log34.warn(this.tag, "Failed to update agent session to working");
13503
13086
  }
13504
13087
  }
13505
13088
  }
@@ -13508,7 +13091,7 @@ ${prompt}`;
13508
13091
  return;
13509
13092
  this.aborted = true;
13510
13093
  this.state = "cancelling";
13511
- log35.info(this.tag, `Cancelling work on ${this.cardId}`);
13094
+ log34.info(this.tag, `Cancelling work on ${this.cardId}`);
13512
13095
  this.motorAbort?.abort();
13513
13096
  if (this.sdkRunner) {
13514
13097
  await this.sdkRunner.stop(this.timedOut ? "timeout" : "user_requested");
@@ -13526,14 +13109,14 @@ ${prompt}`;
13526
13109
  ...buildTokenPayload(stats)
13527
13110
  });
13528
13111
  } catch (err) {
13529
- log35.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13112
+ log34.warn(this.tag, `endAgentSession after cancel failed: ${err instanceof Error ? err.message : err}`);
13530
13113
  }
13531
13114
  }
13532
13115
  }
13533
13116
  async runPlanningPhase(enriched) {
13534
13117
  const planning = this.config.planning;
13535
13118
  const { card } = enriched;
13536
- log35.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13119
+ log34.info(this.tag, `Planning pass for #${card.short_id} (mode=${planning.mode}, model=${planning.model})`);
13537
13120
  await this.client.updateAgentProgress(card.id, {
13538
13121
  agentIdentifier: this.sessionIdentifier,
13539
13122
  agentName: AGENT_NAME,
@@ -13546,7 +13129,7 @@ ${prompt}`;
13546
13129
  let planTimedOut = false;
13547
13130
  const planTimeout = setTimeout(() => {
13548
13131
  planTimedOut = true;
13549
- log35.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13132
+ log34.warn(this.tag, "Planning pass exceeded timeout — abandoning, implementing directly");
13550
13133
  if (this.sdkRunner) {
13551
13134
  this.sdkRunner.stop("timeout").catch(() => {});
13552
13135
  } else if (this.process && !this.process.killed) {
@@ -13564,7 +13147,7 @@ ${prompt}`;
13564
13147
  initialPhase: "planning"
13565
13148
  });
13566
13149
  } catch (err) {
13567
- log35.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13150
+ log34.warn(this.tag, `Planning pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13568
13151
  return false;
13569
13152
  } finally {
13570
13153
  clearTimeout(planTimeout);
@@ -13575,7 +13158,7 @@ ${prompt}`;
13575
13158
  await this.chargeDailyLedger(card.id, card.short_id);
13576
13159
  const planText = stats?.lastAssistantText ?? "";
13577
13160
  if (!planText.trim()) {
13578
- log35.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13161
+ log34.warn(this.tag, `Planning pass for #${card.short_id} produced no text — implementing directly`);
13579
13162
  return false;
13580
13163
  }
13581
13164
  const artifact = extractPlanArtifact(planText, card.title);
@@ -13596,9 +13179,9 @@ ${prompt}`;
13596
13179
  });
13597
13180
  planId = createdId;
13598
13181
  }
13599
- log35.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13182
+ log34.info(this.tag, `Stored plan ${planId ?? "(unlinked)"} for #${card.short_id} (${artifact.tasks.length} tasks)`);
13600
13183
  } catch (err) {
13601
- log35.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13184
+ log34.warn(this.tag, `Failed to store/link plan (non-fatal): ${err instanceof Error ? err.message : err}`);
13602
13185
  }
13603
13186
  if (planning.mode === "gated" && planId) {
13604
13187
  try {
@@ -13617,11 +13200,11 @@ ${prompt}`;
13617
13200
  ...buildTokenPayload(stats)
13618
13201
  }
13619
13202
  }, { store: this.stateStore, runId: this.runId ?? undefined });
13620
- log35.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13203
+ log34.info(this.tag, `#${card.short_id} parked in "${planning.awaitingApprovalColumn}" for plan approval`);
13621
13204
  this.lastSessionStats = undefined;
13622
13205
  return true;
13623
13206
  } 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}`);
13207
+ 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
13208
  }
13626
13209
  }
13627
13210
  if (planId && planning.postComment) {
@@ -13631,7 +13214,7 @@ ${prompt}`;
13631
13214
  agentSessionId: this.sessionId ?? undefined
13632
13215
  });
13633
13216
  } catch (err) {
13634
- log35.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13217
+ log34.warn(this.tag, `Failed to post advisory plan comment (non-fatal): ${err instanceof Error ? err.message : err}`);
13635
13218
  }
13636
13219
  }
13637
13220
  return false;
@@ -13641,10 +13224,10 @@ ${prompt}`;
13641
13224
  const { card } = enriched;
13642
13225
  const existing = await this.loadPinnedContract(card.id);
13643
13226
  if (existing) {
13644
- log35.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13227
+ log34.info(this.tag, `Contract already pinned for #${card.short_id} (${existing.assertions.length} assertions) — reusing`);
13645
13228
  return;
13646
13229
  }
13647
- log35.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13230
+ log34.info(this.tag, `Contract pass for #${card.short_id} (model=${contractCfg.model})`);
13648
13231
  await this.client.updateAgentProgress(card.id, {
13649
13232
  agentIdentifier: this.sessionIdentifier,
13650
13233
  agentName: AGENT_NAME,
@@ -13657,7 +13240,7 @@ ${prompt}`;
13657
13240
  let contractTimedOut = false;
13658
13241
  const contractTimeout = setTimeout(() => {
13659
13242
  contractTimedOut = true;
13660
- log35.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13243
+ log34.warn(this.tag, "Contract pass exceeded timeout — abandoning, implementing directly");
13661
13244
  if (this.sdkRunner) {
13662
13245
  this.sdkRunner.stop("timeout").catch(() => {});
13663
13246
  } else if (this.process && !this.process.killed) {
@@ -13675,7 +13258,7 @@ ${prompt}`;
13675
13258
  initialPhase: "planning"
13676
13259
  });
13677
13260
  } catch (err) {
13678
- log35.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13261
+ log34.warn(this.tag, `Contract pass failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13679
13262
  return;
13680
13263
  } finally {
13681
13264
  clearTimeout(contractTimeout);
@@ -13686,12 +13269,12 @@ ${prompt}`;
13686
13269
  await this.chargeDailyLedger(card.id, card.short_id);
13687
13270
  const contractText = stats?.lastAssistantText ?? "";
13688
13271
  if (!contractText.trim()) {
13689
- log35.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13272
+ log34.warn(this.tag, `Contract pass for #${card.short_id} produced no text — implementing directly`);
13690
13273
  return;
13691
13274
  }
13692
13275
  const contract = extractContract(contractText, card);
13693
13276
  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`);
13277
+ log34.warn(this.tag, `Contract for #${card.short_id} had ${contract.assertions.length} assertion(s) (< ${contractCfg.minAssertions}) — not pinning, implementing directly`);
13695
13278
  return;
13696
13279
  }
13697
13280
  try {
@@ -13699,9 +13282,9 @@ ${prompt}`;
13699
13282
  commentType: "decision",
13700
13283
  agentSessionId: this.sessionId ?? undefined
13701
13284
  });
13702
- log35.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13285
+ log34.info(this.tag, `Pinned acceptance contract for #${card.short_id} (${contract.assertions.length} assertions)`);
13703
13286
  } catch (err) {
13704
- log35.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13287
+ log34.warn(this.tag, `Failed to pin contract (non-fatal): ${err instanceof Error ? err.message : err}`);
13705
13288
  }
13706
13289
  }
13707
13290
  async loadPinnedContract(cardId) {
@@ -13711,7 +13294,7 @@ ${prompt}`;
13711
13294
  return null;
13712
13295
  return extractPinnedContract(comments, this.identity);
13713
13296
  } catch (err) {
13714
- log35.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13297
+ log34.warn(this.tag, `pinned-contract fetch failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13715
13298
  return null;
13716
13299
  }
13717
13300
  }
@@ -13724,13 +13307,13 @@ ${prompt}`;
13724
13307
  const res = await this.client.getPendingUserMessages(this.cardId, this.sessionId, this.lastDrainedSeq);
13725
13308
  messages = res.messages ?? [];
13726
13309
  } catch (err) {
13727
- log35.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13310
+ log34.warn(this.tag, `Failed to fetch steering messages (non-fatal): ${err instanceof Error ? err.message : err}`);
13728
13311
  return;
13729
13312
  }
13730
13313
  if (messages.length === 0)
13731
13314
  return;
13732
13315
  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)`);
13316
+ log34.info(this.tag, `Steering #${card.short_id}: resuming with ${messages.length} queued message(s)`);
13734
13317
  this.state = "running";
13735
13318
  await this.recordPhase("running");
13736
13319
  try {
@@ -13742,7 +13325,7 @@ ${prompt}`;
13742
13325
  ...this.activeRunSpawnOpts ?? {}
13743
13326
  });
13744
13327
  } catch (err) {
13745
- log35.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13328
+ log34.warn(this.tag, `Steering resume failed (non-fatal): ${err instanceof Error ? err.message : err}`);
13746
13329
  return;
13747
13330
  }
13748
13331
  }
@@ -13777,10 +13360,10 @@ ${prompt}`;
13777
13360
  "--",
13778
13361
  prompt
13779
13362
  ];
13780
- log35.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13363
+ log34.info(this.tag, `Spawning: claude ${args.slice(0, 4).join(" ")} ...`);
13781
13364
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13782
13365
  if (runLog) {
13783
- log35.info(this.tag, `Run log: ${runLog.path}`);
13366
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13784
13367
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} started=${new Date().toISOString()}
13785
13368
  ` + `# args: ${args.slice(0, -2).join(" ")} -- <prompt:${prompt.length} chars>
13786
13369
 
@@ -13817,7 +13400,7 @@ ${prompt}`;
13817
13400
  });
13818
13401
  }
13819
13402
  parser.on("parse_error", (msg) => {
13820
- log35.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13403
+ log34.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
13821
13404
  runLog?.stream.write(`
13822
13405
  [parse_error] ${msg}
13823
13406
  `);
@@ -13890,10 +13473,10 @@ ${prompt}`;
13890
13473
  const disallowedTools = opts.disallowedTools ? opts.disallowedTools.split(",").map((t) => t.trim()).filter(Boolean) : undefined;
13891
13474
  const initialPhase = opts.initialPhase ?? "exploring";
13892
13475
  const maxBudgetUsd = this.effectiveMaxBudgetUsd;
13893
- log35.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13476
+ log34.info(this.tag, `Spawning Agent SDK runner (model=${model}, maxBudgetUsd=${maxBudgetUsd || "off"}, maxTurns=${maxTurns}${opts.resumeSessionId ? ", resume" : ""})`);
13894
13477
  const runLog = openRunLog(this.tag, this.runId, card.short_id);
13895
13478
  if (runLog) {
13896
- log35.info(this.tag, `Run log: ${runLog.path}`);
13479
+ log34.info(this.tag, `Run log: ${runLog.path}`);
13897
13480
  runLog.stream.write(`# run=${this.runId} card=#${card.short_id} runner=sdk started=${new Date().toISOString()}
13898
13481
  ` + `# model=${model} maxTurns=${maxTurns} <prompt:${prompt.length} chars>
13899
13482
 
@@ -14028,7 +13611,7 @@ ${prompt}`;
14028
13611
  try {
14029
13612
  await teardownWorktree2(this.client, this.cardId, this.worktreePath, this.branchName ?? undefined, this.sessionId);
14030
13613
  } catch {
14031
- log35.warn(this.tag, "Failed to cleanup worktree");
13614
+ log34.warn(this.tag, "Failed to cleanup worktree");
14032
13615
  }
14033
13616
  }
14034
13617
  this.process = null;
@@ -14047,7 +13630,7 @@ ${prompt}`;
14047
13630
  this.chargedTokens = emptyTokens();
14048
13631
  }
14049
13632
  }
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;
13633
+ 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
13634
  var init_worker = __esm(() => {
14052
13635
  init_dist();
14053
13636
  init_board_helpers();
@@ -14078,7 +13661,7 @@ var init_worker = __esm(() => {
14078
13661
  });
14079
13662
 
14080
13663
  // src/workspace-model-cache.ts
14081
- import { log as log36 } from "@gethmy/harness";
13664
+ import { log as log35 } from "@gethmy/harness";
14082
13665
 
14083
13666
  class WorkspaceModelCache {
14084
13667
  fetcher;
@@ -14113,7 +13696,7 @@ class WorkspaceModelCache {
14113
13696
  this.stale = false;
14114
13697
  } catch (err) {
14115
13698
  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)}`);
13699
+ 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
13700
  }
14118
13701
  return this.value;
14119
13702
  }
@@ -14124,8 +13707,14 @@ var init_workspace_model_cache = () => {};
14124
13707
  import {
14125
13708
  cooldownMsFor,
14126
13709
  describeApiError as describeApiError3,
14127
- log as log37
13710
+ log as log36
14128
13711
  } from "@gethmy/harness";
13712
+ function httpStatusOf(err) {
13713
+ if (typeof err !== "object" || err === null)
13714
+ return;
13715
+ const status = own(err, "status");
13716
+ return typeof status === "number" ? status : undefined;
13717
+ }
14129
13718
  async function routeBudgetDecision(d, run, actions, cardId) {
14130
13719
  if (!run) {
14131
13720
  if (!cardId)
@@ -14220,11 +13809,11 @@ class Pool {
14220
13809
  }
14221
13810
  async enqueue(card, column, labels, subtasks, mode = "implement") {
14222
13811
  if (card.done || card.archived_at) {
14223
- log37.debug(TAG33, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
13812
+ log36.debug(TAG32, `#${card.short_id} skipped — ${card.done ? "done" : "archived"} (finished work is never enqueued, #1102)`);
14224
13813
  return;
14225
13814
  }
14226
13815
  if (this.isCardKnown(card.id) || this.reservations.has(card.id)) {
14227
- log37.debug(TAG33, `Card ${card.id} already queued, active, or reserved, skipping`);
13816
+ log36.debug(TAG32, `Card ${card.id} already queued, active, or reserved, skipping`);
14228
13817
  return;
14229
13818
  }
14230
13819
  this.reservations.add(card.id);
@@ -14232,19 +13821,19 @@ class Pool {
14232
13821
  try {
14233
13822
  const account = this.accountGuard?.check();
14234
13823
  if (account && !account.running) {
14235
- log37.debug(TAG33, `#${card.short_id} held — ${account.detail}`);
13824
+ log36.debug(TAG32, `#${card.short_id} held — ${account.detail}`);
14236
13825
  await this.emitWaiting(card.id, account.detail);
14237
13826
  return;
14238
13827
  }
14239
13828
  if (mode === "implement") {
14240
13829
  if (this.authPaused) {
14241
- log37.debug(TAG33, `#${card.short_id} held — agent paused (auth error)`);
13830
+ log36.debug(TAG32, `#${card.short_id} held — agent paused (auth error)`);
14242
13831
  await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
14243
13832
  return;
14244
13833
  }
14245
13834
  const cooldownMs = this.apiCooldownRemainingMs();
14246
13835
  if (cooldownMs > 0) {
14247
- log37.debug(TAG33, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
13836
+ log36.debug(TAG32, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
14248
13837
  await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
14249
13838
  return;
14250
13839
  }
@@ -14253,19 +13842,19 @@ class Pool {
14253
13842
  if (decision.reason === "daily_budget") {
14254
13843
  await this.denyDailyBudget(card, decision.detail);
14255
13844
  } else {
14256
- log37.debug(TAG33, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
13845
+ log36.debug(TAG32, `#${card.short_id} skipped (${decision.reason}): ${decision.detail}`);
14257
13846
  }
14258
13847
  return;
14259
13848
  }
14260
13849
  const { blockers, successors } = await getChainSignals(this.client, card, this.projectId);
14261
13850
  chainSuccessors = successors;
14262
13851
  if (blockers === null) {
14263
- log37.warn(TAG33, `#${card.short_id} blocker check failed — deferring to next tick`);
13852
+ log36.warn(TAG32, `#${card.short_id} blocker check failed — deferring to next tick`);
14264
13853
  return;
14265
13854
  }
14266
13855
  if (blockers.length > 0) {
14267
13856
  const list = blockers.map((b) => `#${b.shortId}`).join(", ");
14268
- log37.info(TAG33, `#${card.short_id} blocked by ${list} — waiting`);
13857
+ log36.info(TAG32, `#${card.short_id} blocked by ${list} — waiting`);
14269
13858
  await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
14270
13859
  return;
14271
13860
  }
@@ -14297,9 +13886,9 @@ class Pool {
14297
13886
  const reason = `Daily budget reached — waiting for reset (${detail})`;
14298
13887
  const line = `#${card.short_id} skipped (daily_budget): ${detail}`;
14299
13888
  if (this.lastWaitingEmit.get(card.id) === reason)
14300
- log37.debug(TAG33, line);
13889
+ log36.debug(TAG32, line);
14301
13890
  else
14302
- log37.warn(TAG33, line);
13891
+ log36.warn(TAG32, line);
14303
13892
  await this.emitWaiting(card.id, reason);
14304
13893
  }
14305
13894
  lastWaitingEmit = new Map;
@@ -14316,7 +13905,7 @@ class Pool {
14316
13905
  });
14317
13906
  this.lastWaitingEmit.set(cardId, currentTask);
14318
13907
  } catch (err) {
14319
- log37.debug(TAG33, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
13908
+ log36.debug(TAG32, `waiting emit failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
14320
13909
  }
14321
13910
  }
14322
13911
  noteApiError(err) {
@@ -14324,13 +13913,13 @@ class Pool {
14324
13913
  return;
14325
13914
  if (err.kind === "spend_limit") {
14326
13915
  this.accountGuard?.halt("spend_limit").catch((hErr) => {
14327
- log37.error(TAG33, `Failed to latch the account halt: ${hErr}`);
13916
+ log36.error(TAG32, `Failed to latch the account halt: ${hErr}`);
14328
13917
  });
14329
13918
  return;
14330
13919
  }
14331
13920
  if (err.kind === "auth") {
14332
13921
  if (!this.authPaused) {
14333
- log37.error(TAG33, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
13922
+ log36.error(TAG32, "Auth error from Claude CLI — pausing implement pickups until the daemon is restarted with valid credentials");
14334
13923
  }
14335
13924
  this.authPaused = true;
14336
13925
  return;
@@ -14339,7 +13928,7 @@ class Pool {
14339
13928
  const until = Date.now() + cooldownMs;
14340
13929
  if (until > this.apiCooldownUntil) {
14341
13930
  this.apiCooldownUntil = until;
14342
- log37.warn(TAG33, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
13931
+ log36.warn(TAG32, `${describeApiError3(err.kind)} — pausing implement pickups for ${Math.round(cooldownMs / 1000)}s`);
14343
13932
  }
14344
13933
  }
14345
13934
  apiCooldownRemainingMs() {
@@ -14353,13 +13942,13 @@ class Pool {
14353
13942
  const removed = queue.remove(cardId);
14354
13943
  if (removed) {
14355
13944
  this.cardDataCache.delete(cardId);
14356
- log37.info(TAG33, `Removed #${removed.shortId} from ${removed.mode} queue`);
13945
+ log36.info(TAG32, `Removed #${removed.shortId} from ${removed.mode} queue`);
14357
13946
  return;
14358
13947
  }
14359
13948
  }
14360
13949
  const worker = this.implWorkers.find((w) => w.cardId === cardId) ?? this.reviewWorkers.find((w) => w.cardId === cardId);
14361
13950
  if (worker) {
14362
- log37.info(TAG33, `Cancelling worker ${worker.id} for card ${cardId}`);
13951
+ log36.info(TAG32, `Cancelling worker ${worker.id} for card ${cardId}`);
14363
13952
  await worker.cancel("unassigned");
14364
13953
  }
14365
13954
  }
@@ -14416,10 +14005,10 @@ class Pool {
14416
14005
  }
14417
14006
  const worker = this.implWorkers.find((w) => w.cardId === cardId && w.isActive) ?? this.reviewWorkers.find((w) => w.cardId === cardId && w.isActive);
14418
14007
  if (!worker) {
14419
- log37.debug(TAG33, `No active worker for card ${cardId}, ignoring ${command}`);
14008
+ log36.debug(TAG32, `No active worker for card ${cardId}, ignoring ${command}`);
14420
14009
  return;
14421
14010
  }
14422
- log37.info(TAG33, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
14011
+ log36.info(TAG32, `Agent command: ${command} → worker ${worker.id} (card ${cardId})`);
14423
14012
  switch (command) {
14424
14013
  case "pause":
14425
14014
  await worker.pause();
@@ -14467,7 +14056,7 @@ class Pool {
14467
14056
  };
14468
14057
  }
14469
14058
  async shutdown() {
14470
- log37.info(TAG33, "Shutting down pool...");
14059
+ log36.info(TAG32, "Shutting down pool...");
14471
14060
  this.shuttingDown = true;
14472
14061
  const active = [
14473
14062
  ...this.implWorkers.filter((w) => w.isActive),
@@ -14475,7 +14064,7 @@ class Pool {
14475
14064
  ];
14476
14065
  await Promise.all(active.map((w) => w.cancel("shutdown")));
14477
14066
  this.sleepGuard.stop();
14478
- log37.info(TAG33, "Pool shutdown complete");
14067
+ log36.info(TAG32, "Pool shutdown complete");
14479
14068
  }
14480
14069
  async drainBudgetDecisions(cardId) {
14481
14070
  const targets = cardId ? [cardId] : [
@@ -14506,7 +14095,11 @@ class Pool {
14506
14095
  try {
14507
14096
  ({ decisions } = await this.client.getBudgetDecisions(cardId, new Date(sinceMs).toISOString()));
14508
14097
  } catch (err) {
14509
- log37.warn(TAG33, `getBudgetDecisions failed for ${cardId}: ${err}`);
14098
+ if (httpStatusOf(err) === 404) {
14099
+ await this.forgetDeletedCard(cardId, run);
14100
+ return;
14101
+ }
14102
+ log36.warn(TAG32, `getBudgetDecisions failed for ${cardId}: ${err}`);
14510
14103
  return;
14511
14104
  }
14512
14105
  if (decisions.length > 0) {
@@ -14530,6 +14123,25 @@ class Pool {
14530
14123
  this.draining.delete(cardId);
14531
14124
  }
14532
14125
  }
14126
+ async forgetDeletedCard(cardId, run) {
14127
+ if (run) {
14128
+ try {
14129
+ await this.stateStore.endRun(run.runId, "failed", {
14130
+ errorMessage: "card deleted"
14131
+ });
14132
+ } catch (err) {
14133
+ log36.warn(TAG32, `Failed to end the parked run for the deleted card ${cardId}: ${err}`);
14134
+ }
14135
+ }
14136
+ try {
14137
+ const dropped = await this.stateStore.forgetCard(cardId);
14138
+ if (dropped) {
14139
+ log36.info(TAG32, `Card ${cardId} no longer exists on the server — dropped from the local ledger; its budget question can never be answered`);
14140
+ }
14141
+ } catch (err) {
14142
+ log36.warn(TAG32, `Failed to drop the deleted card ${cardId}: ${err}`);
14143
+ }
14144
+ }
14533
14145
  async releaseExpiredPark(run) {
14534
14146
  try {
14535
14147
  await this.client.addComment(run.cardId, formatExpiredParkComment({
@@ -14541,7 +14153,7 @@ class Pool {
14541
14153
  ...run.blockerCommentId ? { replyToId: run.blockerCommentId } : {}
14542
14154
  });
14543
14155
  } catch (err) {
14544
- log37.warn(TAG33, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14156
+ log36.warn(TAG32, `Failed to post the expired-park closing comment for ${run.cardId}: ${err}`);
14545
14157
  }
14546
14158
  try {
14547
14159
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14555,14 +14167,14 @@ class Pool {
14555
14167
  });
14556
14168
  }
14557
14169
  } catch (err) {
14558
- log37.error(TAG33, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14170
+ log36.error(TAG32, `Failed to move #${run.cardShortId} after an expired park: ${err}`);
14559
14171
  }
14560
14172
  try {
14561
14173
  await this.stateStore.endRun(run.runId, "failed", {
14562
14174
  errorMessage: "budget decision expired"
14563
14175
  });
14564
14176
  } catch (err) {
14565
- log37.warn(TAG33, `Failed to release the expired park for ${run.cardId}: ${err}`);
14177
+ log36.warn(TAG32, `Failed to release the expired park for ${run.cardId}: ${err}`);
14566
14178
  }
14567
14179
  }
14568
14180
  async releaseExpiredAttemptCap(cardId, blockerCommentId) {
@@ -14572,7 +14184,7 @@ class Pool {
14572
14184
  ...blockerCommentId ? { replyToId: blockerCommentId } : {}
14573
14185
  });
14574
14186
  } catch (err) {
14575
- log37.warn(TAG33, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14187
+ log36.warn(TAG32, `Failed to post the expired attempt-cap note for ${cardId}: ${err}`);
14576
14188
  }
14577
14189
  try {
14578
14190
  await this.client.endAgentSession(cardId, {
@@ -14581,7 +14193,7 @@ class Pool {
14581
14193
  failureSummary: "The attempt-budget decision expired with no answer. Reassign the card to grant a fresh attempt."
14582
14194
  });
14583
14195
  } catch (err) {
14584
- log37.warn(TAG33, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14196
+ log36.warn(TAG32, `Failed to end the expired attempt-cap session for ${cardId}: ${err}`);
14585
14197
  }
14586
14198
  await this.stateStore.clearAwaitingDecision(cardId);
14587
14199
  }
@@ -14592,16 +14204,16 @@ class Pool {
14592
14204
  }
14593
14205
  const account = this.accountGuard?.check();
14594
14206
  if (account && !account.running) {
14595
- log37.debug(TAG33, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14207
+ log36.debug(TAG32, `#${run.cardShortId}: granted continue held — ${account.detail}`);
14596
14208
  return;
14597
14209
  }
14598
14210
  const first = !this.adoptAnnounced.has(run.runId);
14599
14211
  this.adoptAnnounced.add(run.runId);
14600
14212
  const line = `#${run.cardShortId}: granted continue never reached a worker — re-enqueueing (${run.pipeline})`;
14601
14213
  if (first)
14602
- log37.warn(TAG33, line);
14214
+ log36.warn(TAG32, line);
14603
14215
  else
14604
- log37.debug(TAG33, line);
14216
+ log36.debug(TAG32, line);
14605
14217
  await this.enqueueCard(run.cardId, run.pipeline);
14606
14218
  }
14607
14219
  adoptAnnounced = new Set;
@@ -14620,7 +14232,7 @@ class Pool {
14620
14232
  async continueRun(run, opts) {
14621
14233
  const turns = this.budget.checkCardTurns(run.cardId);
14622
14234
  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.`);
14235
+ 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
14236
  try {
14625
14237
  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
14238
 
@@ -14629,14 +14241,14 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14629
14241
  agentSessionId: run.sessionId ?? undefined
14630
14242
  });
14631
14243
  } catch (err) {
14632
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14244
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14633
14245
  }
14634
14246
  await this.stopRun(run, "Continue refused: the card is at its per-card turn cap.");
14635
14247
  return;
14636
14248
  }
14637
14249
  const runsSpent = this.budget.checkCardRuns(run.cardId);
14638
14250
  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.`);
14251
+ 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
14252
  try {
14641
14253
  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
14254
 
@@ -14645,7 +14257,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14645
14257
  agentSessionId: run.sessionId ?? undefined
14646
14258
  });
14647
14259
  } catch (err) {
14648
- log37.warn(TAG33, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14260
+ log36.warn(TAG32, `Could not explain the refused Continue on ${run.cardId}: ${err instanceof Error ? err.message : err}`);
14649
14261
  }
14650
14262
  await this.stopRun(run, "Continue refused: the card is at its per-card run backstop.");
14651
14263
  return;
@@ -14669,7 +14281,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14669
14281
  awaitingDecisionUntil: null
14670
14282
  });
14671
14283
  } catch (err) {
14672
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14284
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14673
14285
  }
14674
14286
  if (run.blockerCommentId) {
14675
14287
  try {
@@ -14677,7 +14289,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14677
14289
  resolve: true
14678
14290
  });
14679
14291
  } catch (err) {
14680
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14292
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14681
14293
  }
14682
14294
  }
14683
14295
  await this.enqueueCard(run.cardId, run.pipeline);
@@ -14701,7 +14313,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14701
14313
  awaitingDecisionUntil: null
14702
14314
  });
14703
14315
  } catch (err) {
14704
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14316
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14705
14317
  }
14706
14318
  if (run.blockerCommentId) {
14707
14319
  try {
@@ -14709,13 +14321,13 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14709
14321
  resolve: true
14710
14322
  });
14711
14323
  } catch (err) {
14712
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14324
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14713
14325
  }
14714
14326
  }
14715
14327
  await this.enqueueCard(run.cardId, run.pipeline);
14716
14328
  released += 1;
14717
14329
  } catch (err) {
14718
- log37.error(TAG33, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14330
+ log36.error(TAG32, `Failed to release the account-limit park on ${run.cardId}: ${err}`);
14719
14331
  }
14720
14332
  }
14721
14333
  return released;
@@ -14727,7 +14339,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14727
14339
  resolve: true
14728
14340
  });
14729
14341
  } catch (err) {
14730
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14342
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14731
14343
  }
14732
14344
  }
14733
14345
  try {
@@ -14736,7 +14348,7 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14736
14348
  awaitingDecisionUntil: null
14737
14349
  });
14738
14350
  } catch (err) {
14739
- log37.warn(TAG33, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14351
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${run.cardId}: ${err}`);
14740
14352
  }
14741
14353
  try {
14742
14354
  const { verdict, card } = await guardedHandback(this.client, run.cardId, {
@@ -14758,26 +14370,26 @@ I am handing the card back rather than holding it parked. Reassign it — that c
14758
14370
  await this.client.endAgentSession(run.cardId, endSession);
14759
14371
  }
14760
14372
  } catch (err) {
14761
- log37.error(TAG33, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14373
+ log36.error(TAG32, `Failed to hand #${run.cardShortId} back after a stop: ${err}`);
14762
14374
  }
14763
14375
  try {
14764
14376
  await this.stateStore.endRun(run.runId, "failed", {
14765
14377
  errorMessage: "budget_decision_stop"
14766
14378
  });
14767
14379
  } catch (err) {
14768
- log37.warn(TAG33, `Failed to end the local run record for ${run.cardId}: ${err}`);
14380
+ log36.warn(TAG32, `Failed to end the local run record for ${run.cardId}: ${err}`);
14769
14381
  }
14770
14382
  }
14771
14383
  async grantAttempt(cardId) {
14772
14384
  const turns = this.budget.checkCardTurns(cardId);
14773
14385
  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.`);
14386
+ 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
14387
  try {
14776
14388
  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
14389
 
14778
14390
  Reassign the card — that clears the turn count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14779
14391
  } catch (err) {
14780
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14392
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14781
14393
  }
14782
14394
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14783
14395
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card turn cap.");
@@ -14785,13 +14397,13 @@ Reassign the card — that clears the turn count and starts it fresh — or rais
14785
14397
  }
14786
14398
  const runsSpent = this.budget.checkCardRuns(cardId);
14787
14399
  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.`);
14400
+ 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
14401
  try {
14790
14402
  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
14403
 
14792
14404
  Reassign the card — that clears the run count and starts it fresh — or raise the cap in the daemon config.`, { commentType: "blocker" });
14793
14405
  } catch (err) {
14794
- log37.warn(TAG33, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14406
+ log36.warn(TAG32, `Could not explain the capped attempt grant on ${cardId}: ${err instanceof Error ? err.message : err}`);
14795
14407
  }
14796
14408
  await this.stateStore.resetAttempts(cardId, { clearTurns: false });
14797
14409
  await this.stopAttemptCap(cardId, "Attempt budget cleared, but the card is at its per-card run backstop.");
@@ -14806,7 +14418,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14806
14418
  awaitingDecisionUntil: null
14807
14419
  });
14808
14420
  } catch (err) {
14809
- log37.warn(TAG33, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14421
+ log36.warn(TAG32, `Failed to clear the attempt-cap decision deadline for ${cardId}: ${err}`);
14810
14422
  }
14811
14423
  await this.enqueueCard(cardId, "implement");
14812
14424
  }
@@ -14817,7 +14429,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14817
14429
  try {
14818
14430
  await this.client.updateComment(blockerCommentId, { resolve: true });
14819
14431
  } catch (err) {
14820
- log37.warn(TAG33, `Failed to resolve the blocker comment: ${err}`);
14432
+ log36.warn(TAG32, `Failed to resolve the blocker comment: ${err}`);
14821
14433
  }
14822
14434
  }
14823
14435
  try {
@@ -14826,7 +14438,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14826
14438
  awaitingDecisionUntil: null
14827
14439
  });
14828
14440
  } catch (err) {
14829
- log37.warn(TAG33, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14441
+ log36.warn(TAG32, `Failed to clear the decision deadline for ${cardId}: ${err}`);
14830
14442
  }
14831
14443
  try {
14832
14444
  await this.client.endAgentSession(cardId, {
@@ -14835,7 +14447,7 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14835
14447
  failureSummary
14836
14448
  });
14837
14449
  } catch (err) {
14838
- log37.warn(TAG33, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14450
+ log36.warn(TAG32, `Failed to end the attempt-cap session for ${cardId}: ${err}`);
14839
14451
  }
14840
14452
  await this.stateStore.clearAwaitingDecision(cardId);
14841
14453
  }
@@ -14866,12 +14478,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14866
14478
  const subtasks = card.subtasks ?? [];
14867
14479
  await this.enqueue(card, column, cardLabels, subtasks, mode);
14868
14480
  } catch (err) {
14869
- log37.error(TAG33, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14481
+ log36.error(TAG32, `Failed to re-enqueue ${cardId} after a budget decision: ${err}`);
14870
14482
  }
14871
14483
  }
14872
14484
  async retireUnroutableRuns(shortId, cardId, reason = "column not found on this board") {
14873
14485
  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`);
14486
+ log36.warn(TAG32, `#${shortId}: ${reason} — retiring ${unended.length} run record(s) instead of re-enqueueing`);
14875
14487
  for (const run of unended) {
14876
14488
  await this.stateStore.endRun(run.runId, "orphaned", {
14877
14489
  errorMessage: `${reason} at re-enqueue — retired as unroutable (#1057/#1102)`
@@ -14884,12 +14496,12 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14884
14496
  if (this.shuttingDown)
14885
14497
  return false;
14886
14498
  if (this.accountGuard && !this.accountGuard.check().running) {
14887
- log37.debug(TAG33, `${label} dispatch held — the account is halted`);
14499
+ log36.debug(TAG32, `${label} dispatch held — the account is halted`);
14888
14500
  return false;
14889
14501
  }
14890
14502
  const idle = workers.find((w) => w.isIdle);
14891
14503
  if (!idle) {
14892
- log37.debug(TAG33, `No idle ${label} workers (queue: ${queue.length})`);
14504
+ log36.debug(TAG32, `No idle ${label} workers (queue: ${queue.length})`);
14893
14505
  return false;
14894
14506
  }
14895
14507
  const next = queue.dequeue();
@@ -14897,18 +14509,18 @@ Reassign the card — that clears the run count and starts it fresh — or raise
14897
14509
  return false;
14898
14510
  const data = this.cardDataCache.get(next.cardId);
14899
14511
  if (!data) {
14900
- log37.warn(TAG33, `No cached data for card ${next.cardId}, skipping`);
14512
+ log36.warn(TAG32, `No cached data for card ${next.cardId}, skipping`);
14901
14513
  return false;
14902
14514
  }
14903
14515
  this.cardDataCache.delete(next.cardId);
14904
14516
  this.lastWaitingEmit.delete(next.cardId);
14905
- log37.info(TAG33, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14517
+ log36.info(TAG32, `Dispatching #${next.shortId} to ${label} worker ${idle.id}`);
14906
14518
  this.sleepGuard.acquire();
14907
14519
  idle.run(data.card, data.column, data.labels, data.subtasks);
14908
14520
  return true;
14909
14521
  }
14910
14522
  }
14911
- var TAG33 = "pool";
14523
+ var TAG32 = "pool";
14912
14524
  var init_pool = __esm(() => {
14913
14525
  init_dist();
14914
14526
  init_board_helpers();
@@ -14942,7 +14554,7 @@ import {
14942
14554
  writeFileSync as writeFileSync4
14943
14555
  } from "node:fs";
14944
14556
  import { dirname as dirname5 } from "node:path";
14945
- import { log as log38 } from "@gethmy/harness";
14557
+ import { log as log37 } from "@gethmy/harness";
14946
14558
  function defaultRegistryPath() {
14947
14559
  return portRegistryPath();
14948
14560
  }
@@ -14957,7 +14569,7 @@ function load(path) {
14957
14569
  }
14958
14570
  return emptyRegistry();
14959
14571
  } catch (err) {
14960
- log38.warn(TAG34, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14572
+ log37.warn(TAG33, `failed to read ${path}: ${err instanceof Error ? err.message : err}`);
14961
14573
  return emptyRegistry();
14962
14574
  }
14963
14575
  }
@@ -14978,7 +14590,7 @@ function recordDaemonPort(projectId, entry, path = defaultRegistryPath()) {
14978
14590
  registry[projectId] = { ...entry, updatedAt: Date.now() };
14979
14591
  save(path, registry);
14980
14592
  } catch (err) {
14981
- log38.warn(TAG34, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14593
+ log37.warn(TAG33, `failed to record port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14982
14594
  }
14983
14595
  }
14984
14596
  function daemonBaseUrl(bindAddr, port) {
@@ -14998,17 +14610,17 @@ function clearDaemonPort(projectId, pid, path = defaultRegistryPath()) {
14998
14610
  delete registry[projectId];
14999
14611
  save(path, registry);
15000
14612
  } catch (err) {
15001
- log38.warn(TAG34, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
14613
+ log37.warn(TAG33, `failed to clear port for ${projectId}: ${err instanceof Error ? err.message : err}`);
15002
14614
  }
15003
14615
  }
15004
- var TAG34 = "port-registry";
14616
+ var TAG33 = "port-registry";
15005
14617
  var init_port_registry = __esm(() => {
15006
14618
  init_dist();
15007
14619
  init_paths();
15008
14620
  });
15009
14621
 
15010
14622
  // src/recovery.ts
15011
- import { log as log39, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
14623
+ import { log as log38, teardownWorktree as teardownWorktree3 } from "@gethmy/harness";
15012
14624
  function isProcessAlive(pid, currentPid) {
15013
14625
  if (pid === currentPid)
15014
14626
  return true;
@@ -15024,7 +14636,7 @@ async function fetchCardSafely(client, cardId) {
15024
14636
  const { card } = await client.getCard(cardId);
15025
14637
  return card;
15026
14638
  } catch (err) {
15027
- log39.warn(TAG35, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
14639
+ log38.warn(TAG34, `cannot fetch card ${cardId}: ${err instanceof Error ? err.message : err}`);
15028
14640
  return null;
15029
14641
  }
15030
14642
  }
@@ -15034,7 +14646,7 @@ async function recoverOrphans(store, client, config, opts = {}) {
15034
14646
  return [];
15035
14647
  }
15036
14648
  const outcomes = [];
15037
- log39.info(TAG35, `recovering ${active.length} orphan run(s) from prior daemon`);
14649
+ log38.info(TAG34, `recovering ${active.length} orphan run(s) from prior daemon`);
15038
14650
  for (const run of active) {
15039
14651
  const outcome = {
15040
14652
  runId: run.runId,
@@ -15046,16 +14658,16 @@ async function recoverOrphans(store, client, config, opts = {}) {
15046
14658
  };
15047
14659
  outcomes.push(outcome);
15048
14660
  if (isBudgetHeldRun(run)) {
15049
- log39.info(TAG35, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
14661
+ log38.info(TAG34, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15050
14662
  outcome.actions.push("skipped: held for a human budget decision");
15051
14663
  continue;
15052
14664
  }
15053
14665
  if (isProcessAlive(run.daemonPid, process.pid)) {
15054
- log39.warn(TAG35, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
14666
+ log38.warn(TAG34, `run ${run.runId} claims live daemon pid ${run.daemonPid} — skipping`);
15055
14667
  outcome.actions.push("skipped: daemon pid still alive");
15056
14668
  continue;
15057
14669
  }
15058
- log39.info(TAG35, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
14670
+ log38.info(TAG34, `recovering ${run.pipeline} run ${run.runId} for card #${run.cardShortId}`);
15059
14671
  await recoverRun(run, store, client, config, outcome, {
15060
14672
  rollbackAttempt: true,
15061
14673
  agentId: opts.agentId
@@ -15076,7 +14688,7 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15076
14688
  } catch (err) {
15077
14689
  const msg = err instanceof Error ? err.message : String(err);
15078
14690
  outcome.errors.push(`endAgentSession: ${msg}`);
15079
- log39.warn(TAG35, `endAgentSession failed for ${run.cardId}: ${msg}`);
14691
+ log38.warn(TAG34, `endAgentSession failed for ${run.cardId}: ${msg}`);
15080
14692
  }
15081
14693
  const card = await fetchCardSafely(client, run.cardId);
15082
14694
  if (card) {
@@ -15136,9 +14748,9 @@ async function recoverRun(run, store, client, config, outcome, opts = {}) {
15136
14748
  outcome.errors.push(`decrementAttempt: ${msg}`);
15137
14749
  }
15138
14750
  }
15139
- log39.info(TAG35, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
14751
+ log38.info(TAG34, `recovered run ${run.runId} (card #${run.cardShortId}): ${outcome.actions.join(", ")}${outcome.errors.length ? ` | errors: ${outcome.errors.join("; ")}` : ""}`);
15140
14752
  }
15141
- var TAG35 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
14753
+ var TAG34 = "recovery", RECOVERED_LABEL = "agent-recovered", RECOVERED_LABEL_COLOR = "#f59e0b";
15142
14754
  var init_recovery = __esm(() => {
15143
14755
  init_board_helpers();
15144
14756
  init_handback();
@@ -15160,18 +14772,18 @@ var init_repo_dirs = __esm(() => {
15160
14772
  });
15161
14773
 
15162
14774
  // src/claim.ts
15163
- import { log as log40 } from "@gethmy/harness";
14775
+ import { log as log39 } from "@gethmy/harness";
15164
14776
  async function claimUnassignedCard(client, cardId, agentId, opts) {
15165
14777
  try {
15166
14778
  const { claimed } = opts ? await client.claimCard(cardId, agentId, opts) : await client.claimCard(cardId, agentId);
15167
- log40.debug(TAG36, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
14779
+ log39.debug(TAG35, `claim ${cardId} → ${claimed ? "won" : "lost"}`);
15168
14780
  return claimed;
15169
14781
  } catch (err) {
15170
- log40.error(TAG36, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
14782
+ log39.error(TAG35, `claim ${cardId} failed: ${err instanceof Error ? err.message : err}`);
15171
14783
  return false;
15172
14784
  }
15173
14785
  }
15174
- var TAG36 = "claim";
14786
+ var TAG35 = "claim";
15175
14787
  var init_claim = () => {};
15176
14788
 
15177
14789
  // src/strand-recovery.ts
@@ -15179,7 +14791,7 @@ var exports_strand_recovery = {};
15179
14791
  __export(exports_strand_recovery, {
15180
14792
  reclaimPreReviewStrands: () => reclaimPreReviewStrands
15181
14793
  });
15182
- import { log as log41, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
14794
+ import { log as log40, resolvePrUrl as resolvePrUrl2 } from "@gethmy/harness";
15183
14795
  async function reclaimPreReviewStrands(opts) {
15184
14796
  const {
15185
14797
  client,
@@ -15223,22 +14835,22 @@ async function reclaimPreReviewStrands(opts) {
15223
14835
  continue;
15224
14836
  const won = await claimUnassignedCard(client, card.id, agentId);
15225
14837
  if (!won) {
15226
- log41.debug(TAG37, `#${card.short_id} — lost the review claim race, skipping`);
14838
+ log40.debug(TAG36, `#${card.short_id} — lost the review claim race, skipping`);
15227
14839
  continue;
15228
14840
  }
15229
- log41.warn(TAG37, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
14841
+ log40.warn(TAG36, `#${card.short_id} claimed for review (branch pushed, no PR, unowned)`);
15230
14842
  reclaimed.push(card.id);
15231
14843
  if (opts.onClaimed) {
15232
14844
  try {
15233
14845
  await opts.onClaimed(card);
15234
14846
  } catch (err) {
15235
- log41.error(TAG37, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
14847
+ log40.error(TAG36, `onClaimed for #${card.short_id} failed: ${err instanceof Error ? err.message : err}`);
15236
14848
  }
15237
14849
  }
15238
14850
  }
15239
14851
  return reclaimed;
15240
14852
  }
15241
- var TAG37 = "strand-recovery";
14853
+ var TAG36 = "strand-recovery";
15242
14854
  var init_strand_recovery = __esm(() => {
15243
14855
  init_board_helpers();
15244
14856
  init_claim();
@@ -15404,7 +15016,7 @@ var init_scope = __esm(() => {
15404
15016
  });
15405
15017
 
15406
15018
  // src/sweep.ts
15407
- import { log as log42 } from "@gethmy/harness";
15019
+ import { log as log41 } from "@gethmy/harness";
15408
15020
  function rankSweepCandidates(opts) {
15409
15021
  const {
15410
15022
  agentId,
@@ -15523,10 +15135,10 @@ async function sweepForCard(opts) {
15523
15135
  let { candidates, skipped, scope } = rankSweepCandidates(opts);
15524
15136
  const cohesionCounts = opts.ranking.cohesionWeight !== 0;
15525
15137
  if (cohesionCounts) {
15526
- log42.debug(TAG38, describeActiveScope(scope.active));
15138
+ log41.debug(TAG37, describeActiveScope(scope.active));
15527
15139
  }
15528
15140
  if (candidates.length === 0) {
15529
- log42.debug(TAG38, `no claimable card (${skipped.length} skipped in a pickup column)`);
15141
+ log41.debug(TAG37, `no claimable card (${skipped.length} skipped in a pickup column)`);
15530
15142
  return { claimed: null, skipped, probed: 0 };
15531
15143
  }
15532
15144
  const probeWindow = candidates.slice(0, maxProbes);
@@ -15542,12 +15154,12 @@ async function sweepForCard(opts) {
15542
15154
  chainNeighbors: chainNeighbors(chain2)
15543
15155
  }));
15544
15156
  } else if (chainTermsCount && candidates.length > 1) {
15545
- log42.debug(TAG38, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15157
+ log41.debug(TAG37, `chain signals not ranked — maxProbesPerTick=${maxProbes} leaves nothing to reorder among ${candidates.length} candidates`);
15546
15158
  }
15547
15159
  let probed = 0;
15548
15160
  for (const candidate of candidates) {
15549
15161
  if (probed >= maxProbes) {
15550
- log42.debug(TAG38, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15162
+ log41.debug(TAG37, `probe budget ${maxProbes} spent — ${candidates.length - probed} candidate(s) deferred to the next tick`);
15551
15163
  break;
15552
15164
  }
15553
15165
  probed++;
@@ -15625,10 +15237,10 @@ async function sweepForCard(opts) {
15625
15237
  continue;
15626
15238
  }
15627
15239
  verified.card.assigned_agent_id = agentId;
15628
- log42.info(TAG38, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15240
+ log41.info(TAG37, claimLine(verified, probed, candidates, skipped, cohesionCounts ? scope.active : null));
15629
15241
  return { claimed: verified, skipped, probed };
15630
15242
  }
15631
- log42.debug(TAG38, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15243
+ log41.debug(TAG37, `claimed nothing this sweep (${probed} probed, ${skipped.length} skipped)`);
15632
15244
  return { claimed: null, skipped, probed };
15633
15245
  }
15634
15246
  function claimLine(claimed, rank, candidates, skipped, scope) {
@@ -15649,7 +15261,7 @@ async function refetchCard(client, cardId) {
15649
15261
  const { card } = await client.getCard(cardId);
15650
15262
  return card ?? null;
15651
15263
  } catch (err) {
15652
- log42.warn(TAG38, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15264
+ log41.warn(TAG37, `re-read failed for ${cardId}: ${err instanceof Error ? err.message : err}`);
15653
15265
  return null;
15654
15266
  }
15655
15267
  }
@@ -15658,11 +15270,11 @@ async function hasLiveSession(client, cardId) {
15658
15270
  const { session } = await client.getAgentSession(cardId);
15659
15271
  return session != null;
15660
15272
  } catch (err) {
15661
- log42.warn(TAG38, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15273
+ log41.warn(TAG37, `session lookup failed for ${cardId} — treating as busy: ${err instanceof Error ? err.message : err}`);
15662
15274
  return true;
15663
15275
  }
15664
15276
  }
15665
- var TAG38 = "sweep";
15277
+ var TAG37 = "sweep";
15666
15278
  var init_sweep = __esm(() => {
15667
15279
  init_board_helpers();
15668
15280
  init_claim();
@@ -15673,7 +15285,7 @@ var init_sweep = __esm(() => {
15673
15285
  });
15674
15286
 
15675
15287
  // src/sweep-commands.ts
15676
- import { log as log43 } from "@gethmy/harness";
15288
+ import { log as log42 } from "@gethmy/harness";
15677
15289
  function parseSweepCommands(payload) {
15678
15290
  if (!payload || typeof payload !== "object")
15679
15291
  return [];
@@ -15700,14 +15312,14 @@ function parseSweepCommands(payload) {
15700
15312
  async function claimSweepCommands(client, agentId, projectId, daemonId) {
15701
15313
  const request = client.request?.bind(client);
15702
15314
  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");
15315
+ 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
15316
  return [];
15705
15317
  }
15706
15318
  try {
15707
15319
  const res = await request("POST", `/agents/${encodeURIComponent(agentId)}/sweep-commands/claim`, { projectId, daemonId });
15708
15320
  return parseSweepCommands(res);
15709
15321
  } catch (err) {
15710
- log43.warn(TAG39, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15322
+ log42.warn(TAG38, `could not claim sweep commands: ${err instanceof Error ? err.message : err}`);
15711
15323
  return [];
15712
15324
  }
15713
15325
  }
@@ -15720,15 +15332,15 @@ async function applySweepCommands(commands, actions) {
15720
15332
  await actions.resume();
15721
15333
  }
15722
15334
  applied = command.verb;
15723
- log43.info(TAG39, `applied "${command.verb}" from the board (${command.id})`);
15335
+ log42.info(TAG38, `applied "${command.verb}" from the board (${command.id})`);
15724
15336
  }
15725
15337
  return applied;
15726
15338
  }
15727
- var TAG39 = "sweep-cmd";
15339
+ var TAG38 = "sweep-cmd";
15728
15340
  var init_sweep_commands = () => {};
15729
15341
 
15730
15342
  // src/sweep-guard.ts
15731
- import { log as log44 } from "@gethmy/harness";
15343
+ import { log as log43 } from "@gethmy/harness";
15732
15344
 
15733
15345
  class SweepGuard {
15734
15346
  config;
@@ -15784,7 +15396,7 @@ class SweepGuard {
15784
15396
  await this.store.haltSweep(reason);
15785
15397
  if (!already) {
15786
15398
  const claimed = this.store.getSweep().claimed;
15787
- log44.info(TAG40, `claiming stopped (${reason}) after ${claimed} claimed`);
15399
+ log43.info(TAG39, `claiming stopped (${reason}) after ${claimed} claimed`);
15788
15400
  }
15789
15401
  return this.snapshot();
15790
15402
  }
@@ -15793,7 +15405,7 @@ class SweepGuard {
15793
15405
  const was = before.haltReason ? this.describeStop(before.haltReason) : null;
15794
15406
  await this.store.resumeSweep();
15795
15407
  if (was)
15796
- log44.info(TAG40, `claiming resumed by the operator — was stopped: ${was}`);
15408
+ log43.info(TAG39, `claiming resumed by the operator — was stopped: ${was}`);
15797
15409
  return this.snapshot();
15798
15410
  }
15799
15411
  snapshot() {
@@ -15855,11 +15467,11 @@ function sweepBannerLine(config) {
15855
15467
  const authors = extra ? `you + ${extra} trusted author${extra === 1 ? "" : "s"}` : "you only";
15856
15468
  return `Sweep ON — claims ${scope} in ${config.pickupColumns.join(", ")}, ` + `authored by ${authors}; caps: ${describeCaps(sweep, config.budget.dailyBudgetCents)}; ` + `${sweep.maxProbesPerTick} probes/tick`;
15857
15469
  }
15858
- var TAG40 = "sweep";
15470
+ var TAG39 = "sweep";
15859
15471
  var init_sweep_guard = () => {};
15860
15472
 
15861
15473
  // src/reconcile.ts
15862
- import { detectGitProvider as detectGitProvider5, log as log45 } from "@gethmy/harness";
15474
+ import { detectGitProvider as detectGitProvider5, log as log44 } from "@gethmy/harness";
15863
15475
  function daemonProcessLabels(approvedLabel) {
15864
15476
  const names = ["agent", "agent-recovered", NEED_REVIEW_LABEL, approvedLabel];
15865
15477
  return new Set(names.filter(Boolean).map((n) => n.toLowerCase()));
@@ -15922,7 +15534,7 @@ class Reconciler {
15922
15534
  clearInterval(this.timer);
15923
15535
  this.timer = null;
15924
15536
  }
15925
- log45.info(TAG41, "Heartbeat stopped");
15537
+ log44.info(TAG40, "Heartbeat stopped");
15926
15538
  }
15927
15539
  async recoverStaleRuns() {
15928
15540
  if (!this.stateStore || !this.agentConfig)
@@ -15933,7 +15545,7 @@ class Reconciler {
15933
15545
  const pool = this.pool;
15934
15546
  for (const run of active) {
15935
15547
  if (isBudgetHeldRun(run)) {
15936
- log45.info(TAG41, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15548
+ log44.info(TAG40, `run ${run.runId} (#${run.cardShortId}) is held for a human budget decision — leaving it`);
15937
15549
  continue;
15938
15550
  }
15939
15551
  const foreignDaemon = run.daemonPid !== process.pid;
@@ -15943,7 +15555,7 @@ class Reconciler {
15943
15555
  if (!daemonDead && !(heartbeatStale && ourZombie))
15944
15556
  continue;
15945
15557
  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`);
15558
+ log44.warn(TAG40, `zombie run ${run.runId} (#${run.cardShortId}): ${reason} — recovering`);
15947
15559
  await recoverRun(run, this.stateStore, this.client, this.agentConfig, {
15948
15560
  runId: run.runId,
15949
15561
  cardId: run.cardId,
@@ -15970,11 +15582,11 @@ class Reconciler {
15970
15582
  const stalledAt = Date.parse(card.updated_at ?? "");
15971
15583
  if (!Number.isFinite(stalledAt) || now - stalledAt < graceMs)
15972
15584
  continue;
15973
- log45.warn(TAG41, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15585
+ log44.warn(TAG40, `#${card.short_id} stranded in "${inProgressCol.name}" (no live run) — requeueing to "${pickupCol.name}"`);
15974
15586
  try {
15975
15587
  await this.client.moveCard(card.id, pickupCol.id);
15976
15588
  } catch (err) {
15977
- log45.error(TAG41, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15589
+ log44.error(TAG40, `stranded requeue failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15978
15590
  }
15979
15591
  }
15980
15592
  }
@@ -16006,7 +15618,7 @@ class Reconciler {
16006
15618
  return;
16007
15619
  const cardLabels = resolveCardLabels(card, labelMap);
16008
15620
  const subtasks = card.subtasks ?? [];
16009
- log45.info(TAG41, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
15621
+ log44.info(TAG40, `Enqueuing claimed review card #${card.short_id} (agent-agnostic pickup)`);
16010
15622
  await this.pool.enqueue(card, column, cardLabels, subtasks, "review");
16011
15623
  }
16012
15624
  });
@@ -16030,11 +15642,11 @@ class Reconciler {
16030
15642
  const parkedAt = Date.parse(card.updated_at ?? "");
16031
15643
  if (!Number.isFinite(parkedAt) || now - parkedAt < ttlMs)
16032
15644
  continue;
16033
- log45.warn(TAG41, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
15645
+ log44.warn(TAG40, `#${card.short_id} parked for approval > ${planning.approvalTtlHours}h — auto-releasing to "${pickupCol.name}"`);
16034
15646
  try {
16035
15647
  await this.client.moveCard(card.id, pickupCol.id);
16036
15648
  } catch (err) {
16037
- log45.error(TAG41, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
15649
+ log44.error(TAG40, `auto-release failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
16038
15650
  }
16039
15651
  }
16040
15652
  }
@@ -16069,7 +15681,7 @@ class Reconciler {
16069
15681
  }
16070
15682
  this.lastSweepStopReported = null;
16071
15683
  if (!this.pool.hasFreeImplementSlot()) {
16072
- log45.debug(TAG41, "sweep skipped — no free implement slot");
15684
+ log44.debug(TAG40, "sweep skipped — no free implement slot");
16073
15685
  return;
16074
15686
  }
16075
15687
  const { claimed } = await sweepForCard({
@@ -16088,9 +15700,9 @@ class Reconciler {
16088
15700
  reportSweepStopped(reason, detail) {
16089
15701
  const line = `sweep stopped claiming — ${detail}`;
16090
15702
  if (this.lastSweepStopReported === reason)
16091
- log45.debug(TAG41, line);
15703
+ log44.debug(TAG40, line);
16092
15704
  else
16093
- log45.warn(TAG41, line);
15705
+ log44.warn(TAG40, line);
16094
15706
  this.lastSweepStopReported = reason;
16095
15707
  }
16096
15708
  setSweepPresenceSink(sink) {
@@ -16128,7 +15740,7 @@ class Reconciler {
16128
15740
  return;
16129
15741
  this.lastSweepNudgeAt = now;
16130
15742
  this.drainSweepCommands().catch((err) => {
16131
- log45.error(TAG41, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
15743
+ log44.error(TAG40, `sweep command nudge failed: ${err instanceof Error ? err.message : err}`);
16132
15744
  });
16133
15745
  }
16134
15746
  resolveRepoDirectories() {
@@ -16137,9 +15749,9 @@ class Reconciler {
16137
15749
  const dirs = readRepoDirectories(process.cwd());
16138
15750
  this.repoDirectories = dirs;
16139
15751
  if (dirs.size === 0) {
16140
- log45.warn(TAG41, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
15752
+ log44.warn(TAG40, `Could not read top-level directories of ${process.cwd()} — sweep cohesion runs without its path signal`);
16141
15753
  } else {
16142
- log45.debug(TAG41, `Path signal allows ${dirs.size} top-level directories`);
15754
+ log44.debug(TAG40, `Path signal allows ${dirs.size} top-level directories`);
16143
15755
  }
16144
15756
  return dirs;
16145
15757
  }
@@ -16175,7 +15787,7 @@ class Reconciler {
16175
15787
  if (accountHalt !== this.lastAccountHoldReported) {
16176
15788
  if (accountHalt) {
16177
15789
  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\``);
15790
+ log44.warn(TAG40, `Account halted (${accountHalt}) — ${unqueued} assigned card(s) not queued; nothing is dispatched until \`harmony-agent resume\``);
16179
15791
  }
16180
15792
  this.lastAccountHoldReported = accountHalt;
16181
15793
  }
@@ -16191,24 +15803,24 @@ class Reconciler {
16191
15803
  const subtasks = card.subtasks ?? [];
16192
15804
  const mode = route.mode;
16193
15805
  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`);
15806
+ 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
15807
  }
16196
15808
  if (mode === "review" && this.approvedLabel && hasLabel(cardLabels, this.approvedLabel)) {
16197
- log45.debug(TAG41, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
15809
+ log44.debug(TAG40, `Skipping #${card.short_id} — already has "${this.approvedLabel}" label`);
16198
15810
  continue;
16199
15811
  }
16200
15812
  if (mode === "review" && hasLabel(cardLabels, NEED_REVIEW_LABEL)) {
16201
- log45.debug(TAG41, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
15813
+ log44.debug(TAG40, `Skipping #${card.short_id} — has "${NEED_REVIEW_LABEL}" label (needs human)`);
16202
15814
  continue;
16203
15815
  }
16204
15816
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
16205
- log45.debug(TAG41, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
15817
+ log44.debug(TAG40, `Skipping #${card.short_id} — no branch or PR reference (not qualified for auto-review)`);
16206
15818
  continue;
16207
15819
  }
16208
15820
  if (accountHalt) {
16209
- log45.debug(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
15821
+ log44.debug(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — holding, account halted (${accountHalt})`);
16210
15822
  } else {
16211
- log45.info(TAG41, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
15823
+ log44.info(TAG40, `Missed assignment: #${card.short_id} "${card.title}" (${mode}) — enqueueing`);
16212
15824
  }
16213
15825
  await this.pool.enqueue(card, column, cardLabels, subtasks, mode);
16214
15826
  }
@@ -16219,13 +15831,13 @@ class Reconciler {
16219
15831
  try {
16220
15832
  await this.pool.drainBudgetDecisions();
16221
15833
  } catch (err) {
16222
- log45.error(TAG41, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
15834
+ log44.error(TAG40, `budget decisions were not drained this tick: ${err instanceof Error ? err.message : err}`);
16223
15835
  }
16224
15836
  await this.recoverStrandedInProgress(cards, columns, knownCardIds);
16225
15837
  await this.recoverStrandedReview(cards, columns, labelMap, knownCardIds);
16226
15838
  for (const knownId of knownCardIds) {
16227
15839
  if (!allAgentCardIds.has(knownId)) {
16228
- log45.info(TAG41, `Missed unassign: ${knownId} — removing`);
15840
+ log44.info(TAG40, `Missed unassign: ${knownId} — removing`);
16229
15841
  await this.pool.removeCard(knownId);
16230
15842
  }
16231
15843
  }
@@ -16233,20 +15845,20 @@ class Reconciler {
16233
15845
  try {
16234
15846
  await this.drainSweepCommands();
16235
15847
  } catch (err) {
16236
- log45.error(TAG41, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
15848
+ log44.error(TAG40, `sweep commands were not drained this tick: ${err instanceof Error ? err.message : err}`);
16237
15849
  }
16238
15850
  try {
16239
15851
  await this.sweepForWork(cards, columns, labelMap, pickupConfig);
16240
15852
  } catch (err) {
16241
- log45.error(TAG41, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
15853
+ log44.error(TAG40, `sweep failed this tick: ${err instanceof Error ? err.message : err}`);
16242
15854
  }
16243
- log45.debug(TAG41, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
15855
+ log44.debug(TAG40, `Reconciled: ${assignedCards.length} assigned, ${knownCardIds.size} known`);
16244
15856
  } catch (err) {
16245
- log45.error(TAG41, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
15857
+ log44.error(TAG40, `Heartbeat failed: ${err instanceof Error ? err.message : err}`);
16246
15858
  }
16247
15859
  }
16248
15860
  }
16249
- var TAG41 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
15861
+ var TAG40 = "reconcile", SWEEP_NUDGE_COOLDOWN_MS = 15000;
16250
15862
  var init_reconcile = __esm(() => {
16251
15863
  init_board_helpers();
16252
15864
  init_recovery();
@@ -16266,7 +15878,7 @@ __export(exports_startup_banner, {
16266
15878
  createStartupBanner: () => createStartupBanner,
16267
15879
  contextSourceLine: () => contextSourceLine
16268
15880
  });
16269
- import { isPretty, log as log46 } from "@gethmy/harness";
15881
+ import { isPretty, log as log45 } from "@gethmy/harness";
16270
15882
  function createStartupBanner(config, version) {
16271
15883
  return isPretty() ? prettyBanner(config, version) : jsonBanner(config, version);
16272
15884
  }
@@ -16291,7 +15903,7 @@ function prettyBanner(config, version) {
16291
15903
  checks.push({ kind: "ok", message });
16292
15904
  },
16293
15905
  warn(message) {
16294
- log46.warn(TAG42, message);
15906
+ log45.warn(TAG41, message);
16295
15907
  checks.push({ kind: "warn", message: message.split(`
16296
15908
  `, 1)[0] });
16297
15909
  },
@@ -16316,26 +15928,26 @@ function prettyBanner(config, version) {
16316
15928
  };
16317
15929
  }
16318
15930
  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)}`);
15931
+ log45.info(TAG41, `Harmony Agent Daemon v${version} starting...`);
15932
+ log45.info(TAG41, `Project: ${config.projectId} | Pool: ${config.agent.poolSize} | Model: ${config.agent.claude.model} | Runner: ${config.agent.runner} | Pickup: ${config.agent.pickupColumns.join(", ")}`);
15933
+ log45.info(TAG41, `Config: ${contextSourceLine(config)}`);
16322
15934
  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}`);
15935
+ log45.info(TAG41, `Review: enabled | Columns: ${config.agent.review.pickupColumns.join(", ")} | → ${config.agent.review.moveToColumn} / ${config.agent.review.failColumn}`);
16324
15936
  }
16325
15937
  let failed = false;
16326
15938
  return {
16327
15939
  setProjectName(_name) {},
16328
15940
  setGitProvider(provider) {
16329
- log46.info(TAG42, `Git provider: ${provider}`);
15941
+ log45.info(TAG41, `Git provider: ${provider}`);
16330
15942
  },
16331
15943
  setHttpPort(port) {
16332
- log46.info(TAG42, `HTTP server on port ${port}`);
15944
+ log45.info(TAG41, `HTTP server on port ${port}`);
16333
15945
  },
16334
15946
  check(message) {
16335
- log46.info(TAG42, message);
15947
+ log45.info(TAG41, message);
16336
15948
  },
16337
15949
  warn(message) {
16338
- log46.warn(TAG42, message);
15950
+ log45.warn(TAG41, message);
16339
15951
  },
16340
15952
  fail() {
16341
15953
  failed = true;
@@ -16343,7 +15955,7 @@ function jsonBanner(config, version) {
16343
15955
  async ready(message) {
16344
15956
  if (failed)
16345
15957
  return;
16346
- log46.info(TAG42, message);
15958
+ log45.info(TAG41, message);
16347
15959
  }
16348
15960
  };
16349
15961
  }
@@ -16436,7 +16048,7 @@ function cyan(s) {
16436
16048
  function yellow(s) {
16437
16049
  return `${ANSI.yellow}${s}${ANSI.reset}`;
16438
16050
  }
16439
- var TAG42 = "daemon", RULE_WIDTH = 70, ANSI;
16051
+ var TAG41 = "daemon", RULE_WIDTH = 70, ANSI;
16440
16052
  var init_startup_banner = __esm(() => {
16441
16053
  init_port_registry();
16442
16054
  ANSI = {
@@ -16457,7 +16069,7 @@ import {
16457
16069
  writeFileSync as writeFileSync5
16458
16070
  } from "node:fs";
16459
16071
  import { dirname as dirname6, resolve as resolve2, sep as sep2 } from "node:path";
16460
- import { log as log47 } from "@gethmy/harness";
16072
+ import { log as log46 } from "@gethmy/harness";
16461
16073
  function migrationMarkerPath(targetPath) {
16462
16074
  return `${targetPath}.migrated`;
16463
16075
  }
@@ -16531,7 +16143,7 @@ function migrateLegacyStateFile(opts) {
16531
16143
  throw new Error("not an object");
16532
16144
  legacy = parsed;
16533
16145
  } 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})`);
16146
+ log46.warn(TAG42, `legacy state file unreadable — skipping the split this start; it retries on the next (${err instanceof Error ? err.message : err})`);
16535
16147
  return NO_MIGRATION;
16536
16148
  }
16537
16149
  const runs = Array.isArray(legacy.runs) ? legacy.runs : [];
@@ -16553,13 +16165,13 @@ function migrateLegacyStateFile(opts) {
16553
16165
  const legacyVersion = typeof legacy.version === "number" ? legacy.version : SCHEMA_VERSION;
16554
16166
  const existing = existsSync5(targetPath) ? readTargetFile(targetPath) : null;
16555
16167
  if (existsSync5(targetPath) && !existing) {
16556
- log47.warn(TAG43, "existing project state file unreadable — the split overwrites it");
16168
+ log46.warn(TAG42, "existing project state file unreadable — the split overwrites it");
16557
16169
  }
16558
16170
  let target;
16559
16171
  if (existing) {
16560
16172
  const existingVersion = typeof existing.version === "number" ? existing.version : SCHEMA_VERSION;
16561
16173
  if (existingVersion !== legacyVersion) {
16562
- log47.warn(TAG43, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16174
+ log46.warn(TAG42, `legacy state is schema v${legacyVersion} but the project store is v${existingVersion} — skipping the split`);
16563
16175
  return NO_MIGRATION;
16564
16176
  }
16565
16177
  const existingRuns = Array.isArray(existing.runs) ? existing.runs : [];
@@ -16605,7 +16217,7 @@ function migrateLegacyStateFile(opts) {
16605
16217
  if (!existsSync5(backupPath))
16606
16218
  copyFileSync(legacyPath, backupPath);
16607
16219
  } catch (err) {
16608
- log47.warn(TAG43, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16220
+ log46.warn(TAG42, `could not back up the legacy state file (continuing): ${err instanceof Error ? err.message : err}`);
16609
16221
  }
16610
16222
  const remainingRuns = runs.filter((r) => !ownRunIds.has(r.runId));
16611
16223
  const remainingCards = cards.filter((c) => !ownCardIds.has(c.cardId));
@@ -16629,10 +16241,10 @@ function migrateLegacyStateFile(opts) {
16629
16241
  copiedIndeterminateCards: indeterminateCards.length,
16630
16242
  foreignUnendedRuns: remainingRuns.filter((r) => r.endedAt === null).length
16631
16243
  };
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`);
16244
+ 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
16245
  return result;
16634
16246
  }
16635
- var TAG43 = "state-migration", NO_MIGRATION;
16247
+ var TAG42 = "state-migration", NO_MIGRATION;
16636
16248
  var init_state_migration = __esm(() => {
16637
16249
  init_dist();
16638
16250
  init_state_store();
@@ -16739,7 +16351,7 @@ var init_stream_parser_selftest = __esm(() => {
16739
16351
 
16740
16352
  // src/watcher.ts
16741
16353
  import { randomUUID as randomUUID3 } from "node:crypto";
16742
- import { isPretty as isPretty2, log as log48 } from "@gethmy/harness";
16354
+ import { isPretty as isPretty2, log as log47 } from "@gethmy/harness";
16743
16355
  import { createClient } from "@supabase/supabase-js";
16744
16356
  function toPresenceColumns(names) {
16745
16357
  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 +16412,7 @@ class Watcher {
16800
16412
  const stillHeld = this.supabase?.getChannels().some((c) => c.topic === old.topic) ?? false;
16801
16413
  if (!stillHeld)
16802
16414
  return true;
16803
- log48.warn(TAG44, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16415
+ log47.warn(TAG43, `removeChannel(${old.topic}) returned "${status}" and the client still holds that topic — retrying the removal`);
16804
16416
  return false;
16805
16417
  }
16806
16418
  constructor(credentials, projectId, identity, routing, onCardBroadcast, onAgentCommand, onSweepCommandNudge) {
@@ -16814,7 +16426,7 @@ class Watcher {
16814
16426
  }
16815
16427
  async start() {
16816
16428
  if (!isPretty2()) {
16817
- log48.info(TAG44, "Connecting to Supabase realtime (broadcast)...");
16429
+ log47.info(TAG43, "Connecting to Supabase realtime (broadcast)...");
16818
16430
  }
16819
16431
  this.supabase = createClient(this.credentials.supabaseUrl, this.credentials.supabaseAnonKey);
16820
16432
  this.subscribeBroadcast();
@@ -16852,7 +16464,7 @@ class Watcher {
16852
16464
  status = `threw (${String(err)})`;
16853
16465
  }
16854
16466
  if (status !== "ok") {
16855
- log48.debug(TAG44, `Presence sweep update returned "${status}"`);
16467
+ log47.debug(TAG43, `Presence sweep update returned "${status}"`);
16856
16468
  }
16857
16469
  })();
16858
16470
  }
@@ -16863,7 +16475,7 @@ class Watcher {
16863
16475
  const presenceChannel = this.supabase.channel(`board-presence-${this.projectId}`);
16864
16476
  this.presenceChannel = presenceChannel;
16865
16477
  presenceChannel.on("presence", { event: "sync" }, () => {
16866
- log48.debug(TAG44, "Presence sync");
16478
+ log47.debug(TAG43, "Presence sync");
16867
16479
  }).subscribe(async (status) => {
16868
16480
  if (gen !== this.presenceGen)
16869
16481
  return;
@@ -16879,13 +16491,13 @@ class Watcher {
16879
16491
  if (trackStatus !== "ok") {
16880
16492
  this.presenceTracked = false;
16881
16493
  if (!this.stopping) {
16882
- log48.warn(TAG44, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16494
+ log47.warn(TAG43, `Presence track returned "${trackStatus}" — scheduling reconnect`);
16883
16495
  this.schedulePresenceReconnect();
16884
16496
  }
16885
16497
  return;
16886
16498
  }
16887
16499
  if (!isPretty2() || !this.suppressStartupLogs) {
16888
- log48.info(TAG44, "Presence tracked on board-presence channel");
16500
+ log47.info(TAG43, "Presence tracked on board-presence channel");
16889
16501
  }
16890
16502
  this.presenceTracked = true;
16891
16503
  this.presenceReconnectAttempts = 0;
@@ -16893,7 +16505,7 @@ class Watcher {
16893
16505
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16894
16506
  this.presenceTracked = false;
16895
16507
  if (!this.stopping) {
16896
- log48.warn(TAG44, `Presence subscription ${status} — scheduling reconnect`);
16508
+ log47.warn(TAG43, `Presence subscription ${status} — scheduling reconnect`);
16897
16509
  this.schedulePresenceReconnect();
16898
16510
  }
16899
16511
  }
@@ -16912,7 +16524,7 @@ class Watcher {
16912
16524
  async reconnectPresence() {
16913
16525
  if (this.stopping || !this.supabase)
16914
16526
  return;
16915
- log48.warn(TAG44, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16527
+ log47.warn(TAG43, `Reconnecting presence subscription (attempt ${this.presenceReconnectAttempts})`);
16916
16528
  if (this.presenceChannel) {
16917
16529
  const old = this.presenceChannel;
16918
16530
  this.presenceChannel = null;
@@ -16935,13 +16547,13 @@ class Watcher {
16935
16547
  return;
16936
16548
  const gen = ++this.broadcastGen;
16937
16549
  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)}`);
16550
+ log47.debug(TAG43, `Broadcast: card_update ${JSON.stringify(msg.payload)}`);
16939
16551
  this.onCardBroadcast({
16940
16552
  event: "card_update",
16941
16553
  payload: msg.payload ?? {}
16942
16554
  });
16943
16555
  }).on("broadcast", { event: "card_created" }, (msg) => {
16944
- log48.debug(TAG44, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16556
+ log47.debug(TAG43, `Broadcast: card_created ${JSON.stringify(msg.payload)}`);
16945
16557
  this.onCardBroadcast({
16946
16558
  event: "card_created",
16947
16559
  payload: msg.payload ?? {}
@@ -16951,11 +16563,11 @@ class Watcher {
16951
16563
  const cardId = payload.card_id;
16952
16564
  const command = payload.command;
16953
16565
  if (cardId && command) {
16954
- log48.info(TAG44, `Broadcast: agent_command ${command} for ${cardId}`);
16566
+ log47.info(TAG43, `Broadcast: agent_command ${command} for ${cardId}`);
16955
16567
  this.onAgentCommand?.({ cardId, command });
16956
16568
  }
16957
16569
  }).on("broadcast", { event: "sweep_command" }, () => {
16958
- log48.debug(TAG44, "Broadcast: sweep_command — draining");
16570
+ log47.debug(TAG43, "Broadcast: sweep_command — draining");
16959
16571
  this.onSweepCommandNudge?.();
16960
16572
  }).subscribe((status) => {
16961
16573
  if (gen !== this.broadcastGen)
@@ -16964,13 +16576,13 @@ class Watcher {
16964
16576
  this.connected = true;
16965
16577
  this.reconnectAttempts = 0;
16966
16578
  if (!isPretty2() || !this.suppressStartupLogs) {
16967
- log48.info(TAG44, "Broadcast subscription active");
16579
+ log47.info(TAG43, "Broadcast subscription active");
16968
16580
  }
16969
16581
  this.maybeResolveReady();
16970
16582
  } else if (status === "CHANNEL_ERROR" || status === "TIMED_OUT" || status === "CLOSED") {
16971
16583
  this.connected = false;
16972
16584
  if (!this.stopping) {
16973
- log48.warn(TAG44, `Broadcast subscription ${status} — scheduling reconnect`);
16585
+ log47.warn(TAG43, `Broadcast subscription ${status} — scheduling reconnect`);
16974
16586
  this.scheduleReconnect();
16975
16587
  }
16976
16588
  }
@@ -16989,7 +16601,7 @@ class Watcher {
16989
16601
  async reconnectBroadcast() {
16990
16602
  if (this.stopping || !this.supabase)
16991
16603
  return;
16992
- log48.warn(TAG44, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16604
+ log47.warn(TAG43, `Reconnecting broadcast subscription (attempt ${this.reconnectAttempts})`);
16993
16605
  if (this.channel) {
16994
16606
  const old = this.channel;
16995
16607
  this.channel = null;
@@ -17031,10 +16643,10 @@ class Watcher {
17031
16643
  }
17032
16644
  this.connected = false;
17033
16645
  this.presenceTracked = false;
17034
- log48.info(TAG44, "Broadcast subscription stopped");
16646
+ log47.info(TAG43, "Broadcast subscription stopped");
17035
16647
  }
17036
16648
  }
17037
- var TAG44 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
16649
+ var TAG43 = "watcher", MAX_PRESENCE_COLUMNS = 24, MAX_PRESENCE_COLUMN_LENGTH = 120;
17038
16650
  var init_watcher = __esm(() => {
17039
16651
  init_sweep_guard();
17040
16652
  });
@@ -17308,7 +16920,7 @@ __export(exports_run_gc, {
17308
16920
  pruneRunLogs: () => pruneRunLogs
17309
16921
  });
17310
16922
  import { unlinkSync as unlinkSync2 } from "node:fs";
17311
- import { log as log49 } from "@gethmy/harness";
16923
+ import { log as log48 } from "@gethmy/harness";
17312
16924
  function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17313
16925
  let deleted = 0;
17314
16926
  let bytesFreed = 0;
@@ -17322,7 +16934,7 @@ function pruneRunLogs(dir, beforeMs, keepRunIds = new Set) {
17322
16934
  deleted++;
17323
16935
  bytesFreed += file.sizeBytes;
17324
16936
  } catch (err) {
17325
- log49.debug(TAG45, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
16937
+ log48.debug(TAG44, `Could not remove ${file.path}: ${err instanceof Error ? err.message : err}`);
17326
16938
  }
17327
16939
  }
17328
16940
  return { deleted, bytesFreed };
@@ -17345,7 +16957,7 @@ async function runRetentionGc(store, opts) {
17345
16957
  logs = pruneRunLogs(opts.runsDirectory ?? runsDir(), now - opts.runLogDays * DAY_MS2, openRunIds);
17346
16958
  }
17347
16959
  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)`);
16960
+ log48.info(TAG44, `Retention sweep: trimmed ${runRecordsPurged} run record(s), removed ${logs.deleted} run log(s) (${Math.round(logs.bytesFreed / 1024)} KB)`);
17349
16961
  }
17350
16962
  return {
17351
16963
  runRecordsPurged,
@@ -17353,7 +16965,7 @@ async function runRetentionGc(store, opts) {
17353
16965
  logBytesFreed: logs.bytesFreed
17354
16966
  };
17355
16967
  }
17356
- var TAG45 = "gc", DAY_MS2 = 86400000;
16968
+ var TAG44 = "gc", DAY_MS2 = 86400000;
17357
16969
  var init_run_gc = __esm(() => {
17358
16970
  init_paths();
17359
16971
  init_run_stats();
@@ -17370,7 +16982,7 @@ __export(exports_worktree_gc, {
17370
16982
  import { execFileSync as execFileSync8 } from "node:child_process";
17371
16983
  import { existsSync as existsSync6, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
17372
16984
  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";
16985
+ import { cleanupWorktree as cleanupWorktree5, GIT_NO_HOOKS as GIT_NO_HOOKS9, log as log49 } from "@gethmy/harness";
17374
16986
  function isTransientGitNetworkError(message) {
17375
16987
  return TRANSIENT_GIT_NETWORK_ERROR.test(message);
17376
16988
  }
@@ -17483,10 +17095,10 @@ function runWorktreeGc(basePath, store, opts = {}) {
17483
17095
  });
17484
17096
  } catch {}
17485
17097
  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(", ")}`);
17098
+ log49.info(TAG45, `GC removed ${result.removed.length} orphan worktree(s): ${result.removed.map((p) => p.split("/").pop()).join(", ")}`);
17487
17099
  }
17488
17100
  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("; ")}`);
17101
+ log49.warn(TAG45, `GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.path}: ${e.error}`).join("; ")}`);
17490
17102
  }
17491
17103
  return result;
17492
17104
  }
@@ -17516,7 +17128,7 @@ function pruneFailedRemoteBranches(opts) {
17516
17128
  } catch (err) {
17517
17129
  const detail = gitErrorDetail2(err);
17518
17130
  if (isTransientGitNetworkError(detail)) {
17519
- log50.debug(TAG46, `Remote branch GC skipped — remote unreachable: ${detail}`);
17131
+ log49.debug(TAG45, `Remote branch GC skipped — remote unreachable: ${detail}`);
17520
17132
  return result;
17521
17133
  }
17522
17134
  result.errors.push({ ref: "fetch", error: detail });
@@ -17556,7 +17168,7 @@ function pruneFailedRemoteBranches(opts) {
17556
17168
  continue;
17557
17169
  }
17558
17170
  if (clock() > sweepDeadline) {
17559
- log50.debug(TAG46, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17171
+ log49.debug(TAG45, `Remote branch GC budget spent — removed ${result.removed.length}, remaining deferred to next tick`);
17560
17172
  break;
17561
17173
  }
17562
17174
  try {
@@ -17569,17 +17181,17 @@ function pruneFailedRemoteBranches(opts) {
17569
17181
  } catch (err) {
17570
17182
  const detail = gitErrorDetail2(err);
17571
17183
  if (isTransientGitNetworkError(detail)) {
17572
- log50.debug(TAG46, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17184
+ log49.debug(TAG45, `Remote branch GC interrupted — remote unreachable: ${detail}`);
17573
17185
  break;
17574
17186
  }
17575
17187
  result.errors.push({ ref, error: detail });
17576
17188
  }
17577
17189
  }
17578
17190
  if (result.removed.length > 0) {
17579
- log50.info(TAG46, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17191
+ log49.info(TAG45, `Pruned ${result.removed.length} stale remote branch(es) under ${opts.prefix}: ${result.removed.join(", ")}`);
17580
17192
  }
17581
17193
  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("; ")}`);
17194
+ log49.warn(TAG45, `Remote branch GC had ${result.errors.length} error(s): ${result.errors.map((e) => `${e.ref}: ${e.error}`).join("; ")}`);
17583
17195
  }
17584
17196
  return result;
17585
17197
  }
@@ -17612,18 +17224,18 @@ class WorktreeGc {
17612
17224
  try {
17613
17225
  runWorktreeGc(this.basePath, this.store);
17614
17226
  } catch (err) {
17615
- log50.warn(TAG46, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17227
+ log49.warn(TAG45, `GC tick failed: ${err instanceof Error ? err.message : err}`);
17616
17228
  }
17617
17229
  if (this.remoteOpts) {
17618
17230
  try {
17619
17231
  pruneFailedRemoteBranches(this.remoteOpts);
17620
17232
  } catch (err) {
17621
- log50.warn(TAG46, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17233
+ log49.warn(TAG45, `Remote GC tick failed: ${err instanceof Error ? err.message : err}`);
17622
17234
  }
17623
17235
  }
17624
17236
  if (this.retentionOpts) {
17625
17237
  runRetentionGc(this.store, this.retentionOpts).catch((err) => {
17626
- log50.warn(TAG46, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17238
+ log49.warn(TAG45, `Retention GC tick failed: ${err instanceof Error ? err.message : err}`);
17627
17239
  });
17628
17240
  }
17629
17241
  }
@@ -17637,7 +17249,7 @@ function getRepoRoot2() {
17637
17249
  return null;
17638
17250
  }
17639
17251
  }
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;
17252
+ 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
17253
  var init_worktree_gc = __esm(() => {
17642
17254
  init_run_gc();
17643
17255
  GIT_NETWORK_EXEC = {
@@ -17678,7 +17290,7 @@ import { resolve as resolve4 } from "node:path";
17678
17290
  import {
17679
17291
  detectGitProvider as detectGitProvider6,
17680
17292
  GIT_NO_HOOKS as GIT_NO_HOOKS10,
17681
- log as log51,
17293
+ log as log50,
17682
17294
  validateGitProviderCli
17683
17295
  } from "@gethmy/harness";
17684
17296
  async function validatePrerequisites(config, banner) {
@@ -17755,7 +17367,7 @@ async function main() {
17755
17367
  } catch (err) {
17756
17368
  if (err instanceof ConfigValidationError) {
17757
17369
  banner.fail();
17758
- log51.error(TAG47, err.message);
17370
+ log50.error(TAG46, err.message);
17759
17371
  process.exit(1);
17760
17372
  }
17761
17373
  throw err;
@@ -17773,7 +17385,7 @@ async function main() {
17773
17385
  } catch (err) {
17774
17386
  if (err instanceof ConfigValidationError) {
17775
17387
  banner.fail();
17776
- log51.error(TAG47, err.message);
17388
+ log50.error(TAG46, err.message);
17777
17389
  process.exit(1);
17778
17390
  }
17779
17391
  throw err;
@@ -17797,7 +17409,7 @@ async function main() {
17797
17409
  try {
17798
17410
  await client.reportAgentConfig(config.workspaceId, agentId, effectiveModelReport(config.agent));
17799
17411
  } catch (err) {
17800
- log51.warn(TAG47, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17412
+ log50.warn(TAG46, `Could not report model config: ${err instanceof Error ? err.message : String(err)}`);
17801
17413
  }
17802
17414
  migrateConfigDir();
17803
17415
  try {
@@ -17807,7 +17419,7 @@ async function main() {
17807
17419
  worktreePrefix: resolve4(config.repoRoot, config.agent.worktree.basePath)
17808
17420
  });
17809
17421
  } catch (err) {
17810
- log51.error(TAG47, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17422
+ log50.error(TAG46, `legacy state split failed — starting with the project store as-is: ${err instanceof Error ? err.message : err}`);
17811
17423
  }
17812
17424
  const stateStore = StateStore.open({ projectId: config.projectId });
17813
17425
  const daemonId = randomUUID4();
@@ -17958,7 +17570,7 @@ async function main() {
17958
17570
  if (shuttingDown)
17959
17571
  return;
17960
17572
  shuttingDown = true;
17961
- log51.info(TAG47, `Received ${signal}, shutting down gracefully...`);
17573
+ log50.info(TAG46, `Received ${signal}, shutting down gracefully...`);
17962
17574
  reconciler.stop();
17963
17575
  mergeMonitor?.stop();
17964
17576
  worktreeGc.stop();
@@ -17969,19 +17581,19 @@ async function main() {
17969
17581
  }
17970
17582
  await watcher.stop();
17971
17583
  await pool.shutdown();
17972
- log51.info(TAG47, "Daemon stopped.");
17584
+ log50.info(TAG46, "Daemon stopped.");
17973
17585
  process.exit(exitCode);
17974
17586
  };
17975
17587
  process.on("SIGINT", () => shutdown("SIGINT"));
17976
17588
  process.on("SIGTERM", () => shutdown("SIGTERM"));
17977
17589
  process.on("SIGHUP", () => shutdown("SIGHUP"));
17978
17590
  process.on("uncaughtException", (err) => {
17979
- log51.error(TAG47, `Uncaught exception: ${err.message}`);
17591
+ log50.error(TAG46, `Uncaught exception: ${err.message}`);
17980
17592
  exitCode = 1;
17981
17593
  shutdown("uncaughtException");
17982
17594
  });
17983
17595
  process.on("unhandledRejection", (reason) => {
17984
- log51.error(TAG47, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17596
+ log50.error(TAG46, `Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
17985
17597
  exitCode = 1;
17986
17598
  shutdown("unhandledRejection");
17987
17599
  });
@@ -18041,33 +17653,33 @@ async function handleBroadcast(event, client, pool, config, agentId) {
18041
17653
  if (assignedAgentId === undefined)
18042
17654
  return;
18043
17655
  if (assignedAgentId === agentId) {
18044
- log51.info(TAG47, `Broadcast: card ${cardId} assigned to agent`);
17656
+ log50.info(TAG46, `Broadcast: card ${cardId} assigned to agent`);
18045
17657
  try {
18046
17658
  await pool.resetAttemptsForReassign(cardId);
18047
17659
  await tryEnqueueCard(cardId, client, pool, config, agentId);
18048
17660
  } catch (err) {
18049
- log51.error(TAG47, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
17661
+ log50.error(TAG46, `Failed to process assignment: ${err instanceof Error ? err.message : err}`);
18050
17662
  }
18051
17663
  } else if (pool.isCardKnown(cardId)) {
18052
- log51.info(TAG47, `Broadcast: card ${cardId} unassigned from agent`);
17664
+ log50.info(TAG46, `Broadcast: card ${cardId} unassigned from agent`);
18053
17665
  await pool.removeCard(cardId);
18054
17666
  }
18055
17667
  }
18056
17668
  async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18057
17669
  const { card } = await client.getCard(cardId);
18058
17670
  if (card.assigned_agent_id !== agentId) {
18059
- log51.debug(TAG47, `Card ${cardId} no longer assigned to agent — skipping`);
17671
+ log50.debug(TAG46, `Card ${cardId} no longer assigned to agent — skipping`);
18060
17672
  return;
18061
17673
  }
18062
17674
  if (card.done || card.archived_at) {
18063
- log51.debug(TAG47, `Card ${cardId} is finished — skipping`);
17675
+ log50.debug(TAG46, `Card ${cardId} is finished — skipping`);
18064
17676
  return;
18065
17677
  }
18066
17678
  const board = await client.getBoard(config.projectId, { summary: true });
18067
17679
  const columns = board.columns;
18068
17680
  const column = columns.find((c) => c.id === card.column_id);
18069
17681
  if (!column) {
18070
- log51.warn(TAG47, `Column not found for card ${cardId}`);
17682
+ log50.warn(TAG46, `Column not found for card ${cardId}`);
18071
17683
  return;
18072
17684
  }
18073
17685
  const route = classifyPickup(card, column.name, {
@@ -18076,31 +17688,31 @@ async function tryEnqueueCard(cardId, client, pool, config, agentId) {
18076
17688
  playbooks: config.agent.playbooks
18077
17689
  });
18078
17690
  if (!route) {
18079
- log51.info(TAG47, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
17691
+ log50.info(TAG46, `Card #${card.short_id} is in "${column.name}", not a pickup/review/stage column — skipping`);
18080
17692
  return;
18081
17693
  }
18082
17694
  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`);
17695
+ 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
17696
  }
18085
17697
  const mode = route.mode;
18086
17698
  const labelMap = buildLabelMap(board.labels ?? []);
18087
17699
  const cardLabels = resolveCardLabels(card, labelMap);
18088
17700
  const subtasks = card.subtasks ?? [];
18089
17701
  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`);
17702
+ log50.debug(TAG46, `Card #${card.short_id} already has "${config.agent.review.approvedLabel}" — skipping review`);
18091
17703
  return;
18092
17704
  }
18093
17705
  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`);
17706
+ log50.debug(TAG46, `Card #${card.short_id} has "${NEED_REVIEW_LABEL}" label (needs human) — skipping review`);
18095
17707
  return;
18096
17708
  }
18097
17709
  if (mode === "review" && !qualifiesForAutoReview(card.description)) {
18098
- log51.info(TAG47, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
17710
+ log50.info(TAG46, `Card #${card.short_id} has no branch or PR reference — skipping auto-review`);
18099
17711
  return;
18100
17712
  }
18101
17713
  await pool.enqueue(card, column, cardLabels, subtasks, mode);
18102
17714
  }
18103
- var TAG47 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
17715
+ var TAG46 = "daemon", BASE_REMOTE = "origin", PKG_VERSION;
18104
17716
  var init_src = __esm(() => {
18105
17717
  init_account_guard();
18106
17718
  init_account_probe();
@@ -18224,22 +17836,22 @@ function realOrResolved(path) {
18224
17836
  var init_local_pin_migration = () => {};
18225
17837
 
18226
17838
  // src/head-anchor.ts
18227
- import { log as log52 } from "@gethmy/harness";
17839
+ import { log as log51 } from "@gethmy/harness";
18228
17840
  function sealProvenHead(sha, provenance) {
18229
17841
  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`);
17842
+ 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
17843
  return;
18232
17844
  }
18233
17845
  return sha;
18234
17846
  }
18235
- var TAG48 = "head-anchor";
17847
+ var TAG47 = "head-anchor";
18236
17848
  var init_head_anchor = () => {};
18237
17849
 
18238
17850
  // src/merge-cleanup.ts
18239
17851
  import { execFileSync as execFileSync11 } from "node:child_process";
18240
17852
  import { existsSync as existsSync7, realpathSync as realpathSync2, statSync as statSync6 } from "node:fs";
18241
17853
  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";
17854
+ import { cleanupWorktree as cleanupWorktree6, GIT_NO_HOOKS as GIT_NO_HOOKS12, log as log52 } from "@gethmy/harness";
18243
17855
  function canonicalize(p) {
18244
17856
  const original = isAbsolute(p) ? p : `${process.cwd()}${sep4}${p}`;
18245
17857
  try {
@@ -18314,7 +17926,7 @@ function linkedWorktreePaths(cwd) {
18314
17926
  if (main2 !== null && records.some((r) => r.path === main2)) {
18315
17927
  return records.filter((r) => r.path !== main2).map((r) => r.path);
18316
17928
  }
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.`);
17929
+ 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
17930
  return records.slice(1).map((r) => r.path);
18319
17931
  }
18320
17932
  function sameDirectoryIgnoringCase(asked, registered) {
@@ -18345,18 +17957,18 @@ function isRegisteredWorktree(worktreePath, cwd) {
18345
17957
  function cleanupMergedWorktree(args) {
18346
17958
  if (!isRegisteredWorktree(args.worktreePath, args.cwd)) {
18347
17959
  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);
17960
+ log52.warn(TAG48, reason);
18349
17961
  return { removed: false, reason };
18350
17962
  }
18351
17963
  if (cwdIsInsideWorktree(args.cwd, args.worktreePath) || cwdIsInsideWorktree(process.cwd(), args.worktreePath)) {
18352
17964
  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);
17965
+ log52.warn(TAG48, reason);
18354
17966
  return { removed: false, reason };
18355
17967
  }
18356
17968
  cleanupWorktree6(args.worktreePath, args.branchName ?? undefined);
18357
17969
  return { removed: !existsSync7(args.worktreePath) };
18358
17970
  }
18359
- var TAG49 = "merge-cleanup";
17971
+ var TAG48 = "merge-cleanup";
18360
17972
  var init_merge_cleanup = () => {};
18361
17973
 
18362
17974
  // src/merge-command.ts
@@ -18371,7 +17983,7 @@ import { resolve as resolve7 } from "node:path";
18371
17983
  import { promisify as promisify2 } from "node:util";
18372
17984
  import {
18373
17985
  GIT_NO_HOOKS as GIT_NO_HOOKS13,
18374
- log as log54,
17986
+ log as log53,
18375
17987
  resolvePrHeadBranch as resolvePrHeadBranch3
18376
17988
  } from "@gethmy/harness";
18377
17989
  function buildFindingsBlock(items) {
@@ -18398,7 +18010,7 @@ async function gitRevParse(what, at) {
18398
18010
  async function cwdIsRepositoryTopLevel(cwd) {
18399
18011
  const top = await gitRevParse("--show-toplevel", cwd);
18400
18012
  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.`);
18013
+ 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
18014
  return false;
18403
18015
  }
18404
18016
  const gitDir = await gitRevParse("--git-dir", cwd);
@@ -18410,7 +18022,7 @@ async function cwdIsRepositoryTopLevel(cwd) {
18410
18022
  }
18411
18023
  if (isRegisteredWorktree(cwd, cwd))
18412
18024
  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.`);
18025
+ log53.warn(TAG49, `not reading a local head from ${cwd} — git does not list it as a worktree of its own repository.`);
18414
18026
  return false;
18415
18027
  }
18416
18028
  function realpathOr(p) {
@@ -18435,7 +18047,7 @@ async function readValidatedWorktreeHead(deps) {
18435
18047
  const registration = classifyWorktreeRegistration(worktreePath, cwd);
18436
18048
  if (registration.kind !== "registered") {
18437
18049
  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.`);
18050
+ 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
18051
  return { sha: undefined, detail };
18440
18052
  }
18441
18053
  }
@@ -18449,7 +18061,7 @@ async function readValidatedWorktreeHead(deps) {
18449
18061
  const raw = await gitRevParse("HEAD", readAt);
18450
18062
  const sha = raw ? sealProvenHead(raw, worktreePath ? "registered-worktree" : "repository-top-level") : undefined;
18451
18063
  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`);
18064
+ 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
18065
  return {
18454
18066
  sha: undefined,
18455
18067
  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 +18070,14 @@ async function readValidatedWorktreeHead(deps) {
18458
18070
  if (worktreePath) {
18459
18071
  const resolved = await resolvePrHeadBranch3(deps.prUrl, cwd, deps.provider);
18460
18072
  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.`);
18073
+ log53.warn(TAG49, `not corroborating ${worktreePath} against the head branch of ${deps.prUrl}: ${resolved.reason}. The anchor stands on the head sha alone.`);
18462
18074
  } else {
18463
18075
  const branch = await checkedOutBranch(worktreePath);
18464
18076
  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.`);
18077
+ 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
18078
  } else if (branch !== resolved.branch) {
18467
18079
  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}`);
18080
+ log53.warn(TAG49, `refusing the anchor from ${worktreePath}.${detail}`);
18469
18081
  return { sha: undefined, detail };
18470
18082
  }
18471
18083
  }
@@ -18515,7 +18127,7 @@ async function runMergeCommand(deps) {
18515
18127
  });
18516
18128
  } catch (err) {
18517
18129
  const detail = err instanceof Error ? err.message : String(err);
18518
- log54.warn(TAG50, `merge attempt failed: ${detail}`);
18130
+ log53.warn(TAG49, `merge attempt failed: ${detail}`);
18519
18131
  deps.emit({
18520
18132
  type: "parked",
18521
18133
  reason: `the merge attempt failed: ${detail}`
@@ -18536,7 +18148,7 @@ async function runMergeCommand(deps) {
18536
18148
  if (outcome === "report-findings") {
18537
18149
  const reported = findings[0];
18538
18150
  if (!reported) {
18539
- log54.warn(TAG50, "the merge reported findings but none arrived through the callback — parking rather than reporting an empty list");
18151
+ log53.warn(TAG49, "the merge reported findings but none arrived through the callback — parking rather than reporting an empty list");
18540
18152
  deps.emit({
18541
18153
  type: "parked",
18542
18154
  reason: "the independent review posted blocking findings, but they could not be reported — the card stays in Review for a person"
@@ -18586,7 +18198,7 @@ async function branchRefGone(branchName, cwd) {
18586
18198
  const stderr = String(failure.stderr ?? "").trim();
18587
18199
  if (failure.code === 1 && !stderr)
18588
18200
  return true;
18589
- log54.warn(TAG50, `could not determine whether ${branchName} still exists (code=${String(failure.code)}${stderr ? `, ${stderr}` : ""}) — reporting it as possibly present`);
18201
+ log53.warn(TAG49, `could not determine whether ${branchName} still exists (code=${String(failure.code)}${stderr ? `, ${stderr}` : ""}) — reporting it as possibly present`);
18590
18202
  return false;
18591
18203
  }
18592
18204
  }
@@ -18597,7 +18209,7 @@ async function finish(deps) {
18597
18209
  const resolved = await resolvePrHeadBranch3(deps.prUrl, deps.cwd, deps.provider);
18598
18210
  const branch = resolved.kind === "branch" ? resolved.branch : null;
18599
18211
  if (resolved.kind === "skip") {
18600
- log54.warn(TAG50, `no head branch for ${deps.prUrl}: ${resolved.reason}`);
18212
+ log53.warn(TAG49, `no head branch for ${deps.prUrl}: ${resolved.reason}`);
18601
18213
  }
18602
18214
  const out = cleanupMergedWorktree({
18603
18215
  worktreePath,
@@ -18606,12 +18218,12 @@ async function finish(deps) {
18606
18218
  });
18607
18219
  if (!out.removed) {
18608
18220
  const reason = out.reason ?? "the worktree directory still exists after cleanup";
18609
- log54.warn(TAG50, `cleanup refused for ${worktreePath}: ${reason}`);
18221
+ log53.warn(TAG49, `cleanup refused for ${worktreePath}: ${reason}`);
18610
18222
  deps.emit({ type: "cleanup_refused", worktree: worktreePath, reason });
18611
18223
  } else {
18612
18224
  const branchGone = branch ? await branchRefGone(branch, deps.cwd) : true;
18613
18225
  if (branch && !branchGone) {
18614
- log54.warn(TAG50, `local branch ${branch} may still exist after cleanup`);
18226
+ log53.warn(TAG49, `local branch ${branch} may still exist after cleanup`);
18615
18227
  }
18616
18228
  deps.emit({
18617
18229
  type: "cleaned",
@@ -18621,7 +18233,7 @@ async function finish(deps) {
18621
18233
  }
18622
18234
  } catch (err) {
18623
18235
  const detail = err instanceof Error ? err.message : String(err);
18624
- log54.warn(TAG50, `worktree cleanup failed for ${worktreePath}: ${detail}`);
18236
+ log53.warn(TAG49, `worktree cleanup failed for ${worktreePath}: ${detail}`);
18625
18237
  deps.emit({
18626
18238
  type: "cleanup_refused",
18627
18239
  worktree: worktreePath,
@@ -18639,16 +18251,16 @@ async function finish(deps) {
18639
18251
  });
18640
18252
  if (!out.moved) {
18641
18253
  const reason = out.reason ?? "the card could not be moved out of Review";
18642
- log54.warn(TAG50, `board not updated after merge: ${reason}`);
18254
+ log53.warn(TAG49, `board not updated after merge: ${reason}`);
18643
18255
  deps.emit({ type: "board_incomplete", reason });
18644
18256
  }
18645
18257
  } catch (err) {
18646
18258
  const detail = err instanceof Error ? err.message : String(err);
18647
- log54.warn(TAG50, `board not updated after merge: ${detail}`);
18259
+ log53.warn(TAG49, `board not updated after merge: ${detail}`);
18648
18260
  deps.emit({ type: "board_incomplete", reason: detail });
18649
18261
  }
18650
18262
  }
18651
- var TAG50 = "merge-command", POLL_INTERVAL_MS = 30000, execFileAsync2, KEEP_WAITING, PARK_REASONS;
18263
+ var TAG49 = "merge-command", POLL_INTERVAL_MS = 30000, execFileAsync2, KEEP_WAITING, PARK_REASONS;
18652
18264
  var init_merge_command = __esm(() => {
18653
18265
  init_dist();
18654
18266
  init_auto_merge();
@@ -18787,9 +18399,10 @@ var init_scan_commands = __esm(() => {
18787
18399
  });
18788
18400
 
18789
18401
  // src/cli.ts
18790
- import { realpathSync as realpathSync4 } from "node:fs";
18402
+ import { readFileSync as readFileSync11, realpathSync as realpathSync4 } from "node:fs";
18403
+ import { dirname as dirname9, join as join10 } from "node:path";
18791
18404
  import { fileURLToPath } from "node:url";
18792
- import { log as log55 } from "@gethmy/harness";
18405
+ import { log as log54 } from "@gethmy/harness";
18793
18406
  var USAGE = `
18794
18407
  Harmony Agent — push-based daemon + ops toolkit.
18795
18408
 
@@ -18831,6 +18444,11 @@ Usage:
18831
18444
  Search across run logs
18832
18445
  harmony-agent stats [--json] Aggregate cost/turns/failure bottlenecks
18833
18446
  harmony-agent help Show this help
18447
+ harmony-agent --version Print the package version AND the resolved
18448
+ entry point. Both, because a command that
18449
+ resolves can still be an old build: an npx
18450
+ cache freezes what it first installed, so the
18451
+ path is what says WHICH build answered.
18834
18452
 
18835
18453
  Flags:
18836
18454
  --pretty Force colored human log output
@@ -19033,6 +18651,35 @@ async function fixLocalPinCommand(cwd) {
19033
18651
  return 1;
19034
18652
  }
19035
18653
  }
18654
+ async function reportBuildFreshness(version) {
18655
+ process.stderr.write(`preflight: @gethmy/agent ${version}
18656
+ `);
18657
+ try {
18658
+ process.stderr.write(`preflight: running ${fileURLToPath(import.meta.url)}
18659
+ `);
18660
+ } catch {}
18661
+ const { execFile: execFile3 } = await import("node:child_process");
18662
+ const { promisify: promisify3 } = await import("node:util");
18663
+ let published;
18664
+ try {
18665
+ const { stdout } = await promisify3(execFile3)("npm", ["view", "@gethmy/agent", "version"], { timeout: 1e4 });
18666
+ published = stdout.trim();
18667
+ } catch (err) {
18668
+ process.stderr.write(`preflight: could not check npm for a newer build (${err instanceof Error ? err.message.split(`
18669
+ `)[0] : String(err)})
18670
+ `);
18671
+ return;
18672
+ }
18673
+ if (!/^\d+\.\d+\.\d+/.test(published)) {
18674
+ process.stderr.write(`preflight: could not check npm for a newer build (unparseable answer ${JSON.stringify(published)})
18675
+ `);
18676
+ return;
18677
+ }
18678
+ if (published === version)
18679
+ return;
18680
+ 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.
18681
+ `);
18682
+ }
19036
18683
  async function doctorCommand() {
19037
18684
  const { loadDaemonConfig: loadDaemonConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
19038
18685
  const { validatePrerequisites: validatePrerequisites2 } = await Promise.resolve().then(() => (init_src(), exports_src));
@@ -19061,6 +18708,7 @@ async function doctorCommand() {
19061
18708
  validateRetentionConfig2(config.agent);
19062
18709
  validateVerificationConfig2(config.agent);
19063
18710
  validateHttpConfig2(config.agent);
18711
+ await reportBuildFreshness(version);
19064
18712
  const banner = createStartupBanner2(config, version);
19065
18713
  const userId = await validatePrerequisites2(config, banner);
19066
18714
  await banner.ready(`preflight ok — agent user ${userId}`);
@@ -19369,8 +19017,8 @@ async function runsShowCommand(rest) {
19369
19017
  `);
19370
19018
  let content;
19371
19019
  try {
19372
- const { readFileSync: readFileSync11 } = await import("node:fs");
19373
- content = readFileSync11(logFile.path, "utf-8");
19020
+ const { readFileSync: readFileSync12 } = await import("node:fs");
19021
+ content = readFileSync12(logFile.path, "utf-8");
19374
19022
  } catch (err) {
19375
19023
  process.stderr.write(`could not read log: ${err instanceof Error ? err.message : err}
19376
19024
  `);
@@ -19547,6 +19195,11 @@ async function dispatch(argv) {
19547
19195
  return runsCommand(args.slice(1));
19548
19196
  case "stats":
19549
19197
  return statsCommand();
19198
+ case "--version":
19199
+ case "-v":
19200
+ process.stdout.write(`${versionReport(import.meta.url)}
19201
+ `);
19202
+ return 0;
19550
19203
  case "help":
19551
19204
  case "--help":
19552
19205
  case "-h":
@@ -19560,6 +19213,31 @@ ${USAGE}
19560
19213
  return 2;
19561
19214
  }
19562
19215
  }
19216
+ function versionReport(moduleUrl) {
19217
+ let entry = moduleUrl;
19218
+ try {
19219
+ entry = fileURLToPath(moduleUrl);
19220
+ } catch {
19221
+ return `unknown
19222
+ ${moduleUrl}`;
19223
+ }
19224
+ let dir = dirname9(entry);
19225
+ for (let up = 0;up < 4; up++) {
19226
+ try {
19227
+ const manifest = JSON.parse(readFileSync11(join10(dir, "package.json"), "utf8"));
19228
+ if (manifest.version) {
19229
+ return `${manifest.name ?? "unknown"} ${manifest.version}
19230
+ ${entry}`;
19231
+ }
19232
+ } catch {}
19233
+ const parent = dirname9(dir);
19234
+ if (parent === dir)
19235
+ break;
19236
+ dir = parent;
19237
+ }
19238
+ return `unknown
19239
+ ${entry}`;
19240
+ }
19563
19241
  function isMainModule() {
19564
19242
  const entry = process.argv[1];
19565
19243
  if (!entry)
@@ -19575,11 +19253,12 @@ if (isMainModule()) {
19575
19253
  if (code !== 0)
19576
19254
  process.exit(code);
19577
19255
  }).catch((err) => {
19578
- log55.error("cli", err instanceof Error ? err.message : String(err));
19256
+ log54.error("cli", err instanceof Error ? err.message : String(err));
19579
19257
  process.exit(1);
19580
19258
  });
19581
19259
  }
19582
19260
  export {
19261
+ versionReport,
19583
19262
  statsCommand,
19584
19263
  runsShowCommand,
19585
19264
  runsListCommand,