@hivemoot-dev/cli 0.1.7 → 0.1.8
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 +159 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -383,7 +383,113 @@ async function fetchCurrentUser() {
|
|
|
383
383
|
return login;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
+
// src/github/votes.ts
|
|
387
|
+
var METADATA_RE = /<!--\s*hivemoot-metadata:\s*(\{[\s\S]*?\})\s*-->/;
|
|
388
|
+
var REACTION_EMOJI = {
|
|
389
|
+
THUMBS_UP: "\u{1F44D}",
|
|
390
|
+
THUMBS_DOWN: "\u{1F44E}",
|
|
391
|
+
CONFUSED: "\u{1F615}",
|
|
392
|
+
EYES: "\u{1F440}",
|
|
393
|
+
HOORAY: "\u{1F389}",
|
|
394
|
+
HEART: "\u2764\uFE0F",
|
|
395
|
+
ROCKET: "\u{1F680}",
|
|
396
|
+
LAUGH: "\u{1F604}"
|
|
397
|
+
};
|
|
398
|
+
var QUERY = `
|
|
399
|
+
query ($owner: String!, $repo: String!, $number: Int!) {
|
|
400
|
+
repository(owner: $owner, name: $repo) {
|
|
401
|
+
issue(number: $number) {
|
|
402
|
+
comments(last: 50) {
|
|
403
|
+
nodes {
|
|
404
|
+
body
|
|
405
|
+
createdAt
|
|
406
|
+
reactions(first: 100) {
|
|
407
|
+
nodes {
|
|
408
|
+
content
|
|
409
|
+
createdAt
|
|
410
|
+
user { login }
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}`;
|
|
418
|
+
function isVotingComment(body) {
|
|
419
|
+
const match = body.match(METADATA_RE);
|
|
420
|
+
if (!match) return false;
|
|
421
|
+
try {
|
|
422
|
+
const meta = JSON.parse(match[1]);
|
|
423
|
+
return meta.type === "voting";
|
|
424
|
+
} catch {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function extractVote(comments, currentUser) {
|
|
429
|
+
let votingComment;
|
|
430
|
+
for (const comment of comments) {
|
|
431
|
+
if (isVotingComment(comment.body)) {
|
|
432
|
+
votingComment = comment;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
if (!votingComment) return void 0;
|
|
436
|
+
for (const reaction of votingComment.reactions.nodes) {
|
|
437
|
+
if (reaction.user?.login === currentUser) {
|
|
438
|
+
const emoji = REACTION_EMOJI[reaction.content] ?? reaction.content;
|
|
439
|
+
return { reaction: emoji, createdAt: reaction.createdAt };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return void 0;
|
|
443
|
+
}
|
|
444
|
+
async function fetchVoteForIssue(repo, issueNumber, currentUser) {
|
|
445
|
+
const raw = await gh([
|
|
446
|
+
"api",
|
|
447
|
+
"graphql",
|
|
448
|
+
"-f",
|
|
449
|
+
`query=${QUERY}`,
|
|
450
|
+
"-F",
|
|
451
|
+
`owner=${repo.owner}`,
|
|
452
|
+
"-F",
|
|
453
|
+
`repo=${repo.repo}`,
|
|
454
|
+
"-F",
|
|
455
|
+
`number=${issueNumber}`
|
|
456
|
+
]);
|
|
457
|
+
const response = JSON.parse(raw);
|
|
458
|
+
const comments = response.data?.repository?.issue?.comments?.nodes;
|
|
459
|
+
if (!comments) return void 0;
|
|
460
|
+
return extractVote(comments, currentUser);
|
|
461
|
+
}
|
|
462
|
+
async function fetchVotes(repo, issueNumbers, currentUser) {
|
|
463
|
+
const map = /* @__PURE__ */ new Map();
|
|
464
|
+
if (issueNumbers.length === 0 || !currentUser) return map;
|
|
465
|
+
const results = await Promise.allSettled(
|
|
466
|
+
issueNumbers.map((num) => fetchVoteForIssue(repo, num, currentUser))
|
|
467
|
+
);
|
|
468
|
+
for (let i = 0; i < issueNumbers.length; i++) {
|
|
469
|
+
const result = results[i];
|
|
470
|
+
if (result.status === "fulfilled" && result.value) {
|
|
471
|
+
map.set(issueNumbers[i], result.value);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return map;
|
|
475
|
+
}
|
|
476
|
+
|
|
386
477
|
// src/summary/utils.ts
|
|
478
|
+
function commentContext(item, currentUser, now) {
|
|
479
|
+
let latestTime;
|
|
480
|
+
for (const comment of item.comments) {
|
|
481
|
+
if (comment.author?.login === currentUser) {
|
|
482
|
+
if (!latestTime || comment.createdAt > latestTime) {
|
|
483
|
+
latestTime = comment.createdAt;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (!latestTime) return null;
|
|
488
|
+
return { yourComment: "commented", yourCommentAge: timeAgo(latestTime, now) };
|
|
489
|
+
}
|
|
490
|
+
function isVotingIssue(labels) {
|
|
491
|
+
return hasExactLabel(labels, "phase:voting") || hasExactLabel(labels, "phase:extended-voting") || hasLabel(labels, "vote");
|
|
492
|
+
}
|
|
387
493
|
function hasLabel(labels, keyword) {
|
|
388
494
|
return labels.some(
|
|
389
495
|
(l) => l.name.toLowerCase().split(/[:\-_]/).some((seg) => seg === keyword)
|
|
@@ -512,7 +618,7 @@ function compactMergeable(raw) {
|
|
|
512
618
|
if (raw === "no conflicts") return "clean";
|
|
513
619
|
return raw;
|
|
514
620
|
}
|
|
515
|
-
function classifyIssue(issue, now) {
|
|
621
|
+
function classifyIssue(issue, currentUser, now) {
|
|
516
622
|
const age = timeAgo(issue.createdAt, now);
|
|
517
623
|
const assigned = issue.assignees.length > 0 ? issue.assignees.map((a) => a.login).join(", ") : void 0;
|
|
518
624
|
const tags = issue.labels.map((l) => l.name);
|
|
@@ -528,6 +634,13 @@ function classifyIssue(issue, now) {
|
|
|
528
634
|
lastComment: latestCommentAge(issue, now),
|
|
529
635
|
updated: timeAgo(issue.updatedAt, now)
|
|
530
636
|
};
|
|
637
|
+
if (currentUser) {
|
|
638
|
+
const ctx = commentContext(issue, currentUser, now);
|
|
639
|
+
if (ctx) {
|
|
640
|
+
base.yourComment = ctx.yourComment;
|
|
641
|
+
base.yourCommentAge = ctx.yourCommentAge;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
531
644
|
if (hasExactLabel(issue.labels, "needs:human")) {
|
|
532
645
|
return {
|
|
533
646
|
bucket: "needsHuman",
|
|
@@ -593,7 +706,7 @@ function buildCompetitionMap(prs, currentUser) {
|
|
|
593
706
|
}
|
|
594
707
|
return map;
|
|
595
708
|
}
|
|
596
|
-
function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new Date()) {
|
|
709
|
+
function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new Date(), votes = /* @__PURE__ */ new Map()) {
|
|
597
710
|
const needsHuman = [];
|
|
598
711
|
const voteOn = [];
|
|
599
712
|
const discuss = [];
|
|
@@ -601,12 +714,19 @@ function buildSummary(repo, issues, prs, currentUser, now = /* @__PURE__ */ new
|
|
|
601
714
|
const reviewPRs = [];
|
|
602
715
|
const addressFeedback = [];
|
|
603
716
|
for (const issue of issues) {
|
|
604
|
-
const { bucket, item } = classifyIssue(issue, now);
|
|
717
|
+
const { bucket, item } = classifyIssue(issue, currentUser, now);
|
|
605
718
|
if (bucket === "needsHuman") needsHuman.push(item);
|
|
606
719
|
else if (bucket === "voteOn") voteOn.push(item);
|
|
607
720
|
else if (bucket === "discuss") discuss.push(item);
|
|
608
721
|
else if (bucket === "implement") implement.push(item);
|
|
609
722
|
}
|
|
723
|
+
for (const item of voteOn) {
|
|
724
|
+
const vote = votes.get(item.number);
|
|
725
|
+
if (vote) {
|
|
726
|
+
item.yourVote = vote.reaction;
|
|
727
|
+
item.yourVoteAge = timeAgo(vote.createdAt, now);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
610
730
|
const competitionMap = buildCompetitionMap(prs, currentUser);
|
|
611
731
|
for (const item of implement) {
|
|
612
732
|
const count = competitionMap.get(item.number) ?? 0;
|
|
@@ -691,20 +811,38 @@ function formatMeta(item, sectionType, currentUser) {
|
|
|
691
811
|
const isYou = item.author === currentUser;
|
|
692
812
|
const authorVal = isYou ? chalk.green(`${item.author} (you)`) : chalk.dim(item.author);
|
|
693
813
|
const parts = [`by: ${authorVal}`];
|
|
694
|
-
if (sectionType === "
|
|
695
|
-
parts.push(kv("assigned", item.assigned ?? "--"));
|
|
814
|
+
if (sectionType === "vote" || sectionType === "discuss" || sectionType === "driveDiscussion") {
|
|
696
815
|
parts.push(kv("comments", item.comments));
|
|
816
|
+
const youParts = [];
|
|
817
|
+
if (item.yourComment) {
|
|
818
|
+
const commentAge = item.yourCommentAge ? ` (${item.yourCommentAge})` : "";
|
|
819
|
+
youParts.push(`${item.yourComment}${commentAge}`);
|
|
820
|
+
}
|
|
821
|
+
if (item.yourVote) {
|
|
822
|
+
const voteAge = item.yourVoteAge ? ` (${item.yourVoteAge})` : "";
|
|
823
|
+
youParts.push(`voted ${item.yourVote}${voteAge}`);
|
|
824
|
+
} else if (sectionType === "vote") {
|
|
825
|
+
youParts.push("not voted");
|
|
826
|
+
}
|
|
827
|
+
if (youParts.length > 0) {
|
|
828
|
+
parts.push(kv("you", youParts.join(", ")));
|
|
829
|
+
}
|
|
697
830
|
if (item.lastComment) parts.push(kv("last-comment", item.lastComment));
|
|
698
831
|
if (item.updated) parts.push(kv("updated", item.updated));
|
|
699
832
|
parts.push(kv("created", item.age));
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
} else if (sectionType === "vote" || sectionType === "discuss" || sectionType === "driveDiscussion") {
|
|
833
|
+
} else if (sectionType === "implement" || sectionType === "needsHuman") {
|
|
834
|
+
parts.push(kv("assigned", item.assigned ?? "--"));
|
|
704
835
|
parts.push(kv("comments", item.comments));
|
|
836
|
+
if (item.yourComment) {
|
|
837
|
+
const commentAge = item.yourCommentAge ? ` (${item.yourCommentAge})` : "";
|
|
838
|
+
parts.push(kv("you", `${item.yourComment}${commentAge}`));
|
|
839
|
+
}
|
|
705
840
|
if (item.lastComment) parts.push(kv("last-comment", item.lastComment));
|
|
706
841
|
if (item.updated) parts.push(kv("updated", item.updated));
|
|
707
842
|
parts.push(kv("created", item.age));
|
|
843
|
+
if (item.competingPRs !== void 0) {
|
|
844
|
+
parts.push(kv("competing", item.competingPRs));
|
|
845
|
+
}
|
|
708
846
|
} else {
|
|
709
847
|
if (item.status !== void 0) {
|
|
710
848
|
const statusVal = /changes.requested/i.test(item.status) ? chalk.red(item.status) : chalk.dim(item.status);
|
|
@@ -893,7 +1031,15 @@ async function buzzCommand(options) {
|
|
|
893
1031
|
const issues = issuesResult.status === "fulfilled" ? issuesResult.value : [];
|
|
894
1032
|
const prs = prsResult.status === "fulfilled" ? prsResult.value : [];
|
|
895
1033
|
const currentUser = userResult.status === "fulfilled" ? userResult.value : "";
|
|
896
|
-
const
|
|
1034
|
+
const votingIssueNumbers = issues.filter((issue) => isVotingIssue(issue.labels)).map((issue) => issue.number);
|
|
1035
|
+
let votes = /* @__PURE__ */ new Map();
|
|
1036
|
+
let voteFetchFailed = false;
|
|
1037
|
+
try {
|
|
1038
|
+
votes = await fetchVotes(repo, votingIssueNumbers, currentUser);
|
|
1039
|
+
} catch {
|
|
1040
|
+
voteFetchFailed = true;
|
|
1041
|
+
}
|
|
1042
|
+
const summary = buildSummary(repo, issues, prs, currentUser, /* @__PURE__ */ new Date(), votes);
|
|
897
1043
|
if (issuesResult.status === "rejected" && prsResult.status === "rejected") {
|
|
898
1044
|
summary.notes.push(
|
|
899
1045
|
`Could not fetch issues (${errorDetail(issuesResult.reason)}) or pull requests (${errorDetail(prsResult.reason)}) \u2014 showing limited summary.`
|
|
@@ -908,6 +1054,9 @@ async function buzzCommand(options) {
|
|
|
908
1054
|
`Could not determine GitHub user (${errorDetail(userResult.reason)}) \u2014 drive sections, competition counts, and author highlighting are unavailable.`
|
|
909
1055
|
);
|
|
910
1056
|
}
|
|
1057
|
+
if (voteFetchFailed) {
|
|
1058
|
+
summary.notes.push("Could not fetch vote data \u2014 vote status unavailable.");
|
|
1059
|
+
}
|
|
911
1060
|
if (issues.length >= fetchLimit) {
|
|
912
1061
|
summary.notes.push(`Only the first ${fetchLimit} issues were fetched. Use --fetch-limit to increase.`);
|
|
913
1062
|
}
|
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/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"]}
|
|
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/github/votes.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; author: { login: string } | null }>;\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; author: { login: string } | null }>;\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 yourComment?: string; // \"commented\"\n yourCommentAge?: string; // \"3h ago\" — when you last commented\n yourVote?: string; // \"👍\" | \"👎\" | \"😕\" | \"👀\"\n yourVoteAge?: string; // \"1d ago\" — when you voted\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 { RepoRef } from \"../config/types.js\";\nimport { gh } from \"./client.js\";\n\nexport interface VoteInfo {\n reaction: string; // emoji: \"👍\" | \"👎\" | \"😕\" | \"👀\" | \"🎉\" | \"❤️\" | \"🚀\"\n createdAt: string; // ISO timestamp of the reaction\n}\n\nexport type VoteMap = Map<number, VoteInfo>;\n\nconst METADATA_RE = /<!--\\s*hivemoot-metadata:\\s*(\\{[\\s\\S]*?\\})\\s*-->/;\n\nconst REACTION_EMOJI: Record<string, string> = {\n THUMBS_UP: \"👍\",\n THUMBS_DOWN: \"👎\",\n CONFUSED: \"😕\",\n EYES: \"👀\",\n HOORAY: \"🎉\",\n HEART: \"❤️\",\n ROCKET: \"🚀\",\n LAUGH: \"😄\",\n};\n\ninterface GraphQLComment {\n body: string;\n createdAt: string;\n reactions: {\n nodes: Array<{\n content: string;\n createdAt: string;\n user: { login: string } | null;\n }>;\n };\n}\n\ninterface GraphQLResponse {\n data: {\n repository: {\n issue: {\n comments: {\n nodes: GraphQLComment[];\n };\n } | null;\n };\n };\n}\n\nconst QUERY = `\nquery ($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n issue(number: $number) {\n comments(last: 50) {\n nodes {\n body\n createdAt\n reactions(first: 100) {\n nodes {\n content\n createdAt\n user { login }\n }\n }\n }\n }\n }\n }\n}`;\n\nfunction isVotingComment(body: string): boolean {\n const match = body.match(METADATA_RE);\n if (!match) return false;\n try {\n const meta = JSON.parse(match[1]);\n return meta.type === \"voting\";\n } catch {\n return false;\n }\n}\n\n/**\n * Find the current user's reaction on the latest voting comment for a single issue.\n */\nfunction extractVote(comments: GraphQLComment[], currentUser: string): VoteInfo | undefined {\n // Find the latest voting comment (last in array = most recent)\n let votingComment: GraphQLComment | undefined;\n for (const comment of comments) {\n if (isVotingComment(comment.body)) {\n votingComment = comment;\n }\n }\n if (!votingComment) return undefined;\n\n // Find the current user's reaction\n for (const reaction of votingComment.reactions.nodes) {\n if (reaction.user?.login === currentUser) {\n const emoji = REACTION_EMOJI[reaction.content] ?? reaction.content;\n return { reaction: emoji, createdAt: reaction.createdAt };\n }\n }\n return undefined;\n}\n\nasync function fetchVoteForIssue(\n repo: RepoRef,\n issueNumber: number,\n currentUser: string,\n): Promise<VoteInfo | undefined> {\n const raw = await gh([\n \"api\",\n \"graphql\",\n \"-f\",\n `query=${QUERY}`,\n \"-F\",\n `owner=${repo.owner}`,\n \"-F\",\n `repo=${repo.repo}`,\n \"-F\",\n `number=${issueNumber}`,\n ]);\n\n const response: GraphQLResponse = JSON.parse(raw);\n const comments = response.data?.repository?.issue?.comments?.nodes;\n if (!comments) return undefined;\n\n return extractVote(comments, currentUser);\n}\n\n/**\n * Fetch the current user's vote reactions on voting-phase issues.\n * Returns a map from issue number to vote info.\n * Returns empty map when inputs are empty — avoids unnecessary API calls.\n */\nexport async function fetchVotes(\n repo: RepoRef,\n issueNumbers: number[],\n currentUser: string,\n): Promise<VoteMap> {\n const map: VoteMap = new Map();\n if (issueNumbers.length === 0 || !currentUser) return map;\n\n const results = await Promise.allSettled(\n issueNumbers.map((num) => fetchVoteForIssue(repo, num, currentUser)),\n );\n\n for (let i = 0; i < issueNumbers.length; i++) {\n const result = results[i];\n if (result.status === \"fulfilled\" && result.value) {\n map.set(issueNumbers[i], result.value);\n }\n }\n\n return map;\n}\n","import type { GitHubPR } from \"../config/types.js\";\n\n// ── Comment context ──────────────────────────────────────────────\n\nexport interface CommentContext {\n yourComment: string;\n yourCommentAge: string;\n}\n\n/**\n * Compute the current user's latest comment on an issue/PR.\n * Returns null if the user has not commented.\n */\nexport function commentContext(\n item: { comments: Array<{ createdAt: string; author: { login: string } | null }> },\n currentUser: string,\n now: Date,\n): CommentContext | null {\n let latestTime: string | undefined;\n for (const comment of item.comments) {\n if (comment.author?.login === currentUser) {\n if (!latestTime || comment.createdAt > latestTime) {\n latestTime = comment.createdAt;\n }\n }\n }\n if (!latestTime) return null;\n return { yourComment: \"commented\", yourCommentAge: timeAgo(latestTime, now) };\n}\n\n// ── Voting issue detection ───────────────────────────────────────\n\n/**\n * Whether an issue is in a voting phase based on its labels.\n * Matches: phase:voting, phase:extended-voting, or the keyword \"vote\".\n */\nexport function isVotingIssue(labels: Array<{ name: string }>): boolean {\n return (\n hasExactLabel(labels, \"phase:voting\") ||\n hasExactLabel(labels, \"phase:extended-voting\") ||\n hasLabel(labels, \"vote\")\n );\n}\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 type { VoteMap } from \"../github/votes.js\";\nimport { hasLabel, hasExactLabel, hasCIFailure, checkStatus, mergeStatus, approvalCount, changesRequestedCount, timeAgo, reviewContext, latestCommitAge, latestCommentAge, commentContext } 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 currentUser: string,\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 // Populate comment context for the current user\n if (currentUser) {\n const ctx = commentContext(issue, currentUser, now);\n if (ctx) {\n base.yourComment = ctx.yourComment;\n base.yourCommentAge = ctx.yourCommentAge;\n }\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 votes: VoteMap = new Map(),\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, currentUser, 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 voting items with vote reactions from the votes map\n for (const item of voteOn) {\n const vote = votes.get(item.number);\n if (vote) {\n item.yourVote = vote.reaction;\n item.yourVoteAge = timeAgo(vote.createdAt, now);\n }\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 === \"vote\" || sectionType === \"discuss\" || sectionType === \"driveDiscussion\") {\n parts.push(kv(\"comments\", item.comments));\n\n // Build \"you:\" composite field for issue sections\n const youParts: string[] = [];\n if (item.yourComment) {\n const commentAge = item.yourCommentAge ? ` (${item.yourCommentAge})` : \"\";\n youParts.push(`${item.yourComment}${commentAge}`);\n }\n if (item.yourVote) {\n const voteAge = item.yourVoteAge ? ` (${item.yourVoteAge})` : \"\";\n youParts.push(`voted ${item.yourVote}${voteAge}`);\n } else if (sectionType === \"vote\") {\n // Always show vote status on voting sections\n youParts.push(\"not voted\");\n }\n if (youParts.length > 0) {\n parts.push(kv(\"you\", youParts.join(\", \")));\n }\n\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 if (sectionType === \"implement\" || sectionType === \"needsHuman\") {\n parts.push(kv(\"assigned\", item.assigned ?? \"--\"));\n parts.push(kv(\"comments\", item.comments));\n\n // Show \"you:\" on non-voting issue sections only if user has commented\n if (item.yourComment) {\n const commentAge = item.yourCommentAge ? ` (${item.yourCommentAge})` : \"\";\n parts.push(kv(\"you\", `${item.yourComment}${commentAge}`));\n }\n\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 {\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, type GitHubIssue } 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 { fetchVotes } from \"../github/votes.js\";\nimport { buildSummary } from \"../summary/builder.js\";\nimport { isVotingIssue } from \"../summary/utils.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 // Fetch vote reactions for voting-phase issues\n const votingIssueNumbers = issues\n .filter((issue: GitHubIssue) => isVotingIssue(issue.labels))\n .map((issue: GitHubIssue) => issue.number);\n\n let votes = new Map<number, { reaction: string; createdAt: string }>();\n let voteFetchFailed = false;\n try {\n votes = await fetchVotes(repo, votingIssueNumbers, currentUser);\n } catch {\n voteFetchFailed = true;\n }\n\n const summary = buildSummary(repo, issues, prs, currentUser, new Date(), votes);\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 (voteFetchFailed) {\n summary.notes.push(\"Could not fetch vote data — vote status unavailable.\");\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"]}
|