Files
harness-tools/__archived/extensions/workflow/store.ts
T

931 lines
29 KiB
TypeScript

import { createHash, randomUUID } from "node:crypto";
import {
link,
lstat,
mkdir,
open,
readdir,
readFile,
realpath,
rename,
rm,
stat,
} from "node:fs/promises";
import * as path from "node:path";
import {
DEFAULT_WORKFLOW_CONFIG,
type PlanArtifact,
type WorkflowReportArtifact,
type WorkflowRun,
} from "./domain.ts";
import { deriveRunLabel } from "./run-label.ts";
const SNAPSHOT_VERSION = 1;
const MAX_JSON_BYTES = 4 * 1024 * 1024;
const MAX_DOCUMENT_BYTES = 1024 * 1024;
const MAX_PROTOTYPE_ARTIFACT_BYTES = 8 * 1024 * 1024;
async function readVerifiedDocument(
artifact: { path: string; digest: string },
label: string,
maxBytes = MAX_DOCUMENT_BYTES,
) {
const details = await stat(artifact.path);
if (!details.isFile() || details.size > maxBytes) {
throw new Error(`${label} artifact exceeds the verified document limit`);
}
const contents = await readFile(artifact.path, "utf8");
const digest = createHash("sha256").update(contents).digest("hex");
if (digest !== artifact.digest) {
throw new Error(`${label} artifact digest mismatch: ${artifact.path}`);
}
return contents;
}
export function readVerifiedPlanArtifact(artifact: PlanArtifact) {
return readVerifiedDocument(artifact, "Plan");
}
export function readVerifiedReportArtifact(artifact: WorkflowReportArtifact) {
return readVerifiedDocument(artifact, "Report");
}
export function readVerifiedTranscriptArtifact(artifact: {
path: string;
digest: string;
}) {
return readVerifiedDocument(artifact, "Transcript", MAX_JSON_BYTES);
}
interface StoredSnapshot {
schemaVersion: 0 | typeof SNAPSHOT_VERSION;
run: WorkflowRun;
}
export interface AssignmentLeaseRecord {
token: string;
processId: number;
heartbeatAt: number;
}
export interface StartRecord {
key: string;
fingerprint: string;
runId: string;
status: "pending" | "completed";
result?: unknown;
}
export interface WorkflowStoreOptions {
beforeRename?: (target: string) => void | Promise<void>;
afterRunLoadMiss?: (runId: string) => void | Promise<void>;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
function json(value: unknown, label: string) {
const contents = `${JSON.stringify(value, null, 2)}\n`;
if (Buffer.byteLength(contents) > MAX_JSON_BYTES) {
throw new Error(`${label} exceeds ${MAX_JSON_BYTES} bytes`);
}
return contents;
}
async function syncDirectory(directory: string) {
let handle;
try {
handle = await open(directory, "r");
await handle.sync();
} catch {
// Some filesystems do not support directory fsync.
} finally {
await handle?.close();
}
}
export class WorkflowStore {
readonly root: string;
private readonly options: WorkflowStoreOptions;
constructor(root: string, options: WorkflowStoreOptions = {}) {
this.root = root;
this.options = options;
}
async initialize() {
await mkdir(this.root, { recursive: true, mode: 0o700 });
await mkdir(this.runsRoot(), { recursive: true, mode: 0o700 });
await mkdir(this.startsRoot(), { recursive: true, mode: 0o700 });
}
async createRun(run: WorkflowRun) {
await this.initialize();
const directory = this.runDirectory(run.runId);
try {
return { run: await this.loadRun(run.runId), created: false as const };
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
await this.options.afterRunLoadMiss?.(run.runId);
const existing = await stat(directory).catch(() => undefined);
if (existing) {
try {
return { run: await this.loadRun(run.runId), created: false as const };
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
throw new Error(
`Workflow Run ${run.runId} has an incomplete published directory; inspect and remove it before retrying`,
);
}
const staging = path.join(
this.runsRoot(),
`.${run.runId}.${process.pid}.${randomUUID()}.creating`,
);
try {
await mkdir(staging, { mode: 0o700 });
await this.writeInitialRun(staging, run);
await rename(staging, directory);
await syncDirectory(this.runsRoot());
return { run, created: true as const };
} catch (error) {
await rm(staging, { recursive: true, force: true });
if (
(error as NodeJS.ErrnoException).code === "EEXIST" ||
(error as NodeJS.ErrnoException).code === "ENOTEMPTY"
) {
return {
run: await this.loadRun(run.runId),
created: false as const,
};
}
throw error;
}
}
async saveRun(run: WorkflowRun, expectedRevision?: number) {
const current = await this.loadRun(run.runId);
const expected = expectedRevision ?? current.revision;
if (current.revision !== expected || run.revision !== expected + 1) {
throw new Error(
`Stale workflow revision ${expected}; current revision is ${current.revision}`,
);
}
const snapshot: StoredSnapshot = { schemaVersion: SNAPSHOT_VERSION, run };
const contents = json(snapshot, `workflow ${run.runId}`);
try {
await this.atomicCreate(
this.revisionPath(run.runId, run.revision),
contents,
);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "EEXIST") {
const latest = await this.loadRun(run.runId);
throw new Error(
`Stale workflow revision ${expected}; current revision is ${latest.revision}`,
);
}
throw error;
}
await this.atomicWrite(
path.join(this.runDirectory(run.runId), "workflow.json"),
contents,
);
}
async createAssignmentLease(
runId: string,
assignmentId: string,
lease: AssignmentLeaseRecord,
) {
const existing = await this.loadAssignmentLease(runId, assignmentId);
if (existing && existing.token !== lease.token) {
throw new Error(`Assignment ${assignmentId} already has an active lease`);
}
await this.atomicWrite(
this.assignmentLeasePath(runId, assignmentId),
json(lease, `assignment lease ${assignmentId}`),
);
return lease;
}
async heartbeatAssignmentLease(
runId: string,
assignmentId: string,
token: string,
heartbeatAt: number,
) {
const existing = await this.loadAssignmentLease(runId, assignmentId);
if (!existing || existing.token !== token) return false;
await this.atomicWrite(
this.assignmentLeasePath(runId, assignmentId),
json({ ...existing, heartbeatAt }, `assignment lease ${assignmentId}`),
);
return true;
}
async loadAssignmentLease(
runId: string,
assignmentId: string,
): Promise<AssignmentLeaseRecord | undefined> {
try {
const parsed = await readJson(
this.assignmentLeasePath(runId, assignmentId),
);
if (
!isRecord(parsed) ||
typeof parsed.token !== "string" ||
typeof parsed.processId !== "number" ||
typeof parsed.heartbeatAt !== "number"
) {
throw new Error(`Assignment ${assignmentId} has an invalid lease`);
}
return {
token: parsed.token,
processId: parsed.processId,
heartbeatAt: parsed.heartbeatAt,
};
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
throw error;
}
}
async releaseAssignmentLease(
runId: string,
assignmentId: string,
token: string,
) {
const existing = await this.loadAssignmentLease(runId, assignmentId);
if (!existing || existing.token !== token) return false;
await rm(this.assignmentLeasePath(runId, assignmentId), { force: true });
return true;
}
async loadRun(runId: string): Promise<WorkflowRun> {
const revisions = path.join(this.runDirectory(runId), "revisions");
const entries = await readdir(revisions);
const latest = entries
.map((entry) => /^(\d+)\.json$/.exec(entry))
.filter((match): match is RegExpExecArray => match !== null)
.map((match) => Number(match[1]))
.sort((left, right) => right - left)[0];
if (latest === undefined) {
throw new Error(`${revisions}: no workflow revisions`);
}
const file = this.revisionPath(runId, latest);
const parsed = await readJson(file);
if (
!isRecord(parsed) ||
(parsed.schemaVersion !== 0 &&
parsed.schemaVersion !== SNAPSHOT_VERSION) ||
!isRecord(parsed.run) ||
parsed.run.runId !== runId
) {
throw new Error(`${file}: unsupported or invalid workflow snapshot`);
}
// SAFETY: saveRun is the sole writer; the wrapper version and run ID were validated above.
const run = parsed.run as unknown as WorkflowRun;
run.background ??= false;
run.assignments ??= [];
run.deliveries ??= [];
run.prototypeCandidates ??= [];
run.commandReceipts ??= [];
run.mutatorProfileNames ??= [];
run.prototypeCleanupCompleted ??= false;
run.uiImpactEvidence ??= [];
run.affectedUiSurfaces ??= [];
run.reviewCycles ??= 0;
run.verificationCycles ??= 0;
run.effectiveConfig.standardAgents ??= structuredClone(
DEFAULT_WORKFLOW_CONFIG.standardAgents,
);
for (const assignment of run.assignments) {
if (assignment.gitBefore) assignment.gitBefore.pathStatuses ??= {};
if (assignment.gitAfter) assignment.gitAfter.pathStatuses ??= {};
}
for (const delivery of run.deliveries) {
try {
const receipt = await readJson(
this.deliveryReceiptPath(run.runId, delivery.key),
);
if (isRecord(receipt) && typeof receipt.sentAt === "number") {
delivery.state = "sent";
delivery.sentAt = receipt.sentAt;
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
return run;
}
async listRuns() {
await this.initialize();
const entries = await readdir(this.runsRoot(), { withFileTypes: true });
const runs: WorkflowRun[] = [];
for (const entry of entries.sort((left, right) =>
left.name === right.name ? 0 : left.name < right.name ? -1 : 1,
)) {
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
const snapshot = path.join(this.runsRoot(), entry.name, "workflow.json");
try {
await stat(snapshot);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") continue;
throw error;
}
runs.push(await this.loadRun(entry.name));
}
return runs;
}
async saveReport(run: WorkflowRun) {
const lines = [
`# workflow ${deriveRunLabel(run)}`,
"",
`- Run ID: ${run.runId}`,
`- Status: ${run.status}`,
`- Revision: ${run.revision}`,
`- Mode: ${run.mode}`,
`- Request: ${reportText(run.request, 8_000)}`,
`- Worktree: ${run.workspace.root ?? "not required"}`,
`- Branch: ${run.workspace.branch ?? "not required"}`,
`- Plan: ${run.planArtifact?.path ?? "none"}`,
"",
"## Gates",
...boundedReportEntries(
run.gates,
(gate) =>
`- ${gate.kind}: ${gate.status} (${gate.id}, revision ${gate.revision})`,
),
"",
"## Decisions",
...boundedReportEntries(
run.decisions,
(decision) =>
`- ${decision.gateId} revision ${decision.revision}: ${reportText(decision.value)}`,
),
"",
"## Assignments",
...boundedReportEntries(
run.assignments,
(assignment) =>
`- ${assignment.role}/${assignment.profileName}: ${assignment.status} (${assignment.id})`,
1_024,
),
"",
"## Prototype Evidence",
...boundedReportEntries(
run.prototypeCandidates,
(candidate) =>
`- ${candidate.id}: ${reportText(candidate.route, 500)} | ${candidate.artifactPath}`,
),
"",
"## Verification",
...(run.verificationEvidence
? boundedReportEntries(
run.verificationEvidence.commands,
(command) =>
`- ${command.kind}: ${command.status} | ${reportText(`${command.executable} ${command.args.join(" ")}`, 2_000)}`,
1_024,
)
: ["- none"]),
"",
"## Review",
"```json",
reportText(run.reviewVerdict ?? null, 64 * 1024),
"```",
...(run.error
? [
"",
"## Error",
`${run.error.code}: ${reportText(run.error.message, 8_000)}`,
]
: []),
];
const contents = boundedReportDocument(lines.join("\n"));
const digest = createHash("sha256").update(contents).digest("hex");
const reportPath = path.join(
this.runDirectory(run.runId),
"artifacts",
`report-${run.revision}-${digest}.md`,
);
await this.atomicWrite(reportPath, contents);
return { path: reportPath, digest, revision: run.revision };
}
async ensureResult(run: WorkflowRun) {
try {
await stat(path.join(this.runDirectory(run.runId), "result.json"));
return;
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
await this.publishResult(run);
}
async publishResult(run: WorkflowRun) {
await this.atomicWrite(
path.join(this.runDirectory(run.runId), "result.json"),
json(
{
runId: run.runId,
revision: run.reportArtifact?.revision ?? run.revision,
snapshotRevision: run.revision,
status: run.status,
reportPath: run.reportArtifact?.path,
planPath: run.planArtifact?.path,
worktreePath: run.workspace.root,
reviewVerdict: run.reviewVerdict,
error: run.error,
},
"workflow result",
),
);
}
async savePlan(runId: string, revision: number, contents: string) {
const bounded = boundedDocument(contents, "plan");
const digest = createHash("sha256").update(bounded).digest("hex");
const directory = this.runDirectory(runId);
const file = path.join(directory, "plan.md");
const versionedFile = path.join(
directory,
"artifacts",
`plan-${revision}-${digest}.md`,
);
await this.atomicWrite(versionedFile, bounded);
await this.atomicWrite(file, bounded);
const artifact: PlanArtifact = {
path: versionedFile,
revision,
digest,
};
return artifact;
}
async savePrototypeArtifact(
runId: string,
candidateId: string,
evidence: unknown,
sourceRoot: string,
artifactFiles: string[],
) {
if (!/^[a-zA-Z0-9_-]+$/.test(candidateId)) {
throw new Error("invalid prototype candidate ID");
}
const root = await realpath(sourceRoot);
const artifactRoot = path.join(
this.runDirectory(runId),
"artifacts",
"prototypes",
candidateId,
);
let totalBytes = 0;
const retainedFiles: string[] = [];
for (const relativePath of [...new Set(artifactFiles)]) {
if (!relativePath || path.isAbsolute(relativePath)) {
throw new Error("prototype artifact path must be relative");
}
const target = await realpath(path.resolve(root, relativePath));
if (target !== root && !target.startsWith(`${root}${path.sep}`)) {
throw new Error("prototype artifact path escapes source root");
}
const details = await lstat(target);
if (details.isSymbolicLink() || !details.isFile()) {
throw new Error("prototype artifacts must be regular files");
}
const contents = await readFile(target);
totalBytes += contents.byteLength;
if (totalBytes > MAX_PROTOTYPE_ARTIFACT_BYTES) {
throw new Error("prototype artifacts exceed the 8 MiB retained limit");
}
const digest = createHash("sha256").update(contents).digest("hex");
const destination = path.join(
artifactRoot,
`${digest}-${path.basename(relativePath)}`,
);
await this.atomicWrite(destination, contents);
retainedFiles.push(destination);
}
const file = path.join(artifactRoot, "candidate.json");
const contents = json(
{ candidate: evidence, retainedFiles },
`prototype candidate ${candidateId}`,
);
await this.atomicWrite(file, contents);
return { path: file, retainedFiles };
}
async saveAssignmentTranscript(
runId: string,
assignmentId: string,
transcript: unknown[],
) {
if (!/^[a-zA-Z0-9_-]+$/.test(assignmentId)) {
throw new Error("invalid assignment ID");
}
const contents = json(transcript, `assignment transcript ${assignmentId}`);
const file = path.join(
this.runDirectory(runId),
"artifacts",
"transcripts",
`${assignmentId}.json`,
);
await this.atomicWrite(file, contents);
return {
path: file,
digest: createHash("sha256").update(contents).digest("hex"),
};
}
async claimDelivery(
runId: string,
key: string,
token: string,
claimedAt: number,
) {
const claimPath = this.deliveryClaimPath(runId, key);
await mkdir(path.dirname(claimPath), { recursive: true, mode: 0o700 });
for (let attempt = 0; attempt < 3; attempt++) {
let handle;
try {
handle = await open(claimPath, "wx", 0o600);
await handle.writeFile(
`${JSON.stringify({ key, token, claimedAt })}\n`,
"utf8",
);
await handle.sync();
await handle.close();
await syncDirectory(path.dirname(claimPath));
return true;
} catch (error) {
await handle?.close();
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
}
const existing = await readJson(claimPath).catch(() => undefined);
if (
!isRecord(existing) ||
typeof existing.claimedAt !== "number" ||
claimedAt - existing.claimedAt < 30_000
) {
return false;
}
const stalePath = `${claimPath}.${randomUUID()}.stale`;
try {
await rename(claimPath, stalePath);
await rm(stalePath, { force: true });
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
return false;
}
async clearDeliveryClaim(runId: string, key: string) {
await rm(this.deliveryClaimPath(runId, key), { force: true });
}
async releaseDeliveryClaim(runId: string, key: string, token: string) {
const claimPath = this.deliveryClaimPath(runId, key);
const existing = await readJson(claimPath).catch(() => undefined);
if (!isRecord(existing) || existing.token !== token) return;
const releasedPath = `${claimPath}.${randomUUID()}.released`;
try {
await rename(claimPath, releasedPath);
await rm(releasedPath, { force: true });
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
async markDeliverySent(runId: string, key: string, sentAt: number) {
const run = await this.loadRun(runId);
const delivery = run.deliveries.find((candidate) => candidate.key === key);
if (!delivery || delivery.state === "sent") return run;
await this.atomicWrite(
this.deliveryReceiptPath(runId, key),
`${JSON.stringify({ key, sentAt })}\n`,
);
delivery.state = "sent";
delivery.sentAt = sentAt;
return run;
}
async getStart(key: string) {
const directory = this.startDirectory(key);
try {
await stat(path.join(directory, "record.json"));
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
throw error;
}
return this.readStartRecord(directory);
}
async reserveStart(key: string, fingerprint: string, runId: string) {
await this.initialize();
const directory = this.startDirectory(key);
await mkdir(directory, { recursive: true, mode: 0o700 });
let created = false;
let record: StartRecord;
try {
record = await this.readStartRecord(directory);
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
const candidate: StartRecord = {
key,
fingerprint,
runId,
status: "pending",
};
try {
await this.atomicCreate(
path.join(directory, "record.json"),
json(candidate, "start record"),
);
record = candidate;
created = true;
} catch (createError) {
if ((createError as NodeJS.ErrnoException).code !== "EEXIST") {
throw createError;
}
record = await this.readStartRecord(directory);
}
}
if (record.key !== key || record.fingerprint !== fingerprint) {
throw new Error(
"idempotency key was already used with another start command",
);
}
return { created, claimed: true as const, record };
}
async completeStart(key: string, result: unknown) {
const directory = this.startDirectory(key);
const record = await this.readStartRecord(directory);
if (
!isRecord(result) ||
result.runId !== record.runId ||
!Number.isInteger(result.revision) ||
(result.revision as number) < 0
) {
throw new Error("start result does not match its Workflow Run revision");
}
const target = path.join(
directory,
"results",
`${result.revision as number}.json`,
);
try {
await this.atomicCreate(target, json(result, "start result"));
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
}
return this.readStartRecord(directory);
}
async findRunByBranch(branch: string) {
const runs = await this.listRuns();
return runs.find((run) => run.workspace.branch === branch);
}
private async writeInitialRun(directory: string, run: WorkflowRun) {
await mkdir(path.join(directory, "profiles"), { mode: 0o700 });
await mkdir(path.join(directory, "handoffs"), { mode: 0o700 });
await mkdir(path.join(directory, "artifacts"), { mode: 0o700 });
await mkdir(path.join(directory, "assignment-leases"), { mode: 0o700 });
await mkdir(path.join(directory, "revisions"), { mode: 0o700 });
const snapshot: StoredSnapshot = { schemaVersion: SNAPSHOT_VERSION, run };
const contents = json(snapshot, `workflow ${run.runId}`);
await this.atomicWrite(
path.join(directory, "revisions", "0.json"),
contents,
);
await this.atomicWrite(path.join(directory, "workflow.json"), contents);
await this.atomicWrite(
path.join(directory, "request.md"),
boundedDocument(run.request, "request"),
);
await this.atomicWrite(
path.join(directory, "config.json"),
json(run.effectiveConfig, "effective configuration"),
);
for (const profile of run.pinnedProfiles) {
await this.atomicWrite(
path.join(directory, "profiles", `${profile.name}.json`),
json(profile, `profile ${profile.name}`),
);
}
}
private runsRoot() {
return path.join(this.root, "runs");
}
private startsRoot() {
return path.join(this.root, "starts");
}
private runDirectory(runId: string) {
if (!/^[a-zA-Z0-9_-]+$/.test(runId)) throw new Error("invalid run ID");
return path.join(this.runsRoot(), runId);
}
private deliveryClaimPath(runId: string, key: string) {
const digest = createHash("sha256").update(key).digest("hex");
return path.join(
this.runDirectory(runId),
"delivery-claims",
`${digest}.json`,
);
}
private deliveryReceiptPath(runId: string, key: string) {
const digest = createHash("sha256").update(key).digest("hex");
return path.join(
this.runDirectory(runId),
"delivery-receipts",
`${digest}.json`,
);
}
private revisionPath(runId: string, revision: number) {
if (!Number.isInteger(revision) || revision < 0) {
throw new Error("invalid workflow revision");
}
return path.join(this.runDirectory(runId), "revisions", `${revision}.json`);
}
private assignmentLeasePath(runId: string, assignmentId: string) {
if (!/^[a-zA-Z0-9_-]+$/.test(assignmentId)) {
throw new Error("invalid assignment ID");
}
return path.join(
this.runDirectory(runId),
"assignment-leases",
`${assignmentId}.json`,
);
}
private startDigest(key: string) {
return createHash("sha256").update(key).digest("hex");
}
private startDirectory(key: string) {
return path.join(this.startsRoot(), this.startDigest(key));
}
private async readStartRecord(directory: string) {
const file = path.join(directory, "record.json");
let parsed: unknown;
try {
parsed = await readJson(file);
} catch (error) {
throw error;
}
if (
!isRecord(parsed) ||
typeof parsed.key !== "string" ||
typeof parsed.fingerprint !== "string" ||
typeof parsed.runId !== "string" ||
(parsed.status !== "pending" && parsed.status !== "completed")
) {
throw new Error(`${file}: invalid start record`);
}
// SAFETY: all persisted StartRecord identity and discriminator fields were validated above.
const intent = parsed as unknown as StartRecord;
const resultsDirectory = path.join(directory, "results");
let resultEntries: string[] = [];
try {
resultEntries = await readdir(resultsDirectory);
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
const latest = resultEntries
.map((entry) => /^(\d+)\.json$/.exec(entry))
.filter((match): match is RegExpExecArray => match !== null)
.map((match) => Number(match[1]))
.sort((left, right) => right - left)[0];
if (latest === undefined) return { ...intent, status: "pending" as const };
const result = await readJson(
path.join(resultsDirectory, `${latest}.json`),
);
if (
!isRecord(result) ||
result.runId !== intent.runId ||
result.revision !== latest
) {
throw new Error(`${resultsDirectory}: invalid start result`);
}
return { ...intent, status: "completed" as const, result };
}
private async atomicCreate(target: string, contents: string) {
await mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
const temporary = path.join(
path.dirname(target),
`.${path.basename(target)}.${process.pid}.${randomUUID()}.tmp`,
);
let handle;
try {
handle = await open(temporary, "wx", 0o600);
await handle.writeFile(contents, "utf8");
await handle.sync();
await handle.close();
handle = undefined;
await this.options.beforeRename?.(target);
await link(temporary, target);
await rm(temporary, { force: true });
await syncDirectory(path.dirname(target));
} catch (error) {
await handle?.close();
await rm(temporary, { force: true });
throw error;
}
}
private async atomicWrite(target: string, contents: string | Uint8Array) {
await mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
const temporary = path.join(
path.dirname(target),
`.${path.basename(target)}.${process.pid}.${randomUUID()}.tmp`,
);
let handle;
try {
handle = await open(temporary, "wx", 0o600);
if (typeof contents === "string") await handle.writeFile(contents, "utf8");
else await handle.writeFile(contents);
await handle.sync();
await handle.close();
handle = undefined;
await this.options.beforeRename?.(target);
await rename(temporary, target);
await syncDirectory(path.dirname(target));
} catch (error) {
await handle?.close();
await rm(temporary, { force: true });
throw error;
}
}
}
function reportText(value: unknown, maxCharacters = 2_000) {
const text = typeof value === "string" ? value : JSON.stringify(value);
const characters = [...text];
return characters.length <= maxCharacters
? text
: `${characters.slice(0, maxCharacters).join("")}\n[truncated]`;
}
function boundedReportEntries<T>(
entries: T[],
render: (entry: T) => string,
limit = 128,
) {
const included = entries.slice(-limit).map(render);
if (entries.length > limit) {
included.unshift(`- [${entries.length - limit} earlier entries omitted]`);
}
return included;
}
function boundedReportDocument(contents: string) {
const normalized = contents.endsWith("\n") ? contents : `${contents}\n`;
if (Buffer.byteLength(normalized, "utf8") <= MAX_DOCUMENT_BYTES) return normalized;
const marker = "\n[report truncated to 1 MiB]\n";
const limit = MAX_DOCUMENT_BYTES - Buffer.byteLength(marker, "utf8");
let bytes = 0;
const kept: string[] = [];
for (const character of normalized) {
const width = Buffer.byteLength(character, "utf8");
if (bytes + width > limit) break;
kept.push(character);
bytes += width;
}
return `${kept.join("")}${marker}`;
}
function boundedDocument(contents: string, label: string) {
if (Buffer.byteLength(contents) > MAX_DOCUMENT_BYTES) {
throw new Error(`${label} exceeds ${MAX_DOCUMENT_BYTES} bytes`);
}
return contents.endsWith("\n") ? contents : `${contents}\n`;
}
async function readJson(file: string) {
const info = await stat(file);
if (info.size > MAX_JSON_BYTES)
throw new Error(`${file}: JSON file is too large`);
const contents = await readFile(file, "utf8");
try {
return JSON.parse(contents) as unknown;
} catch (error) {
throw new Error(`${file}: invalid JSON`, { cause: error });
}
}