mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 16:26:36 +00:00
* refactor(domain): consolidate canonical ordering and digest helpers (#624) * refactor(domain): consolidate canonical ordering and digest helpers Single owner for code-point ordering (domain/canonicalOrdering.ts) and canonical JSON digests (domain/comparisonSemantics.ts). Delete all local compareCodePoints/compareText/digestCanonical duplicates and migrate every importer. No re-export shims. * fix(ci): allow slower real browser startup * chore(config): remove dead eslint, dedupe scripts, cacheable turbo tasks Delete eslint.config.js (oxlint is the linter), drop lint:dead alias, pin smol-toml, fold jscpd/scan:todos into check:pr, make test:run cacheable, align oxlint ignores. * fix(config): hash all test inputs for cached runs * docs: fix architecture diagram and pretty-print tool catalog Drop dangling REPLAY edges, add dotnet/reference/error/evaluation nodes. Emit 2-space JSON from the catalog generator and regenerate. * test: extract shared fixtures, drop knip carve-outs Dedupe android/apple session tests, bundler adapter headers, and reconstruction helpers into tests/support fixtures. Delete unused type aliases and the knip ignoreIssues block. Lower jscpd threshold 2.7 to 2.5. * refactor(app): split Setup and ProcessOwnership modules Extract SetupTypes/SetupHost from Setup.ts and move observation helpers into ProcessOwnershipObservation/ProcessTree. Migrate all importers including CLI commands. No re-export shims. * refactor(runtime): centralize safe JSON parsing and preserve error causes Add domain/safeJson.safeParseJson and migrate all raw JSON.parse call sites. Name catch causes and preserve failure reasons instead of swallowing; annotate genuine best-effort cleanup. * fix(runtime): retain JSON parse error causes
82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import {
|
|
isHopperStartupFailureCode,
|
|
type HopperStartupDiagnostic,
|
|
} from "../domain/hopperStartupFailure.js";
|
|
import { safeParseJson } from "../domain/safeJson.js";
|
|
|
|
export const LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX = "REA_X11_DIAGNOSTIC=";
|
|
|
|
const diagnosticContextSchema = z.object({
|
|
component: z.literal("hopper_private_display"),
|
|
operation: z.enum(["probe", "launch"]),
|
|
reason: z.string().regex(/^[a-z0-9_]+$/u),
|
|
socket_directory: z.literal("/tmp/.X11-unix"),
|
|
socket_directory_mode: z
|
|
.string()
|
|
.regex(/^[0-7]{4}$/u)
|
|
.nullable(),
|
|
mount_read_only: z.boolean().nullable(),
|
|
effective_socket_directory_mode: z
|
|
.string()
|
|
.regex(/^[0-7]{4}$/u)
|
|
.nullable(),
|
|
effective_mount_read_only: z.boolean().nullable(),
|
|
wsl: z.boolean(),
|
|
strategy: z.enum(["direct", "user-mount-namespace", "unavailable"]),
|
|
fallback_reason: z
|
|
.string()
|
|
.regex(/^[a-z0-9_]+$/u)
|
|
.nullable(),
|
|
xvfb_stderr_bytes: z.number().int().nonnegative().safe(),
|
|
});
|
|
|
|
const failureCodeSchema = z.string().transform((value, context) => {
|
|
if (isHopperStartupFailureCode(value)) return value;
|
|
context.addIssue({
|
|
code: "custom",
|
|
message: "Unknown startup failure code",
|
|
});
|
|
return z.NEVER;
|
|
});
|
|
|
|
const diagnosticSchema = z.discriminatedUnion("status", [
|
|
diagnosticContextSchema
|
|
.extend({ status: z.literal("ready"), failure_code: z.null() })
|
|
.strict(),
|
|
diagnosticContextSchema
|
|
.extend({ status: z.literal("error"), failure_code: failureCodeSchema })
|
|
.strict(),
|
|
]);
|
|
|
|
export type LinuxPrivateDisplayDiagnosticParse =
|
|
| { readonly ok: true; readonly value: HopperStartupDiagnostic }
|
|
| {
|
|
readonly ok: false;
|
|
readonly reason:
|
|
| "diagnostic_missing"
|
|
| "diagnostic_multiple"
|
|
| "diagnostic_malformed";
|
|
};
|
|
|
|
/** Parse exactly one helper diagnostic from stderr. */
|
|
export const parseLinuxPrivateDisplayDiagnostic = (
|
|
stderr: string,
|
|
): LinuxPrivateDisplayDiagnosticParse => {
|
|
const records = stderr
|
|
.split("\n")
|
|
.filter((line) => line.startsWith(LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX));
|
|
if (records.length === 0) return { ok: false, reason: "diagnostic_missing" };
|
|
if (records.length !== 1) return { ok: false, reason: "diagnostic_multiple" };
|
|
const record = records[0];
|
|
if (record === undefined) return { ok: false, reason: "diagnostic_missing" };
|
|
const decoded = safeParseJson(
|
|
record.slice(LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX.length),
|
|
);
|
|
if (!decoded.ok) return { ok: false, reason: "diagnostic_malformed" };
|
|
const parsed = diagnosticSchema.safeParse(decoded.value);
|
|
if (!parsed.success) return { ok: false, reason: "diagnostic_malformed" };
|
|
return { ok: true, value: parsed.data };
|
|
};
|