Initial curated projectbrain source from 8a7b1e0651dbdab97d744cbd2e653ab3970ac6c5
This commit is contained in:
commit
5aa3e8d685
700 files changed
+132801
No files matched your search
@@ -0,0 +1,155 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const proofDir = process.env.PROJECTBRAIN_PROOF_ARCHIVE_DIR ?? "checkpoints/release-proof";
|
||||
const signoffDir = process.env.PROJECTBRAIN_SIGNOFF_ARCHIVE_DIR ?? "checkpoints/release-signoff";
|
||||
const keepArg = process.argv.find((arg) => arg.startsWith("--keep="));
|
||||
const keep = Number.parseInt(keepArg?.slice("--keep=".length) ?? process.env.PROJECTBRAIN_EVIDENCE_KEEP ?? "20", 10);
|
||||
const shouldPrune = process.argv.includes("--prune");
|
||||
const confirmed = process.argv.includes("--yes") || process.env.PROJECTBRAIN_EVIDENCE_PRUNE_CONFIRM === "1";
|
||||
|
||||
const run = (command, args) => spawnSync(command, args, {
|
||||
encoding: "utf8",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
|
||||
const getGitCommit = () => {
|
||||
const result = run("git", ["rev-parse", "--short", "HEAD"]);
|
||||
return result.status === 0 ? result.stdout.trim() : "unknown";
|
||||
};
|
||||
|
||||
const parseField = (text, label) => {
|
||||
const match = text.match(new RegExp(`^${label}:\\s*(.+)$`, "m"));
|
||||
return match?.[1]?.trim() ?? "unknown";
|
||||
};
|
||||
|
||||
const displayPath = (filePath) => filePath.split(path.sep).join("/");
|
||||
|
||||
const safeKeep = Number.isFinite(keep) && keep > 0 ? keep : 20;
|
||||
|
||||
const listMarkdownFiles = (archiveDir, type) => {
|
||||
if (!fs.existsSync(archiveDir)) return [];
|
||||
|
||||
return fs.readdirSync(archiveDir)
|
||||
.filter((fileName) => fileName.endsWith(".md"))
|
||||
.map((fileName) => path.join(archiveDir, fileName))
|
||||
.filter((filePath) => fs.statSync(filePath).isFile())
|
||||
.map((filePath) => {
|
||||
const text = fs.readFileSync(filePath, "utf8");
|
||||
const stat = fs.statSync(filePath);
|
||||
const generated = parseField(text, "Generated");
|
||||
|
||||
return {
|
||||
type,
|
||||
filePath,
|
||||
displayPath: displayPath(filePath),
|
||||
fileName: path.basename(filePath),
|
||||
generated,
|
||||
modifiedAt: stat.mtime.toISOString(),
|
||||
commit: parseField(text, "Commit"),
|
||||
verdict: parseField(text, "Verdict"),
|
||||
freshness: parseField(text, "Freshness"),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const sortNewestFirst = (items) => items.sort((a, b) => {
|
||||
const generatedDelta = Date.parse(b.generated) - Date.parse(a.generated);
|
||||
if (Number.isFinite(generatedDelta) && generatedDelta !== 0) return generatedDelta;
|
||||
|
||||
const modifiedDelta = Date.parse(b.modifiedAt) - Date.parse(a.modifiedAt);
|
||||
if (Number.isFinite(modifiedDelta) && modifiedDelta !== 0) return modifiedDelta;
|
||||
|
||||
return b.fileName.localeCompare(a.fileName);
|
||||
});
|
||||
|
||||
const createArchive = (archiveDir, type) => {
|
||||
const items = sortNewestFirst(listMarkdownFiles(archiveDir, type));
|
||||
const keepers = items.slice(0, safeKeep);
|
||||
const candidates = items.slice(safeKeep);
|
||||
|
||||
return {
|
||||
type,
|
||||
archiveDir,
|
||||
items,
|
||||
keepers,
|
||||
candidates,
|
||||
};
|
||||
};
|
||||
|
||||
const deleteCandidate = (candidate, archiveDir) => {
|
||||
const resolvedArchiveDir = path.resolve(archiveDir);
|
||||
const resolvedFile = path.resolve(candidate.filePath);
|
||||
|
||||
if (!resolvedFile.startsWith(`${resolvedArchiveDir}${path.sep}`)) {
|
||||
throw new Error(`Refusing to delete outside archive: ${candidate.displayPath}`);
|
||||
}
|
||||
|
||||
if (!candidate.fileName.endsWith(".md")) {
|
||||
throw new Error(`Refusing to delete non-markdown artifact: ${candidate.displayPath}`);
|
||||
}
|
||||
|
||||
fs.unlinkSync(candidate.filePath);
|
||||
};
|
||||
|
||||
const currentCommit = getGitCommit();
|
||||
const archives = [
|
||||
createArchive(proofDir, "proof"),
|
||||
createArchive(signoffDir, "signoff"),
|
||||
];
|
||||
const candidates = archives.flatMap((archive) => archive.candidates.map((candidate) => ({
|
||||
...candidate,
|
||||
archiveDir: archive.archiveDir,
|
||||
})));
|
||||
|
||||
const lines = [
|
||||
"# ProjectBrain Release Evidence Retention",
|
||||
"",
|
||||
`Current commit: ${currentCommit}`,
|
||||
`Mode: ${shouldPrune ? confirmed ? "prune" : "dry-run prune" : "list"}`,
|
||||
`Keep newest per archive: ${safeKeep}`,
|
||||
"",
|
||||
"| Archive | Type | Snapshots | Kept | Prune candidates |",
|
||||
"| --- | --- | --- | --- | --- |",
|
||||
];
|
||||
|
||||
for (const archive of archives) {
|
||||
lines.push(`| ${archive.archiveDir} | ${archive.type} | ${archive.items.length} | ${archive.keepers.length} | ${archive.candidates.length} |`);
|
||||
}
|
||||
|
||||
lines.push("");
|
||||
|
||||
if (!candidates.length) {
|
||||
lines.push("No release evidence cleanup candidates found.");
|
||||
} else {
|
||||
lines.push("## Cleanup Candidates");
|
||||
lines.push("");
|
||||
lines.push("| Generated | Type | Commit | Verdict/Freshness | File |");
|
||||
lines.push("| --- | --- | --- | --- | --- |");
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const state = candidate.type === "proof" ? candidate.verdict : candidate.freshness;
|
||||
lines.push(`| ${candidate.generated} | ${candidate.type} | ${candidate.commit} | ${state} | ${candidate.displayPath} |`);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldPrune && !confirmed) {
|
||||
lines.push("");
|
||||
lines.push("Dry-run only. To delete cleanup candidates, rerun with:");
|
||||
lines.push("");
|
||||
lines.push("```bash");
|
||||
lines.push("pnpm run release:evidence-prune -- --yes");
|
||||
lines.push("```");
|
||||
}
|
||||
|
||||
console.log(lines.join("\n"));
|
||||
|
||||
if (shouldPrune && confirmed) {
|
||||
for (const candidate of candidates) {
|
||||
deleteCandidate(candidate, candidate.archiveDir);
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log(`Deleted ${candidates.length} release evidence artifact${candidates.length === 1 ? "" : "s"}.`);
|
||||
}
|
||||
Reference in new issue
Block a user