@hivemoot-dev/cli 0.1.5 → 0.1.7

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/index.js CHANGED
@@ -278,22 +278,76 @@ async function fetchIssues(repo, limit = 200) {
278
278
  }
279
279
 
280
280
  // src/github/pulls.ts
281
+ async function fetchLatestCommitDates(repo, limit) {
282
+ const query = `
283
+ query($owner: String!, $name: String!, $pageSize: Int!, $cursor: String) {
284
+ repository(owner: $owner, name: $name) {
285
+ pullRequests(first: $pageSize, after: $cursor, states: OPEN, orderBy: {field: CREATED_AT, direction: DESC}) {
286
+ pageInfo { hasNextPage endCursor }
287
+ nodes {
288
+ number
289
+ commits(last: 1) { nodes { commit { committedDate } } }
290
+ }
291
+ }
292
+ }
293
+ }`;
294
+ const PAGE_SIZE = 100;
295
+ const map = /* @__PURE__ */ new Map();
296
+ let remaining = limit;
297
+ let cursor = null;
298
+ while (remaining > 0) {
299
+ const pageSize = Math.min(remaining, PAGE_SIZE);
300
+ const args = [
301
+ "api",
302
+ "graphql",
303
+ "-F",
304
+ `owner=${repo.owner}`,
305
+ "-F",
306
+ `name=${repo.repo}`,
307
+ "-F",
308
+ `pageSize=${pageSize}`,
309
+ "-f",
310
+ `query=${query}`
311
+ ];
312
+ if (cursor) {
313
+ args.push("-F", `cursor=${cursor}`);
314
+ } else {
315
+ args.push("-f", "cursor=");
316
+ }
317
+ const json = await gh(args);
318
+ const data = JSON.parse(json);
319
+ const prs = data?.data?.repository?.pullRequests;
320
+ const nodes = prs?.nodes ?? [];
321
+ for (const pr of nodes) {
322
+ const commit = pr.commits.nodes[0];
323
+ if (commit) map.set(pr.number, commit.commit.committedDate);
324
+ }
325
+ remaining -= nodes.length;
326
+ const hasNext = prs?.pageInfo?.hasNextPage === true;
327
+ if (!hasNext || nodes.length === 0) break;
328
+ cursor = prs.pageInfo.endCursor;
329
+ }
330
+ return map;
331
+ }
281
332
  async function fetchPulls(repo, limit = 200) {
282
- const json = await gh([
283
- "pr",
284
- "list",
285
- "-R",
286
- `${repo.owner}/${repo.repo}`,
287
- "--state",
288
- "open",
289
- "--json",
290
- "number,title,state,author,labels,comments,reviews,createdAt,updatedAt,url,isDraft,reviewDecision,mergeable,statusCheckRollup,closingIssuesReferences",
291
- "--limit",
292
- String(limit)
333
+ const [listJson, commitDates] = await Promise.all([
334
+ gh([
335
+ "pr",
336
+ "list",
337
+ "-R",
338
+ `${repo.owner}/${repo.repo}`,
339
+ "--state",
340
+ "open",
341
+ "--json",
342
+ "number,title,state,author,labels,comments,reviews,createdAt,updatedAt,url,isDraft,reviewDecision,mergeable,statusCheckRollup,closingIssuesReferences",
343
+ "--limit",
344
+ String(limit)
345
+ ]),
346
+ fetchLatestCommitDates(repo, limit)
293
347
  ]);
294
348
  let parsed;
295
349
  try {
296
- parsed = JSON.parse(json);
350
+ parsed = JSON.parse(listJson);
297
351
  } catch {
298
352
  throw new CliError(
299
353
  "Failed to parse pull requests response from gh CLI",
@@ -308,7 +362,12 @@ async function fetchPulls(repo, limit = 200) {
308
362
  1
309
363
  );
310
364
  }
311
- return parsed;
365
+ const prs = parsed;
366
+ for (const pr of prs) {
367
+ const date = commitDates.get(pr.number);
368
+ pr.commits = date ? [{ committedDate: date }] : [];
369
+ }
370
+ return prs;
312
371
  }
313
372
 
314
373
  // src/github/user.ts
@@ -340,10 +399,12 @@ function timeAgo(dateStr, now) {
340
399
  const hours = Math.floor(ms / 36e5);
341
400
  const days = Math.floor(ms / 864e5);
342
401
  if (minutes < 1) return "just now";
343
- if (minutes === 1) return "1 minute ago";
344
- if (minutes < 60) return `${minutes} minutes ago`;
345
- if (hours === 1) return "1 hour ago";
346
- if (hours < 24) return `${hours} hours ago`;
402
+ if (minutes < 60) return `${minutes}m ago`;
403
+ if (hours < 24) {
404
+ const remainingMinutes = minutes % 60;
405
+ if (remainingMinutes === 0) return `${hours}h ago`;
406
+ return `${hours}h${remainingMinutes}m ago`;
407
+ }
347
408
  if (days === 1) return "yesterday";
348
409
  if (days < 7) return `${days} days ago`;
349
410
  if (days < 14) return "1 week ago";
@@ -354,10 +415,6 @@ function timeAgo(dateStr, now) {
354
415
  if (years === 1) return "1 year ago";
355
416
  return `${years} years ago`;
356
417
  }
357
- function daysSince(dateStr, now) {
358
- const diff = now.getTime() - new Date(dateStr).getTime();
359
- return Math.max(0, Math.floor(diff / (1e3 * 60 * 60 * 24)));
360
- }
361
418
  function hasCIFailure(pr) {
362
419
  if (!pr.statusCheckRollup) return false;
363
420
  return pr.statusCheckRollup.some((check) => {
@@ -403,60 +460,42 @@ function changesRequestedCount(pr) {
403
460
  }
404
461
  return count;
405
462
  }
406
-
407
- // src/summary/alerts.ts
408
- var STALE_DISCUSSION_DAYS = 3;
409
- var PR_WAITING_REVIEW_DAYS = 2;
410
- function lastCommentDate(issue) {
411
- if (issue.comments.length === 0) return null;
412
- return issue.comments.reduce(
413
- (latest, c) => c.createdAt > latest.createdAt ? c : latest
414
- ).createdAt;
415
- }
416
- function generateAlerts(issues, prs, now = /* @__PURE__ */ new Date()) {
417
- const alerts = [];
418
- for (const issue of issues) {
419
- if (!hasLabel(issue.labels, "discuss") && !hasExactLabel(issue.labels, "phase:discussion")) continue;
420
- const lastComment = lastCommentDate(issue);
421
- const referenceDate = lastComment ?? issue.createdAt;
422
- const days = daysSince(referenceDate, now);
423
- if (days >= STALE_DISCUSSION_DAYS) {
424
- alerts.push({
425
- icon: "\u26A0\uFE0F",
426
- message: `#${issue.number} in discussion ${days} days, no recent comments`
427
- });
428
- }
429
- }
430
- for (const issue of issues) {
431
- if (hasExactLabel(issue.labels, "needs:human")) {
432
- alerts.push({
433
- icon: "\u{1F6D1}",
434
- message: `#${issue.number} needs human attention`
435
- });
463
+ function reviewContext(pr, currentUser, now) {
464
+ let latestState;
465
+ let latestTime;
466
+ for (const review of pr.reviews ?? []) {
467
+ if (review.author?.login === currentUser) {
468
+ latestState = review.state;
469
+ latestTime = review.submittedAt;
436
470
  }
437
471
  }
438
- const intakePRs = prs.filter((pr) => hasExactLabel(pr.labels, "implementation"));
439
- for (const pr of intakePRs) {
440
- if (pr.isDraft) continue;
441
- if (pr.reviewDecision === "APPROVED" || pr.reviewDecision === "CHANGES_REQUESTED") continue;
442
- const days = daysSince(pr.createdAt, now);
443
- if (days >= PR_WAITING_REVIEW_DAYS) {
444
- alerts.push({
445
- icon: "\u26A0\uFE0F",
446
- message: `PR #${pr.number} waiting on review ${days} days`
447
- });
448
- }
472
+ if (!latestState) return null;
473
+ const stateMap = {
474
+ CHANGES_REQUESTED: "changes-requested",
475
+ APPROVED: "approved",
476
+ COMMENTED: "commented",
477
+ DISMISSED: "dismissed"
478
+ };
479
+ const yourReview = stateMap[latestState] ?? latestState.toLowerCase();
480
+ const yourReviewAge = latestTime ? timeAgo(latestTime, now) : "unknown";
481
+ return { yourReview, yourReviewAge };
482
+ }
483
+ function latestCommitAge(pr, now) {
484
+ const commits = pr.commits ?? [];
485
+ if (commits.length === 0) return void 0;
486
+ let latest = commits[0].committedDate;
487
+ for (let i = 1; i < commits.length; i++) {
488
+ if (commits[i].committedDate > latest) latest = commits[i].committedDate;
449
489
  }
450
- for (const pr of intakePRs) {
451
- if (pr.isDraft) continue;
452
- if (hasCIFailure(pr)) {
453
- alerts.push({
454
- icon: "\u26A0\uFE0F",
455
- message: `PR #${pr.number} has CI failures`
456
- });
457
- }
490
+ return timeAgo(latest, now);
491
+ }
492
+ function latestCommentAge(item, now) {
493
+ if (item.comments.length === 0) return void 0;
494
+ let latest = item.comments[0].createdAt;
495
+ for (let i = 1; i < item.comments.length; i++) {
496
+ if (item.comments[i].createdAt > latest) latest = item.comments[i].createdAt;
458
497
  }
459
- return alerts;
498
+ return timeAgo(latest, now);
460
499
  }
461
500
 
462
501
  // src/summary/builder.ts
@@ -485,7 +524,9 @@ function classifyIssue(issue, now) {
485
524
  tags,
486
525
  author,
487
526
  comments,
488
- age
527
+ age,
528
+ lastComment: latestCommentAge(issue, now),
529
+ updated: timeAgo(issue.updatedAt, now)
489
530
  };
490
531
  if (hasExactLabel(issue.labels, "needs:human")) {
491
532
  return {
@@ -529,13 +570,13 @@ function classifyPR(pr, now) {
529
570
  let status2;
530
571
  if (pr.isDraft) status2 = "draft";
531
572
  else if (pr.reviewDecision === "CHANGES_REQUESTED" || changesRequestedCount(pr) > 0) status2 = "changes-requested";
532
- else status2 = "waiting";
573
+ else status2 = "pending";
533
574
  return {
534
575
  bucket: "addressFeedback",
535
576
  item: { number: pr.number, title: pr.title, tags, author, comments, age, status: status2, checks, mergeable: merge, review }
536
577
  };
537
578
  }
538
- const status = pr.reviewDecision === "APPROVED" ? "approved" : "waiting";
579
+ const status = pr.reviewDecision === "APPROVED" ? "approved" : "pending";
539
580
  return {
540
581
  bucket: "reviewPRs",
541
582
  item: { number: pr.number, title: pr.title, tags, author, comments, age, status, checks, mergeable: merge, review }
@@ -553,6 +594,7 @@ function buildCompetitionMap(prs, currentUser) {
553
594
  return map;
554
595
  }
555
596
  function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new Date()) {
597
+ const needsHuman = [];
556
598
  const voteOn = [];
557
599
  const discuss = [];
558
600
  const implement = [];
@@ -560,7 +602,8 @@ function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new
560
602
  const addressFeedback = [];
561
603
  for (const issue of issues) {
562
604
  const { bucket, item } = classifyIssue(issue, now);
563
- if (bucket === "voteOn") voteOn.push(item);
605
+ if (bucket === "needsHuman") needsHuman.push(item);
606
+ else if (bucket === "voteOn") voteOn.push(item);
564
607
  else if (bucket === "discuss") discuss.push(item);
565
608
  else if (bucket === "implement") implement.push(item);
566
609
  }
@@ -573,10 +616,17 @@ function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new
573
616
  }
574
617
  for (const pr of prs) {
575
618
  const { bucket, item } = classifyPR(pr, now);
619
+ const ctx = reviewContext(pr, currentUser, now);
620
+ if (ctx) {
621
+ item.yourReview = ctx.yourReview;
622
+ item.yourReviewAge = ctx.yourReviewAge;
623
+ }
624
+ item.lastCommit = latestCommitAge(pr, now);
625
+ item.lastComment = latestCommentAge(pr, now);
626
+ item.updated = timeAgo(pr.updatedAt, now);
576
627
  if (bucket === "reviewPRs") reviewPRs.push(item);
577
628
  else addressFeedback.push(item);
578
629
  }
579
- const alerts = generateAlerts(issues, prs, now);
580
630
  const driveDiscussion = [];
581
631
  const driveImplementation = [];
582
632
  const filteredDiscuss = discuss.filter((item) => {
@@ -610,6 +660,7 @@ function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new
610
660
  return {
611
661
  repo,
612
662
  currentUser,
663
+ needsHuman,
613
664
  driveDiscussion,
614
665
  driveImplementation,
615
666
  voteOn: filteredVoteOn,
@@ -617,7 +668,6 @@ function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new
617
668
  implement,
618
669
  reviewPRs: filteredReviewPRs,
619
670
  addressFeedback: filteredAddressFeedback,
620
- alerts,
621
671
  notes: []
622
672
  };
623
673
  }
@@ -641,21 +691,45 @@ function formatMeta(item, sectionType, currentUser) {
641
691
  const isYou = item.author === currentUser;
642
692
  const authorVal = isYou ? chalk.green(`${item.author} (you)`) : chalk.dim(item.author);
643
693
  const parts = [`by: ${authorVal}`];
644
- if (sectionType === "implement") {
694
+ if (sectionType === "implement" || sectionType === "needsHuman") {
645
695
  parts.push(kv("assigned", item.assigned ?? "--"));
646
696
  parts.push(kv("comments", item.comments));
697
+ if (item.lastComment) parts.push(kv("last-comment", item.lastComment));
698
+ if (item.updated) parts.push(kv("updated", item.updated));
647
699
  parts.push(kv("created", item.age));
648
700
  if (item.competingPRs !== void 0) {
649
701
  parts.push(kv("competing", item.competingPRs));
650
702
  }
651
703
  } else if (sectionType === "vote" || sectionType === "discuss" || sectionType === "driveDiscussion") {
652
704
  parts.push(kv("comments", item.comments));
705
+ if (item.lastComment) parts.push(kv("last-comment", item.lastComment));
706
+ if (item.updated) parts.push(kv("updated", item.updated));
653
707
  parts.push(kv("created", item.age));
654
708
  } else {
655
- if (item.status !== void 0) parts.push(kv("status", item.status));
656
- if (item.checks !== void 0 && item.checks !== null) parts.push(kv("checks", item.checks));
657
- if (item.mergeable !== void 0 && item.mergeable !== null) parts.push(kv("merge", item.mergeable));
658
- if (item.review) parts.push(kv("review", `${item.review.approvals} approved, ${item.review.changesRequested} changes-requested`));
709
+ if (item.status !== void 0) {
710
+ const statusVal = /changes.requested/i.test(item.status) ? chalk.red(item.status) : chalk.dim(item.status);
711
+ parts.push(`status: ${statusVal}`);
712
+ }
713
+ if (item.checks !== void 0 && item.checks !== null) {
714
+ const checksVal = /fail/i.test(item.checks) ? chalk.red(item.checks) : chalk.dim(item.checks);
715
+ parts.push(`checks: ${checksVal}`);
716
+ }
717
+ if (item.mergeable !== void 0 && item.mergeable !== null) {
718
+ const mergeVal = /conflict/i.test(item.mergeable) ? chalk.red(item.mergeable) : chalk.dim(item.mergeable);
719
+ parts.push(`merge: ${mergeVal}`);
720
+ }
721
+ if (item.review) {
722
+ const segments = [`${item.review.approvals} approved`];
723
+ if (item.review.changesRequested > 0) segments.push(chalk.red(`${item.review.changesRequested} changes-requested`));
724
+ parts.push(kv("review", segments.join(", ")));
725
+ }
726
+ if (item.yourReview) {
727
+ const age = item.yourReviewAge ? ` (${item.yourReviewAge})` : "";
728
+ parts.push(kv("you", `${item.yourReview}${age}`));
729
+ }
730
+ if (item.lastCommit) parts.push(kv("last-commit", item.lastCommit));
731
+ if (item.lastComment) parts.push(kv("last-comment", item.lastComment));
732
+ if (item.updated) parts.push(kv("updated", item.updated));
659
733
  parts.push(kv("comments", item.comments));
660
734
  parts.push(kv("created", item.age));
661
735
  }
@@ -666,7 +740,9 @@ function formatItem(item, currentUser, sectionType) {
666
740
  const prefix = isYou ? chalk.green("\u2605") : " ";
667
741
  const num = chalk.cyan(`#${item.number}`);
668
742
  const tags = formatTags(item.tags);
669
- const titleLine = `${prefix} ${num} ${item.title}${tags}`;
743
+ const hasProblems = item.checks && /fail/i.test(item.checks) || item.mergeable && /conflict/i.test(item.mergeable);
744
+ const warningIcon = hasProblems ? " " + chalk.red("\u2717") : "";
745
+ const titleLine = `${prefix} ${num} ${item.title}${tags}${warningIcon}`;
670
746
  const metaLine = ` ${formatMeta(item, sectionType, currentUser)}`;
671
747
  return `${titleLine}
672
748
  ${metaLine}`;
@@ -685,15 +761,9 @@ function formatSection(title, items, currentUser, sectionType, limit) {
685
761
  function formatSummaryBody(summary, limit) {
686
762
  const u = summary.currentUser;
687
763
  const sections = [];
688
- if (summary.alerts.length > 0) {
689
- const alertLines = [
690
- sectionDivider("REQUIRES YOUR ATTENTION", summary.alerts.length),
691
- ...summary.alerts.map((a) => ` ${a.icon} ${chalk.yellow(a.message)}`)
692
- ];
693
- sections.push(alertLines.join("\n"));
694
- }
695
764
  sections.push(
696
765
  ...[
766
+ formatSection("NEEDS HUMAN", summary.needsHuman, u, "needsHuman", limit),
697
767
  formatSection("DRIVE THE DISCUSSION", summary.driveDiscussion, u, "driveDiscussion", limit),
698
768
  formatSection("DRIVE THE IMPLEMENTATION", summary.driveImplementation, u, "driveImplementation", limit),
699
769
  formatSection("VOTE ON ISSUES", summary.voteOn, u, "vote", limit),
@@ -718,7 +788,7 @@ function formatBuzz(roleName, role, summary, limit) {
718
788
  chalk.bold("INSTRUCTIONS:"),
719
789
  role.instructions.trimEnd(),
720
790
  "",
721
- `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`,
791
+ summary.currentUser ? `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}` : `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}`,
722
792
  "",
723
793
  formatSummaryBody(summary, limit)
724
794
  ];
@@ -726,7 +796,7 @@ function formatBuzz(roleName, role, summary, limit) {
726
796
  }
727
797
  function formatStatus(summary, limit) {
728
798
  const lines = [
729
- `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`,
799
+ summary.currentUser ? `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}` : `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}`,
730
800
  "",
731
801
  formatSummaryBody(summary, limit)
732
802
  ];
@@ -767,7 +837,7 @@ function jsonBuzz(roleName, role, summary) {
767
837
  implement: summary.implement,
768
838
  reviewPRs: summary.reviewPRs,
769
839
  addressFeedback: summary.addressFeedback,
770
- alerts: summary.alerts,
840
+ needsHuman: summary.needsHuman,
771
841
  notes: summary.notes
772
842
  }
773
843
  },
@@ -787,7 +857,7 @@ function jsonStatus(summary) {
787
857
  implement: summary.implement,
788
858
  reviewPRs: summary.reviewPRs,
789
859
  addressFeedback: summary.addressFeedback,
790
- alerts: summary.alerts,
860
+ needsHuman: summary.needsHuman,
791
861
  notes: summary.notes
792
862
  },
793
863
  null,
@@ -803,15 +873,41 @@ function jsonRoles(teamConfig) {
803
873
  }
804
874
 
805
875
  // src/commands/buzz.ts
876
+ function errorDetail(reason) {
877
+ return reason instanceof Error ? reason.message : String(reason);
878
+ }
806
879
  async function buzzCommand(options) {
807
880
  const repo = await resolveRepo(options.repo);
808
881
  const fetchLimit = options.fetchLimit ?? 200;
809
- const [issues, prs, currentUser] = await Promise.all([
882
+ const [issuesResult, prsResult, userResult] = await Promise.allSettled([
810
883
  fetchIssues(repo, fetchLimit),
811
884
  fetchPulls(repo, fetchLimit),
812
885
  fetchCurrentUser()
813
886
  ]);
887
+ if (issuesResult.status === "rejected" && prsResult.status === "rejected" && userResult.status === "rejected") {
888
+ const cliErrors = [issuesResult, prsResult, userResult].map((r) => r.reason).filter((r) => r instanceof CliError);
889
+ const actionableCodes = ["GH_NOT_AUTHENTICATED", "RATE_LIMITED", "GH_NOT_FOUND"];
890
+ const best = cliErrors.find((e) => actionableCodes.includes(e.code)) ?? cliErrors[0];
891
+ throw best ?? issuesResult.reason;
892
+ }
893
+ const issues = issuesResult.status === "fulfilled" ? issuesResult.value : [];
894
+ const prs = prsResult.status === "fulfilled" ? prsResult.value : [];
895
+ const currentUser = userResult.status === "fulfilled" ? userResult.value : "";
814
896
  const summary = buildSummary(repo, issues, prs, currentUser);
897
+ if (issuesResult.status === "rejected" && prsResult.status === "rejected") {
898
+ summary.notes.push(
899
+ `Could not fetch issues (${errorDetail(issuesResult.reason)}) or pull requests (${errorDetail(prsResult.reason)}) \u2014 showing limited summary.`
900
+ );
901
+ } else if (issuesResult.status === "rejected") {
902
+ summary.notes.push(`Could not fetch issues (${errorDetail(issuesResult.reason)}) \u2014 showing PRs only.`);
903
+ } else if (prsResult.status === "rejected") {
904
+ summary.notes.push(`Could not fetch pull requests (${errorDetail(prsResult.reason)}) \u2014 showing issues only.`);
905
+ }
906
+ if (userResult.status === "rejected") {
907
+ summary.notes.push(
908
+ `Could not determine GitHub user (${errorDetail(userResult.reason)}) \u2014 drive sections, competition counts, and author highlighting are unavailable.`
909
+ );
910
+ }
815
911
  if (issues.length >= fetchLimit) {
816
912
  summary.notes.push(`Only the first ${fetchLimit} issues were fetched. Use --fetch-limit to increase.`);
817
913
  }
@@ -912,7 +1008,7 @@ function parseLimit(value) {
912
1008
  var program = new Command();
913
1009
  program.name("hivemoot").description("CLI for Hivemoot agents \u2014 role instructions and repo work summaries").version(version).option("--github-token <token>", "GitHub personal access token (or set GITHUB_TOKEN env var)");
914
1010
  program.hook("preAction", () => {
915
- const token = program.opts().githubToken;
1011
+ const token = program.opts().githubToken ?? process.env.GITHUB_TOKEN;
916
1012
  if (token) {
917
1013
  setGhToken(token);
918
1014
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config/types.ts","../src/config/loader.ts","../src/github/client.ts","../src/github/repo.ts","../src/github/issues.ts","../src/github/pulls.ts","../src/github/user.ts","../src/summary/utils.ts","../src/summary/alerts.ts","../src/summary/builder.ts","../src/output/formatter.ts","../src/output/json.ts","../src/commands/buzz.ts","../src/commands/roles.ts","../src/commands/init.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command, InvalidArgumentError } from \"commander\";\nimport { buzzCommand } from \"./commands/buzz.js\";\nimport { rolesCommand } from \"./commands/roles.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { CliError } from \"./config/types.js\";\nimport { setGhToken } from \"./github/client.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nfunction parseLimit(value: string): number {\n const n = parseInt(value, 10);\n if (isNaN(n) || n <= 0) {\n throw new InvalidArgumentError(\"Must be a positive integer.\");\n }\n return n;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"hivemoot\")\n .description(\"CLI for Hivemoot agents — role instructions and repo work summaries\")\n .version(version)\n .option(\"--github-token <token>\", \"GitHub personal access token (or set GITHUB_TOKEN env var)\");\n\nprogram.hook(\"preAction\", () => {\n const token = program.opts().githubToken as string | undefined;\n if (token) {\n setGhToken(token);\n }\n});\n\nprogram\n .command(\"buzz\")\n .description(\"Get role instructions and repo work summary (omit --role for summary only)\")\n .option(\"--role <role>\", \"Role to assume (e.g. engineer, tech_lead)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--limit <n>\", \"Max items per section\", parseLimit)\n .option(\"--fetch-limit <n>\", \"Max issues/PRs to fetch from GitHub (default: 200)\", parseLimit)\n .option(\"--repo <owner/repo>\", \"Target repository (default: detect from git)\")\n .action(buzzCommand);\n\nprogram\n .command(\"roles\")\n .description(\"List available roles from team config\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--repo <owner/repo>\", \"Target repository (default: detect from git)\")\n .action(rolesCommand);\n\nprogram\n .command(\"init\")\n .description(\"Print a sample .github/hivemoot.yml template\")\n .action(initCommand);\n\n// Global error handler\nprogram.exitOverride();\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n if (err instanceof CliError) {\n // Check if parent command requested --json output\n const isJson = process.argv.includes(\"--json\");\n if (isJson) {\n console.log(JSON.stringify({ error: { code: err.code, message: err.message } }, null, 2));\n } else {\n console.error(`Error: ${err.message}`);\n }\n process.exit(err.exitCode);\n }\n\n // Commander exits for --help, --version, etc.\n if (err instanceof Error && \"exitCode\" in err) {\n const exitCode = (err as Error & { exitCode: number }).exitCode;\n process.exit(exitCode);\n }\n\n console.error(\"Unexpected error:\", err);\n process.exit(1);\n}\n","// ── YAML Config Types ──────────────────────────────────────────────\n\nexport interface RoleConfig {\n description: string;\n instructions: string;\n}\n\nexport interface TeamConfig {\n name?: string;\n roles: Record<string, RoleConfig>;\n}\n\nexport interface HivemootConfig {\n version?: number;\n governance?: unknown;\n team?: TeamConfig;\n}\n\n// ── GitHub Data Types ──────────────────────────────────────────────\n\nexport interface GitHubIssue {\n number: number;\n title: string;\n labels: Array<{ name: string }>;\n assignees: Array<{ login: string }>;\n author: { login: string } | null;\n comments: Array<{ createdAt: string }>;\n createdAt: string;\n updatedAt: string;\n url: string;\n}\n\nexport interface StatusCheck {\n context: string;\n state: string | undefined;\n conclusion: string | null;\n}\n\nexport interface PRReview {\n state: string;\n author: { login: string } | null;\n}\n\nexport interface GitHubPR {\n number: number;\n title: string;\n state: string;\n author: { login: string } | null;\n labels: Array<{ name: string }>;\n comments: Array<{ createdAt: string }>;\n reviews: PRReview[];\n createdAt: string;\n updatedAt: string;\n url: string;\n isDraft: boolean;\n reviewDecision: string;\n mergeable: string;\n statusCheckRollup: StatusCheck[] | null;\n closingIssuesReferences: Array<{ number: number }>;\n}\n\n// ── Repo Identity ──────────────────────────────────────────────────\n\nexport interface RepoRef {\n owner: string;\n repo: string;\n}\n\n// ── Summary Types ──────────────────────────────────────────────────\n\nexport interface ReviewSummary {\n approvals: number;\n changesRequested: number;\n}\n\nexport interface SummaryItem {\n number: number;\n title: string;\n tags: string[];\n author: string;\n // Common fields\n comments: number;\n age: string; // \"just now\" | \"5 minutes ago\" | \"2 hours ago\" | \"3 days ago\"\n // Issue-specific\n assigned?: string; // comma-separated logins, or undefined (= unassigned)\n competingPRs?: number; // only on implement items with competing PRs\n // PR-specific\n status?: string; // \"waiting\" | \"approved\" | \"changes-requested\" | \"draft\"\n checks?: string | null; // \"passing\" | \"failing\" | \"pending\" | null\n mergeable?: string | null; // \"clean\" | \"conflicts\" | null\n review?: ReviewSummary;\n}\n\nexport interface Alert {\n icon: string;\n message: string;\n}\n\nexport interface RepoSummary {\n repo: RepoRef;\n currentUser: string;\n driveDiscussion: SummaryItem[];\n driveImplementation: SummaryItem[];\n voteOn: SummaryItem[];\n discuss: SummaryItem[];\n implement: SummaryItem[];\n reviewPRs: SummaryItem[];\n addressFeedback: SummaryItem[];\n alerts: Alert[];\n notes: string[];\n}\n\n// ── CLI Options ────────────────────────────────────────────────────\n\nexport interface BuzzOptions {\n role?: string;\n json?: boolean;\n limit?: number;\n fetchLimit?: number;\n repo?: string;\n}\n\nexport interface RolesOptions {\n json?: boolean;\n repo?: string;\n}\n\n// ── Error Types ────────────────────────────────────────────────────\n\nexport type ErrorCode =\n | \"GH_NOT_FOUND\"\n | \"GH_NOT_AUTHENTICATED\"\n | \"NOT_GIT_REPO\"\n | \"CONFIG_NOT_FOUND\"\n | \"NO_TEAM_CONFIG\"\n | \"ROLE_NOT_FOUND\"\n | \"INVALID_CONFIG\"\n | \"RATE_LIMITED\"\n | \"GH_ERROR\";\n\nexport class CliError extends Error {\n constructor(\n message: string,\n public readonly code: ErrorCode,\n public readonly exitCode: number = 1,\n ) {\n super(message);\n this.name = \"CliError\";\n }\n}\n","import yaml from \"js-yaml\";\nimport { gh } from \"../github/client.js\";\nimport type { HivemootConfig, TeamConfig, RepoRef, RoleConfig } from \"./types.js\";\nimport { CliError } from \"./types.js\";\n\nconst ROLE_SLUG_RE = /^[a-z][a-z0-9_]{0,49}$/;\nconst MAX_DESCRIPTION_LENGTH = 500;\nconst MAX_INSTRUCTIONS_LENGTH = 10_000;\n\nfunction validateTeamConfig(raw: HivemootConfig): TeamConfig {\n if (!raw.team) {\n throw new CliError(\n \"No team config in .github/hivemoot.yml. Run: hivemoot init\",\n \"NO_TEAM_CONFIG\",\n 1,\n );\n }\n\n const { team } = raw;\n\n if (!team.roles || typeof team.roles !== \"object\" || Object.keys(team.roles).length === 0) {\n throw new CliError(\n \"Config error: team.roles must contain at least one role\",\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n const validatedRoles: Record<string, RoleConfig> = {};\n\n for (const [slug, role] of Object.entries(team.roles)) {\n if (!ROLE_SLUG_RE.test(slug)) {\n throw new CliError(\n `Config error: invalid role slug \"${slug}\" — must match /^[a-z][a-z0-9_]{0,49}$/`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof role !== \"object\" || role === null) {\n throw new CliError(\n `Config error: role \"${slug}\" must be an object`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n const r = role as unknown as Record<string, unknown>;\n\n if (typeof r.description !== \"string\" || r.description.length === 0) {\n throw new CliError(\n `Config error: role \"${slug}\" is missing a description`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (r.description.length > MAX_DESCRIPTION_LENGTH) {\n throw new CliError(\n `Config error: role \"${slug}\" description exceeds ${MAX_DESCRIPTION_LENGTH} characters`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof r.instructions !== \"string\" || r.instructions.length === 0) {\n throw new CliError(\n `Config error: role \"${slug}\" is missing instructions`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (r.instructions.length > MAX_INSTRUCTIONS_LENGTH) {\n throw new CliError(\n `Config error: role \"${slug}\" instructions exceeds ${MAX_INSTRUCTIONS_LENGTH} characters`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n validatedRoles[slug] = {\n description: r.description,\n instructions: r.instructions,\n };\n }\n\n return {\n name: typeof team.name === \"string\" ? team.name : undefined,\n roles: validatedRoles,\n };\n}\n\nexport async function loadTeamConfig(repo: RepoRef): Promise<TeamConfig> {\n let rawJson: string;\n\n try {\n rawJson = await gh([\n \"api\",\n `repos/${repo.owner}/${repo.repo}/contents/.github/hivemoot.yml`,\n ]);\n } catch (err) {\n if (err instanceof Error && /404|Not Found/i.test(err.message)) {\n throw new CliError(\n \"No .github/hivemoot.yml found. Run: hivemoot init\",\n \"CONFIG_NOT_FOUND\",\n 1,\n );\n }\n throw err;\n }\n\n let content: string;\n try {\n const parsed = JSON.parse(rawJson);\n content = Buffer.from(parsed.content, \"base64\").toString(\"utf-8\");\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : \"\";\n throw new CliError(\n `Config error: failed to decode .github/hivemoot.yml content${detail}`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n let config: HivemootConfig;\n try {\n config = yaml.load(content, { schema: yaml.JSON_SCHEMA }) as HivemootConfig;\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : \"\";\n throw new CliError(\n `Config error: invalid YAML in .github/hivemoot.yml${detail}`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof config !== \"object\" || config === null) {\n throw new CliError(\n \"Config error: .github/hivemoot.yml must be a YAML object\",\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n return validateTeamConfig(config);\n}\n","import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { CliError } from \"../config/types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nlet ghToken: string | undefined;\n\n/** Set the GitHub token used for all subsequent `gh` calls. */\nexport function setGhToken(token: string): void {\n ghToken = token;\n}\n\n/**\n * Execute a `gh` CLI command and return stdout.\n * All GitHub I/O goes through this single function.\n */\nexport async function gh(args: string[]): Promise<string> {\n try {\n const opts: { timeout: number; env?: NodeJS.ProcessEnv } = {\n timeout: 30_000,\n };\n if (ghToken) {\n opts.env = { ...process.env, GH_TOKEN: ghToken };\n }\n const { stdout } = await execFileAsync(\"gh\", args, opts);\n return stdout.trim();\n } catch (err: unknown) {\n const error = err as NodeJS.ErrnoException & {\n stderr?: string;\n code?: string | number;\n };\n\n if (error.code === \"ENOENT\") {\n throw new CliError(\n \"gh CLI not found. Install: https://cli.github.com\",\n \"GH_NOT_FOUND\",\n 2,\n );\n }\n\n const stderr = error.stderr ?? error.message ?? \"\";\n\n if (/gh auth login|not logged in|authentication required/i.test(stderr)) {\n throw new CliError(\n \"Not authenticated. Pass --github-token <token>, set GITHUB_TOKEN, or run: gh auth login\",\n \"GH_NOT_AUTHENTICATED\",\n 2,\n );\n }\n\n if (/rate.?limit|API rate limit/i.test(stderr)) {\n throw new CliError(\n \"GitHub rate limited. Try again later.\",\n \"RATE_LIMITED\",\n 3,\n );\n }\n\n throw new CliError(stderr || \"gh command failed\", \"GH_ERROR\", 1);\n }\n}\n","import { CliError, type RepoRef } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nconst GITHUB_NAME_RE = /^[a-zA-Z0-9._-]+$/;\n\nexport async function resolveRepo(repoFlag?: string): Promise<RepoRef> {\n if (repoFlag) {\n const parts = repoFlag.split(\"/\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new CliError(\n `Invalid repo format: \"${repoFlag}\". Expected OWNER/REPO`,\n \"GH_ERROR\",\n 1,\n );\n }\n if (!GITHUB_NAME_RE.test(parts[0]) || !GITHUB_NAME_RE.test(parts[1])) {\n throw new CliError(\n `Invalid repo name: \"${repoFlag}\". Owner and repo must match ${GITHUB_NAME_RE}`,\n \"GH_ERROR\",\n 1,\n );\n }\n return { owner: parts[0], repo: parts[1] };\n }\n\n try {\n const json = await gh([\"repo\", \"view\", \"--json\", \"owner,name\"]);\n let data: { owner?: { login?: string } | string; name?: string };\n try {\n data = JSON.parse(json);\n } catch {\n throw new CliError(\n \"Failed to parse repo info from gh CLI. Use --repo OWNER/REPO\",\n \"GH_ERROR\",\n 1,\n );\n }\n // gh returns owner as an object { login: \"...\" } not a plain string\n const owner =\n typeof data.owner === \"object\" && data.owner !== null\n ? data.owner.login\n : data.owner;\n const name = data.name;\n if (typeof owner !== \"string\" || !owner || typeof name !== \"string\" || !name) {\n throw new CliError(\n \"Could not detect repo owner/name. Use --repo OWNER/REPO\",\n \"NOT_GIT_REPO\",\n 2,\n );\n }\n return { owner, repo: name };\n } catch (err) {\n if (err instanceof CliError) {\n throw err;\n }\n throw new CliError(\n \"Not in a git repository. Use --repo OWNER/REPO\",\n \"NOT_GIT_REPO\",\n 2,\n );\n }\n}\n","import type { GitHubIssue, RepoRef } from \"../config/types.js\";\nimport { CliError } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nexport async function fetchIssues(repo: RepoRef, limit = 200): Promise<GitHubIssue[]> {\n const json = await gh([\n \"issue\",\n \"list\",\n \"-R\",\n `${repo.owner}/${repo.repo}`,\n \"--state\",\n \"open\",\n \"--json\",\n \"number,title,labels,assignees,author,comments,createdAt,updatedAt,url\",\n \"--limit\",\n String(limit),\n ]);\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new CliError(\n \"Failed to parse issues response from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n if (!Array.isArray(parsed)) {\n throw new CliError(\n \"Unexpected issues response format from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n return parsed as GitHubIssue[];\n}\n","import type { GitHubPR, RepoRef } from \"../config/types.js\";\nimport { CliError } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nexport async function fetchPulls(repo: RepoRef, limit = 200): Promise<GitHubPR[]> {\n const json = await gh([\n \"pr\",\n \"list\",\n \"-R\",\n `${repo.owner}/${repo.repo}`,\n \"--state\",\n \"open\",\n \"--json\",\n \"number,title,state,author,labels,comments,reviews,createdAt,updatedAt,url,isDraft,reviewDecision,mergeable,statusCheckRollup,closingIssuesReferences\",\n \"--limit\",\n String(limit),\n ]);\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new CliError(\n \"Failed to parse pull requests response from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n if (!Array.isArray(parsed)) {\n throw new CliError(\n \"Unexpected pull requests response format from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n return parsed as GitHubPR[];\n}\n","import { gh } from \"./client.js\";\nimport { CliError } from \"../config/types.js\";\n\n/**\n * Return the login of the currently authenticated GitHub user.\n */\nexport async function fetchCurrentUser(): Promise<string> {\n const login = await gh([\"api\", \"user\", \"--jq\", \".login\"]);\n if (!login) {\n throw new CliError(\n \"Could not determine GitHub username. Pass --github-token <token>, set GITHUB_TOKEN, or run: gh auth login\",\n \"GH_NOT_AUTHENTICATED\",\n 2,\n );\n }\n return login;\n}\n","import type { GitHubPR } from \"../config/types.js\";\n\nexport function hasLabel(labels: Array<{ name: string }>, keyword: string): boolean {\n return labels.some((l) =>\n l.name.toLowerCase().split(/[:\\-_]/).some((seg) => seg === keyword),\n );\n}\n\nexport function hasExactLabel(labels: Array<{ name: string }>, labelName: string): boolean {\n return labels.some((l) => l.name.toLowerCase() === labelName.toLowerCase());\n}\n\n/** Human-relative time string (\"just now\", \"5 minutes ago\", \"yesterday\", etc.). */\nexport function timeAgo(dateStr: string, now: Date): string {\n const ms = now.getTime() - new Date(dateStr).getTime();\n if (ms < 0) return \"just now\"; // future date — clock skew or bad data\n\n const minutes = Math.floor(ms / 60_000);\n const hours = Math.floor(ms / 3_600_000);\n const days = Math.floor(ms / 86_400_000);\n\n if (minutes < 1) return \"just now\";\n if (minutes === 1) return \"1 minute ago\";\n if (minutes < 60) return `${minutes} minutes ago`;\n if (hours === 1) return \"1 hour ago\";\n if (hours < 24) return `${hours} hours ago`;\n if (days === 1) return \"yesterday\";\n if (days < 7) return `${days} days ago`;\n if (days < 14) return \"1 week ago\";\n if (days < 30) return `${Math.floor(days / 7)} weeks ago`;\n if (days < 60) return \"1 month ago\";\n if (days < 365) return `${Math.floor(days / 30)} months ago`;\n const years = Math.floor(days / 365);\n if (years === 1) return \"1 year ago\";\n return `${years} years ago`;\n}\n\nexport function daysSince(dateStr: string, now: Date): number {\n const diff = now.getTime() - new Date(dateStr).getTime();\n return Math.max(0, Math.floor(diff / (1000 * 60 * 60 * 24)));\n}\n\nexport function hasCIFailure(pr: GitHubPR): boolean {\n if (!pr.statusCheckRollup) return false;\n return pr.statusCheckRollup.some((check) => {\n const conclusion = check.conclusion?.toUpperCase();\n const state = check.state?.toUpperCase();\n return conclusion === \"FAILURE\" || state === \"FAILURE\";\n });\n}\n\n/**\n * Summarize all status checks into a single label.\n * Returns null when there are no checks to report.\n */\nexport function checkStatus(pr: GitHubPR): string | null {\n if (!pr.statusCheckRollup || pr.statusCheckRollup.length === 0) return null;\n\n const hasFailing = hasCIFailure(pr);\n if (hasFailing) return \"checks failing\";\n\n const hasPending = pr.statusCheckRollup.some((c) => {\n const s = c.state?.toUpperCase();\n return s === \"PENDING\" || s === \"QUEUED\" || s === \"IN_PROGRESS\";\n });\n if (hasPending) return \"checks pending\";\n\n return \"checks passing\";\n}\n\n/**\n * Return a merge-conflict label, or null if no conflict info.\n */\nexport function mergeStatus(pr: GitHubPR): string | null {\n if (pr.mergeable === \"CONFLICTING\") return \"has conflicts\";\n if (pr.mergeable === \"MERGEABLE\") return \"no conflicts\";\n return null;\n}\n\n/** Collapse reviews to the latest state per author. */\nfunction latestReviewByAuthor(pr: GitHubPR): Map<string, string> {\n const map = new Map<string, string>();\n for (const review of pr.reviews ?? []) {\n map.set(review.author?.login ?? \"ghost\", review.state);\n }\n return map;\n}\n\n/** Count unique approvals (latest review per author). */\nexport function approvalCount(pr: GitHubPR): number {\n let count = 0;\n for (const state of latestReviewByAuthor(pr).values()) {\n if (state === \"APPROVED\") count++;\n }\n return count;\n}\n\n/**\n * Count unique changes-requested reviews (latest review per author).\n * If an author requests changes then later approves, they are no longer counted.\n */\nexport function changesRequestedCount(pr: GitHubPR): number {\n let count = 0;\n for (const state of latestReviewByAuthor(pr).values()) {\n if (state === \"CHANGES_REQUESTED\") count++;\n }\n return count;\n}\n","import type { GitHubIssue, GitHubPR, Alert } from \"../config/types.js\";\nimport { hasLabel, hasExactLabel, daysSince, hasCIFailure } from \"./utils.js\";\n\nconst STALE_DISCUSSION_DAYS = 3;\nconst PR_WAITING_REVIEW_DAYS = 2;\n\nfunction lastCommentDate(issue: GitHubIssue): string | null {\n if (issue.comments.length === 0) return null;\n return issue.comments.reduce((latest, c) =>\n c.createdAt > latest.createdAt ? c : latest,\n ).createdAt;\n}\n\nexport function generateAlerts(\n issues: GitHubIssue[],\n prs: GitHubPR[],\n now: Date = new Date(),\n): Alert[] {\n const alerts: Alert[] = [];\n\n // Stale discussions: discuss-labeled issues with no recent comments\n for (const issue of issues) {\n if (!hasLabel(issue.labels, \"discuss\") && !hasExactLabel(issue.labels, \"phase:discussion\")) continue;\n const lastComment = lastCommentDate(issue);\n const referenceDate = lastComment ?? issue.createdAt;\n const days = daysSince(referenceDate, now);\n if (days >= STALE_DISCUSSION_DAYS) {\n alerts.push({\n icon: \"\\u26a0\\ufe0f\",\n message: `#${issue.number} in discussion ${days} days, no recent comments`,\n });\n }\n }\n\n // Issues needing human attention\n for (const issue of issues) {\n if (hasExactLabel(issue.labels, \"needs:human\")) {\n alerts.push({\n icon: \"\\ud83d\\uded1\",\n message: `#${issue.number} needs human attention`,\n });\n }\n }\n\n // Only PRs in the governance intake (with \"implementation\" label) generate attention items\n const intakePRs = prs.filter((pr) => hasExactLabel(pr.labels, \"implementation\"));\n\n // PRs waiting on review too long (skip approved/changes-requested/drafts)\n for (const pr of intakePRs) {\n if (pr.isDraft) continue;\n if (pr.reviewDecision === \"APPROVED\" || pr.reviewDecision === \"CHANGES_REQUESTED\") continue;\n const days = daysSince(pr.createdAt, now);\n if (days >= PR_WAITING_REVIEW_DAYS) {\n alerts.push({\n icon: \"\\u26a0\\ufe0f\",\n message: `PR #${pr.number} waiting on review ${days} days`,\n });\n }\n }\n\n // CI failures on non-draft PRs\n for (const pr of intakePRs) {\n if (pr.isDraft) continue;\n if (hasCIFailure(pr)) {\n alerts.push({\n icon: \"\\u26a0\\ufe0f\",\n message: `PR #${pr.number} has CI failures`,\n });\n }\n }\n\n return alerts;\n}\n","import type {\n GitHubIssue,\n GitHubPR,\n RepoRef,\n RepoSummary,\n SummaryItem,\n} from \"../config/types.js\";\nimport { generateAlerts } from \"./alerts.js\";\nimport { hasLabel, hasExactLabel, hasCIFailure, checkStatus, mergeStatus, approvalCount, changesRequestedCount, timeAgo } from \"./utils.js\";\n\n/** Map verbose check labels to compact values for structured output. */\nfunction compactChecks(raw: string | null): string | null {\n if (raw === null) return null;\n if (raw === \"checks failing\") return \"failing\";\n if (raw === \"checks pending\") return \"pending\";\n if (raw === \"checks passing\") return \"passing\";\n return raw;\n}\n\n/** Map verbose merge labels to compact values for structured output. */\nfunction compactMergeable(raw: string | null): string | null {\n if (raw === null) return null;\n if (raw === \"has conflicts\") return \"conflicts\";\n if (raw === \"no conflicts\") return \"clean\";\n return raw;\n}\n\nfunction classifyIssue(\n issue: GitHubIssue,\n now: Date,\n): { bucket: \"voteOn\" | \"discuss\" | \"implement\" | \"needsHuman\"; item: SummaryItem } {\n const age = timeAgo(issue.createdAt, now);\n const assigned =\n issue.assignees.length > 0\n ? issue.assignees.map((a) => a.login).join(\", \")\n : undefined;\n\n const tags = issue.labels.map((l) => l.name);\n const author = issue.author?.login ?? \"ghost\";\n const comments = issue.comments.length;\n\n const base: SummaryItem = {\n number: issue.number,\n title: issue.title,\n tags,\n author,\n comments,\n age,\n };\n\n // Issues needing human attention are excluded from all actionable buckets\n if (hasExactLabel(issue.labels, \"needs:human\")) {\n return {\n bucket: \"needsHuman\",\n item: { ...base, assigned },\n };\n }\n\n // Bot governance labels (exact match)\n if (hasExactLabel(issue.labels, \"phase:voting\") || hasExactLabel(issue.labels, \"phase:extended-voting\")) {\n return { bucket: \"voteOn\", item: base };\n }\n if (hasExactLabel(issue.labels, \"phase:discussion\")) {\n return { bucket: \"discuss\", item: base };\n }\n if (hasExactLabel(issue.labels, \"phase:ready-to-implement\")) {\n return { bucket: \"implement\", item: { ...base, assigned } };\n }\n\n // Keyword fallback (repos without the bot)\n if (hasLabel(issue.labels, \"vote\")) {\n return { bucket: \"voteOn\", item: base };\n }\n if (hasLabel(issue.labels, \"discuss\")) {\n return { bucket: \"discuss\", item: base };\n }\n\n return {\n bucket: \"implement\",\n item: { ...base, assigned },\n };\n}\n\nfunction classifyPR(\n pr: GitHubPR,\n now: Date,\n): { bucket: \"reviewPRs\" | \"addressFeedback\"; item: SummaryItem } {\n const age = timeAgo(pr.createdAt, now);\n const tags = pr.labels.map((l) => l.name);\n const author = pr.author?.login ?? \"ghost\";\n const comments = pr.comments.length;\n const ciFailing = hasCIFailure(pr);\n const checks = compactChecks(checkStatus(pr));\n const merge = compactMergeable(mergeStatus(pr));\n const review = {\n approvals: approvalCount(pr),\n changesRequested: changesRequestedCount(pr),\n };\n\n if (pr.isDraft || ciFailing || pr.reviewDecision === \"CHANGES_REQUESTED\" || changesRequestedCount(pr) > 0) {\n let status: string;\n if (pr.isDraft) status = \"draft\";\n else if (pr.reviewDecision === \"CHANGES_REQUESTED\" || changesRequestedCount(pr) > 0) status = \"changes-requested\";\n else status = \"waiting\";\n\n return {\n bucket: \"addressFeedback\",\n item: { number: pr.number, title: pr.title, tags, author, comments, age, status, checks, mergeable: merge, review },\n };\n }\n\n const status = pr.reviewDecision === \"APPROVED\" ? \"approved\" : \"waiting\";\n\n return {\n bucket: \"reviewPRs\",\n item: { number: pr.number, title: pr.title, tags, author, comments, age, status, checks, mergeable: merge, review },\n };\n}\n\nfunction buildCompetitionMap(prs: GitHubPR[], currentUser: string): Map<number, number> {\n const map = new Map<number, number>();\n for (const pr of prs) {\n if (!hasLabel(pr.labels, \"implementation\")) continue;\n if (pr.author?.login === currentUser) continue;\n for (const ref of pr.closingIssuesReferences) {\n map.set(ref.number, (map.get(ref.number) ?? 0) + 1);\n }\n }\n return map;\n}\n\nexport function buildSummary(\n repo: RepoRef,\n issues: GitHubIssue[],\n prs: GitHubPR[],\n currentUser: string,\n now: Date = new Date(),\n): RepoSummary {\n const voteOn: SummaryItem[] = [];\n const discuss: SummaryItem[] = [];\n const implement: SummaryItem[] = [];\n const reviewPRs: SummaryItem[] = [];\n const addressFeedback: SummaryItem[] = [];\n\n for (const issue of issues) {\n const { bucket, item } = classifyIssue(issue, now);\n if (bucket === \"voteOn\") voteOn.push(item);\n else if (bucket === \"discuss\") discuss.push(item);\n else if (bucket === \"implement\") implement.push(item);\n // \"needsHuman\" issues intentionally excluded from all buckets\n }\n\n // Annotate implement items with competing PR counts\n const competitionMap = buildCompetitionMap(prs, currentUser);\n for (const item of implement) {\n const count = competitionMap.get(item.number) ?? 0;\n if (count > 0) {\n item.competingPRs = count;\n }\n }\n\n for (const pr of prs) {\n const { bucket, item } = classifyPR(pr, now);\n if (bucket === \"reviewPRs\") reviewPRs.push(item);\n else addressFeedback.push(item);\n }\n\n const alerts = generateAlerts(issues, prs, now);\n\n // Extract authored items into \"drive\" buckets so the agent knows what it owns\n const driveDiscussion: SummaryItem[] = [];\n const driveImplementation: SummaryItem[] = [];\n\n const filteredDiscuss = discuss.filter((item) => {\n if (item.author === currentUser) { driveDiscussion.push(item); return false; }\n return true;\n });\n\n const filteredVoteOn = voteOn.filter((item) => {\n if (item.author === currentUser && item.tags.includes(\"phase:extended-voting\")) {\n driveDiscussion.push(item);\n return false;\n }\n return true;\n });\n\n const filteredReviewPRs = reviewPRs.filter((item) => {\n if (item.author === currentUser) { driveImplementation.push(item); return false; }\n return true;\n });\n\n const filteredAddressFeedback = addressFeedback.filter((item) => {\n if (item.author === currentUser) { driveImplementation.push(item); return false; }\n return true;\n });\n\n return {\n repo,\n currentUser,\n driveDiscussion,\n driveImplementation,\n voteOn: filteredVoteOn,\n discuss: filteredDiscuss,\n implement,\n reviewPRs: filteredReviewPRs,\n addressFeedback: filteredAddressFeedback,\n alerts,\n notes: [],\n };\n}\n","import chalk from \"chalk\";\nimport type { RepoSummary, RoleConfig, SummaryItem, TeamConfig } from \"../config/types.js\";\n\nconst DIVIDER_WIDTH = 50;\n\n// Section types determine which metadata keys appear on the second line\ntype SectionType = \"vote\" | \"discuss\" | \"implement\" | \"reviewPRs\" | \"addressFeedback\" | \"driveDiscussion\" | \"driveImplementation\";\n\nfunction sectionDivider(title: string, count: number): string {\n const label = ` ${title} (${count}) `;\n const remaining = Math.max(0, DIVIDER_WIDTH - label.length - 2);\n return chalk.dim(\"──\") + chalk.bold(label) + chalk.dim(\"─\".repeat(remaining));\n}\n\nfunction formatTags(tags: string[]): string {\n if (tags.length === 0) return \"\";\n return \" \" + tags.map((t) => chalk.magenta(`[${t}]`)).join(\" \");\n}\n\nfunction kv(key: string, value: string | number): string {\n return `${key}: ${chalk.dim(String(value))}`;\n}\n\nfunction formatMeta(item: SummaryItem, sectionType: SectionType, currentUser: string): string {\n const isYou = item.author === currentUser;\n const authorVal = isYou ? chalk.green(`${item.author} (you)`) : chalk.dim(item.author);\n const parts: string[] = [`by: ${authorVal}`];\n\n if (sectionType === \"implement\") {\n parts.push(kv(\"assigned\", item.assigned ?? \"--\"));\n parts.push(kv(\"comments\", item.comments));\n parts.push(kv(\"created\", item.age));\n if (item.competingPRs !== undefined) {\n parts.push(kv(\"competing\", item.competingPRs));\n }\n } else if (sectionType === \"vote\" || sectionType === \"discuss\" || sectionType === \"driveDiscussion\") {\n parts.push(kv(\"comments\", item.comments));\n parts.push(kv(\"created\", item.age));\n } else {\n // PR sections: reviewPRs, addressFeedback, driveImplementation\n if (item.status !== undefined) parts.push(kv(\"status\", item.status));\n if (item.checks !== undefined && item.checks !== null) parts.push(kv(\"checks\", item.checks));\n if (item.mergeable !== undefined && item.mergeable !== null) parts.push(kv(\"merge\", item.mergeable));\n if (item.review) parts.push(kv(\"review\", `${item.review.approvals} approved, ${item.review.changesRequested} changes-requested`));\n parts.push(kv(\"comments\", item.comments));\n parts.push(kv(\"created\", item.age));\n }\n\n return parts.join(\" \");\n}\n\nfunction formatItem(item: SummaryItem, currentUser: string, sectionType: SectionType): string {\n const isYou = item.author === currentUser;\n const prefix = isYou ? chalk.green(\"★\") : \" \";\n const num = chalk.cyan(`#${item.number}`);\n const tags = formatTags(item.tags);\n\n const titleLine = `${prefix} ${num} ${item.title}${tags}`;\n const metaLine = ` ${formatMeta(item, sectionType, currentUser)}`;\n\n return `${titleLine}\\n${metaLine}`;\n}\n\nfunction formatSection(\n title: string,\n items: SummaryItem[],\n currentUser: string,\n sectionType: SectionType,\n limit?: number,\n): string {\n if (items.length === 0) return \"\";\n\n const displayed = limit ? items.slice(0, limit) : items;\n const header = sectionDivider(title, items.length);\n const itemBlocks = displayed.map((item) => formatItem(item, currentUser, sectionType));\n\n const parts = [header, ...itemBlocks];\n\n if (limit && items.length > limit) {\n parts.push(chalk.dim(` ... and ${items.length - limit} more`));\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction formatSummaryBody(summary: RepoSummary, limit?: number): string {\n const u = summary.currentUser;\n const sections: string[] = [];\n\n // Attention items at the top\n if (summary.alerts.length > 0) {\n const alertLines = [\n sectionDivider(\"REQUIRES YOUR ATTENTION\", summary.alerts.length),\n ...summary.alerts.map((a) => ` ${a.icon} ${chalk.yellow(a.message)}`),\n ];\n sections.push(alertLines.join(\"\\n\"));\n }\n\n sections.push(\n ...[\n formatSection(\"DRIVE THE DISCUSSION\", summary.driveDiscussion, u, \"driveDiscussion\", limit),\n formatSection(\"DRIVE THE IMPLEMENTATION\", summary.driveImplementation, u, \"driveImplementation\", limit),\n formatSection(\"VOTE ON ISSUES\", summary.voteOn, u, \"vote\", limit),\n formatSection(\"DISCUSS ISSUES\", summary.discuss, u, \"discuss\", limit),\n formatSection(\"READY TO IMPLEMENT ISSUES\", summary.implement, u, \"implement\", limit),\n formatSection(\"REVIEW PRs\", summary.reviewPRs, u, \"reviewPRs\", limit),\n formatSection(\"ADDRESS FEEDBACK PRs\", summary.addressFeedback, u, \"addressFeedback\", limit),\n ].filter(Boolean),\n );\n\n if (summary.notes.length > 0) {\n sections.push(summary.notes.map((n) => chalk.dim(` ${n}`)).join(\"\\n\"));\n }\n\n if (sections.length === 0) {\n return chalk.dim(\" No open issues or PRs.\");\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nexport function formatBuzz(\n roleName: string,\n role: RoleConfig,\n summary: RepoSummary,\n limit?: number,\n): string {\n const lines = [\n chalk.bold(`ROLE: ${roleName}`) + ` — ${role.description}`,\n \"\",\n chalk.bold(\"INSTRUCTIONS:\"),\n role.instructions.trimEnd(),\n \"\",\n `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`,\n \"\",\n formatSummaryBody(summary, limit),\n ];\n\n return lines.join(\"\\n\");\n}\n\nexport function formatStatus(summary: RepoSummary, limit?: number): string {\n const lines = [\n `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`,\n \"\",\n formatSummaryBody(summary, limit),\n ];\n\n return lines.join(\"\\n\");\n}\n\nexport function formatRoles(teamConfig: TeamConfig, repoFullName: string): string {\n const nameLabel = teamConfig.name ? ` (${teamConfig.name})` : \"\";\n const lines = [\n chalk.bold(`ROLES — ${repoFullName}${nameLabel}`),\n \"\",\n ];\n\n const slugs = Object.keys(teamConfig.roles);\n const maxLen = Math.max(...slugs.map((s) => s.length));\n\n for (const slug of slugs) {\n const role = teamConfig.roles[slug];\n const padded = slug.padEnd(maxLen + 2);\n lines.push(` ${chalk.cyan(padded)}${role.description}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { RepoSummary, RoleConfig, TeamConfig } from \"../config/types.js\";\n\nexport function jsonBuzz(\n roleName: string,\n role: RoleConfig,\n summary: RepoSummary,\n): string {\n return JSON.stringify(\n {\n role: {\n name: roleName,\n description: role.description,\n instructions: role.instructions,\n },\n summary: {\n repo: `${summary.repo.owner}/${summary.repo.repo}`,\n currentUser: summary.currentUser,\n driveDiscussion: summary.driveDiscussion,\n driveImplementation: summary.driveImplementation,\n voteOn: summary.voteOn,\n discuss: summary.discuss,\n implement: summary.implement,\n reviewPRs: summary.reviewPRs,\n addressFeedback: summary.addressFeedback,\n alerts: summary.alerts,\n notes: summary.notes,\n },\n },\n null,\n 2,\n );\n}\n\nexport function jsonStatus(summary: RepoSummary): string {\n return JSON.stringify(\n {\n repo: `${summary.repo.owner}/${summary.repo.repo}`,\n currentUser: summary.currentUser,\n driveDiscussion: summary.driveDiscussion,\n driveImplementation: summary.driveImplementation,\n voteOn: summary.voteOn,\n discuss: summary.discuss,\n implement: summary.implement,\n reviewPRs: summary.reviewPRs,\n addressFeedback: summary.addressFeedback,\n alerts: summary.alerts,\n notes: summary.notes,\n },\n null,\n 2,\n );\n}\n\nexport function jsonRoles(teamConfig: TeamConfig): string {\n const roles = Object.entries(teamConfig.roles).map(([slug, role]) => ({\n name: slug,\n description: role.description,\n }));\n\n return JSON.stringify({ roles }, null, 2);\n}\n","import { CliError, type BuzzOptions } from \"../config/types.js\";\nimport { loadTeamConfig } from \"../config/loader.js\";\nimport { resolveRepo } from \"../github/repo.js\";\nimport { fetchIssues } from \"../github/issues.js\";\nimport { fetchPulls } from \"../github/pulls.js\";\nimport { fetchCurrentUser } from \"../github/user.js\";\nimport { buildSummary } from \"../summary/builder.js\";\nimport { formatBuzz, formatStatus } from \"../output/formatter.js\";\nimport { jsonBuzz, jsonStatus } from \"../output/json.js\";\n\nexport async function buzzCommand(options: BuzzOptions): Promise<void> {\n const repo = await resolveRepo(options.repo);\n const fetchLimit = options.fetchLimit ?? 200;\n\n const [issues, prs, currentUser] = await Promise.all([\n fetchIssues(repo, fetchLimit),\n fetchPulls(repo, fetchLimit),\n fetchCurrentUser(),\n ]);\n\n const summary = buildSummary(repo, issues, prs, currentUser);\n\n if (issues.length >= fetchLimit) {\n summary.notes.push(`Only the first ${fetchLimit} issues were fetched. Use --fetch-limit to increase.`);\n }\n if (prs.length >= fetchLimit) {\n summary.notes.push(`Only the first ${fetchLimit} PRs were fetched. Use --fetch-limit to increase.`);\n }\n\n if (options.role) {\n const teamConfig = await loadTeamConfig(repo);\n if (!Object.hasOwn(teamConfig.roles, options.role)) {\n const available = Object.keys(teamConfig.roles).join(\", \");\n throw new CliError(\n `Role '${options.role}' not found. Available: ${available}. Run: hivemoot roles`,\n \"ROLE_NOT_FOUND\",\n 1,\n );\n }\n const roleConfig = teamConfig.roles[options.role];\n\n if (options.json) {\n console.log(jsonBuzz(options.role, roleConfig, summary));\n } else {\n console.log(formatBuzz(options.role, roleConfig, summary, options.limit));\n }\n } else {\n if (options.json) {\n console.log(jsonStatus(summary));\n } else {\n console.log(formatStatus(summary, options.limit));\n }\n }\n}\n","import type { RolesOptions } from \"../config/types.js\";\nimport { loadTeamConfig } from \"../config/loader.js\";\nimport { resolveRepo } from \"../github/repo.js\";\nimport { formatRoles } from \"../output/formatter.js\";\nimport { jsonRoles } from \"../output/json.js\";\n\nexport async function rolesCommand(options: RolesOptions): Promise<void> {\n const repo = await resolveRepo(options.repo);\n const teamConfig = await loadTeamConfig(repo);\n\n if (options.json) {\n console.log(jsonRoles(teamConfig));\n } else {\n console.log(formatRoles(teamConfig, `${repo.owner}/${repo.repo}`));\n }\n}\n","export async function initCommand(): Promise<void> {\n const template = `# Hivemoot team configuration\n# Place this file at .github/hivemoot.yml in your repository.\n#\n# Roles define personas (who the agent is), not workflow.\n# Workflow details belong in .agent/skills/.\n\nteam:\n roles:\n pm:\n description: \"Product manager focused on user value and clarity\"\n instructions: |\n You think from the user's perspective.\n Evaluate ideas by the problem they solve and who benefits.\n Push for clear requirements and well-scoped proposals.\n Ask \"why does this matter?\" before \"how do we build it?\"\n\n engineer:\n description: \"Software engineer focused on clean implementation\"\n instructions: |\n You care about code quality, patterns, and maintainability.\n Favor simple, proven approaches over clever solutions.\n Write clean code with good test coverage.\n Build on existing conventions in the codebase.\n\n architect:\n description: \"Architect focused on system design and long-term health\"\n instructions: |\n You think about how pieces fit together.\n Evaluate proposals for scalability, consistency, and technical debt.\n Guard the system's boundaries and abstractions.\n Push back when short-term wins create long-term problems.\n\n qa:\n description: \"QA engineer focused on reliability and edge cases\"\n instructions: |\n You think about what can go wrong.\n Find edge cases, race conditions, and failure modes others miss.\n Push for thorough error handling and defensive design.\n Ask \"what happens when this fails?\" about everything.\n`;\n\n console.log(template);\n}\n"],"mappings":"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","names":["status","require"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config/types.ts","../src/config/loader.ts","../src/github/client.ts","../src/github/repo.ts","../src/github/issues.ts","../src/github/pulls.ts","../src/github/user.ts","../src/summary/utils.ts","../src/summary/builder.ts","../src/output/formatter.ts","../src/output/json.ts","../src/commands/buzz.ts","../src/commands/roles.ts","../src/commands/init.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command, InvalidArgumentError } from \"commander\";\nimport { buzzCommand } from \"./commands/buzz.js\";\nimport { rolesCommand } from \"./commands/roles.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { CliError } from \"./config/types.js\";\nimport { setGhToken } from \"./github/client.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nfunction parseLimit(value: string): number {\n const n = parseInt(value, 10);\n if (isNaN(n) || n <= 0) {\n throw new InvalidArgumentError(\"Must be a positive integer.\");\n }\n return n;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"hivemoot\")\n .description(\"CLI for Hivemoot agents — role instructions and repo work summaries\")\n .version(version)\n .option(\"--github-token <token>\", \"GitHub personal access token (or set GITHUB_TOKEN env var)\");\n\nprogram.hook(\"preAction\", () => {\n const token = (program.opts().githubToken ?? process.env.GITHUB_TOKEN) as string | undefined;\n if (token) {\n setGhToken(token);\n }\n});\n\nprogram\n .command(\"buzz\")\n .description(\"Get role instructions and repo work summary (omit --role for summary only)\")\n .option(\"--role <role>\", \"Role to assume (e.g. engineer, tech_lead)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--limit <n>\", \"Max items per section\", parseLimit)\n .option(\"--fetch-limit <n>\", \"Max issues/PRs to fetch from GitHub (default: 200)\", parseLimit)\n .option(\"--repo <owner/repo>\", \"Target repository (default: detect from git)\")\n .action(buzzCommand);\n\nprogram\n .command(\"roles\")\n .description(\"List available roles from team config\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--repo <owner/repo>\", \"Target repository (default: detect from git)\")\n .action(rolesCommand);\n\nprogram\n .command(\"init\")\n .description(\"Print a sample .github/hivemoot.yml template\")\n .action(initCommand);\n\n// Global error handler\nprogram.exitOverride();\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n if (err instanceof CliError) {\n // Check if parent command requested --json output\n const isJson = process.argv.includes(\"--json\");\n if (isJson) {\n console.log(JSON.stringify({ error: { code: err.code, message: err.message } }, null, 2));\n } else {\n console.error(`Error: ${err.message}`);\n }\n process.exit(err.exitCode);\n }\n\n // Commander exits for --help, --version, etc.\n if (err instanceof Error && \"exitCode\" in err) {\n const exitCode = (err as Error & { exitCode: number }).exitCode;\n process.exit(exitCode);\n }\n\n console.error(\"Unexpected error:\", err);\n process.exit(1);\n}\n","// ── YAML Config Types ──────────────────────────────────────────────\n\nexport interface RoleConfig {\n description: string;\n instructions: string;\n}\n\nexport interface TeamConfig {\n name?: string;\n roles: Record<string, RoleConfig>;\n}\n\nexport interface HivemootConfig {\n version?: number;\n governance?: unknown;\n team?: TeamConfig;\n}\n\n// ── GitHub Data Types ──────────────────────────────────────────────\n\nexport interface GitHubIssue {\n number: number;\n title: string;\n labels: Array<{ name: string }>;\n assignees: Array<{ login: string }>;\n author: { login: string } | null;\n comments: Array<{ createdAt: string }>;\n createdAt: string;\n updatedAt: string;\n url: string;\n}\n\nexport interface StatusCheck {\n context: string;\n state: string | undefined;\n conclusion: string | null;\n}\n\nexport interface PRReview {\n state: string;\n author: { login: string } | null;\n submittedAt?: string;\n}\n\nexport interface PRCommit {\n committedDate: string;\n}\n\nexport interface GitHubPR {\n number: number;\n title: string;\n state: string;\n author: { login: string } | null;\n labels: Array<{ name: string }>;\n comments: Array<{ createdAt: string }>;\n reviews: PRReview[];\n createdAt: string;\n updatedAt: string;\n url: string;\n isDraft: boolean;\n reviewDecision: string;\n mergeable: string;\n statusCheckRollup: StatusCheck[] | null;\n closingIssuesReferences: Array<{ number: number }>;\n commits: PRCommit[];\n}\n\n// ── Repo Identity ──────────────────────────────────────────────────\n\nexport interface RepoRef {\n owner: string;\n repo: string;\n}\n\n// ── Summary Types ──────────────────────────────────────────────────\n\nexport interface ReviewSummary {\n approvals: number;\n changesRequested: number;\n}\n\nexport interface SummaryItem {\n number: number;\n title: string;\n tags: string[];\n author: string;\n // Common fields\n comments: number;\n age: string; // \"just now\" | \"5 minutes ago\" | \"2 hours ago\" | \"3 days ago\"\n // Issue-specific\n assigned?: string; // comma-separated logins, or undefined (= unassigned)\n competingPRs?: number; // only on implement items with competing PRs\n // PR-specific\n status?: string; // \"pending\" | \"approved\" | \"changes-requested\" | \"draft\"\n checks?: string | null; // \"passing\" | \"failing\" | \"pending\" | null\n mergeable?: string | null; // \"clean\" | \"conflicts\" | null\n review?: ReviewSummary;\n yourReview?: string;\n yourReviewAge?: string; // \"3 days ago\" — when you last reviewed\n lastCommit?: string; // \"2 hours ago\" — when the latest commit landed\n lastComment?: string; // \"5 hours ago\" — when the latest comment was posted\n updated?: string; // \"30 minutes ago\" — pr.updatedAt (catch-all)\n}\n\nexport interface RepoSummary {\n repo: RepoRef;\n currentUser: string;\n needsHuman: SummaryItem[];\n driveDiscussion: SummaryItem[];\n driveImplementation: SummaryItem[];\n voteOn: SummaryItem[];\n discuss: SummaryItem[];\n implement: SummaryItem[];\n reviewPRs: SummaryItem[];\n addressFeedback: SummaryItem[];\n notes: string[];\n}\n\n// ── CLI Options ────────────────────────────────────────────────────\n\nexport interface BuzzOptions {\n role?: string;\n json?: boolean;\n limit?: number;\n fetchLimit?: number;\n repo?: string;\n}\n\nexport interface RolesOptions {\n json?: boolean;\n repo?: string;\n}\n\n// ── Error Types ────────────────────────────────────────────────────\n\nexport type ErrorCode =\n | \"GH_NOT_FOUND\"\n | \"GH_NOT_AUTHENTICATED\"\n | \"NOT_GIT_REPO\"\n | \"CONFIG_NOT_FOUND\"\n | \"NO_TEAM_CONFIG\"\n | \"ROLE_NOT_FOUND\"\n | \"INVALID_CONFIG\"\n | \"RATE_LIMITED\"\n | \"GH_ERROR\";\n\nexport class CliError extends Error {\n constructor(\n message: string,\n public readonly code: ErrorCode,\n public readonly exitCode: number = 1,\n ) {\n super(message);\n this.name = \"CliError\";\n }\n}\n","import yaml from \"js-yaml\";\nimport { gh } from \"../github/client.js\";\nimport type { HivemootConfig, TeamConfig, RepoRef, RoleConfig } from \"./types.js\";\nimport { CliError } from \"./types.js\";\n\nconst ROLE_SLUG_RE = /^[a-z][a-z0-9_]{0,49}$/;\nconst MAX_DESCRIPTION_LENGTH = 500;\nconst MAX_INSTRUCTIONS_LENGTH = 10_000;\n\nfunction validateTeamConfig(raw: HivemootConfig): TeamConfig {\n if (!raw.team) {\n throw new CliError(\n \"No team config in .github/hivemoot.yml. Run: hivemoot init\",\n \"NO_TEAM_CONFIG\",\n 1,\n );\n }\n\n const { team } = raw;\n\n if (!team.roles || typeof team.roles !== \"object\" || Object.keys(team.roles).length === 0) {\n throw new CliError(\n \"Config error: team.roles must contain at least one role\",\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n const validatedRoles: Record<string, RoleConfig> = {};\n\n for (const [slug, role] of Object.entries(team.roles)) {\n if (!ROLE_SLUG_RE.test(slug)) {\n throw new CliError(\n `Config error: invalid role slug \"${slug}\" — must match /^[a-z][a-z0-9_]{0,49}$/`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof role !== \"object\" || role === null) {\n throw new CliError(\n `Config error: role \"${slug}\" must be an object`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n const r = role as unknown as Record<string, unknown>;\n\n if (typeof r.description !== \"string\" || r.description.length === 0) {\n throw new CliError(\n `Config error: role \"${slug}\" is missing a description`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (r.description.length > MAX_DESCRIPTION_LENGTH) {\n throw new CliError(\n `Config error: role \"${slug}\" description exceeds ${MAX_DESCRIPTION_LENGTH} characters`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof r.instructions !== \"string\" || r.instructions.length === 0) {\n throw new CliError(\n `Config error: role \"${slug}\" is missing instructions`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (r.instructions.length > MAX_INSTRUCTIONS_LENGTH) {\n throw new CliError(\n `Config error: role \"${slug}\" instructions exceeds ${MAX_INSTRUCTIONS_LENGTH} characters`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n validatedRoles[slug] = {\n description: r.description,\n instructions: r.instructions,\n };\n }\n\n return {\n name: typeof team.name === \"string\" ? team.name : undefined,\n roles: validatedRoles,\n };\n}\n\nexport async function loadTeamConfig(repo: RepoRef): Promise<TeamConfig> {\n let rawJson: string;\n\n try {\n rawJson = await gh([\n \"api\",\n `repos/${repo.owner}/${repo.repo}/contents/.github/hivemoot.yml`,\n ]);\n } catch (err) {\n if (err instanceof Error && /404|Not Found/i.test(err.message)) {\n throw new CliError(\n \"No .github/hivemoot.yml found. Run: hivemoot init\",\n \"CONFIG_NOT_FOUND\",\n 1,\n );\n }\n throw err;\n }\n\n let content: string;\n try {\n const parsed = JSON.parse(rawJson);\n content = Buffer.from(parsed.content, \"base64\").toString(\"utf-8\");\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : \"\";\n throw new CliError(\n `Config error: failed to decode .github/hivemoot.yml content${detail}`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n let config: HivemootConfig;\n try {\n config = yaml.load(content, { schema: yaml.JSON_SCHEMA }) as HivemootConfig;\n } catch (err) {\n const detail = err instanceof Error ? `: ${err.message}` : \"\";\n throw new CliError(\n `Config error: invalid YAML in .github/hivemoot.yml${detail}`,\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n if (typeof config !== \"object\" || config === null) {\n throw new CliError(\n \"Config error: .github/hivemoot.yml must be a YAML object\",\n \"INVALID_CONFIG\",\n 1,\n );\n }\n\n return validateTeamConfig(config);\n}\n","import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { CliError } from \"../config/types.js\";\n\nconst execFileAsync = promisify(execFile);\n\nlet ghToken: string | undefined;\n\n/** Set the GitHub token used for all subsequent `gh` calls. */\nexport function setGhToken(token: string): void {\n ghToken = token;\n}\n\n/**\n * Execute a `gh` CLI command and return stdout.\n * All GitHub I/O goes through this single function.\n */\nexport async function gh(args: string[]): Promise<string> {\n try {\n const opts: { timeout: number; env?: NodeJS.ProcessEnv } = {\n timeout: 30_000,\n };\n if (ghToken) {\n opts.env = { ...process.env, GH_TOKEN: ghToken };\n }\n const { stdout } = await execFileAsync(\"gh\", args, opts);\n return stdout.trim();\n } catch (err: unknown) {\n const error = err as NodeJS.ErrnoException & {\n stderr?: string;\n code?: string | number;\n };\n\n if (error.code === \"ENOENT\") {\n throw new CliError(\n \"gh CLI not found. Install: https://cli.github.com\",\n \"GH_NOT_FOUND\",\n 2,\n );\n }\n\n const stderr = error.stderr ?? error.message ?? \"\";\n\n if (/gh auth login|not logged in|authentication required/i.test(stderr)) {\n throw new CliError(\n \"Not authenticated. Pass --github-token <token>, set GITHUB_TOKEN, or run: gh auth login\",\n \"GH_NOT_AUTHENTICATED\",\n 2,\n );\n }\n\n if (/rate.?limit|API rate limit/i.test(stderr)) {\n throw new CliError(\n \"GitHub rate limited. Try again later.\",\n \"RATE_LIMITED\",\n 3,\n );\n }\n\n throw new CliError(stderr || \"gh command failed\", \"GH_ERROR\", 1);\n }\n}\n","import { CliError, type RepoRef } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nconst GITHUB_NAME_RE = /^[a-zA-Z0-9._-]+$/;\n\nexport async function resolveRepo(repoFlag?: string): Promise<RepoRef> {\n if (repoFlag) {\n const parts = repoFlag.split(\"/\");\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new CliError(\n `Invalid repo format: \"${repoFlag}\". Expected OWNER/REPO`,\n \"GH_ERROR\",\n 1,\n );\n }\n if (!GITHUB_NAME_RE.test(parts[0]) || !GITHUB_NAME_RE.test(parts[1])) {\n throw new CliError(\n `Invalid repo name: \"${repoFlag}\". Owner and repo must match ${GITHUB_NAME_RE}`,\n \"GH_ERROR\",\n 1,\n );\n }\n return { owner: parts[0], repo: parts[1] };\n }\n\n try {\n const json = await gh([\"repo\", \"view\", \"--json\", \"owner,name\"]);\n let data: { owner?: { login?: string } | string; name?: string };\n try {\n data = JSON.parse(json);\n } catch {\n throw new CliError(\n \"Failed to parse repo info from gh CLI. Use --repo OWNER/REPO\",\n \"GH_ERROR\",\n 1,\n );\n }\n // gh returns owner as an object { login: \"...\" } not a plain string\n const owner =\n typeof data.owner === \"object\" && data.owner !== null\n ? data.owner.login\n : data.owner;\n const name = data.name;\n if (typeof owner !== \"string\" || !owner || typeof name !== \"string\" || !name) {\n throw new CliError(\n \"Could not detect repo owner/name. Use --repo OWNER/REPO\",\n \"NOT_GIT_REPO\",\n 2,\n );\n }\n return { owner, repo: name };\n } catch (err) {\n if (err instanceof CliError) {\n throw err;\n }\n throw new CliError(\n \"Not in a git repository. Use --repo OWNER/REPO\",\n \"NOT_GIT_REPO\",\n 2,\n );\n }\n}\n","import type { GitHubIssue, RepoRef } from \"../config/types.js\";\nimport { CliError } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nexport async function fetchIssues(repo: RepoRef, limit = 200): Promise<GitHubIssue[]> {\n const json = await gh([\n \"issue\",\n \"list\",\n \"-R\",\n `${repo.owner}/${repo.repo}`,\n \"--state\",\n \"open\",\n \"--json\",\n \"number,title,labels,assignees,author,comments,createdAt,updatedAt,url\",\n \"--limit\",\n String(limit),\n ]);\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new CliError(\n \"Failed to parse issues response from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n if (!Array.isArray(parsed)) {\n throw new CliError(\n \"Unexpected issues response format from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n return parsed as GitHubIssue[];\n}\n","import type { GitHubPR, RepoRef } from \"../config/types.js\";\nimport { CliError } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\n/**\n * Fetch the latest commit date for each open PR via GraphQL.\n *\n * `gh pr list --json commits` requests the full commits connection, whose\n * `authors` sub-connection blows through GitHub's 500k node budget on repos\n * with many PRs. Using `commits(last: 1)` avoids this entirely — we only\n * need the most recent commit date per PR.\n *\n * GitHub caps `first` at 100, so we paginate with cursors when limit > 100.\n */\nasync function fetchLatestCommitDates(\n repo: RepoRef,\n limit: number,\n): Promise<Map<number, string>> {\n const query = `\n query($owner: String!, $name: String!, $pageSize: Int!, $cursor: String) {\n repository(owner: $owner, name: $name) {\n pullRequests(first: $pageSize, after: $cursor, states: OPEN, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo { hasNextPage endCursor }\n nodes {\n number\n commits(last: 1) { nodes { commit { committedDate } } }\n }\n }\n }\n }`;\n\n const PAGE_SIZE = 100;\n const map = new Map<number, string>();\n let remaining = limit;\n let cursor: string | null = null;\n\n while (remaining > 0) {\n const pageSize = Math.min(remaining, PAGE_SIZE);\n const args = [\n \"api\", \"graphql\",\n \"-F\", `owner=${repo.owner}`,\n \"-F\", `name=${repo.repo}`,\n \"-F\", `pageSize=${pageSize}`,\n \"-f\", `query=${query}`,\n ];\n if (cursor) {\n args.push(\"-F\", `cursor=${cursor}`);\n } else {\n // gh sends null when the variable is absent, which GraphQL accepts for String?\n args.push(\"-f\", \"cursor=\");\n }\n\n const json = await gh(args);\n const data = JSON.parse(json);\n const prs = data?.data?.repository?.pullRequests;\n const nodes: Array<{ number: number; commits: { nodes: Array<{ commit: { committedDate: string } }> } }>\n = prs?.nodes ?? [];\n\n for (const pr of nodes) {\n const commit = pr.commits.nodes[0];\n if (commit) map.set(pr.number, commit.commit.committedDate);\n }\n\n remaining -= nodes.length;\n const hasNext = prs?.pageInfo?.hasNextPage === true;\n if (!hasNext || nodes.length === 0) break;\n cursor = prs.pageInfo.endCursor;\n }\n\n return map;\n}\n\nexport async function fetchPulls(repo: RepoRef, limit = 200): Promise<GitHubPR[]> {\n // Fetch PR data and latest commit dates in parallel.\n // The main query omits `commits` to stay within GitHub's GraphQL node budget.\n const [listJson, commitDates] = await Promise.all([\n gh([\n \"pr\", \"list\",\n \"-R\", `${repo.owner}/${repo.repo}`,\n \"--state\", \"open\",\n \"--json\", \"number,title,state,author,labels,comments,reviews,createdAt,updatedAt,url,isDraft,reviewDecision,mergeable,statusCheckRollup,closingIssuesReferences\",\n \"--limit\", String(limit),\n ]),\n fetchLatestCommitDates(repo, limit),\n ]);\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(listJson);\n } catch {\n throw new CliError(\n \"Failed to parse pull requests response from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n if (!Array.isArray(parsed)) {\n throw new CliError(\n \"Unexpected pull requests response format from gh CLI\",\n \"GH_ERROR\",\n 1,\n );\n }\n\n // Stitch the latest commit date back into each PR as a single-element array\n // so downstream code (`latestCommitAge`) works unchanged.\n const prs = parsed as GitHubPR[];\n for (const pr of prs) {\n const date = commitDates.get(pr.number);\n pr.commits = date ? [{ committedDate: date }] : [];\n }\n\n return prs;\n}\n","import { gh } from \"./client.js\";\nimport { CliError } from \"../config/types.js\";\n\n/**\n * Return the login of the currently authenticated GitHub user.\n */\nexport async function fetchCurrentUser(): Promise<string> {\n const login = await gh([\"api\", \"user\", \"--jq\", \".login\"]);\n if (!login) {\n throw new CliError(\n \"Could not determine GitHub username. Pass --github-token <token>, set GITHUB_TOKEN, or run: gh auth login\",\n \"GH_NOT_AUTHENTICATED\",\n 2,\n );\n }\n return login;\n}\n","import type { GitHubPR } from \"../config/types.js\";\n\nexport function hasLabel(labels: Array<{ name: string }>, keyword: string): boolean {\n return labels.some((l) =>\n l.name.toLowerCase().split(/[:\\-_]/).some((seg) => seg === keyword),\n );\n}\n\nexport function hasExactLabel(labels: Array<{ name: string }>, labelName: string): boolean {\n return labels.some((l) => l.name.toLowerCase() === labelName.toLowerCase());\n}\n\n/** Human-relative time string (\"just now\", \"5 minutes ago\", \"yesterday\", etc.). */\nexport function timeAgo(dateStr: string, now: Date): string {\n const ms = now.getTime() - new Date(dateStr).getTime();\n if (ms < 0) return \"just now\"; // future date — clock skew or bad data\n\n const minutes = Math.floor(ms / 60_000);\n const hours = Math.floor(ms / 3_600_000);\n const days = Math.floor(ms / 86_400_000);\n\n if (minutes < 1) return \"just now\";\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) {\n const remainingMinutes = minutes % 60;\n if (remainingMinutes === 0) return `${hours}h ago`;\n return `${hours}h${remainingMinutes}m ago`;\n }\n if (days === 1) return \"yesterday\";\n if (days < 7) return `${days} days ago`;\n if (days < 14) return \"1 week ago\";\n if (days < 30) return `${Math.floor(days / 7)} weeks ago`;\n if (days < 60) return \"1 month ago\";\n if (days < 365) return `${Math.floor(days / 30)} months ago`;\n const years = Math.floor(days / 365);\n if (years === 1) return \"1 year ago\";\n return `${years} years ago`;\n}\n\nexport function daysSince(dateStr: string, now: Date): number {\n const diff = now.getTime() - new Date(dateStr).getTime();\n return Math.max(0, Math.floor(diff / (1000 * 60 * 60 * 24)));\n}\n\nexport function hasCIFailure(pr: GitHubPR): boolean {\n if (!pr.statusCheckRollup) return false;\n return pr.statusCheckRollup.some((check) => {\n const conclusion = check.conclusion?.toUpperCase();\n const state = check.state?.toUpperCase();\n return conclusion === \"FAILURE\" || state === \"FAILURE\";\n });\n}\n\n/**\n * Summarize all status checks into a single label.\n * Returns null when there are no checks to report.\n */\nexport function checkStatus(pr: GitHubPR): string | null {\n if (!pr.statusCheckRollup || pr.statusCheckRollup.length === 0) return null;\n\n const hasFailing = hasCIFailure(pr);\n if (hasFailing) return \"checks failing\";\n\n const hasPending = pr.statusCheckRollup.some((c) => {\n const s = c.state?.toUpperCase();\n return s === \"PENDING\" || s === \"QUEUED\" || s === \"IN_PROGRESS\";\n });\n if (hasPending) return \"checks pending\";\n\n return \"checks passing\";\n}\n\n/**\n * Return a merge-conflict label, or null if no conflict info.\n */\nexport function mergeStatus(pr: GitHubPR): string | null {\n if (pr.mergeable === \"CONFLICTING\") return \"has conflicts\";\n if (pr.mergeable === \"MERGEABLE\") return \"no conflicts\";\n return null;\n}\n\n/** Collapse reviews to the latest state per author. */\nfunction latestReviewByAuthor(pr: GitHubPR): Map<string, string> {\n const map = new Map<string, string>();\n for (const review of pr.reviews ?? []) {\n map.set(review.author?.login ?? \"ghost\", review.state);\n }\n return map;\n}\n\n/** Count unique approvals (latest review per author). */\nexport function approvalCount(pr: GitHubPR): number {\n let count = 0;\n for (const state of latestReviewByAuthor(pr).values()) {\n if (state === \"APPROVED\") count++;\n }\n return count;\n}\n\n/**\n * Count unique changes-requested reviews (latest review per author).\n * If an author requests changes then later approves, they are no longer counted.\n */\nexport function changesRequestedCount(pr: GitHubPR): number {\n let count = 0;\n for (const state of latestReviewByAuthor(pr).values()) {\n if (state === \"CHANGES_REQUESTED\") count++;\n }\n return count;\n}\n\n// ── Review context ────────────────────────────────────────────────\n\nexport interface ReviewContext {\n yourReview: string;\n yourReviewAge: string;\n}\n\n/**\n * Compute the current user's review relationship to a PR.\n * Returns null if the user has not reviewed this PR.\n */\nexport function reviewContext(pr: GitHubPR, currentUser: string, now: Date): ReviewContext | null {\n // Find currentUser's latest review (gh returns chronologically, last wins)\n let latestState: string | undefined;\n let latestTime: string | undefined;\n for (const review of pr.reviews ?? []) {\n if (review.author?.login === currentUser) {\n latestState = review.state;\n latestTime = review.submittedAt;\n }\n }\n\n if (!latestState) return null;\n\n const stateMap: Record<string, string> = {\n CHANGES_REQUESTED: \"changes-requested\",\n APPROVED: \"approved\",\n COMMENTED: \"commented\",\n DISMISSED: \"dismissed\",\n };\n const yourReview = stateMap[latestState] ?? latestState.toLowerCase();\n const yourReviewAge = latestTime ? timeAgo(latestTime, now) : \"unknown\";\n\n return { yourReview, yourReviewAge };\n}\n\n// ── Temporal helpers ──────────────────────────────────────────────\n\n/** Relative time of the most recent commit, or undefined if no commits. */\nexport function latestCommitAge(pr: GitHubPR, now: Date): string | undefined {\n const commits = pr.commits ?? [];\n if (commits.length === 0) return undefined;\n let latest = commits[0].committedDate;\n for (let i = 1; i < commits.length; i++) {\n if (commits[i].committedDate > latest) latest = commits[i].committedDate;\n }\n return timeAgo(latest, now);\n}\n\n/** Relative time of the most recent comment, or undefined if no comments. */\nexport function latestCommentAge(item: { comments: Array<{ createdAt: string }> }, now: Date): string | undefined {\n if (item.comments.length === 0) return undefined;\n let latest = item.comments[0].createdAt;\n for (let i = 1; i < item.comments.length; i++) {\n if (item.comments[i].createdAt > latest) latest = item.comments[i].createdAt;\n }\n return timeAgo(latest, now);\n}\n","import type {\n GitHubIssue,\n GitHubPR,\n RepoRef,\n RepoSummary,\n SummaryItem,\n} from \"../config/types.js\";\nimport { hasLabel, hasExactLabel, hasCIFailure, checkStatus, mergeStatus, approvalCount, changesRequestedCount, timeAgo, reviewContext, latestCommitAge, latestCommentAge } from \"./utils.js\";\n\n/** Map verbose check labels to compact values for structured output. */\nfunction compactChecks(raw: string | null): string | null {\n if (raw === null) return null;\n if (raw === \"checks failing\") return \"failing\";\n if (raw === \"checks pending\") return \"pending\";\n if (raw === \"checks passing\") return \"passing\";\n return raw;\n}\n\n/** Map verbose merge labels to compact values for structured output. */\nfunction compactMergeable(raw: string | null): string | null {\n if (raw === null) return null;\n if (raw === \"has conflicts\") return \"conflicts\";\n if (raw === \"no conflicts\") return \"clean\";\n return raw;\n}\n\nfunction classifyIssue(\n issue: GitHubIssue,\n now: Date,\n): { bucket: \"voteOn\" | \"discuss\" | \"implement\" | \"needsHuman\"; item: SummaryItem } {\n const age = timeAgo(issue.createdAt, now);\n const assigned =\n issue.assignees.length > 0\n ? issue.assignees.map((a) => a.login).join(\", \")\n : undefined;\n\n const tags = issue.labels.map((l) => l.name);\n const author = issue.author?.login ?? \"ghost\";\n const comments = issue.comments.length;\n\n const base: SummaryItem = {\n number: issue.number,\n title: issue.title,\n tags,\n author,\n comments,\n age,\n lastComment: latestCommentAge(issue, now),\n updated: timeAgo(issue.updatedAt, now),\n };\n\n // Issues needing human attention are excluded from all actionable buckets\n if (hasExactLabel(issue.labels, \"needs:human\")) {\n return {\n bucket: \"needsHuman\",\n item: { ...base, assigned },\n };\n }\n\n // Bot governance labels (exact match)\n if (hasExactLabel(issue.labels, \"phase:voting\") || hasExactLabel(issue.labels, \"phase:extended-voting\")) {\n return { bucket: \"voteOn\", item: base };\n }\n if (hasExactLabel(issue.labels, \"phase:discussion\")) {\n return { bucket: \"discuss\", item: base };\n }\n if (hasExactLabel(issue.labels, \"phase:ready-to-implement\")) {\n return { bucket: \"implement\", item: { ...base, assigned } };\n }\n\n // Keyword fallback (repos without the bot)\n if (hasLabel(issue.labels, \"vote\")) {\n return { bucket: \"voteOn\", item: base };\n }\n if (hasLabel(issue.labels, \"discuss\")) {\n return { bucket: \"discuss\", item: base };\n }\n\n return {\n bucket: \"implement\",\n item: { ...base, assigned },\n };\n}\n\nfunction classifyPR(\n pr: GitHubPR,\n now: Date,\n): { bucket: \"reviewPRs\" | \"addressFeedback\"; item: SummaryItem } {\n const age = timeAgo(pr.createdAt, now);\n const tags = pr.labels.map((l) => l.name);\n const author = pr.author?.login ?? \"ghost\";\n const comments = pr.comments.length;\n const ciFailing = hasCIFailure(pr);\n const checks = compactChecks(checkStatus(pr));\n const merge = compactMergeable(mergeStatus(pr));\n const review = {\n approvals: approvalCount(pr),\n changesRequested: changesRequestedCount(pr),\n };\n\n if (pr.isDraft || ciFailing || pr.reviewDecision === \"CHANGES_REQUESTED\" || changesRequestedCount(pr) > 0) {\n let status: string;\n if (pr.isDraft) status = \"draft\";\n else if (pr.reviewDecision === \"CHANGES_REQUESTED\" || changesRequestedCount(pr) > 0) status = \"changes-requested\";\n else status = \"pending\";\n\n return {\n bucket: \"addressFeedback\",\n item: { number: pr.number, title: pr.title, tags, author, comments, age, status, checks, mergeable: merge, review },\n };\n }\n\n const status = pr.reviewDecision === \"APPROVED\" ? \"approved\" : \"pending\";\n\n return {\n bucket: \"reviewPRs\",\n item: { number: pr.number, title: pr.title, tags, author, comments, age, status, checks, mergeable: merge, review },\n };\n}\n\nfunction buildCompetitionMap(prs: GitHubPR[], currentUser: string): Map<number, number> {\n const map = new Map<number, number>();\n for (const pr of prs) {\n if (!hasLabel(pr.labels, \"implementation\")) continue;\n if (pr.author?.login === currentUser) continue;\n for (const ref of pr.closingIssuesReferences) {\n map.set(ref.number, (map.get(ref.number) ?? 0) + 1);\n }\n }\n return map;\n}\n\nexport function buildSummary(\n repo: RepoRef,\n issues: GitHubIssue[],\n prs: GitHubPR[],\n currentUser: string,\n now: Date = new Date(),\n): RepoSummary {\n const needsHuman: SummaryItem[] = [];\n const voteOn: SummaryItem[] = [];\n const discuss: SummaryItem[] = [];\n const implement: SummaryItem[] = [];\n const reviewPRs: SummaryItem[] = [];\n const addressFeedback: SummaryItem[] = [];\n\n for (const issue of issues) {\n const { bucket, item } = classifyIssue(issue, now);\n if (bucket === \"needsHuman\") needsHuman.push(item);\n else if (bucket === \"voteOn\") voteOn.push(item);\n else if (bucket === \"discuss\") discuss.push(item);\n else if (bucket === \"implement\") implement.push(item);\n }\n\n // Annotate implement items with competing PR counts\n const competitionMap = buildCompetitionMap(prs, currentUser);\n for (const item of implement) {\n const count = competitionMap.get(item.number) ?? 0;\n if (count > 0) {\n item.competingPRs = count;\n }\n }\n\n for (const pr of prs) {\n const { bucket, item } = classifyPR(pr, now);\n const ctx = reviewContext(pr, currentUser, now);\n if (ctx) {\n item.yourReview = ctx.yourReview;\n item.yourReviewAge = ctx.yourReviewAge;\n }\n item.lastCommit = latestCommitAge(pr, now);\n item.lastComment = latestCommentAge(pr, now);\n item.updated = timeAgo(pr.updatedAt, now);\n if (bucket === \"reviewPRs\") reviewPRs.push(item);\n else addressFeedback.push(item);\n }\n\n // Extract authored items into \"drive\" buckets so the agent knows what it owns\n const driveDiscussion: SummaryItem[] = [];\n const driveImplementation: SummaryItem[] = [];\n\n const filteredDiscuss = discuss.filter((item) => {\n if (item.author === currentUser) { driveDiscussion.push(item); return false; }\n return true;\n });\n\n const filteredVoteOn = voteOn.filter((item) => {\n if (item.author === currentUser && item.tags.includes(\"phase:extended-voting\")) {\n driveDiscussion.push(item);\n return false;\n }\n return true;\n });\n\n const filteredReviewPRs = reviewPRs.filter((item) => {\n if (item.author === currentUser) { driveImplementation.push(item); return false; }\n return true;\n });\n\n const filteredAddressFeedback = addressFeedback.filter((item) => {\n if (item.author === currentUser) { driveImplementation.push(item); return false; }\n return true;\n });\n\n return {\n repo,\n currentUser,\n needsHuman,\n driveDiscussion,\n driveImplementation,\n voteOn: filteredVoteOn,\n discuss: filteredDiscuss,\n implement,\n reviewPRs: filteredReviewPRs,\n addressFeedback: filteredAddressFeedback,\n notes: [],\n };\n}\n","import chalk from \"chalk\";\nimport type { RepoSummary, RoleConfig, SummaryItem, TeamConfig } from \"../config/types.js\";\n\nconst DIVIDER_WIDTH = 50;\n\n// Section types determine which metadata keys appear on the second line\ntype SectionType = \"vote\" | \"discuss\" | \"implement\" | \"reviewPRs\" | \"addressFeedback\" | \"driveDiscussion\" | \"driveImplementation\" | \"needsHuman\";\n\nfunction sectionDivider(title: string, count: number): string {\n const label = ` ${title} (${count}) `;\n const remaining = Math.max(0, DIVIDER_WIDTH - label.length - 2);\n return chalk.dim(\"──\") + chalk.bold(label) + chalk.dim(\"─\".repeat(remaining));\n}\n\nfunction formatTags(tags: string[]): string {\n if (tags.length === 0) return \"\";\n return \" \" + tags.map((t) => chalk.magenta(`[${t}]`)).join(\" \");\n}\n\nfunction kv(key: string, value: string | number): string {\n return `${key}: ${chalk.dim(String(value))}`;\n}\n\nfunction formatMeta(item: SummaryItem, sectionType: SectionType, currentUser: string): string {\n const isYou = item.author === currentUser;\n const authorVal = isYou ? chalk.green(`${item.author} (you)`) : chalk.dim(item.author);\n const parts: string[] = [`by: ${authorVal}`];\n\n if (sectionType === \"implement\" || sectionType === \"needsHuman\") {\n parts.push(kv(\"assigned\", item.assigned ?? \"--\"));\n parts.push(kv(\"comments\", item.comments));\n if (item.lastComment) parts.push(kv(\"last-comment\", item.lastComment));\n if (item.updated) parts.push(kv(\"updated\", item.updated));\n parts.push(kv(\"created\", item.age));\n if (item.competingPRs !== undefined) {\n parts.push(kv(\"competing\", item.competingPRs));\n }\n } else if (sectionType === \"vote\" || sectionType === \"discuss\" || sectionType === \"driveDiscussion\") {\n parts.push(kv(\"comments\", item.comments));\n if (item.lastComment) parts.push(kv(\"last-comment\", item.lastComment));\n if (item.updated) parts.push(kv(\"updated\", item.updated));\n parts.push(kv(\"created\", item.age));\n } else {\n // PR sections: reviewPRs, addressFeedback, driveImplementation\n if (item.status !== undefined) {\n const statusVal = /changes.requested/i.test(item.status) ? chalk.red(item.status) : chalk.dim(item.status);\n parts.push(`status: ${statusVal}`);\n }\n if (item.checks !== undefined && item.checks !== null) {\n const checksVal = /fail/i.test(item.checks) ? chalk.red(item.checks) : chalk.dim(item.checks);\n parts.push(`checks: ${checksVal}`);\n }\n if (item.mergeable !== undefined && item.mergeable !== null) {\n const mergeVal = /conflict/i.test(item.mergeable) ? chalk.red(item.mergeable) : chalk.dim(item.mergeable);\n parts.push(`merge: ${mergeVal}`);\n }\n if (item.review) {\n const segments = [`${item.review.approvals} approved`];\n if (item.review.changesRequested > 0) segments.push(chalk.red(`${item.review.changesRequested} changes-requested`));\n parts.push(kv(\"review\", segments.join(\", \")));\n }\n if (item.yourReview) {\n const age = item.yourReviewAge ? ` (${item.yourReviewAge})` : \"\";\n parts.push(kv(\"you\", `${item.yourReview}${age}`));\n }\n if (item.lastCommit) parts.push(kv(\"last-commit\", item.lastCommit));\n if (item.lastComment) parts.push(kv(\"last-comment\", item.lastComment));\n if (item.updated) parts.push(kv(\"updated\", item.updated));\n parts.push(kv(\"comments\", item.comments));\n parts.push(kv(\"created\", item.age));\n }\n\n return parts.join(\" \");\n}\n\nfunction formatItem(item: SummaryItem, currentUser: string, sectionType: SectionType): string {\n const isYou = item.author === currentUser;\n const prefix = isYou ? chalk.green(\"★\") : \" \";\n const num = chalk.cyan(`#${item.number}`);\n const tags = formatTags(item.tags);\n const hasProblems = (item.checks && /fail/i.test(item.checks)) || (item.mergeable && /conflict/i.test(item.mergeable));\n const warningIcon = hasProblems ? \" \" + chalk.red(\"✗\") : \"\";\n\n const titleLine = `${prefix} ${num} ${item.title}${tags}${warningIcon}`;\n const metaLine = ` ${formatMeta(item, sectionType, currentUser)}`;\n\n return `${titleLine}\\n${metaLine}`;\n}\n\nfunction formatSection(\n title: string,\n items: SummaryItem[],\n currentUser: string,\n sectionType: SectionType,\n limit?: number,\n): string {\n if (items.length === 0) return \"\";\n\n const displayed = limit ? items.slice(0, limit) : items;\n const header = sectionDivider(title, items.length);\n const itemBlocks = displayed.map((item) => formatItem(item, currentUser, sectionType));\n\n const parts = [header, ...itemBlocks];\n\n if (limit && items.length > limit) {\n parts.push(chalk.dim(` ... and ${items.length - limit} more`));\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction formatSummaryBody(summary: RepoSummary, limit?: number): string {\n const u = summary.currentUser;\n const sections: string[] = [];\n\n sections.push(\n ...[\n formatSection(\"NEEDS HUMAN\", summary.needsHuman, u, \"needsHuman\", limit),\n formatSection(\"DRIVE THE DISCUSSION\", summary.driveDiscussion, u, \"driveDiscussion\", limit),\n formatSection(\"DRIVE THE IMPLEMENTATION\", summary.driveImplementation, u, \"driveImplementation\", limit),\n formatSection(\"VOTE ON ISSUES\", summary.voteOn, u, \"vote\", limit),\n formatSection(\"DISCUSS ISSUES\", summary.discuss, u, \"discuss\", limit),\n formatSection(\"READY TO IMPLEMENT ISSUES\", summary.implement, u, \"implement\", limit),\n formatSection(\"REVIEW PRs\", summary.reviewPRs, u, \"reviewPRs\", limit),\n formatSection(\"ADDRESS FEEDBACK PRs\", summary.addressFeedback, u, \"addressFeedback\", limit),\n ].filter(Boolean),\n );\n\n if (summary.notes.length > 0) {\n sections.push(summary.notes.map((n) => chalk.dim(` ${n}`)).join(\"\\n\"));\n }\n\n if (sections.length === 0) {\n return chalk.dim(\" No open issues or PRs.\");\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nexport function formatBuzz(\n roleName: string,\n role: RoleConfig,\n summary: RepoSummary,\n limit?: number,\n): string {\n const lines = [\n chalk.bold(`ROLE: ${roleName}`) + ` — ${role.description}`,\n \"\",\n chalk.bold(\"INSTRUCTIONS:\"),\n role.instructions.trimEnd(),\n \"\",\n summary.currentUser\n ? `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`\n : `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}`,\n \"\",\n formatSummaryBody(summary, limit),\n ];\n\n return lines.join(\"\\n\");\n}\n\nexport function formatStatus(summary: RepoSummary, limit?: number): string {\n const lines = [\n summary.currentUser\n ? `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}, logged in as ${chalk.green(summary.currentUser)}`\n : `You are working on ${chalk.bold(`${summary.repo.owner}/${summary.repo.repo}`)}`,\n \"\",\n formatSummaryBody(summary, limit),\n ];\n\n return lines.join(\"\\n\");\n}\n\nexport function formatRoles(teamConfig: TeamConfig, repoFullName: string): string {\n const nameLabel = teamConfig.name ? ` (${teamConfig.name})` : \"\";\n const lines = [\n chalk.bold(`ROLES — ${repoFullName}${nameLabel}`),\n \"\",\n ];\n\n const slugs = Object.keys(teamConfig.roles);\n const maxLen = Math.max(...slugs.map((s) => s.length));\n\n for (const slug of slugs) {\n const role = teamConfig.roles[slug];\n const padded = slug.padEnd(maxLen + 2);\n lines.push(` ${chalk.cyan(padded)}${role.description}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { RepoSummary, RoleConfig, TeamConfig } from \"../config/types.js\";\n\nexport function jsonBuzz(\n roleName: string,\n role: RoleConfig,\n summary: RepoSummary,\n): string {\n return JSON.stringify(\n {\n role: {\n name: roleName,\n description: role.description,\n instructions: role.instructions,\n },\n summary: {\n repo: `${summary.repo.owner}/${summary.repo.repo}`,\n currentUser: summary.currentUser,\n driveDiscussion: summary.driveDiscussion,\n driveImplementation: summary.driveImplementation,\n voteOn: summary.voteOn,\n discuss: summary.discuss,\n implement: summary.implement,\n reviewPRs: summary.reviewPRs,\n addressFeedback: summary.addressFeedback,\n needsHuman: summary.needsHuman,\n notes: summary.notes,\n },\n },\n null,\n 2,\n );\n}\n\nexport function jsonStatus(summary: RepoSummary): string {\n return JSON.stringify(\n {\n repo: `${summary.repo.owner}/${summary.repo.repo}`,\n currentUser: summary.currentUser,\n driveDiscussion: summary.driveDiscussion,\n driveImplementation: summary.driveImplementation,\n voteOn: summary.voteOn,\n discuss: summary.discuss,\n implement: summary.implement,\n reviewPRs: summary.reviewPRs,\n addressFeedback: summary.addressFeedback,\n needsHuman: summary.needsHuman,\n notes: summary.notes,\n },\n null,\n 2,\n );\n}\n\nexport function jsonRoles(teamConfig: TeamConfig): string {\n const roles = Object.entries(teamConfig.roles).map(([slug, role]) => ({\n name: slug,\n description: role.description,\n }));\n\n return JSON.stringify({ roles }, null, 2);\n}\n","import { CliError, type BuzzOptions } from \"../config/types.js\";\nimport { loadTeamConfig } from \"../config/loader.js\";\nimport { resolveRepo } from \"../github/repo.js\";\nimport { fetchIssues } from \"../github/issues.js\";\nimport { fetchPulls } from \"../github/pulls.js\";\nimport { fetchCurrentUser } from \"../github/user.js\";\nimport { buildSummary } from \"../summary/builder.js\";\nimport { formatBuzz, formatStatus } from \"../output/formatter.js\";\nimport { jsonBuzz, jsonStatus } from \"../output/json.js\";\n\nfunction errorDetail(reason: unknown): string {\n return reason instanceof Error ? reason.message : String(reason);\n}\n\nexport async function buzzCommand(options: BuzzOptions): Promise<void> {\n const repo = await resolveRepo(options.repo);\n const fetchLimit = options.fetchLimit ?? 200;\n\n const [issuesResult, prsResult, userResult] = await Promise.allSettled([\n fetchIssues(repo, fetchLimit),\n fetchPulls(repo, fetchLimit),\n fetchCurrentUser(),\n ]);\n\n // If all three failed, surface the most actionable CliError.\n if (\n issuesResult.status === \"rejected\" &&\n prsResult.status === \"rejected\" &&\n userResult.status === \"rejected\"\n ) {\n const cliErrors = [issuesResult, prsResult, userResult]\n .map((r) => r.reason)\n .filter((r): r is CliError => r instanceof CliError);\n const actionableCodes = [\"GH_NOT_AUTHENTICATED\", \"RATE_LIMITED\", \"GH_NOT_FOUND\"];\n const best = cliErrors.find((e) => actionableCodes.includes(e.code)) ?? cliErrors[0];\n throw best ?? issuesResult.reason;\n }\n\n const issues = issuesResult.status === \"fulfilled\" ? issuesResult.value : [];\n const prs = prsResult.status === \"fulfilled\" ? prsResult.value : [];\n const currentUser = userResult.status === \"fulfilled\" ? userResult.value : \"\";\n\n const summary = buildSummary(repo, issues, prs, currentUser);\n\n if (issuesResult.status === \"rejected\" && prsResult.status === \"rejected\") {\n summary.notes.push(\n `Could not fetch issues (${errorDetail(issuesResult.reason)}) or pull requests (${errorDetail(prsResult.reason)}) — showing limited summary.`,\n );\n } else if (issuesResult.status === \"rejected\") {\n summary.notes.push(`Could not fetch issues (${errorDetail(issuesResult.reason)}) — showing PRs only.`);\n } else if (prsResult.status === \"rejected\") {\n summary.notes.push(`Could not fetch pull requests (${errorDetail(prsResult.reason)}) — showing issues only.`);\n }\n\n if (userResult.status === \"rejected\") {\n summary.notes.push(\n `Could not determine GitHub user (${errorDetail(userResult.reason)}) — drive sections, competition counts, and author highlighting are unavailable.`,\n );\n }\n\n if (issues.length >= fetchLimit) {\n summary.notes.push(`Only the first ${fetchLimit} issues were fetched. Use --fetch-limit to increase.`);\n }\n if (prs.length >= fetchLimit) {\n summary.notes.push(`Only the first ${fetchLimit} PRs were fetched. Use --fetch-limit to increase.`);\n }\n\n if (options.role) {\n const teamConfig = await loadTeamConfig(repo);\n if (!Object.hasOwn(teamConfig.roles, options.role)) {\n const available = Object.keys(teamConfig.roles).join(\", \");\n throw new CliError(\n `Role '${options.role}' not found. Available: ${available}. Run: hivemoot roles`,\n \"ROLE_NOT_FOUND\",\n 1,\n );\n }\n const roleConfig = teamConfig.roles[options.role];\n\n if (options.json) {\n console.log(jsonBuzz(options.role, roleConfig, summary));\n } else {\n console.log(formatBuzz(options.role, roleConfig, summary, options.limit));\n }\n } else {\n if (options.json) {\n console.log(jsonStatus(summary));\n } else {\n console.log(formatStatus(summary, options.limit));\n }\n }\n}\n","import type { RolesOptions } from \"../config/types.js\";\nimport { loadTeamConfig } from \"../config/loader.js\";\nimport { resolveRepo } from \"../github/repo.js\";\nimport { formatRoles } from \"../output/formatter.js\";\nimport { jsonRoles } from \"../output/json.js\";\n\nexport async function rolesCommand(options: RolesOptions): Promise<void> {\n const repo = await resolveRepo(options.repo);\n const teamConfig = await loadTeamConfig(repo);\n\n if (options.json) {\n console.log(jsonRoles(teamConfig));\n } else {\n console.log(formatRoles(teamConfig, `${repo.owner}/${repo.repo}`));\n }\n}\n","export async function initCommand(): Promise<void> {\n const template = `# Hivemoot team configuration\n# Place this file at .github/hivemoot.yml in your repository.\n#\n# Roles define personas (who the agent is), not workflow.\n# Workflow details belong in .agent/skills/.\n\nteam:\n roles:\n pm:\n description: \"Product manager focused on user value and clarity\"\n instructions: |\n You think from the user's perspective.\n Evaluate ideas by the problem they solve and who benefits.\n Push for clear requirements and well-scoped proposals.\n Ask \"why does this matter?\" before \"how do we build it?\"\n\n engineer:\n description: \"Software engineer focused on clean implementation\"\n instructions: |\n You care about code quality, patterns, and maintainability.\n Favor simple, proven approaches over clever solutions.\n Write clean code with good test coverage.\n Build on existing conventions in the codebase.\n\n architect:\n description: \"Architect focused on system design and long-term health\"\n instructions: |\n You think about how pieces fit together.\n Evaluate proposals for scalability, consistency, and technical debt.\n Guard the system's boundaries and abstractions.\n Push back when short-term wins create long-term problems.\n\n qa:\n description: \"QA engineer focused on reliability and edge cases\"\n instructions: |\n You think about what can go wrong.\n Find edge cases, race conditions, and failure modes others miss.\n Push for thorough error handling and defensive design.\n Ask \"what happens when this fails?\" about everything.\n`;\n\n console.log(template);\n}\n"],"mappings":"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","names":["status","require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemoot-dev/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "CLI for Hivemoot agents — role instructions and repo work summaries",
5
5
  "type": "module",
6
6
  "bin": {