@clipboard-health/groundcrew 4.18.0 → 4.18.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAcnE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAoqBD,wBAAsB,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/F;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7D"}
|
package/dist/commands/status.js
CHANGED
|
@@ -307,7 +307,16 @@ function inventoryField(label, value) {
|
|
|
307
307
|
function formatPullRequests(prs) {
|
|
308
308
|
return prs.map((pr) => `${pr.url} (${pr.state})`).join(", ");
|
|
309
309
|
}
|
|
310
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Inventory `ticket:` value: the worktree's remote canonical status. Slots are
|
|
312
|
+
* consumed solely by `in-progress` issues (see `inProgressCount`), so that one
|
|
313
|
+
* status is spelled out as `slot held` to make the otherwise-implicit rule
|
|
314
|
+
* legible on the row; every other status renders bare.
|
|
315
|
+
*/
|
|
316
|
+
function formatTicketStatus(canonicalStatus) {
|
|
317
|
+
return canonicalStatus === "in-progress" ? "in-progress (slot held)" : canonicalStatus;
|
|
318
|
+
}
|
|
319
|
+
async function writeInventoryWorktrees(config, probe, statusByTicket) {
|
|
311
320
|
writeSection("Worktrees");
|
|
312
321
|
const entries = worktrees
|
|
313
322
|
.list(config)
|
|
@@ -338,6 +347,14 @@ async function writeInventoryWorktrees(config, probe) {
|
|
|
338
347
|
writeOutput(inventoryField("title", runState.title));
|
|
339
348
|
}
|
|
340
349
|
writeOutput(inventoryField("state", inventoryStateText(runState, probe, entry.ticket, now)));
|
|
350
|
+
// `state:` is the local run lifecycle; `ticket:` is the remote status that
|
|
351
|
+
// actually drives the slot count. They're sourced independently and can
|
|
352
|
+
// legitimately disagree, so they sit adjacent. Omitted when the board fetch
|
|
353
|
+
// failed (no map) or the ticket isn't in the fetched board.
|
|
354
|
+
const ticketStatus = statusByTicket?.get(entry.ticket);
|
|
355
|
+
if (ticketStatus !== undefined) {
|
|
356
|
+
writeOutput(inventoryField("ticket", formatTicketStatus(ticketStatus)));
|
|
357
|
+
}
|
|
341
358
|
writeOutput(inventoryField("repo", entry.repository));
|
|
342
359
|
writeOutput(inventoryField("worktree", entry.dir));
|
|
343
360
|
if (accessHint !== undefined) {
|
|
@@ -432,6 +449,32 @@ async function fetchBoardForStatus(config) {
|
|
|
432
449
|
return { kind: "error", error };
|
|
433
450
|
}
|
|
434
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* Maps each fetched issue's lowercased natural id to its canonical status when
|
|
454
|
+
* exactly one fetched issue has that natural id, so the Worktrees section can
|
|
455
|
+
* show a `ticket:` field per row without guessing across sources. The key
|
|
456
|
+
* matches the lowercased `WorktreeEntry.ticket` (same join as
|
|
457
|
+
* `inProgressWithoutWorktree`). `undefined` when the board fetch failed —
|
|
458
|
+
* callers then omit the field rather than guess.
|
|
459
|
+
*/
|
|
460
|
+
function statusByWorktreeTicket(boardResult) {
|
|
461
|
+
if (boardResult.kind !== "ok") {
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
const statuses = new Map();
|
|
465
|
+
const matchCounts = new Map();
|
|
466
|
+
for (const issue of boardResult.issues) {
|
|
467
|
+
const ticket = naturalIdFromCanonical(issue.id).toLowerCase();
|
|
468
|
+
matchCounts.set(ticket, (matchCounts.get(ticket) ?? 0) + 1);
|
|
469
|
+
statuses.set(ticket, issue.status);
|
|
470
|
+
}
|
|
471
|
+
for (const [ticket, matchCount] of matchCounts) {
|
|
472
|
+
if (matchCount > 1) {
|
|
473
|
+
statuses.delete(ticket);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return statuses;
|
|
477
|
+
}
|
|
435
478
|
function writeQueueSections(boardResult) {
|
|
436
479
|
if (boardResult.kind === "error") {
|
|
437
480
|
writeSection("Queue");
|
|
@@ -484,6 +527,9 @@ function writeInProgressIssue(issue) {
|
|
|
484
527
|
const naturalId = naturalIdFromCanonical(issue.id);
|
|
485
528
|
writeOutput(issue.url === undefined ? naturalId : `${naturalId} ${issue.url}`);
|
|
486
529
|
writeOutput(inventoryField("title", issue.title));
|
|
530
|
+
// These are all in-progress by definition, but spell out the slot-held
|
|
531
|
+
// status so every holder row reads the same whether or not it has a worktree.
|
|
532
|
+
writeOutput(inventoryField("ticket", formatTicketStatus(issue.status)));
|
|
487
533
|
if (issue.repository !== undefined) {
|
|
488
534
|
writeOutput(inventoryField("repo", issue.repository));
|
|
489
535
|
}
|
|
@@ -508,12 +554,16 @@ async function writeInventoryStatus(config) {
|
|
|
508
554
|
// Banner ("groundcrew status\n=================") dropped: the command
|
|
509
555
|
// you just ran already tells you what report you're looking at, and the
|
|
510
556
|
// section headers (`Worktrees`, `Queue`, etc.) carry the visual anchors.
|
|
557
|
+
// The board fetch runs concurrently with the probe, but we await it before
|
|
558
|
+
// rendering: each Worktrees row carries the remote ticket status, so the
|
|
559
|
+
// inventory can't print until the source resolves. A failed fetch returns
|
|
560
|
+
// quickly and still renders rows (without the `ticket:` field).
|
|
511
561
|
const boardResultPromise = fetchBoardForStatus(config);
|
|
512
562
|
const probe = await withLogOutputSuppressed(async () => await workspaces.probe(config));
|
|
513
|
-
await
|
|
563
|
+
const boardResult = await boardResultPromise;
|
|
564
|
+
await writeInventoryWorktrees(config, probe, statusByWorktreeTicket(boardResult));
|
|
514
565
|
const worktreeTickets = new Set(worktrees.list(config).map((entry) => entry.ticket));
|
|
515
566
|
writeStraySessions(probe, worktreeTickets);
|
|
516
|
-
const boardResult = await boardResultPromise;
|
|
517
567
|
writeInProgressWithoutWorktree(boardResult, worktreeTickets);
|
|
518
568
|
if (boardResult.kind === "ok") {
|
|
519
569
|
const used = inProgressCount(boardResult.issues);
|
package/package.json
CHANGED