chore: clean up content phase organization

This commit is contained in:
Prad Nukala committed 2026-09-25 14:00:22 -04:00
1 parent 5dc2265ee5
commit 6f9e4ecb3b
14 files changed
+706 -45

No files matched your search

+3 -40
View File
@@ -7,6 +7,7 @@
* `set:optional` and `set:deferred` are extra credit. A topic is finished when
* every one of its core sub-issues is closed; optional/deferred state is
* ignored, matching the day rule in each topic body ("Core problems first").
* The rule lives in topics.ts, shared with release-topics.ts.
*
* Like close-solved.ts this reconciles state instead of reacting to an event
* payload: re-runs are no-ops, backfilling needs no special casing, and only
@@ -19,6 +20,7 @@
*/
import { github } from "./github.ts";
import { markdownTable, printTable, writeStepSummary } from "./report.ts";
import { coreSet, readProblems } from "./topics.ts";
const DRY =
process.argv.includes("--dry-run") ||
@@ -53,52 +55,13 @@ for await (const raw of gh.list(`/repos/${gh.repo}/issues?labels=topic&state=ope
}
topics.sort((a, b) => a.number - b.number);
// ── core sub-issue state per topic ───────────────────────────────
interface Core {
/** Core sub-issues, closed and open alike, lowest number first. */
all: number[];
/** The core sub-issues still open — non-empty means the topic stays open. */
pending: number[];
}
/**
* Read a topic's core sub-issue state. The sub_issues payload carries the full
* issue objects (state + labels), so no per-problem follow-up request is needed.
*/
async function readCore(topic: number): Promise<Core> {
const all: number[] = [];
const pending: number[] = [];
for await (const raw of gh.list(`/repos/${gh.repo}/issues/${topic}/sub_issues`)) {
if (!raw || typeof raw !== "object") continue;
if (!("number" in raw) || typeof raw.number !== "number") continue;
if (!("state" in raw) || typeof raw.state !== "string") continue;
if (!("labels" in raw) || !Array.isArray(raw.labels)) continue;
const core = raw.labels.some(
(label) =>
label &&
typeof label === "object" &&
"name" in label &&
label.name === "set:core",
);
if (!core) continue;
all.push(raw.number);
if (raw.state === "open") pending.push(raw.number);
}
all.sort((a, b) => a - b);
pending.sort((a, b) => a - b);
return { all, pending };
}
// ── reconcile ────────────────────────────────────────────────────
const report: string[][] = [];
let closed = 0;
for (const topic of topics) {
const core = await readCore(topic.number);
const core = coreSet(await readProblems(gh, topic.number));
const progress = `${core.all.length - core.pending.length}/${core.all.length}`;
// A topic with no core sub-issues has nothing to complete: never close it,