feat: add uast runtime receipts
This commit is contained in:
parent
f97674ae26
commit
5d9fb0619e
|
|
@ -78,6 +78,9 @@ export type { ExternalEvidenceReceipt } from "./external-evidence.js";
|
||||||
export { createResearchMapReceipt, writeResearchMapReceipt } from "./research-map-receipt.js";
|
export { createResearchMapReceipt, writeResearchMapReceipt } from "./research-map-receipt.js";
|
||||||
export type { ResearchMapOptions, ResearchMapReceipt } 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 { channelPath, emitChannelEvent, readChannelEvents } from "./channel.js";
|
||||||
export type { ChannelEvent, ChannelEventSource, ChannelEventType, NewChannelEvent } from "./channel.js";
|
export type { ChannelEvent, ChannelEventSource, ChannelEventType, NewChannelEvent } from "./channel.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue