clownfish/scripts/publish-result.mjs
2026-05-08 15:25:50 +01:00

1367 lines
50 KiB
JavaScript

#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { githubActionsRunUrl, parseArgs, repoRoot } from "./lib.mjs";
const DASHBOARD_START = "<!-- projectclownfish-dashboard:start -->";
const DASHBOARD_END = "<!-- projectclownfish-dashboard:end -->";
const CLOSE_APPLICATOR_ACTIONS = new Set([
"close",
"close_duplicate",
"close_superseded",
"close_fixed_by_candidate",
"close_low_signal",
"post_merge_close",
]);
const MERGE_APPLICATOR_ACTIONS = new Set(["merge_candidate", "merge_canonical"]);
const APPLICATOR_ACTIONS = new Set([...CLOSE_APPLICATOR_ACTIONS, ...MERGE_APPLICATOR_ACTIONS]);
const POST_FLIGHT_APPLY_ACTIONS = new Set(["finalize_fix_pr", "post_merge_closeout"]);
const PR_INFO_CACHE = new Map();
const ISSUE_INFO_CACHE = new Map();
const archivedClusters = readArchivedClusters();
const args = parseArgs(process.argv.slice(2));
const inputs = args._.length > 0 ? args._ : [path.join(repoRoot(), ".projectclownfish", "runs")];
const metadataByRunId = readRunMetadata(args["runs-json"]);
const published = [];
for (const input of inputs) {
for (const resultPath of findResultPaths(path.resolve(input))) {
const record = publishResult(resultPath);
published.push(record);
}
}
writeAggregateApplyReport();
updateDashboard();
console.log(JSON.stringify({ published: published.length, records: published }, null, 2));
function publishResult(resultPath) {
const runDir = path.dirname(resultPath);
const result = readJson(resultPath);
const applyReport = readSiblingJson(runDir, "apply-report.json") ?? { actions: [] };
const postFlightReport = readSiblingJson(runDir, "post-flight-report.json") ?? { actions: [] };
const fixReport = readSiblingJson(runDir, "fix-execution-report.json") ?? { actions: [] };
const clusterPlan = readSiblingJson(runDir, "cluster-plan.json");
const runId = String(args["run-id"] ?? inferRunId(resultPath) ?? "");
const metadata = runId ? metadataByRunId.get(runId) : undefined;
const previousRecord = runId ? readExistingRunRecord(runId) : null;
const runUrl =
String(args["run-url"] ?? metadata?.url ?? "") ||
previousRecord?.run_url ||
(runId ? githubActionsRunUrl(runId) : null);
const headSha = String(args["head-sha"] ?? metadata?.headSha ?? metadata?.head_sha ?? previousRecord?.head_sha ?? "");
const workflowConclusion = String(args.conclusion ?? metadata?.conclusion ?? previousRecord?.workflow_conclusion ?? "");
const workflowStatus = String(metadata?.status ?? previousRecord?.workflow_status ?? "");
const repo = String(result.repo ?? "unknown/unknown");
const owner = repo.split("/")[0] || "unknown";
const clusterId = String(result.cluster_id ?? path.basename(runDir));
const applyActions = uniquePlainActionRows([
...(applyReport.actions ?? []),
...(postFlightReport.actions ?? []).filter(isPostFlightApplyAction).map(postFlightToApplyAction),
].filter(isApplicatorAction));
const fixActions = (fixReport.actions ?? []).map(sanitizeFixAction);
const report = {
repo,
cluster_id: clusterId,
mode: result.mode ?? null,
run_id: runId || null,
run_url: runUrl,
head_sha: headSha || null,
workflow_conclusion: workflowConclusion || null,
workflow_status: workflowStatus || null,
workflow_created_at: metadata?.createdAt ?? metadata?.created_at ?? previousRecord?.workflow_created_at ?? null,
workflow_updated_at: metadata?.updatedAt ?? metadata?.updated_at ?? previousRecord?.workflow_updated_at ?? null,
result_status: result.status ?? null,
source_job: clusterPlan?.source_job ?? null,
published_at: new Date().toISOString(),
canonical: result.canonical ?? null,
canonical_issue: result.canonical_issue ?? null,
canonical_pr: result.canonical_pr ?? null,
summary: result.summary ?? "",
actions: summarizeActions(result.actions),
action_counts: countBy(result.actions ?? [], (action) => String(action.action ?? "unknown")),
action_status_counts: countBy(result.actions ?? [], (action) => String(action.status ?? "unknown")),
fix_counts: countBy(fixActions, (action) => String(action.status ?? "unknown")),
apply_counts: countBy(applyActions, (action) => String(action.status ?? "unknown")),
needs_human: Array.isArray(result.needs_human) ? result.needs_human : [],
fix_actions: fixActions,
apply_actions: applyActions.map(sanitizeApplyAction),
};
const reportDir = path.join(repoRoot(), "results", owner);
fs.mkdirSync(reportDir, { recursive: true });
fs.writeFileSync(path.join(reportDir, `${slug(clusterId)}.md`), renderClusterReport(report), "utf8");
const runDirOut = path.join(repoRoot(), "results", "runs");
fs.mkdirSync(runDirOut, { recursive: true });
if (runId) {
fs.writeFileSync(path.join(runDirOut, `${runId}.json`), `${JSON.stringify(report, null, 2)}\n`, "utf8");
}
for (const action of report.apply_actions.filter((action) => action.status === "executed")) {
writeClosedRecord(report, action, owner);
}
return {
cluster_id: report.cluster_id,
run_id: report.run_id,
result_status: report.result_status,
workflow_conclusion: report.workflow_conclusion,
fix_counts: report.fix_counts,
apply_counts: report.apply_counts,
};
}
function renderClusterReport(report) {
const actions = report.actions
.slice(0, 80)
.map(
(action) =>
`| ${action.target || ""} | ${action.action || ""} | ${action.status || ""} | ${action.classification || ""} | ${action.reason || ""} |`,
)
.join("\n");
const applyActions = report.apply_actions
.map(
(action) =>
`| ${action.target || ""} | ${action.action || ""} | ${action.status || ""} | ${action.classification || ""} | ${action.reason || ""} |`,
)
.join("\n");
const fixActions = (report.fix_actions ?? [])
.map((action) => `| ${action.action || ""} | ${action.status || ""} | ${action.target || action.pr || ""} | ${action.branch || ""} | ${action.reason || ""} |`)
.join("\n");
const needsHuman =
report.needs_human.length > 0
? report.needs_human.map((item) => `- ${item}`).join("\n")
: "- none";
return `---
repo: ${quote(report.repo)}
cluster_id: ${quote(report.cluster_id)}
mode: ${quote(report.mode)}
run_id: ${quote(report.run_id)}
run_url: ${quote(report.run_url)}
head_sha: ${quote(report.head_sha)}
workflow_conclusion: ${quote(report.workflow_conclusion)}
result_status: ${quote(report.result_status)}
published_at: ${quote(report.published_at)}
canonical: ${quote(report.canonical)}
canonical_issue: ${quote(report.canonical_issue)}
canonical_pr: ${quote(report.canonical_pr)}
actions_total: ${report.actions.length}
fix_executed: ${report.fix_counts.executed ?? 0}
fix_failed: ${report.fix_counts.failed ?? 0}
fix_blocked: ${report.fix_counts.blocked ?? 0}
apply_executed: ${report.apply_counts.executed ?? 0}
apply_blocked: ${report.apply_counts.blocked ?? 0}
apply_skipped: ${report.apply_counts.skipped ?? 0}
needs_human_count: ${report.needs_human.length}
---
# ${report.cluster_id}
Repo: ${report.repo}
Run: ${report.run_url ? markdownLink(report.run_url, report.run_url) : "unknown"}
Workflow conclusion: ${report.workflow_conclusion || "unknown"}
Worker result: ${report.result_status || "unknown"}
Canonical: ${report.canonical || report.canonical_issue || report.canonical_pr || "unknown"}
## Summary
${report.summary || "_No summary emitted._"}
## Impact
| Metric | Count |
| --- | ---: |
| Worker actions | ${report.actions.length} |
| Fix executed | ${report.fix_counts.executed ?? 0} |
| Fix failed | ${report.fix_counts.failed ?? 0} |
| Fix blocked | ${report.fix_counts.blocked ?? 0} |
| Applied executions | ${report.apply_counts.executed ?? 0} |
| Apply blocked | ${report.apply_counts.blocked ?? 0} |
| Apply skipped | ${report.apply_counts.skipped ?? 0} |
| Needs human | ${report.needs_human.length} |
## Fix Execution Actions
| Action | Status | Target | Branch | Reason |
| --- | --- | --- | --- | --- |
${fixActions || "| _None_ | | | | |"}
## Apply Actions
| Target | Action | Status | Classification | Reason |
| --- | --- | --- | --- | --- |
${applyActions || "| _None_ | | | | |"}
## Worker Action Matrix
| Target | Action | Status | Classification | Reason |
| --- | --- | --- | --- | --- |
${actions || "| _None_ | | | | |"}
## Needs Human
${needsHuman}
`;
}
function writeClosedRecord(report, action, owner) {
const targetNumber = String(action.target ?? "").replace(/^#/, "");
if (!/^\d+$/.test(targetNumber)) return;
const closedDir = path.join(repoRoot(), "jobs", owner, "closed");
fs.mkdirSync(closedDir, { recursive: true });
const body = `---
repo: ${quote(report.repo)}
cluster_id: ${quote(report.cluster_id)}
run_id: ${quote(report.run_id)}
target: ${quote(action.target)}
action: ${quote(action.action)}
classification: ${quote(action.classification)}
closed_at: ${quote(report.published_at)}
---
# ${action.target} closed by ${report.cluster_id}
Run: ${report.run_url ? markdownLink(report.run_url, report.run_url) : "unknown"}
Reason: ${action.reason || "closed by ProjectClownfish applicator"}
`;
fs.writeFileSync(path.join(closedDir, `${targetNumber}.md`), body, "utf8");
}
function updateDashboard() {
const readmePath = path.join(repoRoot(), "README.md");
if (!fs.existsSync(readmePath)) return;
const readme = fs.readFileSync(readmePath, "utf8");
const records = readRunRecords();
const allLatestByCluster = latestClusterRecords(records).sort(sortNewestRecordFirst);
const latestByCluster = allLatestByCluster.filter((record) => !archivedClusters.has(record.cluster_id));
const archivedLatestByCluster = allLatestByCluster.filter((record) => archivedClusters.has(record.cluster_id));
const trackedPrRows = buildTrackedPrRows(records);
const latestApplyRows = latestByCluster.flatMap((record) =>
(record.apply_actions ?? []).filter(isApplicatorAction).map((action) => ({ record, action })),
);
const latestFixRows = latestByCluster.flatMap((record) =>
(record.fix_actions ?? []).map((action) => ({ record, action })),
);
const fixRows = uniqueFixRows(
records.flatMap((record) => (record.fix_actions ?? []).map((action) => ({ record, action }))),
);
const applyRows = uniqueActionRows(
records.flatMap((record) =>
(record.apply_actions ?? []).filter(isApplicatorAction).map((action) => ({ record, action })),
),
);
const executedRows = applyRows.filter((row) => row.action.status === "executed");
const closedRows = executedRows.filter((row) => CLOSE_APPLICATOR_ACTIONS.has(String(row.action.action ?? "")));
const mergedRows = executedRows.filter((row) => MERGE_APPLICATOR_ACTIONS.has(String(row.action.action ?? "")));
const closureRows = hydrateClosureRows(closedRows).sort(sortNewestClosureRowFirst);
const blockedRows = applyRows.filter((row) => row.action.status === "blocked");
const skippedRows = applyRows.filter((row) => row.action.status === "skipped");
const latestBlockedRows = latestApplyRows.filter((row) => row.action.status === "blocked");
const latestSkippedRows = latestApplyRows.filter((row) => row.action.status === "skipped");
const latestFailedFixRows = latestFixRows.filter((row) => ["blocked", "failed"].includes(String(row.action.status ?? "")));
const needsHumanRows = latestByCluster.filter((record) => (record.needs_human ?? []).length > 0);
const inspectionRows = buildInspectionRows({
latestByCluster,
latestFailedFixRows,
latestBlockedRows,
latestSkippedRows,
});
const finalizerReport = readFinalizerReport();
const cleanClusters = latestByCluster.filter(
(record) =>
record.workflow_conclusion === "success" &&
(record.needs_human ?? []).length === 0 &&
(record.fix_actions ?? []).every((action) => !["blocked", "failed"].includes(action.status)) &&
(record.apply_actions ?? []).every((action) => !["blocked", "failed"].includes(action.status)),
);
const workflowState =
latestByCluster.some((record) => record.workflow_conclusion === "failure")
? "Failed clusters need inspection"
: latestFailedFixRows.length > 0
? "Fix execution needs repair"
: latestBlockedRows.length > 0
? "Blocked actions need triage"
: needsHumanRows.length > 0
? "Human review needed"
: "Clean";
const mutationRows = applyRows.filter((row) =>
["executed", "blocked", "skipped"].includes(String(row.action.status ?? "")),
);
const duplicateCloses = countRows(closedRows, (row) => row.action.classification === "duplicate");
const supersededCloses = countRows(closedRows, (row) => row.action.classification === "superseded");
const fixedByCandidateCloses = countRows(
closedRows,
(row) => row.action.classification === "fixed_by_candidate",
);
const lowSignalCloses = countRows(closedRows, (row) => row.action.classification === "low_signal");
const totals = {
clusters: latestByCluster.length,
archivedClusters: archivedLatestByCluster.length,
runs: records.length,
success: latestByCluster.filter((record) => record.workflow_conclusion === "success").length,
failure: latestByCluster.filter((record) => record.workflow_conclusion === "failure").length,
cancelled: latestByCluster.filter((record) => record.workflow_conclusion === "cancelled").length,
cleanClusters: cleanClusters.length,
closed: closedRows.length,
merged: mergedRows.length,
trackedPrs: trackedPrRows.length,
openTrackedPrs: countRows(trackedPrRows, (row) => row.state === "open"),
closedUnmergedTrackedPrs: countRows(
trackedPrRows,
(row) => row.state === "closed" && !row.merged,
),
blocked: blockedRows.length,
skipped: skippedRows.length,
fixAttempts: fixRows.length,
fixExecuted: countRows(fixRows, (row) => row.action.status === "executed"),
fixFailed: countRows(fixRows, (row) => row.action.status === "failed"),
fixBlocked: countRows(fixRows, (row) => row.action.status === "blocked"),
latestFixProblemClusters: new Set(latestFailedFixRows.map((row) => row.record.cluster_id)).size,
needsHumanClusters: needsHumanRows.length,
mutationAttempts: mutationRows.length,
duplicateCloses,
supersededCloses,
fixedByCandidateCloses,
lowSignalCloses,
};
const dashboard = `## Dashboard
Last dashboard update: ${formatTimestamp(new Date().toISOString())}
${DASHBOARD_START}
State: ${workflowState}
Scope: ${totals.clusters} active latest cluster reports. ${totals.archivedClusters} policy-archived cluster(s) are excluded from health stats; run attempts are tracked as audit history only.
| Metric | Count | Rate |
| --- | ---: | ---: |
${renderMetricRow("Latest clusters reviewed", totals.clusters, "100%")}
${renderMetricRow("Policy-archived clusters", totals.archivedClusters, "audit")}
${renderMetricRow("Clean completed clusters", totals.cleanClusters, percent(totals.cleanClusters, totals.clusters))}
${renderMetricRow("Needs-human clusters", totals.needsHumanClusters, percent(totals.needsHumanClusters, totals.clusters))}
${renderMetricRow("Latest successful clusters", totals.success, percent(totals.success, totals.clusters))}
${renderMetricRow("Latest failed clusters", totals.failure, percent(totals.failure, totals.clusters))}
${renderMetricRow("Latest cancelled clusters", totals.cancelled, percent(totals.cancelled, totals.clusters))}
${renderMetricRow("Run attempts archived", totals.runs, "audit")}
${renderMetricRow("Fix action attempts", totals.fixAttempts, "audit")}
${renderMetricRow("Fix actions executed", totals.fixExecuted, percent(totals.fixExecuted, totals.fixAttempts))}
${renderMetricRow("Fix actions failed", totals.fixFailed, percent(totals.fixFailed, totals.fixAttempts))}
${renderMetricRow("Fix actions blocked", totals.fixBlocked, percent(totals.fixBlocked, totals.fixAttempts))}
${renderMetricRow("Latest clusters with fix failures", totals.latestFixProblemClusters, percent(totals.latestFixProblemClusters, totals.clusters))}
${renderMetricRow("Distinct PRs touched", totals.trackedPrs, "100%")}
${renderMetricRow("Open PRs tracked", totals.openTrackedPrs, percent(totals.openTrackedPrs, totals.trackedPrs))}
${renderMetricRow(
"Closed unmerged PRs tracked",
totals.closedUnmergedTrackedPrs,
percent(totals.closedUnmergedTrackedPrs, totals.trackedPrs),
)}
${renderMetricRow("Completed close actions", totals.closed, percent(totals.closed, totals.mutationAttempts))}
${renderMetricRow("Completed merge actions", totals.merged, percent(totals.merged, totals.mutationAttempts))}
${renderMetricRow("Duplicate closes", totals.duplicateCloses, percent(totals.duplicateCloses, totals.closed))}
${renderMetricRow("Superseded closes", totals.supersededCloses, percent(totals.supersededCloses, totals.closed))}
${renderMetricRow(
"Fixed-by-candidate closes",
totals.fixedByCandidateCloses,
percent(totals.fixedByCandidateCloses, totals.closed),
)}
${renderMetricRow("Low-signal PR closes", totals.lowSignalCloses, percent(totals.lowSignalCloses, totals.closed))}
${renderMetricRow("Blocked mutation attempts", totals.blocked, percent(totals.blocked, totals.mutationAttempts))}
${renderMetricRow("Skipped mutation attempts", totals.skipped, percent(totals.skipped, totals.mutationAttempts))}
### Clusters Needing Inspection
| Cluster | State | Source job | Reason | Report | Run |
| --- | --- | --- | --- | --- | --- |
${renderInspectionRows(inspectionRows.slice(0, 25))}
### Fix Failure Queue
| Cluster | Status | Target | Branch/PR | Reason | Run |
| --- | --- | --- | --- | --- | --- |
${renderFixFailureRows(latestFailedFixRows.slice(0, 25))}
### Top Blocked Reasons
| Reason | Latest count | Example cluster |
| --- | ---: | --- |
${renderBlockedReasonRows([...latestBlockedRows, ...latestSkippedRows])}
### Open PR Finalizer Queue
| PR | Title | Cluster | Branch | Blockers | Next action |
| --- | --- | --- | --- | --- | --- |
${renderFinalizerRows(finalizerReport)}
### Latest ProjectClownfish Closures
| Target | Type | Title | Closed | Action | Cluster | Report | Run |
| --- | --- | --- | --- | --- | --- | --- | --- |
${renderRecentClosureRows(closureRows.slice(0, 25))}
${DASHBOARD_END}`;
let updated;
const markerPattern = new RegExp(`${escapeRegExp(DASHBOARD_START)}[\\s\\S]*?${escapeRegExp(DASHBOARD_END)}`);
if (markerPattern.test(readme)) {
updated = readme.replace(/## Dashboard[\s\S]*?## How It Works/, `${dashboard}\n\n## How It Works`);
} else if (/## How It Works/.test(readme)) {
updated = readme.replace(/## How It Works/, `${dashboard}\n\n## How It Works`);
} else {
updated = `${readme.trim()}\n\n${dashboard}\n`;
}
fs.writeFileSync(readmePath, updated, "utf8");
}
function writeAggregateApplyReport() {
const records = readRunRecords();
const rows = records.flatMap((record) =>
(record.apply_actions ?? [])
.filter(isApplicatorAction)
.map((action) => ({
repo: record.repo,
run_id: record.run_id,
run_url: record.run_url,
cluster_id: record.cluster_id,
published_at: record.published_at,
...action,
})),
);
fs.writeFileSync(path.join(repoRoot(), "apply-report.json"), `${JSON.stringify(uniquePlainActionRows(rows), null, 2)}\n`, "utf8");
}
function readRunRecords() {
const dir = path.join(repoRoot(), "results", "runs");
if (!fs.existsSync(dir)) return [];
return fs
.readdirSync(dir)
.filter((name) => name.endsWith(".json"))
.map((name) => readJson(path.join(dir, name)))
.sort((left, right) => String(left.run_id ?? "").localeCompare(String(right.run_id ?? "")));
}
function readExistingRunRecord(runId) {
const filePath = path.join(repoRoot(), "results", "runs", `${runId}.json`);
if (!fs.existsSync(filePath)) return null;
return readJson(filePath);
}
function readArchivedClusters() {
const filePath = path.join(repoRoot(), "results", "archived-clusters.json");
if (!fs.existsSync(filePath)) return new Set();
const data = readJson(filePath);
const rows = Array.isArray(data) ? data : data.archived_clusters;
return new Set((Array.isArray(rows) ? rows : []).map((row) => String(row.cluster_id ?? row)).filter(Boolean));
}
function latestClusterRecords(records) {
const byCluster = new Map();
for (const record of records) {
const previous = byCluster.get(record.cluster_id);
if (!previous || String(record.published_at).localeCompare(String(previous.published_at)) > 0) {
byCluster.set(record.cluster_id, record);
}
}
return [...byCluster.values()];
}
function findResultPaths(inputPath) {
if (!fs.existsSync(inputPath)) return [];
if (fs.statSync(inputPath).isFile()) {
return path.basename(inputPath) === "result.json" ? [inputPath] : [];
}
const out = [];
for (const entry of fs.readdirSync(inputPath, { recursive: true })) {
const candidate = path.join(inputPath, String(entry));
if (path.basename(candidate) === "result.json" && fs.statSync(candidate).isFile()) {
out.push(candidate);
}
}
return preferFinalResultPaths(out);
}
function preferFinalResultPaths(paths) {
const byRunAndCluster = new Map();
for (const resultPath of paths.sort()) {
const runId = inferRunId(resultPath);
const clusterId = readResultClusterId(resultPath);
const key = runId && clusterId ? `${runId}:${clusterId}` : resultPath;
const previous = byRunAndCluster.get(key);
if (!previous || resultPathScore(resultPath) > resultPathScore(previous)) {
byRunAndCluster.set(key, resultPath);
}
}
return [...byRunAndCluster.values()].sort();
}
function resultPathScore(resultPath) {
const runDir = path.dirname(resultPath);
let score = 0;
if (fs.existsSync(path.join(runDir, "fix-execution-report.json"))) score += 8;
if (fs.existsSync(path.join(runDir, "post-flight-report.json"))) score += 4;
if (fs.existsSync(path.join(runDir, "apply-report.json"))) score += 2;
if (!resultPath.includes("projectclownfish-worker-")) score += 1;
return score;
}
function readResultClusterId(resultPath) {
try {
return String(readJson(resultPath).cluster_id ?? "");
} catch {
return "";
}
}
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function readSiblingJson(runDir, filename) {
const direct = path.join(runDir, filename);
if (fs.existsSync(direct)) return readJson(direct);
for (const entry of fs.readdirSync(runDir, { recursive: true })) {
const candidate = path.join(runDir, String(entry));
if (path.basename(candidate) === filename && fs.statSync(candidate).isFile()) {
return readJson(candidate);
}
}
return null;
}
function readRunMetadata(filePath) {
if (!filePath || typeof filePath !== "string" || !fs.existsSync(filePath)) return new Map();
const data = readJson(filePath);
const rows = Array.isArray(data) ? data : [data];
return new Map(rows.map((row) => [String(row.databaseId ?? row.run_id ?? row.id), row]));
}
function inferRunId(filePath) {
const match = String(filePath).match(/projectclownfish(?:-worker)?-(\d+)-\d+/);
return match?.[1] ?? null;
}
function summarizeActions(actions) {
return (Array.isArray(actions) ? actions : []).map((action) => ({
target: action.target ?? null,
action: action.action ?? null,
status: action.status ?? null,
classification: action.classification ?? null,
canonical: action.canonical ?? action.duplicate_of ?? null,
candidate_fix: action.candidate_fix ?? null,
reason: action.reason ?? null,
}));
}
function sanitizeApplyAction(action) {
return {
target: action.target ?? null,
action: action.action ?? null,
status: action.status ?? null,
classification: action.classification ?? null,
canonical: action.canonical ?? null,
candidate_fix: action.candidate_fix ?? null,
title: action.title ?? action.target_title ?? action.pr_title ?? null,
idempotency_key: action.idempotency_key ?? null,
source_status: action.source_status ?? null,
source_reason: action.source_reason ?? null,
reason: action.reason ?? null,
merged_at: action.merged_at ?? null,
merge_commit_sha: action.merge_commit_sha ?? null,
live_state: action.live_state ?? null,
live_updated_at: action.live_updated_at ?? null,
};
}
function sanitizeFixAction(action) {
return {
action: action.action ?? null,
status: action.status ?? null,
target: action.target ?? null,
pr: action.pr ?? action.pr_url ?? null,
branch: action.branch ?? action.head_branch ?? null,
source_action: action.source_action ?? null,
source_status: action.source_status ?? null,
repair_strategy: action.repair_strategy ?? null,
reason: action.reason ?? null,
title: action.title ?? null,
url: action.url ?? action.pr_url ?? null,
};
}
function isApplicatorAction(action) {
return APPLICATOR_ACTIONS.has(String(action?.action ?? ""));
}
function isPostFlightApplyAction(action) {
const actionName = String(action?.action ?? "");
if (!POST_FLIGHT_APPLY_ACTIONS.has(actionName)) return false;
if (actionName === "finalize_fix_pr") return Boolean(action?.pr);
return Boolean(action?.target);
}
function postFlightToApplyAction(action) {
if (String(action.action ?? "") === "post_merge_closeout") {
return {
target: action.target,
action: action.source_action ?? "post_merge_close",
status: action.status,
classification: "post_merge_closeout",
canonical: action.canonical ?? null,
candidate_fix: action.candidate_fix ?? null,
title: action.title ?? null,
reason: action.reason ?? null,
merged_at: null,
merge_commit_sha: action.merge_commit_sha ?? null,
live_state: action.live_state ?? null,
live_updated_at: null,
};
}
return {
target: action.pr,
action: "merge_canonical",
status: action.status,
classification: "fix_pr",
title: action.title ?? null,
reason: action.reason ?? null,
merged_at: action.merged_at ?? null,
merge_commit_sha: action.merge_commit_sha ?? null,
live_state: action.status === "executed" ? "merged" : null,
live_updated_at: null,
};
}
function sortNewestRecordFirst(left, right) {
return String(right.published_at ?? "").localeCompare(String(left.published_at ?? ""));
}
function countRows(rows, predicate) {
return rows.filter(predicate).length;
}
function renderRecentClosureRows(rows) {
if (rows.length === 0) return "| _None yet_ | | | | | | | |";
return rows
.map((row) =>
[
markdownTableLink(row.action.target || "target", row.url),
tableCell(row.kind),
tableCell(row.title),
tableCell(row.closed_at ? formatTimestamp(row.closed_at) : "executed"),
tableCell(row.action.action),
markdownTableLink(row.record.cluster_id, clusterReportPath(row.record)),
markdownTableLink("report", clusterReportPath(row.record)),
markdownTableLink(row.record.run_id || "run", row.record.run_url),
].join(" | "),
)
.map((row) => `| ${row} |`)
.join("\n");
}
function buildInspectionRows({ latestByCluster, latestFailedFixRows, latestBlockedRows, latestSkippedRows }) {
const byCluster = new Map();
for (const record of latestByCluster) {
if (record.workflow_conclusion === "failure") {
addInspectionRow(byCluster, record, "workflow failure", record.summary || "cluster worker failed");
}
for (const item of record.needs_human ?? []) {
addInspectionRow(byCluster, record, "needs human", inspectionReason(item) || record.summary);
}
}
for (const row of latestFailedFixRows) {
addInspectionRow(byCluster, row.record, `fix ${row.action.status}`, actionReason(row.action));
}
for (const row of [...latestBlockedRows, ...latestSkippedRows]) {
addInspectionRow(byCluster, row.record, `apply ${row.action.status}`, actionReason(row.action, row.record));
}
return [...byCluster.values()].sort((left, right) =>
String(right.record.published_at ?? "").localeCompare(String(left.record.published_at ?? "")),
);
}
function addInspectionRow(byCluster, record, state, reason) {
if (!record?.cluster_id) return;
const current = byCluster.get(record.cluster_id);
const next = { record, state, reason: compactReason(reason || record.summary || "inspection needed") };
if (!current || inspectionRank(next.state) > inspectionRank(current.state)) {
byCluster.set(record.cluster_id, next);
}
}
function inspectionRank(state) {
if (String(state).startsWith("workflow")) return 5;
if (String(state).startsWith("fix failed")) return 4;
if (String(state).startsWith("fix blocked")) return 3;
if (String(state).startsWith("apply blocked")) return 2;
return 1;
}
function renderInspectionRows(rows) {
if (rows.length === 0) return "| _None_ | | | | | |";
return rows
.map(({ record, state, reason }) =>
[
markdownTableLink(record.cluster_id, clusterReportPath(record)),
tableCell(state),
tableCell(record.source_job ?? ""),
tableCell(reason),
markdownTableLink("report", clusterReportPath(record)),
markdownTableLink(record.run_id || "run", record.run_url),
].join(" | "),
)
.map((row) => `| ${row} |`)
.join("\n");
}
function renderFixFailureRows(rows) {
if (rows.length === 0) return "| _None_ | | | | | |";
return rows
.map(({ record, action }) =>
[
markdownTableLink(record.cluster_id, clusterReportPath(record)),
tableCell(action.status),
tableCell(action.target ?? ""),
tableCell(action.pr ?? action.url ?? action.branch ?? ""),
tableCell(actionReason(action)),
markdownTableLink(record.run_id || "run", record.run_url),
].join(" | "),
)
.map((row) => `| ${row} |`)
.join("\n");
}
function renderBlockedReasonRows(rows) {
const counts = new Map();
for (const row of rows) {
const reason = compactReason(actionReason(row.action, row.record) || "unknown");
const current = counts.get(reason);
counts.set(reason, {
reason,
count: (current?.count ?? 0) + 1,
record: current?.record ?? row.record,
});
}
const ranked = [...counts.values()].sort((left, right) => right.count - left.count || left.reason.localeCompare(right.reason));
if (ranked.length === 0) return "| _None_ | 0 | |";
return ranked
.slice(0, 15)
.map((row) =>
[
tableCell(row.reason),
row.count,
markdownTableLink(row.record.cluster_id, clusterReportPath(row.record)),
].join(" | "),
)
.map((row) => `| ${row} |`)
.join("\n");
}
function renderFinalizerRows(report) {
const prs = Array.isArray(report?.prs) ? report.prs : [];
if (prs.length === 0) return "| _None_ | | | | | |";
return prs
.slice(0, 25)
.map((pr) =>
[
markdownTableLink(`#${pr.number}`, pr.url),
tableCell(pr.title),
tableCell(pr.cluster_id ?? ""),
tableCell(pr.branch ?? ""),
tableCell((pr.blockers ?? []).join(", ") || "ready"),
tableCell(pr.recommended_next_action ?? ""),
].join(" | "),
)
.map((row) => `| ${row} |`)
.join("\n");
}
function actionReason(action, record = null) {
const genericStatus = String(action?.reason ?? "").match(/^action status is (.+)$/);
if (genericStatus) {
const sourceAction = findSourceAction(record, action);
const sourceStatus = action?.source_status ?? sourceAction?.status;
const sourceReason = action?.source_reason ?? sourceAction?.reason;
if (sourceReason) return compactReason([sourceStatus, sourceReason].filter(Boolean).join(": "));
}
return compactReason(
[
action?.code,
action?.reason,
]
.filter(Boolean)
.join(": "),
);
}
function findSourceAction(record, applyAction) {
if (!record || !Array.isArray(record.actions)) return null;
return record.actions.find(
(action) =>
action.target === applyAction?.target &&
action.action === applyAction?.action &&
action.status &&
action.status !== "planned",
);
}
function inspectionReason(item) {
if (typeof item === "string") return item;
if (!item || typeof item !== "object") return "";
return item.reason ?? item.summary ?? item.title ?? item.ref ?? JSON.stringify(item);
}
function compactReason(value) {
return truncate(String(value ?? "").replace(/\s+/g, " ").trim(), 160);
}
function readFinalizerReport() {
const filePath = path.join(repoRoot(), "results", "finalize-open-prs.json");
if (!fs.existsSync(filePath)) return null;
try {
return readJson(filePath);
} catch {
return null;
}
}
function buildTrackedPrRows(records) {
const byPull = new Map();
for (const record of records) {
addTrackedPrRef(byPull, record, record.canonical_pr, { source: "canonical_pr", explicitPull: true });
addTrackedPrRef(byPull, record, record.canonical, { source: "canonical", explicitPull: isPullUrl(record.canonical) });
for (const action of record.actions ?? []) {
const title = action.title ?? action.target_title ?? action.pr_title ?? null;
addTrackedPrRef(byPull, record, action.target, {
source: "target",
explicitPull: false,
title,
});
addTrackedPrRef(byPull, record, action.canonical, {
source: "canonical",
explicitPull: isPullUrl(action.canonical),
title,
});
addTrackedPrRef(byPull, record, action.candidate_fix, {
source: "candidate_fix",
explicitPull: isPullUrl(action.candidate_fix),
title,
});
}
for (const action of record.apply_actions ?? []) {
const actionName = String(action.action ?? "");
const title = action.title ?? action.target_title ?? action.pr_title ?? null;
const projectClownfishMerged =
MERGE_APPLICATOR_ACTIONS.has(actionName) && action.status === "executed";
addTrackedPrRef(byPull, record, action.target, {
source: "apply_target",
explicitPull: false,
title,
assumedMerged: projectClownfishMerged,
projectClownfishMerged,
projectClownfishMergedAt: action.merged_at ?? null,
merged_at: projectClownfishMerged ? action.merged_at ?? null : null,
});
addTrackedPrRef(byPull, record, action.canonical, {
source: "apply_canonical",
explicitPull: isPullUrl(action.canonical),
title,
});
addTrackedPrRef(byPull, record, action.candidate_fix, {
source: "apply_candidate_fix",
explicitPull: isPullUrl(action.candidate_fix),
title,
});
}
}
return hydrateTrackedPrRows([...byPull.values()]).sort(sortNewestPrRowFirst);
}
function addTrackedPrRef(byPull, record, value, options = {}) {
const pull = parseGithubPullRef(record.repo, value);
if (!pull) return;
addTrackedPrRow(byPull, {
record,
repo: pull.repo,
number: pull.number,
title: options.title ?? null,
assumedMerged: Boolean(options.assumedMerged),
merged_at: options.merged_at ?? null,
first_seen_at: record.workflow_created_at ?? record.published_at ?? null,
projectClownfishMerged: Boolean(options.projectClownfishMerged),
projectClownfishMergedAt: options.projectClownfishMergedAt ?? null,
sources: new Set([options.source ?? "ref"]),
explicitPull: Boolean(options.explicitPull),
});
}
function addTrackedPrRow(byPull, row) {
const key = `${row.repo}#${row.number}`;
const previous = byPull.get(key);
if (!previous || preferTrackedPrRow(row, previous)) {
byPull.set(key, mergeTrackedPrRows(row, previous));
} else if (previous) {
byPull.set(key, mergeTrackedPrRows(previous, row));
}
}
function mergeTrackedPrRows(primary, secondary) {
if (!secondary) return primary;
return {
...primary,
title: primary.title ?? secondary.title ?? null,
assumedMerged: Boolean(primary.assumedMerged || secondary.assumedMerged),
merged_at: primary.merged_at ?? secondary.merged_at ?? null,
first_seen_at: earlierIso(primary.first_seen_at, secondary.first_seen_at),
projectClownfishMerged: Boolean(primary.projectClownfishMerged || secondary.projectClownfishMerged),
projectClownfishMergedAt: primary.projectClownfishMergedAt ?? secondary.projectClownfishMergedAt ?? null,
sources: new Set([...(primary.sources ?? []), ...(secondary.sources ?? [])]),
explicitPull: Boolean(primary.explicitPull || secondary.explicitPull),
};
}
function preferTrackedPrRow(candidate, current) {
if (candidate.assumedMerged && !current.assumedMerged) return true;
if (!candidate.assumedMerged && current.assumedMerged) return false;
return String(candidate.record.published_at ?? "").localeCompare(String(current.record.published_at ?? "")) > 0;
}
function hydrateTrackedPrRows(rows) {
const infoByPull = githubPullInfo(rows);
return rows
.map((row) => {
const info = infoByPull.get(`${row.repo}#${row.number}`);
if (!info && !row.explicitPull) return null;
const projectClownfishMerged = Boolean(row.projectClownfishMerged);
const merged = Boolean(row.merged_at || info?.merged);
const mergedAt = row.merged_at ?? info?.merged_at ?? null;
const state = merged ? "merged" : normalizePullState(info?.state) ?? "tracked";
return {
...row,
title: row.title ?? info?.title ?? `PR #${row.number}`,
url: info?.html_url ?? githubPullUrl(row.repo, row.number),
state,
merged,
merged_at: mergedAt,
projectClownfishMerged,
projectClownfishMergedAt: row.projectClownfishMergedAt ?? null,
};
})
.filter(Boolean);
}
function sortNewestPrRowFirst(left, right) {
return String(right.merged_at ?? right.record.published_at ?? "").localeCompare(
String(left.merged_at ?? left.record.published_at ?? ""),
);
}
function hydrateClosureRows(rows) {
const infoByIssue = githubIssueInfo(rows);
return rows.map((row) => {
const target = parseGithubIssueRef(row.record.repo, row.action.target);
const info = target ? infoByIssue.get(`${target.repo}#${target.number}`) : null;
return {
...row,
kind: info?.kind ?? "issue_or_pr",
title: info?.title ?? row.action.title ?? row.action.reason ?? String(row.action.target ?? "closed target"),
url: info?.html_url ?? (target ? githubIssueUrl(target.repo, target.number) : ""),
closed_at: info?.closed_at ?? row.action.closed_at ?? row.record.workflow_updated_at ?? row.record.published_at ?? null,
};
});
}
function sortNewestClosureRowFirst(left, right) {
return String(right.closed_at ?? right.record.published_at ?? "").localeCompare(
String(left.closed_at ?? left.record.published_at ?? ""),
);
}
function uniqueActionRows(rows) {
const byKey = new Map();
for (const row of rows) {
const record = row.record ?? row;
const action = row.action ?? row;
const key = [
record.repo,
action.target,
action.action,
].join(":");
const previous = byKey.get(key);
if (!previous || preferActionRow(row, previous)) {
byKey.set(key, row);
}
}
return [...byKey.values()];
}
function uniquePlainActionRows(rows) {
const byKey = new Map();
for (const row of rows) {
const key = [
row.repo,
row.cluster_id,
row.target,
row.action,
].join(":");
const previous = byKey.get(key);
if (!previous || preferActionRow(row, previous)) {
byKey.set(key, row);
}
}
return [...byKey.values()];
}
function uniqueFixRows(rows) {
const byKey = new Map();
for (const row of rows) {
const record = row.record ?? row;
const action = row.action ?? row;
const key = [
record.repo,
record.cluster_id,
action.action,
action.target,
action.pr,
action.branch,
action.repair_strategy,
action.source_action,
].join(":");
const previous = byKey.get(key);
if (!previous || preferActionRow(row, previous)) {
byKey.set(key, row);
}
}
return [...byKey.values()];
}
function preferActionRow(candidate, previous) {
const candidateRecord = candidate.record && typeof candidate.record === "object" ? candidate.record : candidate;
const previousRecord = previous.record && typeof previous.record === "object" ? previous.record : previous;
const candidateAction = candidate.action && typeof candidate.action === "object" ? candidate.action : candidate;
const previousAction = previous.action && typeof previous.action === "object" ? previous.action : previous;
const candidateRank = actionStatusRank(candidateAction.status);
const previousRank = actionStatusRank(previousAction.status);
if (candidateRank !== previousRank) return candidateRank > previousRank;
return String(candidateRecord.published_at ?? "").localeCompare(String(previousRecord.published_at ?? "")) > 0;
}
function actionStatusRank(status) {
switch (status) {
case "executed":
return 6;
case "merged":
return 6;
case "failed":
return 5;
case "blocked":
return 4;
case "skipped":
return 3;
case "planned":
return 2;
default:
return 1;
}
}
function githubPullInfo(rows) {
const byRepo = new Map();
for (const row of rows) {
if (!row.repo || !row.number) continue;
const key = `${row.repo}#${row.number}`;
if (PR_INFO_CACHE.has(key)) continue;
const numbers = byRepo.get(row.repo) ?? new Set();
numbers.add(String(row.number));
byRepo.set(row.repo, numbers);
}
for (const [repo, numbers] of byRepo) {
for (const batch of chunks([...numbers], 50)) {
for (const [key, info] of githubPullInfoBatch(repo, batch)) {
PR_INFO_CACHE.set(key, info);
}
for (const number of batch) {
const key = `${repo}#${number}`;
if (!PR_INFO_CACHE.has(key)) PR_INFO_CACHE.set(key, null);
}
}
}
return new Map(rows.map((row) => [`${row.repo}#${row.number}`, PR_INFO_CACHE.get(`${row.repo}#${row.number}`)]));
}
function githubIssueInfo(rows) {
const byRepo = new Map();
for (const row of rows) {
const target = parseGithubIssueRef(row.record?.repo ?? row.repo, row.action?.target ?? row.target);
if (!target) continue;
const key = `${target.repo}#${target.number}`;
if (ISSUE_INFO_CACHE.has(key)) continue;
const numbers = byRepo.get(target.repo) ?? new Set();
numbers.add(String(target.number));
byRepo.set(target.repo, numbers);
}
for (const [repo, numbers] of byRepo) {
for (const batch of chunks([...numbers], 50)) {
for (const [key, info] of githubIssueInfoBatch(repo, batch)) {
ISSUE_INFO_CACHE.set(key, info);
}
for (const number of batch) {
const key = `${repo}#${number}`;
if (!ISSUE_INFO_CACHE.has(key)) ISSUE_INFO_CACHE.set(key, null);
}
}
}
return new Map(rows.map((row) => {
const target = parseGithubIssueRef(row.record?.repo ?? row.repo, row.action?.target ?? row.target);
return target ? [`${target.repo}#${target.number}`, ISSUE_INFO_CACHE.get(`${target.repo}#${target.number}`)] : ["", null];
}));
}
function githubIssueInfoBatch(repo, numbers) {
const [owner, name] = String(repo).split("/");
if (!owner || !name || numbers.length === 0) return new Map();
const fields = numbers
.map(
(number, index) =>
`i${index}: issueOrPullRequest(number: ${Number(number)}) { __typename ... on Issue { number title state closedAt url } ... on PullRequest { number title state closedAt merged mergedAt url } }`,
)
.join("\n");
const query = `query { repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { ${fields} } }`;
const body = runGhGraphql(query);
if (!body) return new Map();
const data = parseGhJson(body, `issue info for ${repo}`);
if (!data) return new Map();
const repository = data?.data?.repository ?? {};
const out = new Map();
numbers.forEach((number, index) => {
const info = repository[`i${index}`];
if (!info) return;
out.set(`${repo}#${number}`, {
html_url: info.url ?? githubIssueUrl(repo, number),
kind: info.__typename === "PullRequest" ? "pull_request" : "issue",
closed_at: info.closedAt ?? info.mergedAt ?? null,
merged: Boolean(info.merged),
merged_at: info.mergedAt ?? null,
state: normalizePullState(info.state),
title: info.title ?? null,
});
});
return out;
}
function githubPullInfoBatch(repo, numbers) {
const [owner, name] = String(repo).split("/");
if (!owner || !name || numbers.length === 0) return new Map();
const fields = numbers
.map(
(number, index) =>
`p${index}: pullRequest(number: ${Number(number)}) { number title state merged mergedAt url }`,
)
.join("\n");
const query = `query { repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { ${fields} } }`;
const body = runGhGraphql(query);
if (!body) return new Map();
const data = parseGhJson(body, `pull info for ${repo}`);
if (!data) return new Map();
const repository = data?.data?.repository ?? {};
const out = new Map();
numbers.forEach((number, index) => {
const info = repository[`p${index}`];
if (!info) return;
out.set(`${repo}#${number}`, {
html_url: info.url ?? githubPullUrl(repo, number),
merged: Boolean(info.merged),
merged_at: info.mergedAt ?? null,
state: normalizePullState(info.state),
title: info.title ?? null,
});
});
return out;
}
function runGhGraphql(query) {
const env = { ...process.env, NO_COLOR: "1", CLICOLOR: "0" };
delete env.FORCE_COLOR;
if (!env.GH_TOKEN && env.CLOWNFISH_READ_GH_TOKEN) env.GH_TOKEN = env.CLOWNFISH_READ_GH_TOKEN;
if (!env.GH_TOKEN && env.GITHUB_TOKEN) env.GH_TOKEN = env.GITHUB_TOKEN;
try {
const text = execFileSync("gh", ["api", "graphql", "-f", `query=${query}`], {
encoding: "utf8",
env,
maxBuffer: 8 * 1024 * 1024,
stdio: ["ignore", "pipe", "ignore"],
});
return stripAnsi(text);
} catch (error) {
return stripAnsi(error.stdout || error.output?.[1]?.toString() || "");
}
}
function parseGhJson(body, context) {
const text = String(body ?? "").trim();
if (!text) return null;
if (!text.startsWith("{") && !text.startsWith("[")) {
console.warn(`warning: ignoring non-json GitHub response for ${context}`);
return null;
}
try {
return JSON.parse(text);
} catch (error) {
console.warn(`warning: could not parse GitHub response for ${context}: ${error.message}`);
return null;
}
}
function stripAnsi(text) {
return String(text ?? "").replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, "");
}
function parseGithubPullRef(defaultRepo, value) {
const text = String(value ?? "").trim();
if (!text) return null;
let match = text.match(/^#?(\d+)$/);
if (match && defaultRepo) return { repo: defaultRepo, number: match[1] };
match = text.match(/^([^/\s]+\/[^#\s]+)#(\d+)$/);
if (match) return { repo: match[1], number: match[2] };
match = text.match(/github\.com\/([^/\s]+)\/([^/\s]+)\/pull\/(\d+)/);
if (match) return { repo: `${match[1]}/${match[2]}`, number: match[3] };
return null;
}
function parseGithubIssueRef(defaultRepo, value) {
const text = String(value ?? "").trim();
if (!text) return null;
let match = text.match(/^#?(\d+)$/);
if (match && defaultRepo) return { repo: defaultRepo, number: match[1] };
match = text.match(/^([^/\s]+\/[^#\s]+)#(\d+)$/);
if (match) return { repo: match[1], number: match[2] };
match = text.match(/github\.com\/([^/\s]+)\/([^/\s]+)\/(?:issues|pull)\/(\d+)/);
if (match) return { repo: `${match[1]}/${match[2]}`, number: match[3] };
return null;
}
function isPullUrl(value) {
return /github\.com\/[^/\s]+\/[^/\s]+\/pull\/\d+/.test(String(value ?? ""));
}
function normalizePullState(state) {
if (!state) return null;
return String(state).toLowerCase();
}
function githubPullUrl(repo, ref) {
const number = String(ref ?? "").replace(/^#/, "");
if (!/^\d+$/.test(number) || !repo) return "";
return `https://github.com/${repo}/pull/${number}`;
}
function githubIssueUrl(repo, ref) {
const number = String(ref ?? "").replace(/^#/, "");
if (!/^\d+$/.test(number) || !repo) return "";
return `https://github.com/${repo}/issues/${number}`;
}
function earlierIso(left, right) {
if (!left) return right ?? null;
if (!right) return left ?? null;
return String(left).localeCompare(String(right)) <= 0 ? left : right;
}
function renderMetricRow(metric, count, rate) {
return `| ${tableCell(metric)} | ${count} | ${tableCell(rate)} |`;
}
function percent(count, total) {
if (!total) return "0.0%";
return `${((Number(count) / Number(total)) * 100).toFixed(1)}%`;
}
function chunks(values, size) {
const out = [];
for (let index = 0; index < values.length; index += size) {
out.push(values.slice(index, index + size));
}
return out;
}
function clusterReportPath(record) {
const owner = String(record.repo ?? "").split("/")[0] || "openclaw";
return `results/${owner}/${slug(record.cluster_id)}.md`;
}
function markdownTableLink(label, url) {
const safeLabel = tableCell(label || "unknown");
return url ? `[${safeLabel}](${url})` : safeLabel;
}
function tableCell(value) {
return truncate(String(value ?? "").replaceAll("|", "\\|").replace(/\s+/g, " ").trim(), 140);
}
function truncate(value, maxLength) {
const text = String(value ?? "");
if (text.length <= maxLength) return text;
return `${text.slice(0, maxLength - 3)}...`;
}
function countBy(values, keyFn) {
const out = {};
for (const value of Array.isArray(values) ? values : []) {
const key = keyFn(value);
out[key] = (out[key] ?? 0) + 1;
}
return out;
}
function sum(values, selector) {
return values.reduce((total, value) => total + Number(selector(value) ?? 0), 0);
}
function quote(value) {
if (value === null || value === undefined || value === "") return "null";
return JSON.stringify(String(value));
}
function slug(value) {
return String(value)
.toLowerCase()
.replace(/[^a-z0-9_.-]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, 120) || "unknown";
}
function markdownLink(label, url) {
return `[${String(label).replaceAll("|", "\\|")}](${url})`;
}
function formatTimestamp(iso) {
const date = new Date(iso);
if (Number.isNaN(date.getTime())) return "unknown";
return new Intl.DateTimeFormat("en", {
month: "short",
day: "numeric",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: "UTC",
timeZoneName: "short",
}).format(date);
}
function escapeRegExp(value) {
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}