feat(scanner): complete localized artifact quality checkpoint
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
existsSync,
|
||||
readFileSync,
|
||||
readdirSync,
|
||||
realpathSync,
|
||||
statSync,
|
||||
} from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const COMPLETE_RUN_FILES = [
|
||||
"manifest.json",
|
||||
"status.json",
|
||||
"capture-jobs.jsonl",
|
||||
"scan-results.json",
|
||||
"processing-report.json",
|
||||
] as const;
|
||||
|
||||
export interface NativeScannerRunDirectoryOptions {
|
||||
outputRoot: string;
|
||||
requestedRunDir?: string;
|
||||
activeRunDir?: string;
|
||||
}
|
||||
|
||||
export function resolveNativeScannerRunDirectory({
|
||||
outputRoot,
|
||||
requestedRunDir,
|
||||
activeRunDir,
|
||||
}: NativeScannerRunDirectoryOptions) {
|
||||
const root = path.resolve(outputRoot);
|
||||
const requested = requestedRunDir?.trim();
|
||||
if (requested) return resolveContainedDirectory(root, requested);
|
||||
|
||||
const active = activeRunDir?.trim();
|
||||
if (active) return resolveContainedDirectory(root, active);
|
||||
|
||||
return newestCompleteNativeScannerRun(root);
|
||||
}
|
||||
|
||||
export function newestCompleteNativeScannerRun(outputRoot: string) {
|
||||
const root = path.resolve(outputRoot);
|
||||
if (!isDirectory(root)) return "";
|
||||
|
||||
try {
|
||||
const candidates = readdirSync(root, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map((entry) => completeRunCandidate(root, path.join(root, entry.name)))
|
||||
.filter((entry): entry is CompleteRunCandidate => Boolean(entry))
|
||||
.sort((left, right) => right.createdAt - left.createdAt || right.name.localeCompare(left.name));
|
||||
return candidates[0]?.runDir ?? "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
interface CompleteRunCandidate {
|
||||
runDir: string;
|
||||
name: string;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
function completeRunCandidate(root: string, candidate: string): CompleteRunCandidate | null {
|
||||
const runDir = resolveContainedDirectory(root, candidate);
|
||||
if (!runDir || COMPLETE_RUN_FILES.some((file) => !existsSync(path.join(runDir, file)))) return null;
|
||||
|
||||
try {
|
||||
const statusPayload = JSON.parse(readFileSync(path.join(runDir, "status.json"), "utf8"));
|
||||
const status = statusPayload?.scanner ?? statusPayload;
|
||||
const target = Number(status?.target ?? 0);
|
||||
const captured = Number(status?.captured ?? 0);
|
||||
if (status?.running !== false || status?.status !== "done" || target < 1 || captured < target) return null;
|
||||
|
||||
const results = JSON.parse(readFileSync(path.join(runDir, "scan-results.json"), "utf8"));
|
||||
if (!Array.isArray(results) || results.length < captured) return null;
|
||||
|
||||
const manifest = JSON.parse(readFileSync(path.join(runDir, "manifest.json"), "utf8"));
|
||||
const manifestCreatedAt = Date.parse(String(manifest?.createdAt ?? ""));
|
||||
return {
|
||||
runDir,
|
||||
name: path.basename(runDir),
|
||||
createdAt: Number.isFinite(manifestCreatedAt) ? manifestCreatedAt : statSync(runDir).mtimeMs,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveContainedDirectory(root: string, candidate: string) {
|
||||
try {
|
||||
const resolvedRoot = realpathSync(root);
|
||||
const resolvedCandidate = realpathSync(path.resolve(candidate));
|
||||
if (!isPathInside(resolvedRoot, resolvedCandidate) || !isDirectory(resolvedCandidate)) return "";
|
||||
return resolvedCandidate;
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function isDirectory(candidate: string) {
|
||||
try {
|
||||
return statSync(candidate).isDirectory();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isPathInside(root: string, candidate: string) {
|
||||
const relative = path.relative(root, candidate);
|
||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
||||
}
|
||||
Reference in New Issue
Block a user