@pourkit/cli 0.0.0-next-20260727021939 → 0.0.0-next-20260729083209

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.
package/dist/cli.js CHANGED
@@ -11965,10 +11965,49 @@ async function claimReadyPrdChild(options) {
11965
11965
  }
11966
11966
  };
11967
11967
  }
11968
+ async function listInProgressPrdChildren(options) {
11969
+ const epicId = derivePrdEpicId(options.prdRef);
11970
+ let result;
11971
+ try {
11972
+ result = await runBdJson({
11973
+ repoRoot: options.repoRoot,
11974
+ args: [
11975
+ "list",
11976
+ "--parent",
11977
+ epicId,
11978
+ "--status",
11979
+ "in_progress",
11980
+ "--limit",
11981
+ "0",
11982
+ "--json"
11983
+ ],
11984
+ logger: options.logger
11985
+ });
11986
+ } catch (error) {
11987
+ return {
11988
+ ok: false,
11989
+ epicId,
11990
+ reason: error instanceof Error ? error.message : String(error)
11991
+ };
11992
+ }
11993
+ return {
11994
+ ok: true,
11995
+ epicId,
11996
+ children: findListChildren(result)
11997
+ };
11998
+ }
11968
11999
  async function releaseClaimedPrdChild(options) {
11969
12000
  const result = await runBdJson({
11970
12001
  repoRoot: options.repoRoot,
11971
- args: ["update", options.childId, "--status", "open", "--json"],
12002
+ args: [
12003
+ "update",
12004
+ options.childId,
12005
+ "--status",
12006
+ "open",
12007
+ "--assignee",
12008
+ "",
12009
+ "--json"
12010
+ ],
11972
12011
  logger: options.logger
11973
12012
  });
11974
12013
  const child = findReadyClaim(result);
@@ -11998,6 +12037,15 @@ function findReadyClaim(value) {
11998
12037
  }
11999
12038
  return void 0;
12000
12039
  }
12040
+ function findListChildren(value) {
12041
+ if (!value) return [];
12042
+ const entries = Array.isArray(value) ? value : value.id ? [value] : Object.values(value);
12043
+ return entries.filter((entry) => Boolean(entry?.id)).map((entry) => ({
12044
+ id: entry.id,
12045
+ title: entry.title,
12046
+ metadata: entry.metadata
12047
+ }));
12048
+ }
12001
12049
  function isMissingIssueMessage3(value) {
12002
12050
  return /no issues? found matching/i.test(value);
12003
12051
  }
@@ -12239,7 +12287,7 @@ async function buildIssueContextFromBeadsChild(options) {
12239
12287
  var PRD_RUN_HEARTBEAT_INTERVAL_MS = 3e4;
12240
12288
  var PRD_RUN_LEASE_STALE_AFTER_MS = 12e4;
12241
12289
  function classifyPrdRunLiveness(options) {
12242
- const { record, now, currentHost, isPidAlive } = options;
12290
+ const { record, now, currentHost, isPidAlive: isPidAlive2 } = options;
12243
12291
  const diagnostics = [];
12244
12292
  if (record.status !== "starting" && record.status !== "running") {
12245
12293
  return {
@@ -12300,8 +12348,8 @@ function classifyPrdRunLiveness(options) {
12300
12348
  };
12301
12349
  }
12302
12350
  const isSameHost = lease.host === currentHost;
12303
- if (isSameHost && isPidAlive !== void 0) {
12304
- const pidAlive = isPidAlive(lease.pid);
12351
+ if (isSameHost && isPidAlive2 !== void 0) {
12352
+ const pidAlive = isPidAlive2(lease.pid);
12305
12353
  if (!pidAlive) {
12306
12354
  return {
12307
12355
  status: "stale",
@@ -12610,6 +12658,14 @@ function enrichLaunchRepairGuidance(options) {
12610
12658
  return guidance;
12611
12659
  }
12612
12660
  var CURRENT_HOST = hostname();
12661
+ function isPidAlive(pid) {
12662
+ try {
12663
+ process.kill(pid, 0);
12664
+ return true;
12665
+ } catch {
12666
+ return false;
12667
+ }
12668
+ }
12613
12669
  function createPrdRunHeartbeatLease(options, prdRef, currentStage) {
12614
12670
  const now = (/* @__PURE__ */ new Date()).toISOString();
12615
12671
  return {
@@ -13472,6 +13528,24 @@ function claimedBeadsChildRepairIssue(child) {
13472
13528
  ...parsed.ok ? { beadsChildRef: parsed.childRef } : {}
13473
13529
  };
13474
13530
  }
13531
+ function buildInProgressBeadsChildGuidance(options) {
13532
+ const countSuffix = options.totalChildren > 1 ? ` (${options.totalChildren} in-progress Beads children found)` : "";
13533
+ const issue = claimedBeadsChildRepairIssue(options.child);
13534
+ return buildPrdRunRepairGuidance({
13535
+ blockedGate: "queue",
13536
+ blockedStage: "queue-drain",
13537
+ failureCode: "beads-child-in-progress",
13538
+ humanReadableReason: `Beads-backed PRD drain found no ready children because Beads child ${options.child.id} is already in progress${countSuffix}.`,
13539
+ repairability: "operator-action",
13540
+ nextAction: "inspect-in-progress-beads-child",
13541
+ nextRecommendedCommand: `bd show ${options.child.id} --json`,
13542
+ diagnostics: [
13543
+ `Beads child ${options.child.id} is in_progress, so bd ready --claim will not select it.`,
13544
+ `Inspect the child runner, worktree, and log; if it is stale, finish the child or reset it before rerunning pourkit prd-run launch ${options.prdRef}.`
13545
+ ],
13546
+ issue
13547
+ });
13548
+ }
13475
13549
  function canRetryQueueGuidanceWithoutIssue(options) {
13476
13550
  const { guidance, startReceipt } = options;
13477
13551
  if (guidance.blockedGate !== "queue") return false;
@@ -13629,7 +13703,8 @@ function shouldRestoreRetryableBeadsProjection(options) {
13629
13703
  if (!retryRepair) return false;
13630
13704
  if (issue.state !== "open") return false;
13631
13705
  const guidance = retryRepair.guidance;
13632
- if (guidance.repairability !== "automatic-retry-safe") return false;
13706
+ const canRepairProjection = guidance.repairability === "automatic-retry-safe" || guidance.failureCode === "beads-child-in-progress";
13707
+ if (!canRepairProjection) return false;
13633
13708
  if (guidance.blockedGate !== "queue") return false;
13634
13709
  if (issue.labels.includes(config.labels.blocked)) return false;
13635
13710
  return !issue.labels.includes(config.labels.readyForAgent) || issue.labels.includes(config.labels.agentInProgress) || issue.labels.includes(config.labels.readyForHuman);
@@ -13673,6 +13748,207 @@ async function closeBeadsChildForClosedIssueProjection(options) {
13673
13748
  logger: options.logger
13674
13749
  });
13675
13750
  }
13751
+ async function repairAndRunInProgressBeadsChild(options) {
13752
+ const guidance = buildInProgressBeadsChildGuidance({
13753
+ prdRef: options.prdRef,
13754
+ child: options.child,
13755
+ totalChildren: options.totalChildren
13756
+ });
13757
+ const contextResult = await buildIssueContextFromBeadsChild({
13758
+ child: options.child,
13759
+ issueProvider: options.issueProvider,
13760
+ expectedPrdRef: options.prdRef
13761
+ });
13762
+ if (!contextResult.ok) {
13763
+ return {
13764
+ kind: "blocked",
13765
+ outcome: buildLaunchBlockedOutcome(
13766
+ options.repoRoot,
13767
+ options.prdRef,
13768
+ buildPrdRunRepairGuidance({
13769
+ blockedGate: "queue",
13770
+ blockedStage: "queue-drain",
13771
+ failureCode: "beads-context-mapping-failed",
13772
+ humanReadableReason: `Failed to map in-progress Beads child ${options.child.id} to Issue context: ${contextResult.reason}`,
13773
+ repairability: "operator-action",
13774
+ nextAction: "inspect-and-retry",
13775
+ nextRecommendedCommand: `pourkit prd-run status ${options.prdRef}`,
13776
+ diagnostics: [contextResult.reason],
13777
+ issue: claimedBeadsChildRepairIssue(options.child)
13778
+ }),
13779
+ options.plan,
13780
+ options.startOutcome,
13781
+ options.targetName,
13782
+ options.startReceipt
13783
+ )
13784
+ };
13785
+ }
13786
+ if (contextResult.issue.state === "closed") {
13787
+ await closeBeadsChildForClosedIssueProjection({
13788
+ repoRoot: options.repoRoot,
13789
+ issue: contextResult.issue,
13790
+ beadsChildId: contextResult.beads.childId,
13791
+ logger: options.logger
13792
+ });
13793
+ return {
13794
+ kind: "processed",
13795
+ result: {
13796
+ beadsChildId: contextResult.beads.childId,
13797
+ issueNumber: contextResult.issue.number,
13798
+ publicationStatus: "merged"
13799
+ }
13800
+ };
13801
+ }
13802
+ let issue;
13803
+ try {
13804
+ issue = await reconcileBlockedBeadsIssueProjection({
13805
+ issue: contextResult.issue,
13806
+ issueProvider: options.issueProvider,
13807
+ config: options.config,
13808
+ prdRef: options.prdRef,
13809
+ repoRoot: options.repoRoot,
13810
+ logger: options.logger,
13811
+ retryRepair: {
13812
+ guidance,
13813
+ beadsChildId: contextResult.beads.childId
13814
+ }
13815
+ });
13816
+ } catch (error) {
13817
+ const msg = error instanceof Error ? error.message : String(error);
13818
+ return {
13819
+ kind: "blocked",
13820
+ outcome: buildLaunchBlockedOutcome(
13821
+ options.repoRoot,
13822
+ options.prdRef,
13823
+ buildPrdRunRepairGuidance({
13824
+ blockedGate: "queue",
13825
+ blockedStage: "queue-drain",
13826
+ failureCode: "beads-child-repair-failed",
13827
+ humanReadableReason: `Failed to repair stale Beads child ${contextResult.beads.childId} projection for Issue #${contextResult.issue.number}: ${msg}`,
13828
+ repairability: "operator-action",
13829
+ nextAction: "inspect-and-retry",
13830
+ nextRecommendedCommand: `pourkit prd-run status ${options.prdRef}`,
13831
+ diagnostics: [msg],
13832
+ issue: {
13833
+ number: contextResult.issue.number,
13834
+ title: contextResult.issue.title,
13835
+ beadsChildId: contextResult.beads.childId,
13836
+ beadsChildRef: contextResult.beads.childRef
13837
+ }
13838
+ }),
13839
+ options.plan,
13840
+ options.startOutcome,
13841
+ options.targetName,
13842
+ options.startReceipt
13843
+ )
13844
+ };
13845
+ }
13846
+ if (issue.labels.includes(options.config.labels.blocked)) {
13847
+ return { kind: "skipped-blocked", child: options.child };
13848
+ }
13849
+ if (!issue.labels.includes(options.config.labels.readyForAgent) || issue.labels.includes(options.config.labels.agentInProgress)) {
13850
+ return {
13851
+ kind: "blocked",
13852
+ outcome: buildLaunchBlockedOutcome(
13853
+ options.repoRoot,
13854
+ options.prdRef,
13855
+ buildPrdRunRepairGuidance({
13856
+ blockedGate: "queue",
13857
+ blockedStage: "queue-drain",
13858
+ failureCode: "beads-child-repair-failed",
13859
+ humanReadableReason: `Failed to restore runnable GitHub labels for stale Beads child ${contextResult.beads.childId}.`,
13860
+ repairability: "operator-action",
13861
+ nextAction: "inspect-and-retry",
13862
+ nextRecommendedCommand: `pourkit prd-run status ${options.prdRef}`,
13863
+ diagnostics: [
13864
+ `Issue #${issue.number} labels after repair: ${issue.labels.join(", ") || "none"}`
13865
+ ],
13866
+ issue: {
13867
+ number: issue.number,
13868
+ title: issue.title,
13869
+ beadsChildId: contextResult.beads.childId,
13870
+ beadsChildRef: contextResult.beads.childRef
13871
+ }
13872
+ }),
13873
+ options.plan,
13874
+ options.startOutcome,
13875
+ options.targetName,
13876
+ options.startReceipt
13877
+ )
13878
+ };
13879
+ }
13880
+ try {
13881
+ logCoordinatorStep(
13882
+ options.logger,
13883
+ "info",
13884
+ `Resuming stale in-progress Beads child ${contextResult.beads.childId} through GitHub Issue #${issue.number}.`
13885
+ );
13886
+ const runResult = await runClaimedPrdIssueCommand({
13887
+ targetName: options.targetName,
13888
+ config: options.config,
13889
+ issueProvider: options.issueProvider,
13890
+ prProvider: options.prProvider,
13891
+ executionProvider: options.executionProvider,
13892
+ force: false,
13893
+ logger: options.logger,
13894
+ repoRoot: options.repoRoot,
13895
+ issue,
13896
+ queueRunContext: {
13897
+ prdRef: options.prdRef,
13898
+ prdBranch: options.startReceipt.prdBranch,
13899
+ beadsChild: contextResult.beads
13900
+ }
13901
+ });
13902
+ return {
13903
+ kind: "processed",
13904
+ result: {
13905
+ beadsChildId: contextResult.beads.childId,
13906
+ issueNumber: runResult.selected.number,
13907
+ noOp: runResult.runResult.noOp,
13908
+ publicationStatus: runResult.runResult.publicationStatus
13909
+ }
13910
+ };
13911
+ } catch (error) {
13912
+ const msg = error instanceof Error ? error.message : String(error);
13913
+ const repair = buildQueueIssueRunRepairMetadata(
13914
+ msg,
13915
+ "beads-issue-run-failed",
13916
+ options.prdRef
13917
+ );
13918
+ const guidanceDiagnostics = [msg, ...repair.classifierDiagnostics ?? []];
13919
+ return {
13920
+ kind: "blocked",
13921
+ outcome: buildLaunchBlockedOutcome(
13922
+ options.repoRoot,
13923
+ options.prdRef,
13924
+ buildPrdRunRepairGuidance({
13925
+ blockedGate: "queue",
13926
+ blockedStage: "queue-drain",
13927
+ failureCode: repair.failureCode,
13928
+ humanReadableReason: msg,
13929
+ repairability: repair.repairability,
13930
+ nextAction: repair.nextAction,
13931
+ nextRecommendedCommand: repair.nextRecommendedCommand,
13932
+ timeoutClass: repair.timeoutClass,
13933
+ diagnostics: guidanceDiagnostics,
13934
+ issue: {
13935
+ number: issue.number,
13936
+ title: issue.title,
13937
+ beadsChildId: contextResult.beads.childId,
13938
+ beadsChildRef: contextResult.beads.childRef,
13939
+ beadsChildClosed: msg.startsWith(
13940
+ "Projection failure after Beads close"
13941
+ )
13942
+ }
13943
+ }),
13944
+ options.plan,
13945
+ options.startOutcome,
13946
+ options.targetName,
13947
+ options.startReceipt
13948
+ )
13949
+ };
13950
+ }
13951
+ }
13676
13952
  function extractIssueFromQueueError(error) {
13677
13953
  if (!error || typeof error !== "object" || !("issue" in error)) {
13678
13954
  return void 0;
@@ -14317,7 +14593,8 @@ async function launchPrdRun(options) {
14317
14593
  const liveness = classifyPrdRunLiveness({
14318
14594
  record: rec,
14319
14595
  now: /* @__PURE__ */ new Date(),
14320
- currentHost: CURRENT_HOST
14596
+ currentHost: CURRENT_HOST,
14597
+ isPidAlive
14321
14598
  });
14322
14599
  if (liveness.status === "active") {
14323
14600
  return {
@@ -15498,6 +15775,60 @@ async function launchBeadsQueueDrain(options, prdRef, startReceipt, targetName,
15498
15775
  "info",
15499
15776
  `Beads-backed PRD queue drain for ${prdRef} found no additional ready child work.`
15500
15777
  );
15778
+ if (processedResults.length === 0 && !beadsClaimAttempted) {
15779
+ const inProgressChildren = await listInProgressPrdChildren({
15780
+ repoRoot: options.repoRoot,
15781
+ prdRef,
15782
+ logger
15783
+ });
15784
+ if (!inProgressChildren.ok) {
15785
+ return buildLaunchBlockedOutcome(
15786
+ options.repoRoot,
15787
+ prdRef,
15788
+ buildPrdRunRepairGuidance({
15789
+ blockedGate: "queue",
15790
+ blockedStage: "queue-drain",
15791
+ failureCode: "beads-in-progress-check-failed",
15792
+ humanReadableReason: `Failed to inspect in-progress Beads children for PRD ${prdRef}.`,
15793
+ repairability: "operator-action",
15794
+ nextAction: "inspect-and-retry",
15795
+ nextRecommendedCommand: `pourkit prd-run status ${prdRef}`,
15796
+ diagnostics: [inProgressChildren.reason]
15797
+ }),
15798
+ plan,
15799
+ startOutcome,
15800
+ targetName,
15801
+ startReceipt
15802
+ );
15803
+ }
15804
+ if (inProgressChildren.children.length > 0) {
15805
+ const repairResult = await repairAndRunInProgressBeadsChild({
15806
+ repoRoot: options.repoRoot,
15807
+ prdRef,
15808
+ child: inProgressChildren.children[0],
15809
+ totalChildren: inProgressChildren.children.length,
15810
+ targetName,
15811
+ plan,
15812
+ startOutcome,
15813
+ startReceipt,
15814
+ config: options.config,
15815
+ issueProvider,
15816
+ prProvider,
15817
+ executionProvider,
15818
+ logger
15819
+ });
15820
+ if (repairResult.kind === "blocked") {
15821
+ return repairResult.outcome;
15822
+ }
15823
+ if (repairResult.kind === "skipped-blocked") {
15824
+ skippedBlockedBeadsChildren.push(repairResult.child);
15825
+ break;
15826
+ }
15827
+ beadsClaimAttempted = true;
15828
+ processedResults.push(repairResult.result);
15829
+ continue;
15830
+ }
15831
+ }
15501
15832
  break;
15502
15833
  }
15503
15834
  return buildLaunchBlockedOutcome(
@@ -23078,11 +23409,11 @@ function createCliProgram(version) {
23078
23409
  return program;
23079
23410
  }
23080
23411
  async function resolveCliVersion() {
23081
- if (isPackageVersion("0.0.0-next-20260727021939")) {
23082
- return "0.0.0-next-20260727021939";
23412
+ if (isPackageVersion("0.0.0-next-20260729083209")) {
23413
+ return "0.0.0-next-20260729083209";
23083
23414
  }
23084
- if (isReleaseVersion("0.0.0-next-20260727021939")) {
23085
- return "0.0.0-next-20260727021939";
23415
+ if (isReleaseVersion("0.0.0-next-20260729083209")) {
23416
+ return "0.0.0-next-20260729083209";
23086
23417
  }
23087
23418
  try {
23088
23419
  const root = repoRoot();