mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 01:13:39 +00:00
Require delivered facts, exact cancellation and malformed-input boundaries, and independent metadata expectations. Transfer unique assertions into stronger keepers before removing duplicate cases and overwritten fixture writes; preserve all consumed core fixture bytes. Validation: 1,190 focused tests passed with 39 platform-dependent skips; 134 composition and conformance tests passed. Typecheck, lint, formatting, discovery and Knip passed. Independent preservation reviews and targeted regression controls passed.
254 lines
11 KiB
TypeScript
254 lines
11 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import { access, chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { createTestTempDirectory } from "./temporaryDirectory.js";
|
|
|
|
/**
|
|
* A stand-in for REA inside a build computer: `capture-desktop-application`
|
|
* reads its requests from stdin and acknowledges each as REA's capture does,
|
|
* then publishes a prepared capture folder on stop. It prints the failure in
|
|
* the file `FAKE_REA_CAPTURE_FAILURE` names instead of launching, and the one
|
|
* in `FAKE_REA_MARK_FAILURE` at its first checkpoint, exiting 1 either way;
|
|
* `FAKE_REA_APP_EXITS` names the folder it publishes at once, as when the
|
|
* app exits before its window opens. `describe-...` and
|
|
* `export-...` print outputs the real CLI wrote for that folder, and the
|
|
* export copies the bundle it wrote. A capture given exactly the
|
|
* `--state-path` `FAKE_REA_STATE_PATH` publishes `FAKE_REA_SELECTED_CAPTURE`
|
|
* instead, and the draft and export of its folder print the outputs the real
|
|
* CLI wrote for that capture. With `FAKE_REA_UNLISTED_CHANGES` set, it
|
|
* acknowledges checkpoints without their changed files, as a REA before
|
|
* them did. Each call notes its arguments, its working folder and which
|
|
* AGENTENV_ variables and APT_CONFIG it saw.
|
|
*/
|
|
const FAKE_REA = String.raw`
|
|
import json
|
|
import os
|
|
import shutil
|
|
import sys
|
|
|
|
NOTES = os.environ["FAKE_REA_NOTES"]
|
|
|
|
|
|
def note(name, value):
|
|
with open(os.path.join(NOTES, name), "a") as handle:
|
|
handle.write(json.dumps(value) + "\n")
|
|
|
|
|
|
def progress(message, event=None):
|
|
line = {"rea_progress": {"phase": "desktop_capture", "message": message}}
|
|
if event is not None:
|
|
line["rea_progress"]["event"] = event
|
|
sys.stderr.write(json.dumps(line) + "\n")
|
|
sys.stderr.flush()
|
|
|
|
|
|
def option(args, name):
|
|
return args[args.index(name) + 1] if name in args else None
|
|
|
|
|
|
def options(args, name):
|
|
return [args[index + 1] for index, value in enumerate(args[:-1]) if value == name]
|
|
|
|
|
|
SELECTED = ".fake-selected"
|
|
|
|
|
|
def output(capture, name):
|
|
"""The real CLI's output for the capture folder REA names: of the selected capture, or the prepared one."""
|
|
selected = os.path.exists(os.path.join(capture, SELECTED))
|
|
return os.environ[f"FAKE_REA_SELECTED_{name}" if selected else f"FAKE_REA_{name}"]
|
|
|
|
|
|
command, args = sys.argv[1], sys.argv[2:]
|
|
note("calls.jsonl", {"argv": sys.argv[1:], "cwd": os.getcwd(), "apt_config": os.environ.get("APT_CONFIG"),
|
|
"agentenv": sorted(name for name in os.environ if name.startswith("AGENTENV_"))})
|
|
if command == "capture-desktop-application":
|
|
failure = os.environ.get("FAKE_REA_CAPTURE_FAILURE")
|
|
if failure is not None:
|
|
with open(failure) as handle:
|
|
sys.stdout.write(handle.read())
|
|
sys.exit(1)
|
|
progress("Recorded checkpoint baseline.", {"kind": "checkpoint", "name": "baseline", "trigger": "baseline",
|
|
"at_ms": 0, "entries": 4, "changes": 0, "retained_files": 1,
|
|
"retained_bytes": 17, "changed_files": [], "more_changed_files": 0})
|
|
exited = os.environ.get("FAKE_REA_APP_EXITS")
|
|
if exited is not None:
|
|
# The app exits before its window opens, so the capture ends on its own and publishes what it saw.
|
|
progress("Launching notes.")
|
|
progress("Recorded checkpoint exit.", {"kind": "checkpoint", "name": "exit", "trigger": "exit", "at_ms": 1080,
|
|
"entries": 4, "changes": 0, "retained_files": 0, "retained_bytes": 0,
|
|
"changed_files": [], "more_changed_files": 0})
|
|
out = option(args, "--output")
|
|
shutil.copytree(exited, out)
|
|
with open(os.path.join(out, "capture.json")) as handle:
|
|
sys.stdout.write(handle.read())
|
|
sys.exit(0)
|
|
progress("The application window is open.", {"kind": "window_open"})
|
|
taken = set()
|
|
for line in sys.stdin:
|
|
text = line.strip()
|
|
if text == "stop":
|
|
break
|
|
name = text[len("checkpoint "):].strip()
|
|
failure = os.environ.get("FAKE_REA_MARK_FAILURE")
|
|
if failure is not None:
|
|
with open(failure) as handle:
|
|
sys.stdout.write(handle.read())
|
|
sys.exit(1)
|
|
if name in taken:
|
|
progress("refused", {"kind": "checkpoint_refused", "name": name,
|
|
"reason": f"A checkpoint named {name} was already recorded."})
|
|
continue
|
|
taken.add(name)
|
|
event = {"kind": "checkpoint", "name": name, "trigger": "request", "at_ms": 1000 * len(taken),
|
|
"entries": 5, "changes": 1, "retained_files": 1, "retained_bytes": 5}
|
|
if os.environ.get("FAKE_REA_UNLISTED_CHANGES") is None:
|
|
event.update({"changed_files": ["Documents/today.txt"], "more_changed_files": 0})
|
|
progress(f"Recorded checkpoint {name}.", event)
|
|
note("stopped.jsonl", {"pid": os.getpid()})
|
|
out = option(args, "--output")
|
|
named = os.environ.get("FAKE_REA_STATE_PATH")
|
|
selected = named is not None and options(args, "--state-path") == [named]
|
|
shutil.copytree(os.environ["FAKE_REA_SELECTED_CAPTURE" if selected else "FAKE_REA_CAPTURE"], out)
|
|
if selected:
|
|
open(os.path.join(out, SELECTED), "w").close()
|
|
with open(os.path.join(out, "capture.json")) as handle:
|
|
sys.stdout.write(handle.read())
|
|
elif command == "describe-desktop-application-task":
|
|
with open(output(args[0], "DRAFT")) as handle:
|
|
sys.stdout.write(handle.read())
|
|
elif command == "export-desktop-application":
|
|
if "--schema" in args:
|
|
if os.environ.get("FAKE_REA_SCHEMA_TOKEN"):
|
|
if os.environ["FAKE_REA_SCHEMA_TOKEN"] == "invalid":
|
|
print("fake-control-token-0123456789abcdef")
|
|
sys.exit(0)
|
|
print("runtime output fake-control-token-0123456789abcdef", file=sys.stderr)
|
|
sys.exit(23)
|
|
if os.environ.get("FAKE_REA_SCHEMA_FAILURE"):
|
|
print("runtime cannot load its export command", file=sys.stderr)
|
|
sys.exit(23)
|
|
with open(os.environ["FAKE_REA_SCHEMA"]) as handle:
|
|
schema = json.load(handle)
|
|
if os.environ.get("FAKE_REA_OLD_EXPORT"):
|
|
schema["options"]["properties"].pop("syntheticSeed", None)
|
|
for name in os.environ.get("FAKE_REA_EXPORT_WITHOUT", "").split(","):
|
|
schema["options"]["properties"].pop(name, None)
|
|
print(json.dumps(schema))
|
|
sys.exit(0)
|
|
for path in options(args, "--task"):
|
|
with open(path) as handle:
|
|
note("tasks.jsonl", json.load(handle))
|
|
with open(output(args[0], "EXPORT")) as handle:
|
|
printed = handle.read()
|
|
if "code" not in json.loads(printed):
|
|
shutil.copytree(output(args[0], "BUNDLE"), args[1])
|
|
copy = option(args, "--withheld-copy") if "--withheld-copy" in args else None
|
|
if copy is not None and os.path.isdir(os.environ.get("FAKE_REA_WITHHELD", "")):
|
|
shutil.copytree(os.environ["FAKE_REA_WITHHELD"], copy)
|
|
sys.stdout.write(printed)
|
|
sys.exit(0 if "code" not in json.loads(printed) else 1)
|
|
else:
|
|
sys.exit(f"unexpected command {command}")
|
|
`;
|
|
|
|
/** apt-get update as an ordinary user under APT_CONFIG: one Packages list in the folder it names, before failing when FAKE_APT_PARTIAL is set. */
|
|
const FAKE_APT_GET = String.raw`
|
|
import os
|
|
import re
|
|
import sys
|
|
import json
|
|
|
|
with open(os.path.join(os.environ["FAKE_REA_NOTES"], "apt.jsonl"), "a") as handle:
|
|
handle.write(json.dumps({"argv": sys.argv[1:]}) + "\n")
|
|
with open(os.environ["APT_CONFIG"]) as handle:
|
|
conf = handle.read()
|
|
lists = re.search(r'Dir::State::Lists "([^"]+)"', conf).group(1)
|
|
code = int(os.environ.get("FAKE_APT_EXIT", "0"))
|
|
if os.environ.get("FAKE_APT_EMPTY") and 'APT::Update::Error-Mode "any"' in conf and not os.environ.get("FAKE_APT_IGNORE_ERROR_MODE"):
|
|
print("Err:1 http://archive.ubuntu.com/ubuntu noble InRelease")
|
|
print("E: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/noble/InRelease Temporary failure resolving 'archive.ubuntu.com'")
|
|
sys.exit(100)
|
|
if os.environ.get("FAKE_APT_EMPTY"):
|
|
sys.exit(0)
|
|
if code != 0 and os.environ.get("FAKE_APT_PARTIAL"):
|
|
open(os.path.join(lists, "archive.ubuntu.com_ubuntu_dists_noble_main_binary-amd64_Packages.lz4"), "w").close()
|
|
if code != 0:
|
|
print("Err:1 http://archive.ubuntu.com/ubuntu noble InRelease")
|
|
print("E: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/noble/InRelease Temporary failure resolving 'archive.ubuntu.com'")
|
|
sys.exit(code)
|
|
open(os.path.join(lists, "archive.ubuntu.com_ubuntu_dists_noble_universe_binary-amd64_Packages.lz4"), "w").close()
|
|
open(os.path.join(lists, "archive.ubuntu.com_ubuntu_dists_noble_InRelease"), "w").close()
|
|
print("Reading package lists... Done")
|
|
sys.exit(0)
|
|
`;
|
|
|
|
/** Prepared outputs of the real CLI for the fake REA to print. */
|
|
export interface FakeReaOutputs {
|
|
readonly capture: string;
|
|
readonly draft: string;
|
|
readonly export: string;
|
|
readonly bundle: string;
|
|
readonly schema: string;
|
|
/** Where the real export copied the files it withheld from the seed. */
|
|
readonly withheld?: string;
|
|
}
|
|
|
|
export interface FakeBuildComputerRea {
|
|
readonly home: string;
|
|
readonly bin: string;
|
|
readonly env: Readonly<Record<string, string>>;
|
|
notes(name: string): Promise<unknown[]>;
|
|
}
|
|
|
|
/** A computer home and REA stand-in whose capture, draft and export answer with `outputs`. */
|
|
export const fakeBuildComputerRea = async (
|
|
outputs: FakeReaOutputs,
|
|
): Promise<FakeBuildComputerRea> => {
|
|
const root = await createTestTempDirectory("fake-build-rea-");
|
|
const home = join(root, "home");
|
|
const bin = join(root, "bin");
|
|
const notes = join(root, "notes");
|
|
await Promise.all([home, bin, notes].map((path) => mkdir(path)));
|
|
const python = execFileSync(
|
|
"python3",
|
|
["-c", "import sys; print(sys.executable)"],
|
|
{ encoding: "utf8" },
|
|
).trim();
|
|
for (const [name, source] of [
|
|
["rea", FAKE_REA],
|
|
["apt-get", FAKE_APT_GET],
|
|
] as const) {
|
|
await writeFile(join(bin, name), `#!${python}\n${source}`);
|
|
await chmod(join(bin, name), 0o755);
|
|
}
|
|
return {
|
|
home,
|
|
bin,
|
|
env: {
|
|
FAKE_REA_NOTES: notes,
|
|
FAKE_REA_CAPTURE: outputs.capture,
|
|
FAKE_REA_DRAFT: outputs.draft,
|
|
FAKE_REA_EXPORT: outputs.export,
|
|
FAKE_REA_BUNDLE: outputs.bundle,
|
|
FAKE_REA_SCHEMA: outputs.schema,
|
|
...(outputs.withheld === undefined
|
|
? {}
|
|
: { FAKE_REA_WITHHELD: outputs.withheld }),
|
|
},
|
|
notes: async (name) => {
|
|
const path = join(notes, name);
|
|
try {
|
|
await access(path);
|
|
} catch {
|
|
return [];
|
|
}
|
|
return (await readFile(path, "utf8"))
|
|
.trim()
|
|
.split("\n")
|
|
.map((line) => JSON.parse(line) as unknown);
|
|
},
|
|
};
|
|
};
|