@pourkit/cli 0.0.0-next-20260714055657 → 0.0.0-next-20260714073403

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
@@ -3772,7 +3772,7 @@ function validatePrdPlanWorkspace(options) {
3772
3772
  );
3773
3773
  }
3774
3774
  const children = [];
3775
- const CHILD_REF_PATTERN2 = /^\s*(I-0*\d+)\s*$/i;
3775
+ const CHILD_REF_PATTERN = /^\s*(I-0*\d+)\s*$/i;
3776
3776
  const BLOCKED_BY_SECTION_REGEX2 = /## Blocked by\s*\n([\s\S]*?)(?=\n## |$)/i;
3777
3777
  const PARENT_SECTION_REGEX2 = /## Parent\s*\n([\s\S]*?)(?=\n## |$)/i;
3778
3778
  for (const childFile of childFiles) {
@@ -3810,7 +3810,7 @@ function validatePrdPlanWorkspace(options) {
3810
3810
  if (!line) continue;
3811
3811
  for (const part of line.split(",")) {
3812
3812
  const trimmed = part.trim();
3813
- const match = trimmed.match(CHILD_REF_PATTERN2);
3813
+ const match = trimmed.match(CHILD_REF_PATTERN);
3814
3814
  if (match) {
3815
3815
  blockedByRefs.push(match[1].toUpperCase());
3816
3816
  }
@@ -8815,7 +8815,7 @@ import { isAbsolute as isAbsolute8, join as join22, relative as relative3, resol
8815
8815
  import { readFile as readFile5, readdir as readdir2 } from "fs/promises";
8816
8816
  import { join as join19 } from "path";
8817
8817
  var CHILD_FILE_PATTERN = /^I-0*(\d+)-.+\.md$/i;
8818
- var CHILD_REF_PATTERN = /^\s*(?:[-*]|\d+[.)])?\s*(I-0*\d+)\s*$/i;
8818
+ var CHILD_REF_REGEX = /\bI-0*(\d+)\b/gi;
8819
8819
  var BLOCKED_BY_SECTION_REGEX = /## Blocked by\s*\n([\s\S]*?)(?=\n## |$)/i;
8820
8820
  var PARENT_SECTION_REGEX = /## Parent\s*\n([\s\S]*?)(?=\n## |$)/i;
8821
8821
  function escapeRegExp2(value) {
@@ -8840,19 +8840,10 @@ function parseChildRefsFromBody(body) {
8840
8840
  const section = body.match(BLOCKED_BY_SECTION_REGEX)?.[1];
8841
8841
  if (!section) return [];
8842
8842
  const refs = [];
8843
- for (const rawLine of section.split("\n")) {
8844
- const line = rawLine.trim();
8845
- if (!line) continue;
8846
- const parts = line.split(",");
8847
- for (const part of parts) {
8848
- const trimmed = part.trim();
8849
- const match = trimmed.match(CHILD_REF_PATTERN);
8850
- if (match) {
8851
- refs.push(match[1].toUpperCase());
8852
- }
8853
- }
8843
+ for (const match of section.matchAll(CHILD_REF_REGEX)) {
8844
+ refs.push(`I-${match[1].padStart(2, "0")}`);
8854
8845
  }
8855
- return refs;
8846
+ return Array.from(new Set(refs));
8856
8847
  }
8857
8848
  function extractTitleBody(content) {
8858
8849
  const firstLine = content.split("\n")[0];
@@ -11859,6 +11850,29 @@ async function claimReadyPrdChild(options) {
11859
11850
  }
11860
11851
  };
11861
11852
  }
11853
+ async function releaseClaimedPrdChild(options) {
11854
+ const result = await runBdJson({
11855
+ repoRoot: options.repoRoot,
11856
+ args: ["update", options.childId, "--status", "open", "--json"],
11857
+ logger: options.logger
11858
+ });
11859
+ const child = findReadyClaim(result);
11860
+ if (!child?.id) {
11861
+ return {
11862
+ ok: false,
11863
+ childId: options.childId,
11864
+ reason: `bd update ${options.childId} --status open returned no child.`
11865
+ };
11866
+ }
11867
+ return {
11868
+ ok: true,
11869
+ child: {
11870
+ id: child.id,
11871
+ title: child.title,
11872
+ metadata: child.metadata
11873
+ }
11874
+ };
11875
+ }
11862
11876
  function findReadyClaim(value) {
11863
11877
  if (!value) return void 0;
11864
11878
  if (Array.isArray(value)) return value.find((entry) => Boolean(entry.id));
@@ -13051,6 +13065,32 @@ async function reconcileBlockedBeadsIssueProjection(options) {
13051
13065
  }
13052
13066
  return refreshed;
13053
13067
  }
13068
+ async function releaseSkippedBlockedBeadsChildren(options) {
13069
+ for (const child of options.children) {
13070
+ let result;
13071
+ try {
13072
+ result = await releaseClaimedPrdChild({
13073
+ repoRoot: options.repoRoot,
13074
+ childId: child.id,
13075
+ logger: options.logger
13076
+ });
13077
+ } catch (error) {
13078
+ logCoordinatorStep(
13079
+ options.logger,
13080
+ "warn",
13081
+ `Failed to release skipped Beads child ${child.id}: ${error instanceof Error ? error.message : String(error)}`
13082
+ );
13083
+ continue;
13084
+ }
13085
+ if (!result.ok) {
13086
+ logCoordinatorStep(
13087
+ options.logger,
13088
+ "warn",
13089
+ `Failed to release skipped Beads child ${child.id}: ${result.reason}`
13090
+ );
13091
+ }
13092
+ }
13093
+ }
13054
13094
  function extractIssueFromQueueError(error) {
13055
13095
  if (!error || typeof error !== "object" || !("issue" in error)) {
13056
13096
  return void 0;
@@ -14267,6 +14307,7 @@ async function launchBeadsQueueDrain(options, prdRef, startReceipt, targetName,
14267
14307
  const executionProvider = options.executionProvider;
14268
14308
  const logger = options.logger;
14269
14309
  const processedResults = [];
14310
+ const skippedBlockedBeadsChildren = [];
14270
14311
  const originalGuidance = readPrdRun(options.repoRoot, prdRef).record?.repairGuidance;
14271
14312
  logCoordinatorStep(
14272
14313
  logger,
@@ -14365,33 +14406,42 @@ async function launchBeadsQueueDrain(options, prdRef, startReceipt, targetName,
14365
14406
  prdRef,
14366
14407
  logger
14367
14408
  });
14368
- logCoordinatorStep(
14369
- logger,
14370
- "info",
14371
- `Running GitHub Issue #${issue.number} from Beads child ${contextResult.beads.childId}.`
14372
- );
14373
- const runResult = await runClaimedPrdIssueCommand({
14374
- targetName,
14375
- config: options.config,
14376
- issueProvider,
14377
- prProvider,
14378
- executionProvider,
14379
- force: false,
14380
- logger,
14381
- repoRoot: options.repoRoot,
14382
- issue,
14383
- queueRunContext: {
14384
- prdRef,
14385
- prdBranch: startReceipt.prdBranch,
14386
- beadsChild: contextResult.beads
14387
- }
14388
- });
14389
- processedResults.push({
14390
- beadsChildId: contextResult.beads.childId,
14391
- issueNumber: runResult.selected.number,
14392
- noOp: runResult.runResult.noOp,
14393
- publicationStatus: runResult.runResult.publicationStatus
14394
- });
14409
+ if (issue.labels.includes(options.config.labels.blocked)) {
14410
+ logCoordinatorStep(
14411
+ logger,
14412
+ "info",
14413
+ `Skipping Beads child ${contextResult.beads.childId} because GitHub Issue #${issue.number} remains labeled ${options.config.labels.blocked}.`
14414
+ );
14415
+ skippedBlockedBeadsChildren.push(readResult.child);
14416
+ } else {
14417
+ logCoordinatorStep(
14418
+ logger,
14419
+ "info",
14420
+ `Running GitHub Issue #${issue.number} from Beads child ${contextResult.beads.childId}.`
14421
+ );
14422
+ const runResult = await runClaimedPrdIssueCommand({
14423
+ targetName,
14424
+ config: options.config,
14425
+ issueProvider,
14426
+ prProvider,
14427
+ executionProvider,
14428
+ force: false,
14429
+ logger,
14430
+ repoRoot: options.repoRoot,
14431
+ issue,
14432
+ queueRunContext: {
14433
+ prdRef,
14434
+ prdBranch: startReceipt.prdBranch,
14435
+ beadsChild: contextResult.beads
14436
+ }
14437
+ });
14438
+ processedResults.push({
14439
+ beadsChildId: contextResult.beads.childId,
14440
+ issueNumber: runResult.selected.number,
14441
+ noOp: runResult.runResult.noOp,
14442
+ publicationStatus: runResult.runResult.publicationStatus
14443
+ });
14444
+ }
14395
14445
  } catch (error) {
14396
14446
  const msg = error instanceof Error ? error.message : String(error);
14397
14447
  const repair = buildQueueIssueRunRepairMetadata(
@@ -14469,30 +14519,52 @@ async function launchBeadsQueueDrain(options, prdRef, startReceipt, targetName,
14469
14519
  prdRef,
14470
14520
  logger
14471
14521
  });
14472
- const runResult = await runClaimedPrdIssueCommand({
14473
- targetName,
14474
- config: options.config,
14475
- issueProvider,
14476
- prProvider,
14477
- executionProvider,
14478
- force: false,
14479
- logger,
14480
- repoRoot: options.repoRoot,
14481
- issue: fetchedIssue,
14482
- queueRunContext: {
14483
- prdRef,
14484
- prdBranch: startReceipt.prdBranch,
14485
- ...resumeBeadsContext ? { beadsChild: resumeBeadsContext } : {}
14522
+ if (fetchedIssue.labels.includes(options.config.labels.blocked)) {
14523
+ logCoordinatorStep(
14524
+ logger,
14525
+ "info",
14526
+ `Skipping resume issue #${fetchedIssue.number} because it remains labeled ${options.config.labels.blocked}; selecting another Beads-ready child.`
14527
+ );
14528
+ if (resumeBeadsContext) {
14529
+ skippedBlockedBeadsChildren.push({
14530
+ id: resumeBeadsContext.childId,
14531
+ title: fetchedIssue.title,
14532
+ metadata: {
14533
+ pourkit: {
14534
+ prdRef,
14535
+ childRef: resumeBeadsContext.childRef,
14536
+ githubIssueNumber: resumeIssueNumber
14537
+ }
14538
+ }
14539
+ });
14486
14540
  }
14487
- });
14488
- processedResults.push({
14489
- beadsChildId: resumeIssue?.beadsChildId ?? "resumed",
14490
- issueNumber: runResult.selected.number,
14491
- noOp: runResult.runResult.noOp,
14492
- publicationStatus: runResult.runResult.publicationStatus
14493
- });
14494
- startReceipt.queueDrainedAt = (/* @__PURE__ */ new Date()).toISOString();
14495
- startReceipt.queueProcessedCount = processedResults.length;
14541
+ resumeIssueNumber = void 0;
14542
+ } else {
14543
+ const runResult = await runClaimedPrdIssueCommand({
14544
+ targetName,
14545
+ config: options.config,
14546
+ issueProvider,
14547
+ prProvider,
14548
+ executionProvider,
14549
+ force: false,
14550
+ logger,
14551
+ repoRoot: options.repoRoot,
14552
+ issue: fetchedIssue,
14553
+ queueRunContext: {
14554
+ prdRef,
14555
+ prdBranch: startReceipt.prdBranch,
14556
+ ...resumeBeadsContext ? { beadsChild: resumeBeadsContext } : {}
14557
+ }
14558
+ });
14559
+ processedResults.push({
14560
+ beadsChildId: resumeIssue?.beadsChildId ?? "resumed",
14561
+ issueNumber: runResult.selected.number,
14562
+ noOp: runResult.runResult.noOp,
14563
+ publicationStatus: runResult.runResult.publicationStatus
14564
+ });
14565
+ startReceipt.queueDrainedAt = (/* @__PURE__ */ new Date()).toISOString();
14566
+ startReceipt.queueProcessedCount = processedResults.length;
14567
+ }
14496
14568
  } catch (error) {
14497
14569
  const msg = error instanceof Error ? error.message : String(error);
14498
14570
  const repair = buildQueueIssueRunRepairMetadata(
@@ -14528,143 +14600,160 @@ async function launchBeadsQueueDrain(options, prdRef, startReceipt, targetName,
14528
14600
  }
14529
14601
  }
14530
14602
  let beadsClaimAttempted = false;
14531
- while (true) {
14532
- const claimResult = await claimReadyPrdChild({
14533
- repoRoot: options.repoRoot,
14534
- prdRef,
14535
- logger
14536
- });
14537
- if (!claimResult.ok) {
14538
- if (claimResult.reason === "no-ready-child") {
14539
- logCoordinatorStep(
14540
- logger,
14541
- "info",
14542
- `Beads-backed PRD queue drain for ${prdRef} found no additional ready child work.`
14543
- );
14544
- break;
14545
- }
14546
- return buildLaunchBlockedOutcome(
14547
- options.repoRoot,
14548
- prdRef,
14549
- buildPrdRunRepairGuidance({
14550
- blockedGate: "queue",
14551
- blockedStage: "queue-drain",
14552
- failureCode: "beads-claim-failed",
14553
- humanReadableReason: `Beads claim failed for PRD ${prdRef} epic ${claimResult.epicId}.`,
14554
- repairability: "operator-action",
14555
- nextAction: "inspect-and-retry",
14556
- nextRecommendedCommand: `pourkit prd-run status ${prdRef}`,
14557
- diagnostics: [`Beads claim error for epic ${claimResult.epicId}.`]
14558
- }),
14559
- plan,
14560
- startOutcome,
14561
- targetName,
14562
- startReceipt
14563
- );
14564
- }
14565
- beadsClaimAttempted = true;
14566
- logCoordinatorStep(
14567
- logger,
14568
- "info",
14569
- `Claimed Beads child ${claimResult.child.id} for ${prdRef}; mapping to GitHub Issue context.`
14570
- );
14571
- const contextResult = await buildIssueContextFromBeadsChild({
14572
- child: claimResult.child,
14573
- issueProvider,
14574
- expectedPrdRef: prdRef
14575
- });
14576
- if (!contextResult.ok) {
14577
- return buildLaunchBlockedOutcome(
14578
- options.repoRoot,
14579
- prdRef,
14580
- buildPrdRunRepairGuidance({
14581
- blockedGate: "queue",
14582
- blockedStage: "queue-drain",
14583
- failureCode: "beads-context-mapping-failed",
14584
- humanReadableReason: `Failed to map Beads child ${claimResult.child.id} to Issue context: ${contextResult.reason}`,
14585
- repairability: "operator-action",
14586
- nextAction: "inspect-and-retry",
14587
- nextRecommendedCommand: `pourkit prd-run status ${prdRef}`,
14588
- diagnostics: [contextResult.reason],
14589
- issue: claimedBeadsChildRepairIssue(claimResult.child)
14590
- }),
14591
- plan,
14592
- startOutcome,
14593
- targetName,
14594
- startReceipt
14595
- );
14596
- }
14597
- try {
14598
- const issue = await reconcileBlockedBeadsIssueProjection({
14599
- issue: contextResult.issue,
14600
- issueProvider,
14601
- config: options.config,
14603
+ try {
14604
+ while (true) {
14605
+ const claimResult = await claimReadyPrdChild({
14606
+ repoRoot: options.repoRoot,
14602
14607
  prdRef,
14603
14608
  logger
14604
14609
  });
14610
+ if (!claimResult.ok) {
14611
+ if (claimResult.reason === "no-ready-child") {
14612
+ logCoordinatorStep(
14613
+ logger,
14614
+ "info",
14615
+ `Beads-backed PRD queue drain for ${prdRef} found no additional ready child work.`
14616
+ );
14617
+ break;
14618
+ }
14619
+ return buildLaunchBlockedOutcome(
14620
+ options.repoRoot,
14621
+ prdRef,
14622
+ buildPrdRunRepairGuidance({
14623
+ blockedGate: "queue",
14624
+ blockedStage: "queue-drain",
14625
+ failureCode: "beads-claim-failed",
14626
+ humanReadableReason: `Beads claim failed for PRD ${prdRef} epic ${claimResult.epicId}.`,
14627
+ repairability: "operator-action",
14628
+ nextAction: "inspect-and-retry",
14629
+ nextRecommendedCommand: `pourkit prd-run status ${prdRef}`,
14630
+ diagnostics: [`Beads claim error for epic ${claimResult.epicId}.`]
14631
+ }),
14632
+ plan,
14633
+ startOutcome,
14634
+ targetName,
14635
+ startReceipt
14636
+ );
14637
+ }
14605
14638
  logCoordinatorStep(
14606
14639
  logger,
14607
14640
  "info",
14608
- `Running GitHub Issue #${issue.number} from Beads child ${contextResult.beads.childId}.`
14641
+ `Claimed Beads child ${claimResult.child.id} for ${prdRef}; mapping to GitHub Issue context.`
14609
14642
  );
14610
- const runResult = await runClaimedPrdIssueCommand({
14611
- targetName,
14612
- config: options.config,
14643
+ const contextResult = await buildIssueContextFromBeadsChild({
14644
+ child: claimResult.child,
14613
14645
  issueProvider,
14614
- prProvider,
14615
- executionProvider,
14616
- force: false,
14617
- logger,
14618
- repoRoot: options.repoRoot,
14619
- issue,
14620
- queueRunContext: {
14646
+ expectedPrdRef: prdRef
14647
+ });
14648
+ if (!contextResult.ok) {
14649
+ return buildLaunchBlockedOutcome(
14650
+ options.repoRoot,
14621
14651
  prdRef,
14622
- prdBranch: startReceipt.prdBranch,
14623
- beadsChild: contextResult.beads
14652
+ buildPrdRunRepairGuidance({
14653
+ blockedGate: "queue",
14654
+ blockedStage: "queue-drain",
14655
+ failureCode: "beads-context-mapping-failed",
14656
+ humanReadableReason: `Failed to map Beads child ${claimResult.child.id} to Issue context: ${contextResult.reason}`,
14657
+ repairability: "operator-action",
14658
+ nextAction: "inspect-and-retry",
14659
+ nextRecommendedCommand: `pourkit prd-run status ${prdRef}`,
14660
+ diagnostics: [contextResult.reason],
14661
+ issue: claimedBeadsChildRepairIssue(claimResult.child)
14662
+ }),
14663
+ plan,
14664
+ startOutcome,
14665
+ targetName,
14666
+ startReceipt
14667
+ );
14668
+ }
14669
+ try {
14670
+ const issue = await reconcileBlockedBeadsIssueProjection({
14671
+ issue: contextResult.issue,
14672
+ issueProvider,
14673
+ config: options.config,
14674
+ prdRef,
14675
+ logger
14676
+ });
14677
+ if (issue.labels.includes(options.config.labels.blocked)) {
14678
+ logCoordinatorStep(
14679
+ logger,
14680
+ "info",
14681
+ `Skipping Beads child ${contextResult.beads.childId} because GitHub Issue #${issue.number} remains labeled ${options.config.labels.blocked}.`
14682
+ );
14683
+ skippedBlockedBeadsChildren.push(claimResult.child);
14684
+ continue;
14624
14685
  }
14625
- });
14626
- processedResults.push({
14627
- beadsChildId: claimResult.child.id,
14628
- issueNumber: runResult.selected.number,
14629
- noOp: runResult.runResult.noOp,
14630
- publicationStatus: runResult.runResult.publicationStatus
14631
- });
14632
- } catch (error) {
14633
- const msg = error instanceof Error ? error.message : String(error);
14634
- const repair = buildQueueIssueRunRepairMetadata(
14635
- msg,
14636
- "beads-issue-run-failed",
14637
- prdRef
14638
- );
14639
- const beadsChildClosed = msg.startsWith(
14640
- "Projection failure after Beads close"
14641
- );
14642
- return buildLaunchBlockedOutcome(
14643
- options.repoRoot,
14644
- prdRef,
14645
- buildPrdRunRepairGuidance({
14646
- blockedGate: "queue",
14647
- blockedStage: "queue-drain",
14648
- failureCode: repair.failureCode,
14649
- humanReadableReason: msg,
14650
- repairability: repair.repairability,
14651
- nextAction: repair.nextAction,
14652
- nextRecommendedCommand: repair.nextRecommendedCommand,
14653
- diagnostics: [msg],
14654
- issue: {
14655
- number: contextResult.issue.number,
14656
- title: contextResult.issue.title,
14657
- beadsChildId: contextResult.beads.childId,
14658
- beadsChildRef: contextResult.beads.childRef,
14659
- beadsChildClosed
14686
+ beadsClaimAttempted = true;
14687
+ logCoordinatorStep(
14688
+ logger,
14689
+ "info",
14690
+ `Running GitHub Issue #${issue.number} from Beads child ${contextResult.beads.childId}.`
14691
+ );
14692
+ const runResult = await runClaimedPrdIssueCommand({
14693
+ targetName,
14694
+ config: options.config,
14695
+ issueProvider,
14696
+ prProvider,
14697
+ executionProvider,
14698
+ force: false,
14699
+ logger,
14700
+ repoRoot: options.repoRoot,
14701
+ issue,
14702
+ queueRunContext: {
14703
+ prdRef,
14704
+ prdBranch: startReceipt.prdBranch,
14705
+ beadsChild: contextResult.beads
14660
14706
  }
14661
- }),
14662
- plan,
14663
- startOutcome,
14664
- targetName,
14665
- startReceipt
14666
- );
14707
+ });
14708
+ processedResults.push({
14709
+ beadsChildId: claimResult.child.id,
14710
+ issueNumber: runResult.selected.number,
14711
+ noOp: runResult.runResult.noOp,
14712
+ publicationStatus: runResult.runResult.publicationStatus
14713
+ });
14714
+ } catch (error) {
14715
+ const msg = error instanceof Error ? error.message : String(error);
14716
+ const repair = buildQueueIssueRunRepairMetadata(
14717
+ msg,
14718
+ "beads-issue-run-failed",
14719
+ prdRef
14720
+ );
14721
+ const beadsChildClosed = msg.startsWith(
14722
+ "Projection failure after Beads close"
14723
+ );
14724
+ return buildLaunchBlockedOutcome(
14725
+ options.repoRoot,
14726
+ prdRef,
14727
+ buildPrdRunRepairGuidance({
14728
+ blockedGate: "queue",
14729
+ blockedStage: "queue-drain",
14730
+ failureCode: repair.failureCode,
14731
+ humanReadableReason: msg,
14732
+ repairability: repair.repairability,
14733
+ nextAction: repair.nextAction,
14734
+ nextRecommendedCommand: repair.nextRecommendedCommand,
14735
+ diagnostics: [msg],
14736
+ issue: {
14737
+ number: contextResult.issue.number,
14738
+ title: contextResult.issue.title,
14739
+ beadsChildId: contextResult.beads.childId,
14740
+ beadsChildRef: contextResult.beads.childRef,
14741
+ beadsChildClosed
14742
+ }
14743
+ }),
14744
+ plan,
14745
+ startOutcome,
14746
+ targetName,
14747
+ startReceipt
14748
+ );
14749
+ }
14667
14750
  }
14751
+ } finally {
14752
+ await releaseSkippedBlockedBeadsChildren({
14753
+ repoRoot: options.repoRoot,
14754
+ children: skippedBlockedBeadsChildren,
14755
+ logger
14756
+ });
14668
14757
  }
14669
14758
  if (processedResults.length === 0 && !beadsClaimAttempted) {
14670
14759
  const diagnostics = [
@@ -21450,11 +21539,11 @@ function createCliProgram(version) {
21450
21539
  return program;
21451
21540
  }
21452
21541
  async function resolveCliVersion() {
21453
- if (isPackageVersion("0.0.0-next-20260714055657")) {
21454
- return "0.0.0-next-20260714055657";
21542
+ if (isPackageVersion("0.0.0-next-20260714073403")) {
21543
+ return "0.0.0-next-20260714073403";
21455
21544
  }
21456
- if (isReleaseVersion("0.0.0-next-20260714055657")) {
21457
- return "0.0.0-next-20260714055657";
21545
+ if (isReleaseVersion("0.0.0-next-20260714073403")) {
21546
+ return "0.0.0-next-20260714073403";
21458
21547
  }
21459
21548
  try {
21460
21549
  const root = repoRoot();