import { Command } from "commander"; import { findSeedsDir } from "../config.ts"; import { accent, muted, outputJson, printSuccess } from "../output.ts"; import { issuesPath, readIssues, withLock, writeIssues } from "../store.ts"; // Exported so plan submit/adopt paths can reuse the same normalization // (lowercase, trim, drop empties) when applying step.labels to spawned/ // adopted children (seeds-745e / seeds-bac9 under pl-e5a8). export function normalizeLabels(raw: string[]): string[] { return raw.map((l) => l.trim().toLowerCase()).filter(Boolean); } export async function run(args: string[], seedsDir?: string): Promise { const jsonMode = args.includes("--json"); const positional = args.filter((a) => !a.startsWith("--")); const subcmd = positional[0]; if (!subcmd) throw new Error("Usage: sd label "); const dir = seedsDir ?? (await findSeedsDir()); if (subcmd === "list-all") { const issues = await readIssues(dir); const counts: Record = {}; for (const issue of issues) { for (const label of issue.labels ?? []) { counts[label] = (counts[label] ?? 0) + 1; } } const labels = Object.keys(counts).sort(); if (jsonMode) { await outputJson({ success: true, command: "label list-all", labels, counts }); } else { if (labels.length === 0) { console.log("No labels found."); return; } for (const label of labels) { console.log(` ${accent(label.padEnd(20))} ${muted(String(counts[label]))}`); } console.log(`\n${labels.length} label(s)`); } return; } if (subcmd === "list") { const issueId = positional[1]; if (!issueId) throw new Error("Usage: sd label list "); const issues = await readIssues(dir); const issue = issues.find((i) => i.id === issueId); if (!issue) throw new Error(`Issue not found: ${issueId}`); const labels = issue.labels ?? []; if (jsonMode) { await outputJson({ success: true, command: "label list", issueId, labels }); } else { if (labels.length === 0) { console.log(`${accent.bold(issueId)} has no labels.`); } else { console.log(`${accent.bold(issueId)} ${muted("labels:")}`); for (const label of labels) { console.log(` ${accent(label)}`); } } } return; } if (subcmd === "add") { const issueId = positional[1]; const rawLabels = positional.slice(2); if (!issueId || rawLabels.length === 0) { throw new Error("Usage: sd label add