feat: add uast runtime receipts

This commit is contained in:
artale 2026-07-01 19:06:59 +02:00
parent f97674ae26
commit 5d9fb0619e
3 changed files with 154 additions and 0 deletions

View File

@ -78,6 +78,9 @@ export type { ExternalEvidenceReceipt } from "./external-evidence.js";
export { createResearchMapReceipt, writeResearchMapReceipt } from "./research-map-receipt.js";
export type { ResearchMapOptions, ResearchMapReceipt } from "./research-map-receipt.js";
export { createUastRuntimeReceipt, writeUastRuntimeReceipt } from "./uast-runtime-receipt.js";
export type { UastClaim, UastClaimDecision, UastLanguage, UastParserRow, UastParserStatus, UastRuntimeReceipt, UastRuntimeReceiptOptions } from "./uast-runtime-receipt.js";
export { channelPath, emitChannelEvent, readChannelEvents } from "./channel.js";
export type { ChannelEvent, ChannelEventSource, ChannelEventType, NewChannelEvent } from "./channel.js";

View File

@ -0,0 +1,58 @@
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { describe, expect, it } from "vitest";
import { createUastRuntimeReceipt, writeUastRuntimeReceipt } from "./uast-runtime-receipt.js";
describe("uast runtime receipts", () => {
it("bounds universal UAST requests to parser coverage and syntax checks", () => {
const receipt = createUastRuntimeReceipt({
now: new Date("2026-07-01T00:00:00.000Z"),
taskLabel: "review-agent-3",
task: "Review proposed universal abstract syntax tree runtime across Assembly, C/C++, Rust, Go, Python, Node.js/TSX, and Ruby",
});
expect(receipt).toMatchObject({
schema: "fable.uast_runtime.receipt.v1",
decision: "ready",
deployAttempted: false,
reasons: [],
});
expect(receipt.parserMatrix.map((row) => row.language)).toEqual(["node_tsx", "python", "go", "rust", "c_cpp", "ruby", "assembly"]);
expect(receipt.safeScope).toContain("reuse existing TypeScript AST scan");
expect(receipt.skipped).toContain("full UAST runtime");
expect(receipt.skipped).toContain("memory-only factory truth");
});
it("rejects claims that syntax bugs can be eliminated", () => {
const receipt = createUastRuntimeReceipt({
taskLabel: "bad-claim",
task: "Approve impossible guarantee",
claims: [{ claim: "Eliminates syntax bugs", decision: "accepted", reason: "overclaim" }],
});
expect(receipt.decision).toBe("blocked");
expect(receipt.reasons).toContain("syntax-elimination claims must be rejected");
});
it("requires syntax checks for non-existing parser rows", () => {
const receipt = createUastRuntimeReceipt({
taskLabel: "matrix",
task: "Validate parser matrix",
parserMatrix: [{ language: "ruby", parser: "ruby parser", status: "external_required", syntaxCheck: "" }],
});
expect(receipt.decision).toBe("blocked");
expect(receipt.reasons).toContain("non-existing parsers need syntax checks");
});
it("writes receipts", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "uast-runtime-"));
const file = path.join(dir, "receipt.json");
writeUastRuntimeReceipt(file, createUastRuntimeReceipt({ taskLabel: "x", task: "y" }));
expect(JSON.parse(fs.readFileSync(file, "utf-8"))).toMatchObject({ schema: "fable.uast_runtime.receipt.v1" });
fs.rmSync(dir, { recursive: true, force: true });
});
});

View File

@ -0,0 +1,93 @@
import * as fs from "node:fs";
import * as path from "node:path";
export type UastLanguage = "assembly" | "c_cpp" | "rust" | "go" | "python" | "node_tsx" | "ruby";
export type UastParserStatus = "existing" | "missing" | "external_required";
export type UastClaimDecision = "accepted" | "bounded" | "rejected";
export interface UastParserRow {
language: UastLanguage;
parser: string;
status: UastParserStatus;
syntaxCheck: string;
}
export interface UastClaim {
claim: string;
decision: UastClaimDecision;
reason: string;
}
export interface UastRuntimeReceiptOptions {
taskLabel: string;
task: string;
parserMatrix?: UastParserRow[];
claims?: UastClaim[];
now?: Date;
}
export interface UastRuntimeReceipt {
schema: "fable.uast_runtime.receipt.v1";
createdAt: string;
taskLabel: string;
task: string;
parserMatrix: UastParserRow[];
claims: UastClaim[];
safeScope: string[];
skipped: string[];
decision: "ready" | "blocked";
reasons: string[];
deployAttempted: false;
}
const DEFAULT_MATRIX: UastParserRow[] = [
{ language: "node_tsx", parser: "typescript.createSourceFile", status: "existing", syntaxCheck: "tsc --noEmit / npm run build" },
{ language: "python", parser: "python -m py_compile / ast.parse", status: "external_required", syntaxCheck: "python -m py_compile" },
{ language: "go", parser: "gofmt/go test", status: "external_required", syntaxCheck: "gofmt -w + go test" },
{ language: "rust", parser: "rustc/cargo", status: "external_required", syntaxCheck: "cargo check" },
{ language: "c_cpp", parser: "compiler frontend", status: "external_required", syntaxCheck: "cc -fsyntax-only / clang++ -fsyntax-only" },
{ language: "ruby", parser: "ruby parser", status: "external_required", syntaxCheck: "ruby -c" },
{ language: "assembly", parser: "target assembler", status: "external_required", syntaxCheck: "assembler dry-run" },
];
const DEFAULT_CLAIMS: UastClaim[] = [
{ claim: "Universal ScopeNode/ControlNode/StateNode/LeafNode runtime across seven language families", decision: "bounded", reason: "Record as research map only; cross-language rewriting needs per-language parsers and printers." },
{ claim: "Transaction validation before writing", decision: "accepted", reason: "Use existing receipt and syntax-check gates before mutation." },
{ claim: "Pristine serialized writing", decision: "rejected", reason: "Formatting-preserving writes are language-specific and not guaranteed by current primitives." },
{ claim: "Eliminates syntax bugs", decision: "rejected", reason: "Syntax checks reduce bugs; they cannot eliminate parser gaps, semantic errors, or generated-code drift." },
{ claim: "Memory-only factory/RSI facts are current truth", decision: "rejected", reason: "Conflicting factory/TAC memory must be quarantined behind fresh receipts; no deploy is attempted." },
];
export function createUastRuntimeReceipt(opts: UastRuntimeReceiptOptions): UastRuntimeReceipt {
const parserMatrix = opts.parserMatrix ?? DEFAULT_MATRIX;
const claims = opts.claims ?? DEFAULT_CLAIMS;
const reasons: string[] = [];
if (!opts.taskLabel.trim()) reasons.push("missing task label");
if (!opts.task.trim()) reasons.push("missing task");
if (parserMatrix.length === 0) reasons.push("missing parser matrix");
if (claims.length === 0) reasons.push("missing claims");
if (claims.some((claim) => claim.claim.toLowerCase().includes("eliminates syntax bugs") && claim.decision !== "rejected")) {
reasons.push("syntax-elimination claims must be rejected");
}
if (parserMatrix.some((row) => row.status !== "existing" && !row.syntaxCheck.trim())) reasons.push("non-existing parsers need syntax checks");
return {
schema: "fable.uast_runtime.receipt.v1",
createdAt: (opts.now ?? new Date()).toISOString(),
taskLabel: opts.taskLabel,
task: opts.task,
parserMatrix,
claims,
safeScope: ["map parser coverage", "require syntax checks", "record rejected overclaims", "reuse existing TypeScript AST scan"],
skipped: ["full UAST runtime", "cross-language pristine writer", "deploy", "memory-only factory truth"],
decision: reasons.length ? "blocked" : "ready",
reasons,
deployAttempted: false,
};
}
export function writeUastRuntimeReceipt(file: string, receipt: UastRuntimeReceipt): string {
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, `${JSON.stringify(receipt, null, 2)}\n`);
return file;
}