diff --git a/deno.lock b/deno.lock index 7772922e..6c41800e 100644 --- a/deno.lock +++ b/deno.lock @@ -41,6 +41,7 @@ "npm:@agentclientprotocol/sdk@1.3.0": "1.3.0_zod@4.4.3", "npm:@babel/core@^7.28.0": "7.29.7", "npm:@babel/preset-react@^7.27.1": "7.29.7_@babel+core@7.29.7", + "npm:@bomb.sh/tty@0.9.0": "0.9.0", "npm:@durable-streams/client@~0.2.2": "0.2.6", "npm:@durable-streams/server@~0.3.8": "0.3.8", "npm:@effectionx/context-api@0.6.0": "0.6.0_effection@4.1.0", @@ -467,6 +468,9 @@ "@babel/helper-validator-identifier" ] }, + "@bomb.sh/tty@0.9.0": { + "integrity": "sha512-1fX9lgwdc+kGRQeVEYwv7cJb5i855ysvB/TMCC3/wnnjMiKLZjWew6LLnsAMq4pLzkweivYw+zwYNZRUVhjoBA==" + }, "@clack/core@1.4.3": { "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", "dependencies": [ @@ -3996,6 +4000,7 @@ ], "packageJson": { "dependencies": [ + "npm:@bomb.sh/tty@0.9.0", "npm:@durable-streams/client@~0.2.2", "npm:@durable-streams/server@~0.3.8", "npm:@effectionx/context-api@0.6.0", diff --git a/package.json b/package.json index d17b1b1f..453df398 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "mdast-util-to-string": "^4" }, "devDependencies": { + "@bomb.sh/tty": "0.9.0", "@durable-streams/server": "^0.3.8", "@executablemd/acp": "workspace:*", "@executablemd/cli": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ea97ff7..c39c69a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,9 @@ importers: specifier: ^4.3.6 version: 4.3.6 devDependencies: + '@bomb.sh/tty': + specifier: 0.9.0 + version: 0.9.0 '@durable-streams/server': specifier: ^0.3.8 version: 0.3.8 @@ -502,6 +505,10 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@bomb.sh/tty@0.9.0': + resolution: {integrity: sha512-1fX9lgwdc+kGRQeVEYwv7cJb5i855ysvB/TMCC3/wnnjMiKLZjWew6LLnsAMq4pLzkweivYw+zwYNZRUVhjoBA==} + engines: {node: '>= 22'} + '@clack/core@1.4.3': resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} engines: {node: '>= 20.12.0'} @@ -2673,6 +2680,8 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} + '@bomb.sh/tty@0.9.0': {} + '@clack/core@1.4.3': dependencies: fast-wrap-ansi: 0.2.2 diff --git a/scripts/runtime-test-exclusions.ts b/scripts/runtime-test-exclusions.ts index c254f206..d24e22f9 100644 --- a/scripts/runtime-test-exclusions.ts +++ b/scripts/runtime-test-exclusions.ts @@ -77,6 +77,12 @@ const DENO_ONLY_TOOLING: RuntimeExclusion[] = [ "runs the no-network vendored-source verifier under the Deno executable against altered temporary snapshots", issue: "https://github.com/taras/executable.md/issues/365", }, + { + path: "scripts/tests/session-rendering.test.ts", + reason: + "its subject is a `deno compile` executable and the source run it has to match: it spawns ` run` and ` compile` with Deno's own resolution, permission and `--include` flags, and reads `Deno.permissions` to record what each journey was refused. Under Node and Bun that argument vector names a file called `run`, and the claim — that a binary carries the components it renders — is a claim about Deno's build output", + issue: "https://github.com/taras/executable.md/issues/799", + }, { path: "scripts/tests/build-web-client.test.ts", reason: diff --git a/scripts/tests/session-rendering.test.ts b/scripts/tests/session-rendering.test.ts new file mode 100644 index 00000000..cb2042d1 --- /dev/null +++ b/scripts/tests/session-rendering.test.ts @@ -0,0 +1,363 @@ +/** + * One session view, proved from source and from a binary. + * + * A terminal session is the one part of this system nothing could test: the + * rendering path only existed inside a running agent UI, so a regression in how + * a message is selected, replaced, coalesced, scrolled or repainted showed up + * to a person rather than to a suite. This drives the whole path headlessly — + * `@bomb.sh/tty` does layout, input decoding and ANSI in pure computation with + * no terminal attached — and asks it the questions a person would notice: + * does the right presentation render, does a streaming replacement land in + * place, does a backlog collapse to its latest revision, does the view stay + * where the reader put it across an append and a resize, and does an update + * cost less than a repaint. + * + * Every claim has a control that breaks it. Each control is one value from a + * closed enum, run in a process of its own, and the same invariant checker that + * admits the positive journey has to reject it by name — so a claim that had + * stopped being checked fails here instead of passing quietly. + * + * The journey runs twice: once from TypeScript under Deno, once from a + * `deno compile` executable started outside this checkout. A binary that lost + * an embedded component has nothing to fall back on, so the two records are + * required to be equal in whole. Neither run may reach the network, spawn a + * process, write, or read the host beyond the proof's own component roots. + */ + +import { describe, it } from "@executablemd/test-support/bdd"; +import { expect } from "@executablemd/test-support/expect"; +import { useTempDirectory } from "@executablemd/test-support/temp"; +import { exec } from "@effectionx/process"; +import type { ProcessResult } from "@effectionx/process"; +import { readTextFile } from "@effectionx/fs"; +import { useQuietProcessOutput } from "@executablemd/runtime"; +import { scoped } from "effection"; +import type { Operation } from "effection"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { + categoriesOf, + checkJourney, + checkProductionBoundary, + compareRecords, + parseJourneyReport, + PRESENTATION_COMPONENTS, +} from "./session-rendering/evidence.ts"; +import type { InvariantCategory } from "./session-rendering/evidence.ts"; +import { + JOURNEY_MUTATIONS, + REPORT_SCHEMA, + TTY_PACKAGE, + TTY_VERSION, +} from "./session-rendering/journey.ts"; +import { listWorkspacePaths } from "../lib/workspace.ts"; + +const ROOT = fileURLToPath(new URL("../../", import.meta.url)); +const PROOF = "scripts/tests/session-rendering"; +const ENTRYPOINT = `${PROOF}/entrypoint.ts`; +/** The one asset outside the proof directory an execution reads: core's own catalog. */ +const CORE_DOCUMENTATION = "packages/core/src/components/components.md"; + +/** + * What neither journey may do. + * + * Five of the six are refused outright. Environment is not, and cannot be: the + * module graph an execution loads probes `process.env` while it is still being + * imported — `which` reads `OSTYPE`, and `debug` enumerates the whole + * environment — so a process that denied it could not reach this proof's own + * code at all. Environment authority is therefore withheld where a document can + * see it instead: nothing installs a host `Env` provider, and the document + * filesystem ledger below records every path either journey asked for. + */ +const DENIED = ["--deny-net", "--deny-write", "--deny-run", "--deny-sys", "--deny-ffi"]; + +/** The smallest read grant either journey needs, spelled the same way for both. */ +const READABLE = `${PROOF},packages/core/src`; + +const RESOLUTION = ["--frozen", "--cached-only", "--node-modules-dir=none"]; + +const EMBEDDED = [PROOF + "/defaults", PROOF + "/repository", CORE_DOCUMENTATION]; + +/** + * One child process, with its standard output collected rather than echoed. + * + * A journey's stdout *is* the answer these cases read, so displaying it as well + * would put a whole evidence record into the suite's own output for every run. + * `stderr` is left alone: that is where a failing child explains itself. + */ +function quietly(command: string, argv: string[], cwd: string): Operation { + return scoped(function* () { + yield* useQuietProcessOutput(); + return yield* exec(command, { arguments: argv, cwd }).join(); + }); +} + +/** The journey under Deno, reading its components out of the checkout. */ +function sourceRun(mutation?: string): Operation { + return quietly( + Deno.execPath(), + [ + "run", + ...RESOLUTION, + `--allow-read=${READABLE}`, + "--allow-env", + ...DENIED, + ENTRYPOINT, + ...(mutation === undefined ? [] : [mutation]), + ], + ROOT, + ); +} + +/** `run`, having exited zero, or a failure carrying what it printed. */ +function succeeded(run: ProcessResult, what: string): ProcessResult { + if (run.code !== 0) { + throw new Error(`${what} exited ${run.code}\n${run.stdout}\n${run.stderr}`); + } + return run; +} + +/** Exactly one JSON record, or a failure that says what the process printed. */ +function recordOf(run: ProcessResult, what: string): unknown { + const lines = run.stdout.split("\n").filter((line) => line.trim().length > 0); + if (lines.length !== 1) { + throw new Error( + `${what} printed ${lines.length} stdout records, not one\n${run.stdout}\n${run.stderr}`, + ); + } + return JSON.parse(lines[0]); +} + +function outcomeOf(record: unknown): string { + if (typeof record === "object" && record !== null && "outcome" in record) { + const outcome = Reflect.get(record, "outcome"); + return typeof outcome === "string" ? outcome : "unknown"; + } + return "report"; +} + +function categoriesIn(record: unknown): string[] { + if (typeof record === "object" && record !== null && "categories" in record) { + const categories = Reflect.get(record, "categories"); + if (Array.isArray(categories)) { + return categories.map((category) => String(category)); + } + } + return []; +} + +function detailOf(record: unknown): string { + return JSON.stringify(record).slice(0, 2000); +} + +describe("the session rendering proof", { sanitizeOps: false, sanitizeResources: false }, () => { + it("renders the same versioned journey from source and from a compiled executable", function* () { + const source = succeeded(yield* sourceRun(), "the source journey"); + const sourceRecord = recordOf(source, "the source journey"); + expect(outcomeOf(sourceRecord)).toBe("report"); + + const build = yield* useTempDirectory("xmd-session-rendering-build-"); + const binary = join(build, "session-rendering"); + const compiled = yield* quietly( + Deno.execPath(), + [ + "compile", + ...RESOLUTION, + "--exclude-unused-npm", + `--allow-read=${READABLE}`, + "--allow-env", + ...DENIED, + ...EMBEDDED.flatMap((asset) => ["--include", asset]), + "--output", + binary, + ENTRYPOINT, + ], + ROOT, + ); + succeeded(compiled, "the compile"); + + // Somewhere that is not the checkout: a binary that resolved a component + // through the working directory would find nothing here, so what it + // renders is what `--include` embedded and nothing else. + const elsewhere = yield* useTempDirectory("xmd-session-rendering-run-"); + const binaryRun = yield* quietly(binary, [], elsewhere); + succeeded(binaryRun, "the compiled journey"); + const compiledRecord = recordOf(binaryRun, "the compiled journey"); + + expect(compareRecords(sourceRecord, compiledRecord)).toEqual([]); + + const parsed = parseJourneyReport(sourceRecord); + expect(parsed.schema).toBe(REPORT_SCHEMA); + expect(parsed.dependency).toEqual({ name: TTY_PACKAGE, version: TTY_VERSION }); + expect(checkJourney(parsed)).toEqual([]); + + // The seven names, where each resolved, and the one that came from the + // repository root rather than from the defaults beneath it. + expect(parsed.presentations.map((one) => one.component)).toEqual(PRESENTATION_COMPONENTS); + expect( + parsed.presentations + .filter((one) => one.root === "repository/components") + .map((one) => one.component), + ).toEqual(["Session.Message.Tool"]); + + // An incremental update that is cheaper than a repaint, measured rather + // than spelled: neither the bytes nor the escape sequence is written down + // anywhere here. + expect(parsed.diff.incrementalBytes).toBeGreaterThan(0); + expect(parsed.diff.incrementalBytes).toBeLessThan(parsed.diff.freshBytes); + + // Nothing either journey asked the document filesystem for was outside + // the proof's own roots, and five authorities were refused outright. + expect(parsed.files.filter((request) => !request.admitted)).toEqual([]); + for (const authority of ["net", "write", "run", "sys", "ffi"]) { + expect(parsed.authorities[authority]).toBe("denied"); + } + }); + + describe("every claim has a control that breaks it", () => { + const EXPECTED: Record = { + "omit-component": "presentation-selection", + "default-before-repository": "override-precedence", + "plain-markdown": "structured-markdown", + "unstable-regions": "stable-replacement", + "no-coalescing": "coalescing", + "forced-follow": "follow-unread", + "row-offset-viewport": "resize-preservation", + "whole-history-repaint": "bounded-diff", + "forbidden-read": "forbidden-integration", + }; + + it("names every mutation exactly once", function* () { + expect([...JOURNEY_MUTATIONS].sort()).toEqual(Object.keys(EXPECTED).sort()); + }); + + for (const mutation of JOURNEY_MUTATIONS) { + it(`rejects ${mutation} as ${EXPECTED[mutation]}`, function* () { + const run = yield* sourceRun(mutation); + const record = recordOf(run, `the ${mutation} control`); + // Exit status separates a named rejection from an accident: a control + // that crashed, or one nobody caught, is not a control. + succeeded(run, `the ${mutation} control`); + expect(outcomeOf(record)).toBe("rejected"); + expect(categoriesIn(record)).toContain(EXPECTED[mutation]); + }); + } + + it("proves the scroll transition is necessary, not incidental", function* () { + const run = yield* sourceRun("forced-follow"); + const record = recordOf(run, "the forced-follow control"); + expect(categoriesIn(record)).toContain("history-and-newest"); + expect(categoriesIn(record)).toContain("follow-unread"); + }); + }); + + describe("the host pair and the private boundary", () => { + it("rejects a compiled record that lost or changed a member", function* () { + const source = succeeded(yield* sourceRun(), "the source journey"); + const record = recordOf(source, "the source journey"); + expect(typeof record).toBe("object"); + if (typeof record !== "object" || record === null) { + throw new Error("the source journey printed no record to compare against"); + } + + const withoutMember = { ...record }; + Reflect.deleteProperty(withoutMember, "presentations"); + expect(compareRecords(record, withoutMember).join("; ")).toContain("presentations"); + + const mismatched = { ...record, dependency: { name: TTY_PACKAGE, version: "0.8.0" } }; + expect(compareRecords(record, mismatched).join("; ")).toContain("0.8.0"); + + // And a record identical to itself names no difference at all, so the + // comparison above is not passing because everything differs. + expect(compareRecords(record, record)).toEqual([]); + }); + + it("keeps the proof and its dependency out of every production package", function* () { + const surface = yield* productionSurface(); + expect(Object.keys(surface.dependencies).length).toBeGreaterThan(0); + expect(checkProductionBoundary(surface)).toEqual([]); + + expect( + checkProductionBoundary({ + dependencies: { "packages/core/package.json": ["@bomb.sh/tty"] }, + exports: {}, + }), + ).toEqual(["packages/core/package.json depends on @bomb.sh/tty"]); + expect( + checkProductionBoundary({ + dependencies: {}, + exports: { "packages/core/deno.json": ["./scripts/tests/session-rendering/journey.ts"] }, + }), + ).toHaveLength(1); + }); + }); + + it("is admitted by the checker only when nothing is wrong with it", function* () { + const source = succeeded(yield* sourceRun(), "the source journey"); + const parsed = parseJourneyReport(recordOf(source, "the source journey")); + expect(categoriesOf(checkJourney(parsed))).toEqual([]); + + // The checker is not vacuous: a record with its history emptied is + // rejected by the claims that read history. + const emptied = parseJourneyReport({ ...JSON.parse(JSON.stringify(parsed)), history: [] }); + expect(categoriesOf(checkJourney(emptied))).toContain("stable-replacement"); + }); +}); + +/** + * Every dependency a shipped package declares and every specifier it publishes. + * + * The root manifest's own `devDependencies` are deliberately absent: that is + * where the exact `@bomb.sh/tty` pin belongs, and reading it here would make + * the boundary check pass or fail for the wrong reason. + */ +function* productionSurface(): Operation<{ + dependencies: Record; + exports: Record; +}> { + const dependencies: Record = {}; + const exports: Record = {}; + + const root = new URL("../../", import.meta.url); + const manifest = JSON.parse(yield* readTextFile(new URL("deno.json", root))); + const members = yield* listWorkspacePaths(manifest.workspace, root); + + dependencies["package.json"] = names( + JSON.parse(yield* readTextFile(new URL("package.json", root))).dependencies, + ); + + for (const member of members) { + for (const file of ["package.json", "deno.json"]) { + const url = new URL(`${member}/${file}`, root); + let source: string; + try { + source = yield* readTextFile(url); + } catch { + continue; + } + const parsed = JSON.parse(source); + dependencies[`${member}/${file}`] = [ + ...names(parsed.dependencies), + ...names(parsed.devDependencies), + ...names(parsed.imports), + ]; + exports[`${member}/${file}`] = specifiers(parsed.exports); + } + } + return { dependencies, exports }; +} + +function names(value: unknown): string[] { + return typeof value === "object" && value !== null ? Object.keys(value) : []; +} + +function specifiers(value: unknown): string[] { + if (typeof value === "string") { + return [value]; + } + if (typeof value !== "object" || value === null) { + return []; + } + return Object.values(value).flatMap((entry) => specifiers(entry)); +} diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Assistant.md b/scripts/tests/session-rendering/defaults/Session/Message/Assistant.md new file mode 100644 index 00000000..872d844f --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Assistant.md @@ -0,0 +1,3 @@ +xmd-proof-assistant + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Permission.md b/scripts/tests/session-rendering/defaults/Session/Message/Permission.md new file mode 100644 index 00000000..ec2910fe --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Permission.md @@ -0,0 +1,3 @@ +xmd-proof-permission + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Status.md b/scripts/tests/session-rendering/defaults/Session/Message/Status.md new file mode 100644 index 00000000..06c8ffa7 --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Status.md @@ -0,0 +1,3 @@ +xmd-proof-status + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Thought.md b/scripts/tests/session-rendering/defaults/Session/Message/Thought.md new file mode 100644 index 00000000..6be9206b --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Thought.md @@ -0,0 +1,5 @@ +xmd-proof-thought + + + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Tool.md b/scripts/tests/session-rendering/defaults/Session/Message/Tool.md new file mode 100644 index 00000000..aece91ca --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Tool.md @@ -0,0 +1,3 @@ +xmd-proof-tool-default + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/Unknown.md b/scripts/tests/session-rendering/defaults/Session/Message/Unknown.md new file mode 100644 index 00000000..c7cc5f71 --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/Unknown.md @@ -0,0 +1,3 @@ +xmd-proof-unknown + + diff --git a/scripts/tests/session-rendering/defaults/Session/Message/User.md b/scripts/tests/session-rendering/defaults/Session/Message/User.md new file mode 100644 index 00000000..d414973b --- /dev/null +++ b/scripts/tests/session-rendering/defaults/Session/Message/User.md @@ -0,0 +1,3 @@ +xmd-proof-user + + diff --git a/scripts/tests/session-rendering/entrypoint.ts b/scripts/tests/session-rendering/entrypoint.ts new file mode 100644 index 00000000..d70d6273 --- /dev/null +++ b/scripts/tests/session-rendering/entrypoint.ts @@ -0,0 +1,103 @@ +/** + * The journey as a program, so the same code can be run from source and from a + * `deno compile` executable and the two answers compared. + * + * It prints exactly one JSON record and nothing else. A positive run prints the + * journey report; a run given one of the closed set of mutations prints the + * categories the invariant checker rejected it for. Exit status separates the + * two failures that matter: a mutation that was rejected by name is a working + * control and exits 0, while a mutation nobody caught, a shape nobody can + * parse, or an exception nobody named exits non-zero. + * + * The component roots are located from this module's own URL rather than from + * the working directory, because the compiled binary has no checkout to stand + * in and is deliberately run from somewhere else. + */ + +import { main } from "effection"; +import { fileURLToPath } from "node:url"; + +import { categoriesOf, checkJourney, parseJourneyReport } from "./evidence.ts"; +import { JOURNEY_MUTATIONS, parseJourneyMutation, REPORT_SCHEMA, runJourney } from "./journey.ts"; + +const ROOT = fileURLToPath(new URL(".", import.meta.url)); + +function emit(record: unknown): void { + console.log(JSON.stringify(record)); +} + +await main(function* () { + const [requested, ...extra] = Deno.args; + if (extra.length > 0) { + emit({ + schema: REPORT_SCHEMA, + outcome: "failed", + detail: `expected at most one mutation, got ${[requested, ...extra].join(" ")}`, + }); + Deno.exitCode = 1; + return; + } + + const mutation = requested === undefined ? undefined : parseJourneyMutation(requested); + if (requested !== undefined && mutation === undefined) { + emit({ + schema: REPORT_SCHEMA, + outcome: "failed", + detail: `"${requested}" is not one of ${JOURNEY_MUTATIONS.join(", ")}`, + }); + Deno.exitCode = 1; + return; + } + + let report: unknown; + try { + report = yield* runJourney({ root: ROOT, mutation }); + } catch (error) { + emit({ + schema: REPORT_SCHEMA, + outcome: "failed", + mutation: mutation ?? null, + detail: error instanceof Error ? `${error.name}: ${error.message}` : String(error), + }); + Deno.exitCode = 1; + return; + } + + // The record goes out through the same parser the outer test uses, so a + // journey that emitted a shape nothing can read fails here rather than in the + // comparison. + const parsed = parseJourneyReport(JSON.parse(JSON.stringify(report))); + const violations = checkJourney(parsed); + + if (mutation === undefined) { + if (violations.length > 0) { + // A rejected positive run carries the record it was rejected on: the + // reader of that failure needs the evidence, not just the verdict. + emit({ + schema: REPORT_SCHEMA, + outcome: "rejected", + mutation: null, + categories: categoriesOf(violations), + violations, + report, + }); + Deno.exitCode = 1; + return; + } + emit(report); + return; + } + + if (violations.length === 0) { + emit({ schema: REPORT_SCHEMA, outcome: "admitted", mutation }); + Deno.exitCode = 1; + return; + } + emit({ + schema: REPORT_SCHEMA, + outcome: "rejected", + mutation, + categories: categoriesOf(violations), + violations, + }); +}); diff --git a/scripts/tests/session-rendering/evidence.ts b/scripts/tests/session-rendering/evidence.ts new file mode 100644 index 00000000..e8b93fa8 --- /dev/null +++ b/scripts/tests/session-rendering/evidence.ts @@ -0,0 +1,764 @@ +/** + * What a journey has to have shown, and what it means when it has not. + * + * One checker admits the positive journey and rejects every mutation, so a + * control that "fails" cannot be failing for a reason nobody named: each + * rejection carries the invariant category of the claim it broke. The same + * module parses the JSON a journey process printed, which is what lets the + * source run and the compiled run be compared as values rather than as text. + * + * Parsing is how types arrive here. Nothing is cast: a record that does not + * have the shape below is not a report, and saying so is more useful than + * asserting against fields that were never there. + */ + +import { EMPHASIS_ATTRIBUTE, lexProofMarkdown } from "./markdown-projection.ts"; +import type { OperationDescription } from "./markdown-projection.ts"; + +/** The claim a rejection belongs to. */ +export const INVARIANT_CATEGORIES = [ + "presentation-selection", + "override-precedence", + "structured-markdown", + "stable-replacement", + "coalescing", + "history-and-newest", + "follow-unread", + "resize-preservation", + "bounded-diff", + "forbidden-integration", +] as const; + +export type InvariantCategory = (typeof INVARIANT_CATEGORIES)[number]; + +export interface Violation { + readonly category: InvariantCategory; + readonly detail: string; +} + +/** The seven names this proof selects, in the order history holds them. */ +export const PRESENTATION_COMPONENTS: readonly string[] = [ + "Session.Message.User", + "Session.Message.Assistant", + "Session.Message.Tool", + "Session.Message.Permission", + "Session.Message.Status", + "Session.Message.Unknown", + "Session.Message.Thought", +]; + +/** The name the repository-local override renders, which no default may print. */ +export const REPOSITORY_TOOL_MARKER = "xmd-proof-tool-repository"; + +export const EXPECTED_HISTORY: readonly string[] = [ + "entry-user", + "entry-assistant", + "entry-tool", + "entry-permission", + "entry-status", + "entry-unknown", + "entry-thought", + "entry-appended", + "entry-final", +]; + +const THOUGHT_ID = "entry-thought"; + +export class ReportShapeError extends Error { + constructor(field: string) { + super(`the journey record has no ${field}`); + this.name = "ReportShapeError"; + } +} + +function field(value: unknown, name: string): unknown { + if (typeof value !== "object" || value === null || !(name in value)) { + throw new ReportShapeError(name); + } + return Reflect.get(value, name); +} + +function asString(value: unknown, name: string): string { + const found = field(value, name); + if (typeof found !== "string") { + throw new ReportShapeError(`${name} as a string`); + } + return found; +} + +function asNumber(value: unknown, name: string): number { + const found = field(value, name); + if (typeof found !== "number") { + throw new ReportShapeError(`${name} as a number`); + } + return found; +} + +function asBoolean(value: unknown, name: string): boolean { + const found = field(value, name); + if (typeof found !== "boolean") { + throw new ReportShapeError(`${name} as a boolean`); + } + return found; +} + +function asArray(value: unknown, name: string): unknown[] { + const found = field(value, name); + if (!Array.isArray(found)) { + throw new ReportShapeError(`${name} as an array`); + } + return found; +} + +function asStrings(value: unknown, name: string): string[] { + return asArray(value, name).map((entry) => { + if (typeof entry !== "string") { + throw new ReportShapeError(`${name} as strings`); + } + return entry; + }); +} + +export interface ParsedPresentation { + readonly component: string; + readonly path: string; + readonly root: string; +} + +export interface ParsedProjection { + readonly id: string; + readonly component: string; + readonly componentPath: string; + readonly revision: number; + readonly complete: boolean; + readonly raw: string; +} + +export interface ParsedCommit { + readonly id: string; + readonly revision: number; + readonly complete: boolean; + readonly viewVersion: number; +} + +export interface ParsedFrame { + readonly label: string; + readonly width: number; + readonly height: number; + readonly visible: readonly string[]; + readonly anchor: string; + readonly follow: boolean; + readonly unread: number; + readonly bytes: number; + readonly operations: readonly OperationDescription[]; +} + +export interface ParsedReport { + readonly schema: string; + readonly dependency: { readonly name: string; readonly version: string }; + readonly authorities: Readonly>; + readonly presentations: readonly ParsedPresentation[]; + readonly projections: readonly ParsedProjection[]; + readonly history: readonly string[]; + readonly commits: readonly ParsedCommit[]; + readonly timeline: readonly string[]; + readonly barrier: { + readonly ingestedWhileBlocked: readonly number[]; + readonly releasedAfterVersion: number; + readonly committedAfterRelease: readonly ParsedCommit[]; + }; + readonly frames: readonly ParsedFrame[]; + readonly resize: { + readonly requested: readonly { readonly width: number; readonly height: number }[]; + readonly adopted: { readonly width: number; readonly height: number }; + readonly anchorBefore: string; + readonly anchorAfter: string; + readonly followBefore: boolean; + readonly followAfter: boolean; + readonly unreadBefore: number; + readonly unreadAfter: number; + readonly historyBefore: readonly string[]; + readonly historyAfter: readonly string[]; + }; + readonly diff: { + readonly incrementalBytes: number; + readonly freshBytes: number; + readonly neighbours: readonly string[]; + readonly neighboursBefore: readonly OperationDescription[]; + readonly neighboursAfter: readonly OperationDescription[]; + }; + readonly files: readonly { + readonly operation: string; + readonly path: string; + readonly admitted: boolean; + }[]; + readonly discardedProjections: number; +} + +function parseOperations(value: unknown, name: string): OperationDescription[] { + return asArray(value, name).map((entry) => { + const kind = asString(entry, "kind"); + if (kind === "open") { + const role = asString(entry, "role"); + if (role !== "viewport" && role !== "entry" && role !== "paragraph" && role !== "code") { + throw new ReportShapeError(`${name} with a known role`); + } + return { kind: "open", id: asString(entry, "id"), role }; + } + if (kind === "text") { + return { kind: "text", content: asString(entry, "content"), attrs: asNumber(entry, "attrs") }; + } + if (kind === "close") { + return { kind: "close" }; + } + throw new ReportShapeError(`${name} with a known operation kind`); + }); +} + +function parseCommits(value: unknown, name: string): ParsedCommit[] { + return asArray(value, name).map((entry) => ({ + id: asString(entry, "id"), + revision: asNumber(entry, "revision"), + complete: asBoolean(entry, "complete"), + viewVersion: asNumber(entry, "viewVersion"), + })); +} + +function parseSize(value: unknown): { width: number; height: number } { + return { width: asNumber(value, "width"), height: asNumber(value, "height") }; +} + +/** One journey record, parsed into the shape the oracles read. */ +export function parseJourneyReport(value: unknown): ParsedReport { + const dependency = field(value, "dependency"); + const authoritiesValue = field(value, "authorities"); + if (typeof authoritiesValue !== "object" || authoritiesValue === null) { + throw new ReportShapeError("authorities"); + } + const authorities: Record = {}; + for (const [name, state] of Object.entries(authoritiesValue)) { + if (typeof state !== "string") { + throw new ReportShapeError("authorities as strings"); + } + authorities[name] = state; + } + const barrier = field(value, "barrier"); + const resize = field(value, "resize"); + const diff = field(value, "diff"); + return { + schema: asString(value, "schema"), + dependency: { name: asString(dependency, "name"), version: asString(dependency, "version") }, + authorities, + presentations: asArray(value, "presentations").map((entry) => ({ + component: asString(entry, "component"), + path: asString(entry, "path"), + root: asString(entry, "root"), + })), + projections: asArray(value, "projections").map((entry) => ({ + id: asString(entry, "id"), + component: asString(entry, "component"), + componentPath: asString(entry, "componentPath"), + revision: asNumber(entry, "revision"), + complete: asBoolean(entry, "complete"), + raw: asString(entry, "raw"), + })), + history: asStrings(value, "history"), + commits: parseCommits(value, "commits"), + timeline: asStrings(value, "timeline"), + barrier: { + ingestedWhileBlocked: asArray(barrier, "ingestedWhileBlocked").map((entry) => { + if (typeof entry !== "number") { + throw new ReportShapeError("ingestedWhileBlocked as numbers"); + } + return entry; + }), + releasedAfterVersion: asNumber(barrier, "releasedAfterVersion"), + committedAfterRelease: parseCommits(barrier, "committedAfterRelease"), + }, + frames: asArray(value, "frames").map((entry) => ({ + label: asString(entry, "label"), + width: asNumber(entry, "width"), + height: asNumber(entry, "height"), + visible: asStrings(entry, "visible"), + anchor: asString(entry, "anchor"), + follow: asBoolean(entry, "follow"), + unread: asNumber(entry, "unread"), + bytes: asNumber(entry, "bytes"), + operations: parseOperations(entry, "operations"), + })), + resize: { + requested: asArray(resize, "requested").map(parseSize), + adopted: parseSize(field(resize, "adopted")), + anchorBefore: asString(resize, "anchorBefore"), + anchorAfter: asString(resize, "anchorAfter"), + followBefore: asBoolean(resize, "followBefore"), + followAfter: asBoolean(resize, "followAfter"), + unreadBefore: asNumber(resize, "unreadBefore"), + unreadAfter: asNumber(resize, "unreadAfter"), + historyBefore: asStrings(resize, "historyBefore"), + historyAfter: asStrings(resize, "historyAfter"), + }, + diff: { + incrementalBytes: asNumber(diff, "incrementalBytes"), + freshBytes: asNumber(diff, "freshBytes"), + neighbours: asStrings(diff, "neighbours"), + neighboursBefore: parseOperations(diff, "neighboursBefore"), + neighboursAfter: parseOperations(diff, "neighboursAfter"), + }, + files: asArray(value, "files").map((entry) => ({ + operation: asString(entry, "operation"), + path: asString(entry, "path"), + admitted: asBoolean(entry, "admitted"), + })), + discardedProjections: asNumber(value, "discardedProjections"), + }; +} + +function frameNamed(report: ParsedReport, label: string): ParsedFrame | undefined { + return report.frames.find((frame) => frame.label === label); +} + +function same(left: unknown, right: unknown): boolean { + return JSON.stringify(left) === JSON.stringify(right); +} + +/** The first visible line of a rendering, which is the presentation's marker. */ +function markerOf(raw: string): string { + return ( + raw + .split("\n") + .map((line) => line.trim()) + .find((line) => line.length > 0) ?? "" + ); +} + +function checkPresentations(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => + violations.push({ category: "presentation-selection", detail }); + + if ( + !same( + report.presentations.map((one) => one.component), + PRESENTATION_COMPONENTS, + ) + ) { + reject( + `selected ${report.presentations.length} names (${report.presentations + .map((one) => one.component) + .join(", ")})`, + ); + return; + } + for (const presentation of report.presentations) { + const leaf = presentation.component.split(".").join("/"); + const expected = `${presentation.root}/${leaf}.md`; + if (presentation.path !== expected) { + reject(`${presentation.component} resolved to ${presentation.path}, not ${expected}`); + } + } + const markers = new Map>(); + for (const projection of report.projections) { + const seen = markers.get(projection.component) ?? new Set(); + seen.add(markerOf(projection.raw)); + markers.set(projection.component, seen); + } + const distinct = new Set(); + for (const component of PRESENTATION_COMPONENTS) { + const seen = markers.get(component); + if (seen === undefined || seen.size !== 1) { + reject(`${component} rendered ${seen === undefined ? 0 : seen.size} distinct markers`); + continue; + } + const [marker] = [...seen]; + if (marker.length === 0) { + reject(`${component} rendered no marker`); + } + distinct.add(marker); + } + if (distinct.size !== PRESENTATION_COMPONENTS.length) { + reject(`the seven presentations share ${distinct.size} markers`); + } +} + +function checkOverride(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "override-precedence", detail }); + for (const presentation of report.presentations) { + const expected = + presentation.component === "Session.Message.Tool" ? "repository/components" : "defaults"; + if (presentation.root !== expected) { + reject(`${presentation.component} came from ${presentation.root}, not ${expected}`); + } + } + const tool = report.projections.filter((one) => one.component === "Session.Message.Tool"); + if (tool.length === 0) { + reject("no Tool projection was committed"); + } + for (const projection of tool) { + if (markerOf(projection.raw) !== REPOSITORY_TOOL_MARKER) { + reject(`the Tool rendering printed ${markerOf(projection.raw)}`); + } + } +} + +function checkStructuredMarkdown(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "structured-markdown", detail }); + + let paragraphs = 0; + let emphasised = 0; + let fenced = 0; + for (const projection of report.projections) { + const blocks = lexProofMarkdown(projection.raw); + paragraphs = Math.max(paragraphs, blocks.filter((block) => block.kind === "paragraph").length); + for (const block of blocks) { + if (block.kind === "paragraph" && block.runs.some((run) => run.emphasis)) { + emphasised++; + } + if (block.kind === "code" && block.language === "ts") { + fenced++; + } + } + } + if (paragraphs < 2) { + reject(`the widest capture held ${paragraphs} paragraph(s)`); + } + if (emphasised === 0) { + reject("no capture carried inline emphasis"); + } + if (fenced === 0) { + reject("no capture carried a fenced TypeScript block"); + } + + // Read every frame: the entry carrying the fenced block is not on screen in + // all of them, and what this claim is about is that the projection put the + // three shapes into the operation tree at all. + const ops = report.frames.flatMap((frame) => frame.operations); + if (ops.length === 0) { + reject("there are no frames to read operations from"); + return; + } + if (!ops.some((op) => op.kind === "open" && op.role === "paragraph")) { + reject("the operation tree has no paragraph container"); + } + if (!ops.some((op) => op.kind === "text" && op.attrs === EMPHASIS_ATTRIBUTE)) { + reject("no text operation carries the emphasis attribute"); + } + const code = ops.findIndex((op) => op.kind === "open" && op.role === "code"); + if (code === -1) { + reject("the operation tree has no code container"); + return; + } + const inside = ops[code + 1]; + if (inside === undefined || inside.kind !== "text" || inside.content.length === 0) { + reject("the code container holds no text operation"); + } +} + +function checkStableReplacement(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "stable-replacement", detail }); + + if (!same(report.history, EXPECTED_HISTORY)) { + reject(`history is ${report.history.join(", ")}`); + } + if (new Set(report.history).size !== report.history.length) { + reject("history holds a duplicate id"); + } + const thoughtCommits = report.commits.filter((commit) => commit.id === THOUGHT_ID); + const last = thoughtCommits[thoughtCommits.length - 1]; + if (last === undefined || last.revision !== 5 || !last.complete) { + reject(`the thought's last commit is ${JSON.stringify(last ?? null)}`); + } + if (!same(report.diff.neighboursBefore, report.diff.neighboursAfter)) { + reject(`the neighbours ${report.diff.neighbours.join(", ")} changed across the replacement`); + } + const initial = frameNamed(report, "initial"); + const completion = frameNamed(report, "thought-completion"); + if (initial === undefined || completion === undefined) { + reject("the replacement frames are missing"); + return; + } + if (initial.visible.indexOf(THOUGHT_ID) !== completion.visible.indexOf(THOUGHT_ID)) { + reject("the replacement moved the thought within the visible frame"); + } +} + +function checkCoalescing(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "coalescing", detail }); + + if (report.barrier.ingestedWhileBlocked.length !== 3) { + reject(`${report.barrier.ingestedWhileBlocked.length} snapshot(s) arrived while blocked`); + } + const after = report.barrier.committedAfterRelease; + if (after.length !== 1) { + reject(`${after.length} projection(s) committed after the barrier opened`); + } + const only = after[0]; + if (only === undefined || only.id !== THOUGHT_ID || only.revision !== 5 || !only.complete) { + reject(`the first commit after release is ${JSON.stringify(only ?? null)}`); + } + if (report.discardedProjections < 1) { + reject("no stale projection was discarded"); + } + const engaged = report.timeline.indexOf("barrier:engaged"); + const released = report.timeline.indexOf("barrier:released"); + const resumed = report.timeline.indexOf("barrier:resumed"); + if (engaged === -1 || released === -1 || resumed === -1 || !(engaged < released)) { + reject(`the barrier timeline is ${report.timeline.join(" ")}`); + return; + } + for (const version of report.barrier.ingestedWhileBlocked) { + const at = report.timeline.indexOf(`ingest:v${version}`); + if (!(at > engaged && at < released)) { + reject(`snapshot ${version} was not ingested between engaging and releasing`); + } + } +} + +function checkHistoryAndNewest(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "history-and-newest", detail }); + + const initial = frameNamed(report, "initial"); + const scrolled = frameNamed(report, "scrolled-to-oldest"); + if (initial === undefined || scrolled === undefined) { + reject("the history frames are missing"); + return; + } + if (!initial.follow || initial.unread !== 0) { + reject(`the initial frame is follow=${initial.follow} unread=${initial.unread}`); + } + if (!initial.visible.includes(THOUGHT_ID)) { + reject("the initial frame does not show the newest entry"); + } + if (scrolled.follow) { + reject("paging up left the view following"); + } + if (scrolled.anchor !== report.history[0]) { + reject(`paging up reached ${scrolled.anchor}, not ${report.history[0]}`); + } + for (const id of EXPECTED_HISTORY) { + if (!report.history.includes(id)) { + reject(`history lost ${id}`); + } + } +} + +function checkFollowAndUnread(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "follow-unread", detail }); + + const scrolled = frameNamed(report, "scrolled-to-oldest"); + const appended = frameNamed(report, "appended-off-bottom"); + const returned = frameNamed(report, "returned-to-bottom"); + const following = frameNamed(report, "appended-while-following"); + if ( + scrolled === undefined || + appended === undefined || + returned === undefined || + following === undefined + ) { + reject("the follow frames are missing"); + return; + } + if (appended.anchor !== scrolled.anchor) { + reject(`the append moved the anchor from ${scrolled.anchor} to ${appended.anchor}`); + } + if (appended.follow) { + reject("the append re-enabled following"); + } + if (appended.unread !== 1) { + reject(`the append left unread at ${appended.unread}`); + } + if (!returned.follow || returned.unread !== 0) { + reject(`End left follow=${returned.follow} unread=${returned.unread}`); + } + if (!returned.visible.includes("entry-appended")) { + reject("End did not return to the newest entry"); + } + if (!following.follow || following.unread !== 0) { + reject(`the following append left follow=${following.follow} unread=${following.unread}`); + } + if (!following.visible.includes("entry-final")) { + reject("the following append did not stay at the newest entry"); + } +} + +function checkResize(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "resize-preservation", detail }); + + const last = report.resize.requested[report.resize.requested.length - 1]; + if (last === undefined || !same(last, report.resize.adopted)) { + reject(`the batch adopted ${JSON.stringify(report.resize.adopted)}`); + } + const resized = frameNamed(report, "resized"); + if (resized === undefined) { + reject("there is no resized frame"); + return; + } + if ( + resized.width !== report.resize.adopted.width || + resized.height !== report.resize.adopted.height + ) { + reject(`the resized frame rendered ${resized.width}x${resized.height}`); + } + if (!same(report.resize.historyBefore, report.resize.historyAfter)) { + reject("the resize changed history"); + } + // The anchor claim is about an off-bottom view. A following view is supposed + // to re-anchor when the window grows, and whether this journey was off the + // bottom at all is the follow-and-unread claim rather than this one. + if (report.resize.followBefore) { + return; + } + if (report.resize.anchorBefore !== report.resize.anchorAfter) { + reject( + `the resize moved the anchor from ${report.resize.anchorBefore} to ${report.resize.anchorAfter}`, + ); + } + if (report.resize.followBefore !== report.resize.followAfter) { + reject("the resize changed follow mode"); + } + if (report.resize.unreadBefore !== report.resize.unreadAfter) { + reject("the resize changed the unread count"); + } +} + +function checkBoundedDiff(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "bounded-diff", detail }); + + if (report.diff.incrementalBytes === 0) { + reject("the incremental update produced no bytes"); + } + if (report.diff.incrementalBytes >= report.diff.freshBytes) { + reject( + `the incremental update cost ${report.diff.incrementalBytes} bytes against a fresh frame of ${report.diff.freshBytes}`, + ); + } + if (!same(report.diff.neighboursBefore, report.diff.neighboursAfter)) { + reject("the measured update also changed its neighbours"); + } +} + +function checkForbiddenIntegration(report: ParsedReport, violations: Violation[]): void { + const reject = (detail: string) => violations.push({ category: "forbidden-integration", detail }); + + if (report.files.length === 0) { + reject("the document filesystem ledger saw nothing at all"); + } + for (const request of report.files) { + if (!request.admitted) { + reject(`${request.operation} of ${request.path} was refused by the ledger`); + } + } + for (const authority of ["net", "write", "run", "sys", "ffi"]) { + if (report.authorities[authority] !== "denied") { + reject(`${authority} authority is ${report.authorities[authority]}`); + } + } +} + +/** Every claim this journey failed, or an empty list when it made them all. */ +export function checkJourney(report: ParsedReport): Violation[] { + const violations: Violation[] = []; + if (report.dependency.name !== "@bomb.sh/tty" || report.dependency.version !== "0.9.0") { + violations.push({ + category: "presentation-selection", + detail: `the record names ${report.dependency.name} ${report.dependency.version}`, + }); + } + checkPresentations(report, violations); + checkOverride(report, violations); + checkStructuredMarkdown(report, violations); + checkStableReplacement(report, violations); + checkCoalescing(report, violations); + checkHistoryAndNewest(report, violations); + checkFollowAndUnread(report, violations); + checkResize(report, violations); + checkBoundedDiff(report, violations); + checkForbiddenIntegration(report, violations); + return violations; +} + +/** The categories a set of violations names, in the order the checker found them. */ +export function categoriesOf(violations: readonly Violation[]): InvariantCategory[] { + const seen: InvariantCategory[] = []; + for (const violation of violations) { + if (!seen.includes(violation.category)) { + seen.push(violation.category); + } + } + return seen; +} + +/** + * What differs between the source record and the compiled one. + * + * Whole equality, not a spot check: a binary that shipped a different component, + * lost an embedded asset, or resolved a different dependency answers differently + * somewhere in the record, and naming the first field that differs is how a + * reader finds out where. + */ +export function compareRecords(source: unknown, compiled: unknown): string[] { + const differences: string[] = []; + walk(source, compiled, "", differences); + return differences; +} + +function walk(left: unknown, right: unknown, path: string, differences: string[]): void { + const here = path.length === 0 ? "" : path; + if (Array.isArray(left) || Array.isArray(right)) { + if (!Array.isArray(left) || !Array.isArray(right)) { + differences.push(`${here}: one side is an array and the other is not`); + return; + } + if (left.length !== right.length) { + differences.push(`${here}: ${left.length} entries against ${right.length}`); + return; + } + left.forEach((entry, index) => walk(entry, right[index], `${path}[${index}]`, differences)); + return; + } + if (typeof left === "object" && left !== null && typeof right === "object" && right !== null) { + const names = new Set([...Object.keys(left), ...Object.keys(right)]); + for (const name of [...names].sort()) { + if (!(name in left) || !(name in right)) { + differences.push(`${path}.${name}: present on one side only`); + continue; + } + walk(Reflect.get(left, name), Reflect.get(right, name), `${path}.${name}`, differences); + } + return; + } + if (!Object.is(left, right)) { + differences.push(`${here}: ${JSON.stringify(left)} against ${JSON.stringify(right)}`); + } +} + +export interface ProductionSurface { + /** Every production manifest, by path, with its declared dependency names. */ + readonly dependencies: Readonly>; + /** Every published export specifier, by manifest path. */ + readonly exports: Readonly>; +} + +/** + * What a production package would have to have adopted for this proof to have + * leaked out of `scripts/tests/`. + * + * The proof is disposable test infrastructure: no shipped package may depend on + * the terminal renderer it drives, and no export map may name a module under + * the proof directory. + */ +export function checkProductionBoundary(surface: ProductionSurface): string[] { + const leaks: string[] = []; + for (const [manifest, names] of Object.entries(surface.dependencies)) { + if (names.includes("@bomb.sh/tty")) { + leaks.push(`${manifest} depends on @bomb.sh/tty`); + } + } + for (const [manifest, specifiers] of Object.entries(surface.exports)) { + for (const specifier of specifiers) { + if (specifier.includes("session-rendering")) { + leaks.push(`${manifest} exports ${specifier}`); + } + } + } + return leaks; +} diff --git a/scripts/tests/session-rendering/journey.ts b/scripts/tests/session-rendering/journey.ts new file mode 100644 index 00000000..f361a3b6 --- /dev/null +++ b/scripts/tests/session-rendering/journey.ts @@ -0,0 +1,964 @@ +/** + * One finite session journey, owned by a single Effection scope. + * + * A source publishes immutable snapshots of a conversation. An ingest task + * reduces each one the moment it arrives, and a projector renders whatever the + * newest state says — never the snapshot that woke it, if a later one landed + * while it was suspended. That split is the whole point: while one presentation + * is blocked mid-projection the source keeps publishing, and what commits + * afterwards has to be the latest completed revision rather than the backlog + * replayed in order. + * + * Everything above the terminal belongs here — ordered history, stable entry + * identity, replacement, dirty-id collapsing, which entries are visible, the + * anchor entry, follow mode and the unread count. `@bomb.sh/tty` owns layout, + * clipping, input decoding, resize processing and the ANSI bytes, and is asked + * for a complete operation tree every frame. + * + * The entry shape is private to this module on purpose. It is not a normalized + * entry, it is not a component prop, and nothing outside this directory may + * grow a dependency on it. + */ + +import { createQueue, ensure, Err, Ok, scoped, spawn, until, withResolvers } from "effection"; +import type { Operation, Result } from "effection"; +import { close, createTerm, grow, open } from "@bomb.sh/tty"; +import { createInput } from "@bomb.sh/tty"; +import type { Op, Term } from "@bomb.sh/tty"; +import { join, relative, resolve } from "node:path"; +import { readTextFile } from "@effectionx/fs"; + +import { DocumentOutput } from "../../../packages/core/src/api.ts"; +import { collect } from "../../../packages/core/src/collect.ts"; +import { execute } from "../../../packages/core/src/execute.ts"; +import { inlineSource } from "../../../packages/core/src/root-source.ts"; +import { registerComponents } from "../../../packages/core/src/components/registration.ts"; +import { selectComponent } from "../../../packages/core/src/components/select.ts"; +import { Component } from "../../../packages/core/src/component-api.ts"; +import { FILES_ERROR, Files, FilesError } from "../../../packages/runtime/files.ts"; +import type { + FilePathInput, + FileWriteSuccess, + GlobInput, +} from "../../../packages/runtime/files.ts"; +import { InMemoryStream } from "../../../packages/durable-streams/mod.ts"; +import { + blockRows, + describeOperations, + entryOperations, + entrySlice, + lexProofMarkdown, +} from "./markdown-projection.ts"; +import type { Block, OperationDescription } from "./markdown-projection.ts"; + +/** The evidence schema this journey emits, so a reader can tell versions apart. */ +export const REPORT_SCHEMA = "executablemd.proof.session-rendering/v1"; + +/** The dependency whose operations and bytes this proof is about. */ +export const TTY_PACKAGE = "@bomb.sh/tty"; +export const TTY_VERSION = "0.9.0"; + +/** + * Every way this journey can be made to misbehave, and nothing else. + * + * Each one is a rejecting control for one row of the evidence matrix: it runs + * in a process of its own, and the same invariant checker that admits the + * positive journey has to reject it for the category that names the claim. + */ +export const JOURNEY_MUTATIONS = [ + "omit-component", + "default-before-repository", + "plain-markdown", + "unstable-regions", + "no-coalescing", + "forced-follow", + "row-offset-viewport", + "whole-history-repaint", + "forbidden-read", +] as const; + +export type JourneyMutation = (typeof JOURNEY_MUTATIONS)[number]; + +export function parseJourneyMutation(value: string): JourneyMutation | undefined { + return JOURNEY_MUTATIONS.find((mutation) => mutation === value); +} + +/** The seven presentations this proof selects, in the order history holds them. */ +type Presentation = "user" | "assistant" | "tool" | "permission" | "status" | "unknown" | "thought"; + +/** + * The component each presentation resolves to. + * + * The mapping is private: a document writes the component name, and nothing + * outside this module learns that a local discriminator chose it. + */ +const COMPONENT_OF: Record = { + user: "Session.Message.User", + assistant: "Session.Message.Assistant", + tool: "Session.Message.Tool", + permission: "Session.Message.Permission", + status: "Session.Message.Status", + unknown: "Session.Message.Unknown", + thought: "Session.Message.Thought", +}; + +const HISTORY: readonly Presentation[] = [ + "user", + "assistant", + "tool", + "permission", + "status", + "unknown", + "thought", +]; + +/** One entry as the source publishes it. Immutable, and private to this module. */ +interface Entry { + readonly id: string; + readonly presentation: Presentation; + readonly revision: number; + readonly complete: boolean; + readonly markdown: string; +} + +/** One published snapshot: the whole conversation as the source then saw it. */ +type Snapshot = readonly Entry[]; + +const TWO_PARAGRAPHS = "First *emphasis* line.\n\nSecond line."; +const WITH_CODE = `${TWO_PARAGRAPHS}\n\n\`\`\`ts\nconst proof: number = 1;\n\`\`\``; + +/** The payload each presentation carries on its first publication. */ +const INITIAL_MARKDOWN: Record = { + user: TWO_PARAGRAPHS, + assistant: TWO_PARAGRAPHS, + tool: WITH_CODE, + permission: TWO_PARAGRAPHS, + status: TWO_PARAGRAPHS, + // Carried by an entry the initial viewport shows as well as by the tool, so + // that the structured-content claim does not quietly depend on the view + // having scrolled far enough to reach a fenced block. + unknown: WITH_CODE, + thought: TWO_PARAGRAPHS, +}; + +/** What every payload collapses to when the journey flattens its Markdown. */ +const PLAIN_MARKDOWN = "One line of ordinary prose."; + +const THOUGHT_ID = "entry-thought"; + +function entryId(presentation: Presentation): string { + return `entry-${presentation}`; +} + +function frozen(entries: readonly Entry[]): Snapshot { + return Object.freeze(entries.map((entry) => Object.freeze({ ...entry }))); +} + +/** What one committed projection is: its Markdown, its blocks and its provenance. */ +interface Projection { + readonly id: string; + readonly component: string; + readonly componentPath: string; + readonly revision: number; + readonly complete: boolean; + readonly raw: string; + readonly blocks: readonly Block[]; +} + +/** One request the document filesystem boundary saw, and what the ledger said. */ +export interface FilesRequest { + readonly operation: string; + readonly path: string; + readonly admitted: boolean; +} + +/** One rendered frame, as the report carries it. */ +export interface FrameRecord { + readonly label: string; + readonly width: number; + readonly height: number; + readonly visible: readonly string[]; + readonly anchor: string; + readonly follow: boolean; + readonly unread: number; + readonly bytes: number; + readonly operations: readonly OperationDescription[]; +} + +/** One commit the projector made, in the order it made them. */ +export interface CommitRecord { + readonly id: string; + readonly revision: number; + readonly complete: boolean; + readonly viewVersion: number; +} + +/** Where one of the seven names resolved, asked of the resolver itself. */ +export interface PresentationRecord { + readonly component: string; + readonly path: string; + readonly root: string; +} + +/** One committed projection, as the report carries it. */ +export interface ProjectionRecord { + readonly id: string; + readonly component: string; + readonly componentPath: string; + readonly revision: number; + readonly complete: boolean; + readonly raw: string; +} + +export interface JourneyReport { + readonly schema: string; + readonly dependency: { readonly name: string; readonly version: string }; + readonly authorities: Readonly>; + readonly presentations: readonly PresentationRecord[]; + readonly projections: readonly ProjectionRecord[]; + readonly history: readonly string[]; + readonly commits: readonly CommitRecord[]; + readonly timeline: readonly string[]; + readonly barrier: { + readonly ingestedWhileBlocked: readonly number[]; + readonly releasedAfterVersion: number; + readonly committedAfterRelease: readonly CommitRecord[]; + }; + readonly frames: readonly FrameRecord[]; + readonly resize: { + readonly requested: readonly { readonly width: number; readonly height: number }[]; + readonly adopted: { readonly width: number; readonly height: number }; + readonly anchorBefore: string; + readonly anchorAfter: string; + readonly followBefore: boolean; + readonly followAfter: boolean; + readonly unreadBefore: number; + readonly unreadAfter: number; + readonly historyBefore: readonly string[]; + readonly historyAfter: readonly string[]; + }; + readonly diff: { + readonly incrementalBytes: number; + readonly freshBytes: number; + readonly neighbours: readonly string[]; + readonly neighboursBefore: readonly OperationDescription[]; + readonly neighboursAfter: readonly OperationDescription[]; + }; + readonly files: readonly FilesRequest[]; + readonly discardedProjections: number; +} + +const INITIAL_WIDTH = 60; +const INITIAL_HEIGHT = 12; +const RESIZE_BATCH = [ + { width: 70, height: 14 }, + { width: 80, height: 16 }, +] as const; + +/** The `@bomb.sh/tty` key bytes this journey feeds through the input parser. */ +const PAGE_UP = "\x1b[5~"; +const END = "\x1b[F"; + +/** The permissions the journey reports, queried rather than assumed. */ +function authorities(root: string): Record { + const record: Record = {}; + for (const name of ["net", "write", "run", "sys", "ffi", "env"] as const) { + record[name] = Deno.permissions.querySync({ name }).state; + } + record.read = Deno.permissions.querySync({ name: "read", path: root }).state; + return record; +} + +/** + * The document filesystem ledger. + * + * Every request is recorded with the verdict it got, and only paths inside the + * proof's own component roots are admitted. A journey that reached for anything + * else — a provider file, a session store, a host configuration — leaves a + * refused entry behind, which is what the forbidden-integration oracle reads. + */ +function useFilesLedger(root: string, ledger: FilesRequest[]): Operation { + function admits(input: { readonly cwd: string; readonly path: string }): boolean { + const inside = relative(root, resolve(input.cwd, input.path)); + return inside.length > 0 && !inside.startsWith("..") && !inside.startsWith("/"); + } + + function refuse(operation: "read" | "check-file-path"): Result { + return Err( + new FilesError({ + type: FILES_ERROR, + operation, + phase: "lexical", + reason: "resolved-escape", + }), + ); + } + + function deny(operation: string, path: string): Result { + ledger.push({ operation, path, admitted: false }); + return refuse("check-file-path"); + } + + return Files.around({ + // deno-lint-ignore require-yield + *checkFilePath([input]: [FilePathInput]) { + if (!admits(input)) { + return deny("check-file-path", input.path); + } + ledger.push({ operation: "check-file-path", path: input.path, admitted: true }); + return Ok(undefined); + }, + *readTextFile([input]: [FilePathInput]) { + if (!admits(input)) { + return deny("read", input.path); + } + ledger.push({ operation: "read", path: input.path, admitted: true }); + return Ok(yield* readTextFile(resolve(input.cwd, input.path))); + }, + // deno-lint-ignore require-yield + *writeTextFile([input]: [FilePathInput]) { + return deny("write", input.path); + }, + // deno-lint-ignore require-yield + *deleteFile([input]: [FilePathInput]) { + return deny("delete", input.path); + }, + // deno-lint-ignore require-yield + *ensureDirectory([input]: [FilePathInput]) { + return deny("ensure-directory", input.path); + }, + // deno-lint-ignore require-yield + *globFiles([input]: [GlobInput]) { + return deny("glob", input.include.join(",")); + }, + // deno-lint-ignore require-yield + *temporaryDirectory() { + return deny("temporary-directory", ""); + }, + }); +} + +interface SnapshotScript { + /** One snapshot per presentation, growing the conversation to its full history. */ + readonly initial: readonly Snapshot[]; + /** The revision whose projection blocks. */ + readonly blocking: Snapshot; + /** Two further revisions and the completion, published while that one is held. */ + readonly whileBlocked: readonly Snapshot[]; + readonly appendOffBottom: Snapshot; + readonly appendFollowing: Snapshot; +} + +/** + * The fixed sequence of snapshots this journey publishes. + * + * Everything the journey waits for is an event or a barrier and no step is + * timed, so the same order holds under any scheduling. + */ +function journeySnapshots(mutation: JourneyMutation | undefined): SnapshotScript { + const presentations = + mutation === "omit-component" + ? HISTORY.filter((presentation) => presentation !== "unknown") + : HISTORY; + const markdownOf = (presentation: Presentation): string => + mutation === "plain-markdown" ? PLAIN_MARKDOWN : INITIAL_MARKDOWN[presentation]; + + let conversation: Entry[] = []; + const initial: Snapshot[] = []; + for (const presentation of presentations) { + conversation = [ + ...conversation, + { + id: entryId(presentation), + presentation, + revision: 1, + complete: true, + markdown: markdownOf(presentation), + }, + ]; + initial.push(frozen(conversation)); + } + + const thoughtText = (revision: number): string => + mutation === "plain-markdown" + ? `${PLAIN_MARKDOWN} Revision ${revision}.` + : `First *emphasis* line, revision ${revision}.\n\nSecond line.`; + + const revise = (revision: number, complete: boolean): Snapshot => { + conversation = conversation.map((entry) => + entry.id === THOUGHT_ID + ? { ...entry, revision, complete, markdown: thoughtText(revision) } + : entry, + ); + return frozen(conversation); + }; + + const blocking = revise(2, false); + const whileBlocked = [revise(3, false), revise(4, false), revise(5, true)]; + + conversation = [ + ...conversation, + { + id: "entry-appended", + presentation: "status", + revision: 1, + complete: true, + markdown: markdownOf("status"), + }, + ]; + const appendOffBottom = frozen(conversation); + + conversation = [ + ...conversation, + { + id: "entry-final", + presentation: "assistant", + revision: 1, + complete: true, + markdown: markdownOf("assistant"), + }, + ]; + + return { + initial, + blocking, + whileBlocked, + appendOffBottom, + appendFollowing: frozen(conversation), + }; +} + +export function runJourney(options: { + readonly root: string; + readonly mutation?: JourneyMutation; +}): Operation { + const { root, mutation } = options; + return scoped(function* (): Operation { + const ledger: FilesRequest[] = []; + const timeline: string[] = []; + const commits: CommitRecord[] = []; + const frames: FrameRecord[] = []; + const ingestedWhileBlocked: number[] = []; + let discardedProjections = 0; + let barrierReleased = false; + + // Cleanup is established before anything is acquired or subscribed. The tty + // objects hold no host resource of their own — construction instantiates + // bundled WebAssembly and performs no terminal I/O — so teardown is this + // scope dropping its references. + yield* ensure(() => { + timeline.push("scope:closed"); + }); + + yield* useFilesLedger(root, ledger); + + const includes = + mutation === "default-before-repository" + ? [join(root, "defaults"), join(root, "repository", "components")] + : [join(root, "repository", "components"), join(root, "defaults")]; + + const barrierEngaged = withResolvers(); + const barrierRelease = withResolvers(); + const backlogIngested = withResolvers(); + let thoughtProjections = 0; + + yield* registerComponents([ + { + name: "ProofBarrier", + origin: "session-rendering-proof", + description: "Holds the second Thought projection open so later revisions arrive first.", + props: { type: "object", properties: {}, additionalProperties: false }, + *fn(): Operation { + thoughtProjections++; + if (thoughtProjections === 2) { + timeline.push("barrier:engaged"); + barrierEngaged.resolve(); + yield* barrierRelease.operation; + timeline.push("barrier:resumed"); + } + return ""; + }, + }, + ]); + + const presentations = yield* describePresentations(root, includes, mutation); + + const term = yield* until(createTerm({ width: INITIAL_WIDTH, height: INITIAL_HEIGHT })); + const input = yield* until(createInput({ escLatency: 1 })); + + // The permitted probe: the ledger admits the proof's own component roots, + // and the positive run is the one that shows it admitting something. + yield* Files.operations.checkFilePath({ + cwd: root, + path: join("defaults", "Session", "Message", "User.md"), + }); + if (mutation === "forbidden-read") { + yield* Files.operations.readTextFile({ cwd: root, path: "../../../../etc/hosts" }); + } + + const script = journeySnapshots(mutation); + const snapshots = createQueue(); + const wake = createQueue(); + const settled = createQueue(); + + let state: Snapshot = []; + let version = 0; + const dirty = new Set(); + const backlog: Entry[] = []; + const order: string[] = []; + const committed = new Map(); + + const gates = { + replace: withResolvers(), + appendOffBottom: withResolvers(), + appendFollowing: withResolvers(), + }; + + yield* spawn(function* source(): Operation { + for (const snapshot of script.initial) { + snapshots.add(snapshot); + } + yield* gates.replace.operation; + snapshots.add(script.blocking); + // Published without waiting for anything to render: two later revisions + // and the completion land while the projector is still inside the Thought + // it started before them. + yield* barrierEngaged.operation; + for (const snapshot of script.whileBlocked) { + snapshots.add(snapshot); + } + yield* gates.appendOffBottom.operation; + snapshots.add(script.appendOffBottom); + yield* gates.appendFollowing.operation; + snapshots.add(script.appendFollowing); + }); + + yield* spawn(function* ingest(): Operation { + while (true) { + const arrived = yield* snapshots.next(); + if (arrived.done) { + return; + } + const snapshot = arrived.value; + version++; + for (const entry of snapshot) { + const previous = state.find((candidate) => candidate.id === entry.id); + if ( + previous === undefined || + previous.revision !== entry.revision || + previous.complete !== entry.complete || + previous.markdown !== entry.markdown + ) { + dirty.add(entry.id); + if (mutation === "no-coalescing") { + backlog.push(entry); + } + } + if (!order.includes(entry.id)) { + order.push(entry.id); + } + } + state = snapshot; + timeline.push(`ingest:v${version}`); + if (thoughtProjections === 2 && !barrierReleased) { + ingestedWhileBlocked.push(version); + if (ingestedWhileBlocked.length === script.whileBlocked.length) { + backlogIngested.resolve(); + } + } + wake.add(version); + } + }); + + const viewport = { anchorIndex: 0, follow: true, unread: 0, anchorRowsFromEnd: 0 }; + let width = INITIAL_WIDTH; + let height = INITIAL_HEIGHT; + let currentTerm: Term = term; + + function rowsOf(id: string): number { + const projection = committed.get(id); + return projection === undefined ? 0 : blockRows(projection.blocks); + } + + function bottomAnchorIndex(): number { + let used = 0; + let index = order.length - 1; + while (index >= 0) { + const rows = rowsOf(order[index]); + if (used + rows > height && index < order.length - 1) { + break; + } + used += rows; + index--; + } + return index + 1; + } + + function visibleIds(): string[] { + const visible: string[] = []; + let used = 0; + for (let index = viewport.anchorIndex; index < order.length; index++) { + const rows = rowsOf(order[index]); + if (used + rows > height && visible.length > 0) { + break; + } + used += rows; + visible.push(order[index]); + } + return visible; + } + + function rowsBefore(index: number): number { + let rows = 0; + for (let cursor = 0; cursor < index; cursor++) { + rows += rowsOf(order[cursor]); + } + return rows; + } + + function frameOperations(visible: readonly string[]): Op[] { + const ops: Op[] = [ + open("viewport", { layout: { width: grow(), height: grow(), direction: "ttb" } }), + ]; + for (const id of visible) { + const projection = committed.get(id); + if (projection !== undefined) { + ops.push(...entryOperations(id, projection.blocks)); + } + } + ops.push(close()); + return ops; + } + + function* render(label: string): Operation { + if (viewport.follow) { + viewport.anchorIndex = bottomAnchorIndex(); + } + const visible = visibleIds(); + const ops = frameOperations(visible); + // A whole-history repaint throws the previous frame away, which is what + // makes every update cost a full screen instead of a diff. + if (mutation === "whole-history-repaint") { + currentTerm = yield* until(createTerm({ width, height })); + } + const result = currentTerm.render(ops); + if (result.errors.length > 0) { + throw new Error(`tty reported ${result.errors.length} layout error(s) on frame ${label}`); + } + // The output view expires on the next render or update, so it is copied + // here rather than kept. + const bytes = Uint8Array.from(result.output); + const record: FrameRecord = { + label, + width, + height, + visible, + anchor: order[viewport.anchorIndex] ?? "", + follow: viewport.follow, + unread: viewport.unread, + bytes: bytes.length, + operations: describeOperations(ops), + }; + frames.push(record); + return record; + } + + function* projectOnce(entry: Entry): Operation { + const component = COMPONENT_OF[entry.presentation]; + const selection = yield* scoped(function* () { + return yield* selectComponent(component, { + includes, + registry: yield* Component.operations.registry, + }); + }); + const componentPath = + selection.kind === "repository" ? relative(root, resolve(selection.path)) : selection.kind; + const captured: string[] = []; + yield* scoped(function* () { + yield* DocumentOutput.around({ + *output([text, exact], next) { + captured.push(text); + yield* next(text, exact); + }, + }); + yield* collect( + yield* execute({ + ...inlineSource(`<${component}>\n${entry.markdown}\n\n`), + stream: new InMemoryStream(), + includes, + secretDetection: false, + }), + ); + }); + const raw = captured.join(""); + return { + id: entry.id, + component, + componentPath, + revision: entry.revision, + complete: entry.complete, + raw, + blocks: lexProofMarkdown(raw), + }; + } + + function commit(projection: Projection, shadowed: boolean): void { + if (shadowed) { + const shadow = `${projection.id}#${projection.revision}`; + committed.set(shadow, projection); + order.push(shadow); + } else { + committed.set(projection.id, projection); + } + commits.push({ + id: projection.id, + revision: projection.revision, + complete: projection.complete, + viewVersion: version, + }); + } + + /** + * Project whatever the ingest task has reduced, and commit only that. + * + * A projection records the version it began with. If the source advanced + * while it was suspended, the result describes a state nobody is looking at + * any more, so it is dropped and the newest state is projected instead — + * which is also why a replacement can never be appended: the commit is keyed + * by the entry's own id. + */ + function* drain(): Operation { + while (dirty.size > 0 || backlog.length > 0) { + if (mutation === "no-coalescing") { + const entry = backlog.shift(); + if (entry === undefined) { + dirty.clear(); + continue; + } + commit(yield* projectOnce(entry), false); + dirty.delete(entry.id); + continue; + } + const id = [...dirty][0]; + const began = version; + const entry = state.find((candidate) => candidate.id === id); + if (entry === undefined) { + dirty.delete(id); + continue; + } + const projection = yield* projectOnce(entry); + if (version !== began) { + discardedProjections++; + timeline.push(`project:discarded:${id}`); + continue; + } + dirty.delete(id); + commit(projection, mutation === "unstable-regions" && committed.has(id)); + } + } + + yield* spawn(function* project(): Operation { + while (true) { + const awoken = yield* wake.next(); + if (awoken.done) { + return; + } + yield* drain(); + settled.add(version); + } + }); + + function* settleAt(target: number): Operation { + while (true) { + const next = yield* settled.next(); + if (next.done) { + return; + } + if (next.value >= target && dirty.size === 0) { + return; + } + } + } + + const throughInitial = script.initial.length; + yield* settleAt(throughInitial); + yield* render("initial"); + + gates.replace.resolve(); + yield* barrierEngaged.operation; + // Ingestion has to reach the completion snapshot before the barrier opens; + // that is what makes the coalescing claim a claim about a real backlog. + yield* backlogIngested.operation; + const releasedAfterVersion = version; + barrierReleased = true; + timeline.push("barrier:released"); + const commitsBeforeRelease = commits.length; + barrierRelease.resolve(); + const throughReplacement = throughInitial + 1 + script.whileBlocked.length; + yield* settleAt(throughReplacement); + // Read the post-release commits here, while the replacement is the only + // thing that has happened since: the claim is about what the backlog + // collapsed to, not about everything the journey committed afterwards. + const committedAfterRelease = commits.slice(commitsBeforeRelease); + + const beforeCompletion = frames[frames.length - 1]; + const neighbours = neighbourIds(order, THOUGHT_ID); + const completionFrame = yield* render("thought-completion"); + const freshTerm = yield* until(createTerm({ width, height })); + const freshResult = freshTerm.render(frameOperations(completionFrame.visible)); + const freshBytes = Uint8Array.from(freshResult.output).length; + + // Page Up until the oldest entry is the anchor. Follow is released by the + // decoded key rather than by the loop finishing. + const decoder = new TextEncoder(); + let presses = 0; + while (viewport.anchorIndex > 0 && presses <= order.length) { + presses++; + const scan = input.scan(decoder.encode(PAGE_UP)); + for (const event of scan.events) { + if (event.type !== "keydown" || event.code !== "PageUp") { + continue; + } + if (mutation === "forced-follow") { + continue; + } + viewport.follow = false; + viewport.anchorIndex = Math.max(0, viewport.anchorIndex - Math.max(1, visibleIds().length)); + } + if (mutation === "forced-follow") { + break; + } + } + viewport.anchorRowsFromEnd = rowsBefore(order.length) - rowsBefore(viewport.anchorIndex); + yield* render("scrolled-to-oldest"); + + gates.appendOffBottom.resolve(); + yield* settleAt(throughReplacement + 1); + if (!viewport.follow && !visibleIds().includes(order[order.length - 1])) { + viewport.unread++; + } + yield* render("appended-off-bottom"); + + const anchorBefore = order[viewport.anchorIndex] ?? ""; + const followBefore = viewport.follow; + const unreadBefore = viewport.unread; + const historyBefore = [...order]; + currentTerm.update({ events: RESIZE_BATCH.map((size) => ({ type: "resize", ...size })) }); + const adopted = RESIZE_BATCH[RESIZE_BATCH.length - 1]; + const previousHeight = height; + width = adopted.width; + height = adopted.height; + if (mutation === "row-offset-viewport") { + // The anchor kept as a row offset rather than as an entry: a taller + // viewport moves that offset onto a different entry, which is exactly the + // mistake a stable anchor id cannot make. + viewport.anchorIndex = Math.min( + Math.max(order.length - 1, 0), + viewport.anchorIndex + (height - previousHeight), + ); + } + const resizeFrame = yield* render("resized"); + // Read where the resize left things before anything else moves them: the + // claim is about what one batch of resize events preserved, not about what + // the rest of the journey went on to do. + const resized = { + requested: RESIZE_BATCH.map((size) => ({ ...size })), + adopted: { ...adopted }, + anchorBefore, + anchorAfter: resizeFrame.anchor, + followBefore, + followAfter: resizeFrame.follow, + unreadBefore, + unreadAfter: resizeFrame.unread, + historyBefore, + historyAfter: [...order], + }; + + for (const event of input.scan(decoder.encode(END)).events) { + if (event.type === "keydown" && event.code === "End") { + viewport.follow = true; + viewport.unread = 0; + } + } + yield* render("returned-to-bottom"); + + gates.appendFollowing.resolve(); + yield* settleAt(throughReplacement + 2); + yield* render("appended-while-following"); + + return { + schema: REPORT_SCHEMA, + dependency: { name: TTY_PACKAGE, version: TTY_VERSION }, + authorities: authorities(root), + presentations, + projections: [...committed.values()].map((projection) => ({ + id: projection.id, + component: projection.component, + componentPath: projection.componentPath, + revision: projection.revision, + complete: projection.complete, + raw: projection.raw, + })), + history: [...order], + commits, + timeline, + barrier: { + ingestedWhileBlocked, + releasedAfterVersion, + committedAfterRelease, + }, + frames, + resize: resized, + diff: { + incrementalBytes: completionFrame.bytes, + freshBytes, + neighbours, + neighboursBefore: neighbours.flatMap((id) => entrySlice(beforeCompletion.operations, id)), + neighboursAfter: neighbours.flatMap((id) => entrySlice(completionFrame.operations, id)), + }, + files: ledger, + discardedProjections, + }; + }); +} + +/** The two entries immediately before `id` in history order. */ +function neighbourIds(order: readonly string[], id: string): string[] { + const index = order.indexOf(id); + if (index < 2) { + return order.filter((candidate) => candidate !== id).slice(0, 2); + } + return [order[index - 2], order[index - 1]]; +} + +/** Where each name resolved, asked of the resolver the engine itself uses. */ +function* describePresentations( + root: string, + includes: readonly string[], + mutation: JourneyMutation | undefined, +): Operation { + const presentations = + mutation === "omit-component" + ? HISTORY.filter((presentation) => presentation !== "unknown") + : HISTORY; + const records: PresentationRecord[] = []; + for (const presentation of presentations) { + const component = COMPONENT_OF[presentation]; + const selection = yield* scoped(function* () { + return yield* selectComponent(component, { + includes, + registry: yield* Component.operations.registry, + }); + }); + if (selection.kind !== "repository") { + throw new Error(`${component} resolved to ${selection.kind}, not to a proof Markdown file`); + } + const path = relative(root, resolve(selection.path)); + records.push({ + component, + path, + root: path.startsWith("repository/components") ? "repository/components" : "defaults", + }); + } + return records; +} diff --git a/scripts/tests/session-rendering/markdown-projection.ts b/scripts/tests/session-rendering/markdown-projection.ts new file mode 100644 index 00000000..0f723aa5 --- /dev/null +++ b/scripts/tests/session-rendering/markdown-projection.ts @@ -0,0 +1,251 @@ +/** + * The ordinary Markdown a presentation rendered, projected into `@bomb.sh/tty` + * operations. + * + * The projection is deliberately narrow. It understands paragraphs, inline + * emphasis and fenced code and refuses everything else, because a projector + * that quietly degraded an unsupported token into plain text would let a + * uniform-plain-text rendering pass the structured-content oracle. The three + * shapes it does understand become three independently recognizable things in + * the operation tree — a paragraph container, an emphasis attribute on a text + * operation, and a code container holding one code text operation — so no + * single mistake can satisfy all three at once. + * + * Nothing here formats for a terminal. The Markdown arrives exactly as the + * document emitted it, and `@bomb.sh/tty` alone decides what bytes a frame + * becomes. + */ + +import { marked } from "marked"; +import { close, open, text } from "@bomb.sh/tty"; +import type { Op } from "@bomb.sh/tty"; + +/** + * The italic attribute bit, which `@bomb.sh/tty` 0.9.0 emits as `SGR 3`. + * + * Named for the Markdown it carries rather than for the escape it produces: + * what this proof asserts is that emphasis survived as an attribute, and the + * byte sequence behind it belongs to tty. + */ +export const EMPHASIS_ATTRIBUTE = 4; + +/** An inline run of one paragraph: its text, and whether Markdown emphasized it. */ +export interface InlineRun { + readonly content: string; + readonly emphasis: boolean; +} + +export type Block = + | { readonly kind: "paragraph"; readonly runs: readonly InlineRun[] } + | { readonly kind: "code"; readonly language: string; readonly content: string }; + +/** A token this projector does not understand, named where it was found. */ +export class UnsupportedMarkdownError extends Error { + readonly token: string; + + constructor(token: string) { + super(`the proof projector does not render Markdown token "${token}"`); + this.name = "UnsupportedMarkdownError"; + this.token = token; + } +} + +function tokenType(token: unknown): string { + if (typeof token !== "object" || token === null || !("type" in token)) { + return "unknown"; + } + const type = token.type; + return typeof type === "string" ? type : "unknown"; +} + +function tokenText(token: unknown): string { + if (typeof token === "object" && token !== null && "text" in token) { + const value = token.text; + if (typeof value === "string") { + return value; + } + } + return ""; +} + +function tokenLanguage(token: unknown): string { + if (typeof token === "object" && token !== null && "lang" in token) { + const value = token.lang; + if (typeof value === "string") { + return value; + } + } + return ""; +} + +function childTokens(token: unknown): unknown[] { + if (typeof token === "object" && token !== null && "tokens" in token) { + const value = token.tokens; + if (Array.isArray(value)) { + return value; + } + } + return []; +} + +function inlineRuns(tokens: readonly unknown[]): InlineRun[] { + const runs: InlineRun[] = []; + for (const token of tokens) { + const type = tokenType(token); + if (type === "text") { + runs.push({ content: tokenText(token), emphasis: false }); + continue; + } + if (type === "em") { + // Emphasis nests its own text token; the proof payloads never nest + // further, and anything that did would arrive here as an unsupported + // token rather than as silently flattened prose. + for (const child of childTokens(token)) { + if (tokenType(child) !== "text") { + throw new UnsupportedMarkdownError(tokenType(child)); + } + runs.push({ content: tokenText(child), emphasis: true }); + } + continue; + } + throw new UnsupportedMarkdownError(type); + } + return runs; +} + +/** + * The blocks one presentation's Markdown contains. + * + * Blank space between blocks is Markdown's own separator rather than content, + * so it is dropped; every other token this does not understand stops the + * projection. + */ +export function lexProofMarkdown(source: string): Block[] { + const blocks: Block[] = []; + for (const token of marked.lexer(source)) { + const type = tokenType(token); + if (type === "space") { + continue; + } + if (type === "paragraph") { + blocks.push({ kind: "paragraph", runs: inlineRuns(childTokens(token)) }); + continue; + } + if (type === "code") { + blocks.push({ kind: "code", language: tokenLanguage(token), content: tokenText(token) }); + continue; + } + throw new UnsupportedMarkdownError(type); + } + return blocks; +} + +/** The container id of one entry, which every frame reuses for that entry. */ +export function entryContainerId(entryId: string): string { + return `entry/${entryId}`; +} + +/** + * The operations one entry contributes to a frame. + * + * Container ids are derived from the entry's own stable id, so the same entry + * occupies the same container across every frame it appears in and a + * replacement cannot arrive as a new element. + */ +export function entryOperations(entryId: string, blocks: readonly Block[]): Op[] { + const container = entryContainerId(entryId); + const ops: Op[] = [open(container, { layout: { direction: "ttb" } })]; + blocks.forEach((block, index) => { + if (block.kind === "paragraph") { + ops.push(open(`${container}/paragraph/${index}`, { layout: { direction: "ltr" } })); + for (const run of block.runs) { + ops.push(text(run.content, run.emphasis ? { attrs: EMPHASIS_ATTRIBUTE } : {})); + } + ops.push(close()); + return; + } + ops.push(open(`${container}/code/${index}`, { layout: { direction: "ttb" } })); + ops.push(text(block.content)); + ops.push(close()); + }); + ops.push(close()); + return ops; +} + +/** How many terminal rows an entry's blocks occupy. */ +export function blockRows(blocks: readonly Block[]): number { + return blocks.reduce( + (rows, block) => rows + (block.kind === "paragraph" ? 1 : block.content.split("\n").length), + 0, + ); +} + +/** What a container id says the element is. */ +export type OperationRole = "viewport" | "entry" | "paragraph" | "code"; + +export type OperationDescription = + | { readonly kind: "open"; readonly id: string; readonly role: OperationRole } + | { readonly kind: "text"; readonly content: string; readonly attrs: number } + | { readonly kind: "close" }; + +function roleOf(id: string): OperationRole { + const segments = id.split("/"); + if (segments.length >= 4 && segments[2] === "paragraph") { + return "paragraph"; + } + if (segments.length >= 4 && segments[2] === "code") { + return "code"; + } + if (segments[0] === "entry") { + return "entry"; + } + return "viewport"; +} + +/** + * The evidence form of an operation tree, read back off the operations + * themselves rather than recorded alongside them. + * + * Describing the real `Op` objects is what makes this evidence: a description + * assembled in parallel with the tree could agree with an intention the tree + * never carried. + */ +export function describeOperations(ops: readonly Op[]): OperationDescription[] { + return ops.map((op) => { + if ("id" in op) { + return { kind: "open", id: op.id, role: roleOf(op.id) }; + } + if ("content" in op) { + return { kind: "text", content: op.content, attrs: op.attrs ?? 0 }; + } + return { kind: "close" }; + }); +} + +/** The descriptions belonging to one entry's container, including its own open/close. */ +export function entrySlice( + descriptions: readonly OperationDescription[], + entryId: string, +): OperationDescription[] { + const container = entryContainerId(entryId); + const start = descriptions.findIndex( + (description) => description.kind === "open" && description.id === container, + ); + if (start === -1) { + return []; + } + let depth = 0; + for (let index = start; index < descriptions.length; index++) { + const description = descriptions[index]; + if (description.kind === "open") { + depth++; + } + if (description.kind === "close") { + depth--; + if (depth === 0) { + return descriptions.slice(start, index + 1); + } + } + } + return descriptions.slice(start); +} diff --git a/scripts/tests/session-rendering/repository/components/Session/Message/Tool.md b/scripts/tests/session-rendering/repository/components/Session/Message/Tool.md new file mode 100644 index 00000000..6ebcad57 --- /dev/null +++ b/scripts/tests/session-rendering/repository/components/Session/Message/Tool.md @@ -0,0 +1,3 @@ +xmd-proof-tool-repository + + diff --git a/test-weights.json b/test-weights.json index 24158038..57ca070d 100644 --- a/test-weights.json +++ b/test-weights.json @@ -1,8 +1,8 @@ { "version": 1, "source": { - "commit": "a7f60c024a356d6bd75d3bba4a693019693f6466", - "runUrl": "https://github.com/taras/executable.md/actions/runs/33585991716", + "commit": "9a3cf2473ca706c0ac89b66700a539a6ca368908", + "runUrl": "https://github.com/taras/executable.md/actions/runs/34599573472", "attempt": 1, "runner": "ubuntu-latest", "deno": "deno 2.9.5 (stable, release, x86_64-unknown-linux-gnu)", @@ -11,954 +11,1004 @@ }, "runtimes": { "deno": { - "packages/acp/tests/acceptance.test.ts": 5283, - "packages/acp/tests/acpx-checkpoint-meta.test.ts": 7780, - "packages/acp/tests/acpx-materialization.test.ts": 8165, - "packages/acp/tests/acpx-transient-env.test.ts": 1829, - "packages/acp/tests/adapter-materialization.test.ts": 76640, - "packages/acp/tests/adapter-protocol.test.ts": 42448, - "packages/acp/tests/native-launch.test.ts": 4700, - "packages/acp/tests/permission-bridge.test.ts": 3739, - "packages/acp/tests/provider.test.ts": 4458, - "packages/acp/tests/serial-queue.test.ts": 1565, - "packages/acp/tests/session-key.test.ts": 3521, - "packages/acp/tests/session-route.test.ts": 3748, - "packages/cli/tests/agent-adapters.test.ts": 5790, - "packages/cli/tests/agent-cli.test.ts": 25306, - "packages/cli/tests/agent-config.test.ts": 3328, - "packages/cli/tests/agent-session-coordinator.test.ts": 3988, - "packages/cli/tests/cli-help.test.ts": 14811, - "packages/cli/tests/command.test.ts": 10132, - "packages/cli/tests/compiled-upgrade.test.ts": 10076, - "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 8054, - "packages/cli/tests/document-suites/props/props-markdown.test.ts": 7565, - "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 11440, - "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 9031, - "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 14599, - "packages/cli/tests/fetch-cli.test.ts": 3793, - "packages/cli/tests/file-stream.test.ts": 1785, - "packages/cli/tests/inline-cli.test.ts": 29574, - "packages/cli/tests/launch-timeout.test.ts": 11598, - "packages/cli/tests/packaged-document.test.ts": 4824, - "packages/cli/tests/plan-args.test.ts": 2227, - "packages/cli/tests/plan-cli.test.ts": 32382, - "packages/cli/tests/plan-command-document.test.ts": 5278, - "packages/cli/tests/plan-component.test.ts": 7218, - "packages/cli/tests/plan-host-acts.test.ts": 5649, - "packages/cli/tests/plan.test.ts": 22020, - "packages/cli/tests/process-retention.test.ts": 5492, - "packages/cli/tests/props-cli.test.ts": 28673, - "packages/cli/tests/props-schema.test.ts": 3756, - "packages/cli/tests/props-sources.test.ts": 2294, - "packages/cli/tests/pull-request-read-fork.test.ts": 7542, - "packages/cli/tests/run-composition-deno.test.ts": 7396, - "packages/cli/tests/run-composition-nested.test.ts": 20736, - "packages/cli/tests/run-composition.test.ts": 6713, - "packages/cli/tests/run-deadline.test.ts": 8385, - "packages/cli/tests/run-timeouts.test.ts": 12819, - "packages/cli/tests/secret-detection-cli.test.ts": 19341, - "packages/cli/tests/service-document.test.ts": 4925, - "packages/cli/tests/service-host.test.ts": 4857, - "packages/cli/tests/session-launch-cli.test.ts": 11117, - "packages/cli/tests/stdout-delivery.test.ts": 1558, - "packages/cli/tests/syntax-cli.test.ts": 20524, - "packages/cli/tests/targets-cli.test.ts": 26747, - "packages/cli/tests/test-target.test.ts": 40235, - "packages/cli/tests/testing-activation.test.ts": 4420, - "packages/cli/tests/testing-execution-host.test.ts": 37159, - "packages/cli/tests/upgrade-cli.test.ts": 19987, - "packages/cli/tests/upgrade-command-document.test.ts": 6720, - "packages/cli/tests/upgrade-output.test.ts": 4168, - "packages/cli/tests/value-root.test.ts": 17320, - "packages/cli/tests/verbose-component.test.ts": 5037, - "packages/cli/tests/workflow-agent-sessions.test.ts": 20886, - "packages/cli/tests/workflow-agent.test.ts": 17623, - "packages/cli/tests/workflow-cli.test.ts": 98597, - "packages/cli/tests/workflow-crash.test.ts": 81856, - "packages/cli/tests/workflow-declaration.test.ts": 3993, - "packages/cli/tests/workflow-export-publication.test.ts": 18217, - "packages/cli/tests/workflow-fetch.test.ts": 8400, - "packages/cli/tests/workflow-fork.test.ts": 85734, - "packages/cli/tests/workflow-host.test.ts": 14016, - "packages/cli/tests/workflow-inspection.test.ts": 114902, - "packages/cli/tests/workflow-installation.test.ts": 6023, - "packages/cli/tests/workflow-lifecycle-control.test.ts": 20784, - "packages/cli/tests/workflow-retention.test.ts": 7188, - "packages/cli/tests/workflow-suspension.test.ts": 8876, - "packages/code-review-agent/tests/doctor.test.ts": 1538, - "packages/code-review-agent/tests/parse-diagnostics.test.ts": 1625, - "packages/code-review-agent/tests/parse-diff.test.ts": 1564, - "packages/code-review-agent/tests/parse-doctor.test.ts": 1646, - "packages/code-review-agent/tests/parse-oxlint.test.ts": 1560, - "packages/code-review-agent/tests/policy.test.ts": 1561, - "packages/core/tests/agent-api.test.ts": 1568, - "packages/core/tests/agent-components.test.ts": 4215, - "packages/core/tests/agent-function-components.test.ts": 4740, - "packages/core/tests/agent-session-launch.test.ts": 5083, - "packages/core/tests/agent-stack.test.ts": 3866, - "packages/core/tests/answers-component.test.ts": 4210, - "packages/core/tests/answers-expansion-recursion.test.ts": 2797, - "packages/core/tests/capture-errors.test.ts": 3056, - "packages/core/tests/capture-props.test.ts": 2856, - "packages/core/tests/cli-journal.test.ts": 11900, - "packages/core/tests/code-block-component.test.ts": 4731, - "packages/core/tests/compiler-boundary.test.ts": 3397, - "packages/core/tests/component-api.test.ts": 1978, - "packages/core/tests/component-registration.test.ts": 4220, - "packages/core/tests/component-returns.test.ts": 4576, - "packages/core/tests/component-schema-conformance.test.ts": 2408, - "packages/core/tests/config-api.test.ts": 3675, - "packages/core/tests/construct-error-observation.test.ts": 3105, - "packages/core/tests/contextual-cwd.test.ts": 4647, - "packages/core/tests/daemon-integration.test.ts": 4185, - "packages/core/tests/daemon.test.ts": 2200, - "packages/core/tests/declared-markdown-component.test.ts": 4411, - "packages/core/tests/document-output-api.test.ts": 1546, - "packages/core/tests/document-target-execution.test.ts": 6129, - "packages/core/tests/document-targets.test.ts": 3201, - "packages/core/tests/document-validation.test.ts": 4803, - "packages/core/tests/each.test.ts": 3659, - "packages/core/tests/elicit-component.test.ts": 4125, - "packages/core/tests/ephemeral-service.test.ts": 4063, - "packages/core/tests/eval-bindings.test.ts": 3639, - "packages/core/tests/eval-context.test.ts": 2264, - "packages/core/tests/eval-durable.test.ts": 3691, - "packages/core/tests/eval-error-mode.test.ts": 3951, - "packages/core/tests/eval-interpolate.test.ts": 1609, - "packages/core/tests/eval-middleware.test.ts": 2331, - "packages/core/tests/eval-persist.test.ts": 3715, - "packages/core/tests/eval-return.test.ts": 3635, - "packages/core/tests/eval-scope.test.ts": 3562, - "packages/core/tests/eval-timeout.test.ts": 3693, - "packages/core/tests/eval-transform.test.ts": 2144, - "packages/core/tests/exec-timeout.test.ts": 3666, - "packages/core/tests/execute.test.ts": 4251, - "packages/core/tests/execution-protocol.test.ts": 5110, - "packages/core/tests/expand.test.ts": 3466, - "packages/core/tests/expansion-identity.test.ts": 4325, - "packages/core/tests/expansion-metadata.test.ts": 3098, - "packages/core/tests/expression-props.test.ts": 4191, - "packages/core/tests/fail-component.test.ts": 3900, - "packages/core/tests/failure-printing.test.ts": 3936, - "packages/core/tests/fatal-cause.test.ts": 3092, - "packages/core/tests/fetch-component.test.ts": 5225, - "packages/core/tests/file-component.test.ts": 5638, - "packages/core/tests/file-delete-component.test.ts": 3848, - "packages/core/tests/files-fatal.test.ts": 4685, - "packages/core/tests/foreground-exec.test.ts": 4777, - "packages/core/tests/frontmatter.test.ts": 2096, - "packages/core/tests/function-components.test.ts": 4213, - "packages/core/tests/generated-xmd.test.ts": 4897, - "packages/core/tests/glob-api.test.ts": 1973, - "packages/core/tests/glob-component.test.ts": 4357, - "packages/core/tests/guarded-journal.test.ts": 3730, - "packages/core/tests/has-content.test.ts": 3011, - "packages/core/tests/heal.test.ts": 2979, - "packages/core/tests/if.test.ts": 4298, - "packages/core/tests/inline-root.test.ts": 3842, - "packages/core/tests/invocation-failures.test.ts": 2212, - "packages/core/tests/invocation-identity.test.ts": 4428, - "packages/core/tests/invocation-scope.test.ts": 3149, - "packages/core/tests/journal-source-position.test.ts": 4053, - "packages/core/tests/json-component.test.ts": 3987, - "packages/core/tests/json.test.ts": 2077, - "packages/core/tests/let.test.ts": 3718, - "packages/core/tests/loaded-copy-files.test.ts": 2571, - "packages/core/tests/loop.test.ts": 4420, - "packages/core/tests/named-slots.test.ts": 4439, - "packages/core/tests/output-error-mode.test.ts": 4563, - "packages/core/tests/output-normalize.test.ts": 1590, - "packages/core/tests/output-terminal.test.ts": 1693, - "packages/core/tests/parse-components.test.ts": 3669, - "packages/core/tests/props-binding.test.ts": 3753, - "packages/core/tests/registered-printed-errors.test.ts": 2887, - "packages/core/tests/replay-stream.test.ts": 1574, - "packages/core/tests/retain.test.ts": 3030, - "packages/core/tests/root-props.test.ts": 3692, - "packages/core/tests/root-provider.test.ts": 3881, - "packages/core/tests/sample-component.test.ts": 4406, - "packages/core/tests/scanner.test.ts": 2153, - "packages/core/tests/scope-local.test.ts": 1581, - "packages/core/tests/secret-detection.test.ts": 4454, - "packages/core/tests/secret-files.test.ts": 2107, - "packages/core/tests/secret-rules.test.ts": 2139, - "packages/core/tests/secret-scanner-baseline.test.ts": 1793, - "packages/core/tests/secret-scanner.test.ts": 1970, - "packages/core/tests/source-position.test.ts": 3418, - "packages/core/tests/state-ownership.test.ts": 3530, - "packages/core/tests/streaming-emission.test.ts": 3463, - "packages/core/tests/switch.test.ts": 4151, - "packages/core/tests/syntax-catalog.test.ts": 4161, - "packages/core/tests/temp-dir.test.ts": 5930, - "packages/core/tests/temp-file-compiler.test.ts": 2194, - "packages/core/tests/text-interpolation.test.ts": 2742, - "packages/core/tests/try-content.test.ts": 2729, - "packages/core/tests/unused-in-diff.test.ts": 3481, - "packages/core/tests/validate.test.ts": 2307, - "packages/core/tests/validation-integration.test.ts": 3426, - "packages/core/tests/workflow-component-bundle.test.ts": 3799, - "packages/durable-streams/tests/context.test.ts": 1826, - "packages/durable-streams/tests/deterministic-id.test.ts": 1887, - "packages/durable-streams/tests/divergence-api.test.ts": 1848, - "packages/durable-streams/tests/divergence.test.ts": 1948, - "packages/durable-streams/tests/durable-each.test.ts": 1881, - "packages/durable-streams/tests/durable-position.test.ts": 1869, - "packages/durable-streams/tests/durable-run.test.ts": 1929, - "packages/durable-streams/tests/ephemeral.test.ts": 1870, - "packages/durable-streams/tests/fail-stop.test.ts": 1903, - "packages/durable-streams/tests/guard-stream.test.ts": 1962, - "packages/durable-streams/tests/live-coordinator.test.ts": 1913, - "packages/durable-streams/tests/parse.test.ts": 1849, - "packages/durable-streams/tests/replay-guard.test.ts": 1937, - "packages/durable-streams/tests/replay-index.test.ts": 1707, - "packages/durable-streams/tests/retained.test.ts": 1697, - "packages/durable-streams/tests/serialize-event.test.ts": 1853, - "packages/durable-streams/tests/smoke.test.ts": 1811, - "packages/durable-streams/tests/structured-concurrency.test.ts": 1977, - "packages/durable-streams/tests/terminal-boundary.test.ts": 1927, - "packages/durable-streams/tests/types.test.ts": 1533, - "packages/runtime/tests/agent-session-coordinator.test.ts": 2256, - "packages/runtime/tests/duration.test.ts": 1551, - "packages/runtime/tests/executable-observer.test.ts": 1903, - "packages/runtime/tests/fetch.test.ts": 2326, - "packages/runtime/tests/fs.test.ts": 1750, - "packages/runtime/tests/host-files.test.ts": 2615, - "packages/runtime/tests/native-launcher.test.ts": 3963, - "packages/runtime/tests/process.test.ts": 1742, - "packages/runtime/tests/service.test.ts": 1881, - "packages/test-agent/tests/acp-server.test.ts": 1717, - "packages/test-agent/tests/behavior-engine.test.ts": 4078, - "packages/test-agent/tests/bridge.test.ts": 3411, - "packages/test-agent/tests/command-lazy.test.ts": 7633, - "packages/test-agent/tests/components.test.ts": 60410, - "packages/test-agent/tests/controller.test.ts": 3027, - "packages/test-agent/tests/cross-package-resolution.test.ts": 5854, - "packages/test-agent/tests/native-launch.test.ts": 29835, - "packages/test-agent/tests/net.test.ts": 1621, - "packages/test-agent/tests/profile.test.ts": 3738, - "packages/test-agent/tests/protocol.test.ts": 2530, - "packages/test-agent/tests/provider.test.ts": 4033, - "packages/test-agent/tests/public-api.test.ts": 4704, - "packages/test-agent/tests/route-slot.test.ts": 1578, - "packages/test-agent/tests/smoke.test.ts": 20568, - "packages/test-agent/tests/template.test.ts": 3648, - "packages/test-agent/tests/worker-lifecycle.test.ts": 13116, - "packages/test-support/tests/journal.test.ts": 1890, - "packages/testing/tests/agent-composition.test.ts": 4094, - "packages/testing/tests/assert-throws.test.ts": 5342, - "packages/testing/tests/assert.test.ts": 1636, - "packages/testing/tests/assertions.test.ts": 5964, - "packages/testing/tests/boundary-contract.test.ts": 4847, - "packages/testing/tests/cli.test.ts": 7103, - "packages/testing/tests/execution-harness.test.ts": 8834, - "packages/testing/tests/replay.test.ts": 5272, - "packages/testing/tests/smoke.test.ts": 5416, - "packages/testing/tests/test-component.test.ts": 5981, - "packages/testing/tests/testing-activation.test.ts": 5452, - "packages/testing/tests/testing-boundary.test.ts": 4396, - "packages/testing/tests/testing-mode.test.ts": 6095, - "packages/testing/tests/use-testing.test.ts": 4975, - "packages/web/tests/assets.test.ts": 1645, - "packages/web/tests/client-logic.test.ts": 1674, - "packages/web/tests/compile.test.ts": 4410, - "packages/web/tests/component.test.ts": 4848, - "packages/web/tests/declaration.test.ts": 4293, - "packages/web/tests/document.test.ts": 4594, - "packages/web/tests/elicitation.test.ts": 4168, - "packages/web/tests/live-form.test.ts": 4192, - "packages/web/tests/markdown.test.ts": 1800, - "packages/web/tests/opener.test.ts": 4052, - "packages/web/tests/page.test.ts": 1665, - "packages/web/tests/responder.test.ts": 4331, - "packages/web/tests/server-lifecycle.test.ts": 4217, - "packages/web/tests/server.test.ts": 4669, - "packages/workflow/tests/ambient-authentication.test.ts": 28532, - "packages/workflow/tests/credential-helper.test.ts": 5562, - "packages/workflow/tests/generated-agent-component.test.ts": 9515, - "packages/workflow/tests/generated-observations.test.ts": 3921, - "packages/workflow/tests/git-add-crash.test.ts": 7267, - "packages/workflow/tests/git-add-durability.test.ts": 27331, - "packages/workflow/tests/git-add.test.ts": 35856, - "packages/workflow/tests/git-commit-crash.test.ts": 7505, - "packages/workflow/tests/git-commit-durability.test.ts": 35362, - "packages/workflow/tests/git-commit.test.ts": 41817, - "packages/workflow/tests/git-host-effect.test.ts": 4789, - "packages/workflow/tests/git-push-crash.test.ts": 9785, - "packages/workflow/tests/git-push-durability.test.ts": 40635, - "packages/workflow/tests/git-push.test.ts": 52753, - "packages/workflow/tests/git-switch-crash.test.ts": 7183, - "packages/workflow/tests/git-switch-durability.test.ts": 22945, - "packages/workflow/tests/git-switch.test.ts": 23225, - "packages/workflow/tests/git.test.ts": 1904, - "packages/workflow/tests/issue-github.test.ts": 3925, - "packages/workflow/tests/issue-markdown.test.ts": 11641, - "packages/workflow/tests/issue-records.test.ts": 3760, - "packages/workflow/tests/materialization.test.ts": 5269, - "packages/workflow/tests/public-entrypoint.test.ts": 6246, - "packages/workflow/tests/pull-request-crash.test.ts": 8116, - "packages/workflow/tests/pull-request-durability.test.ts": 41239, - "packages/workflow/tests/pull-request-github.test.ts": 3588, - "packages/workflow/tests/pull-request-read.test.ts": 8044, - "packages/workflow/tests/pull-request-records.test.ts": 3930, - "packages/workflow/tests/pull-request.test.ts": 73197, - "packages/workflow/tests/repository-components.test.ts": 12567, - "packages/workflow/tests/repository-control-plane.test.ts": 11141, - "packages/workflow/tests/repository-materialization.test.ts": 8054, - "packages/workflow/tests/repository-replay.test.ts": 15717, - "packages/workflow/tests/repository-storage.test.ts": 19442, - "packages/workflow/tests/retained-run.test.ts": 4528, - "packages/workflow/tests/run-composition-ambient.test.ts": 12819, - "packages/workflow/tests/run-composition-managed.test.ts": 14874, - "packages/workflow/tests/run-composition-remote.test.ts": 14647, - "packages/workflow/tests/selection-authentication.test.ts": 1872, - "packages/workflow/tests/service-denial.test.ts": 1888, - "packages/workflow/tests/workflow-agent-checkpoints.test.ts": 6318, - "packages/workflow/tests/workflow-agent-sessions.test.ts": 5441, - "packages/workflow/tests/workflow-bundle.test.ts": 4430, - "packages/workflow/tests/workflow-checkpoint.test.ts": 5971, - "packages/workflow/tests/workflow-definition.test.ts": 4089, - "packages/workflow/tests/workflow-export.test.ts": 7855, - "packages/workflow/tests/workflow-fork.test.ts": 4148, - "packages/workflow/tests/workflow-lifecycle-authority.test.ts": 6384, - "packages/workflow/tests/workflow-lifecycle-control.test.ts": 5524, - "packages/workflow/tests/workflow-lifecycle-inspection.test.ts": 11076, - "packages/workflow/tests/workflow-run-journal.test.ts": 7593, - "packages/workflow/tests/workflow-run-storage.test.ts": 8060, - "packages/workflow/tests/workflow-run.test.ts": 4535, - "packages/workflow/tests/workflow-suspension-answer.test.ts": 6337, - "packages/workflow/tests/workflow-suspension.test.ts": 6051, - "packages/workflow/tests/workspace-crash-recovery.test.ts": 8308, - "packages/workflow/tests/workspace-effect-loaded-copy.test.ts": 4604, - "packages/workflow/tests/workspace-effect-transaction.test.ts": 5999, - "packages/workflow/tests/workspace-effect.test.ts": 6722, - "packages/workflow/tests/workspace-files.test.ts": 13754, - "packages/workflow/tests/workspace-root-restoration.test.ts": 7249, - "packages/workflow/tests/workspace-root.test.ts": 5500, - "packages/workflow/tests/workspace-transaction.test.ts": 5513, - "packages/workflow/tests/worktree-replay.test.ts": 6791, - "packages/workflow/tests/xmd-artifact.test.ts": 7215, - "scripts/tests/acpx-vendor.test.ts": 2167, - "scripts/tests/adapter-distribution.test.ts": 4121, - "scripts/tests/adapter-npm-package.test.ts": 33272, - "scripts/tests/adapter-vendor.test.ts": 3688, - "scripts/tests/bootstrap-npm-package.test.ts": 10741, - "scripts/tests/build-npm.test.ts": 5536, - "scripts/tests/build-web-client.test.ts": 30217, - "scripts/tests/bump-version.test.ts": 1649, - "scripts/tests/changed-paths.test.ts": 1646, - "scripts/tests/ci-workflow.test.ts": 3408, - "scripts/tests/cli-npm-bin.test.ts": 90858, - "scripts/tests/cloudflare-dofs-vendor.test.ts": 4410, - "scripts/tests/consumer-cycle.test.ts": 1687, - "scripts/tests/filesystem-contract-workflow.test.ts": 1569, - "scripts/tests/frozen-entry.test.ts": 7698, - "scripts/tests/main-green.test.ts": 1956, - "scripts/tests/main-health.test.ts": 1756, - "scripts/tests/measure-test-weights.test.ts": 2013, - "scripts/tests/no-module-scoped-registry.test.ts": 2411, - "scripts/tests/no-redundant-test-scope.test.ts": 6484, - "scripts/tests/no-sync-filesystem.test.ts": 6480, - "scripts/tests/no-yield-in-finally.test.ts": 2436, - "scripts/tests/oxlint-policy.test.ts": 12638, - "scripts/tests/packaged-document.test.ts": 1533, - "scripts/tests/prefer-effection-operation.test.ts": 7384, - "scripts/tests/prefer-effection-result.test.ts": 5801, - "scripts/tests/prepared-state.test.ts": 2868, - "scripts/tests/publish-workflow-generator.test.ts": 6180, - "scripts/tests/publish-workflow-membership.test.ts": 1552, - "scripts/tests/readme-targets.test.ts": 19063, - "scripts/tests/release-targets.test.ts": 1648, - "scripts/tests/review-infrastructure.test.ts": 5787, - "scripts/tests/runtime-exclusions.test.ts": 2094, - "scripts/tests/runtime-tests.test.ts": 1774, - "scripts/tests/shard-execution.test.ts": 11670, - "scripts/tests/staged-write.test.ts": 1649, - "scripts/tests/test-file-discovery.test.ts": 1842, - "scripts/tests/test-shards.test.ts": 1641, - "scripts/tests/test-weights.test.ts": 1949, - "scripts/tests/tracked.test.ts": 1630, - "scripts/tests/verify-adapter.test.ts": 8052, - "scripts/tests/verify-clean.test.ts": 1837, - "scripts/tests/verify-coordinator.test.ts": 2033, - "scripts/tests/web-client-module.test.ts": 1631, - "scripts/tests/workspace.test.ts": 1607 + "packages/acp/tests/acceptance.test.ts": 5284, + "packages/acp/tests/acpx-checkpoint-meta.test.ts": 8157, + "packages/acp/tests/acpx-materialization.test.ts": 8179, + "packages/acp/tests/acpx-transient-env.test.ts": 1851, + "packages/acp/tests/adapter-materialization.test.ts": 77350, + "packages/acp/tests/adapter-protocol.test.ts": 46882, + "packages/acp/tests/native-launch.test.ts": 5040, + "packages/acp/tests/permission-bridge.test.ts": 4027, + "packages/acp/tests/provider.test.ts": 4795, + "packages/acp/tests/serial-queue.test.ts": 1568, + "packages/acp/tests/session-key.test.ts": 3848, + "packages/acp/tests/session-route.test.ts": 4110, + "packages/cli/tests/agent-adapters.test.ts": 5884, + "packages/cli/tests/agent-cli.test.ts": 23863, + "packages/cli/tests/agent-config.test.ts": 3553, + "packages/cli/tests/agent-session-coordinator.test.ts": 4293, + "packages/cli/tests/cli-help.test.ts": 15707, + "packages/cli/tests/command.test.ts": 10295, + "packages/cli/tests/compiled-upgrade.test.ts": 10653, + "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 8190, + "packages/cli/tests/document-suites/plan/plan-markdown.test.ts": 117678, + "packages/cli/tests/document-suites/props/props-markdown.test.ts": 7888, + "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 11750, + "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 9363, + "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 14986, + "packages/cli/tests/evaluate-component.test.ts": 11948, + "packages/cli/tests/evaluate-workflow.test.ts": 6180, + "packages/cli/tests/fetch-cli.test.ts": 3983, + "packages/cli/tests/file-stream.test.ts": 1802, + "packages/cli/tests/inline-cli.test.ts": 33153, + "packages/cli/tests/launch-timeout.test.ts": 11659, + "packages/cli/tests/packaged-document.test.ts": 5152, + "packages/cli/tests/plan-args.test.ts": 1586, + "packages/cli/tests/plan-cli.test.ts": 90677, + "packages/cli/tests/plan-command-document.test.ts": 10424, + "packages/cli/tests/plan-component.test.ts": 12602, + "packages/cli/tests/plan-host-acts.test.ts": 5848, + "packages/cli/tests/plan.test.ts": 18818, + "packages/cli/tests/process-retention.test.ts": 5434, + "packages/cli/tests/props-cli.test.ts": 29905, + "packages/cli/tests/props-schema.test.ts": 4162, + "packages/cli/tests/props-sources.test.ts": 2361, + "packages/cli/tests/pull-request-read-fork.test.ts": 7698, + "packages/cli/tests/run-composition-deno.test.ts": 7988, + "packages/cli/tests/run-composition-nested.test.ts": 20641, + "packages/cli/tests/run-composition.test.ts": 7226, + "packages/cli/tests/run-deadline.test.ts": 8874, + "packages/cli/tests/run-timeouts.test.ts": 13158, + "packages/cli/tests/secret-detection-cli.test.ts": 20050, + "packages/cli/tests/service-document.test.ts": 5391, + "packages/cli/tests/service-host.test.ts": 5234, + "packages/cli/tests/session-launch-cli.test.ts": 10741, + "packages/cli/tests/stdin-cli.test.ts": 35740, + "packages/cli/tests/stdout-delivery.test.ts": 1561, + "packages/cli/tests/syntax-cli.test.ts": 37082, + "packages/cli/tests/targets-cli.test.ts": 27794, + "packages/cli/tests/test-target.test.ts": 41090, + "packages/cli/tests/testing-activation.test.ts": 4588, + "packages/cli/tests/testing-execution-host.test.ts": 57814, + "packages/cli/tests/upgrade-cli.test.ts": 20347, + "packages/cli/tests/upgrade-command-document.test.ts": 7135, + "packages/cli/tests/upgrade-output.test.ts": 4414, + "packages/cli/tests/value-root.test.ts": 17523, + "packages/cli/tests/verbose-component.test.ts": 5228, + "packages/cli/tests/workflow-agent-sessions.test.ts": 20799, + "packages/cli/tests/workflow-agent.test.ts": 17695, + "packages/cli/tests/workflow-cli.test.ts": 96770, + "packages/cli/tests/workflow-crash.test.ts": 82018, + "packages/cli/tests/workflow-declaration.test.ts": 4266, + "packages/cli/tests/workflow-export-publication.test.ts": 18055, + "packages/cli/tests/workflow-fetch.test.ts": 8789, + "packages/cli/tests/workflow-fork.test.ts": 90811, + "packages/cli/tests/workflow-host.test.ts": 13877, + "packages/cli/tests/workflow-inspection.test.ts": 114944, + "packages/cli/tests/workflow-installation.test.ts": 6340, + "packages/cli/tests/workflow-lifecycle-control.test.ts": 21100, + "packages/cli/tests/workflow-retention.test.ts": 7648, + "packages/cli/tests/workflow-suspension.test.ts": 9280, + "packages/code-review-agent/tests/doctor.test.ts": 1562, + "packages/code-review-agent/tests/parse-diagnostics.test.ts": 1646, + "packages/code-review-agent/tests/parse-diff.test.ts": 1601, + "packages/code-review-agent/tests/parse-doctor.test.ts": 1712, + "packages/code-review-agent/tests/parse-oxlint.test.ts": 1594, + "packages/code-review-agent/tests/policy.test.ts": 1584, + "packages/core/tests/agent-api.test.ts": 1573, + "packages/core/tests/agent-components.test.ts": 4657, + "packages/core/tests/agent-function-components.test.ts": 5186, + "packages/core/tests/agent-session-launch.test.ts": 5718, + "packages/core/tests/agent-stack.test.ts": 4348, + "packages/core/tests/answer-identity.test.ts": 3698, + "packages/core/tests/answers-component.test.ts": 4989, + "packages/core/tests/answers-expansion-recursion.test.ts": 3935, + "packages/core/tests/capture-errors.test.ts": 4134, + "packages/core/tests/capture-props.test.ts": 3943, + "packages/core/tests/cli-journal.test.ts": 12772, + "packages/core/tests/code-block-component.test.ts": 5506, + "packages/core/tests/compiler-boundary.test.ts": 3932, + "packages/core/tests/component-api.test.ts": 3640, + "packages/core/tests/component-registration.test.ts": 4688, + "packages/core/tests/component-returns.test.ts": 5202, + "packages/core/tests/component-schema-conformance.test.ts": 4052, + "packages/core/tests/config-api.test.ts": 4158, + "packages/core/tests/construct-error-observation.test.ts": 4271, + "packages/core/tests/contextual-cwd.test.ts": 5211, + "packages/core/tests/daemon-integration.test.ts": 4676, + "packages/core/tests/daemon.test.ts": 3675, + "packages/core/tests/declared-markdown-component.test.ts": 5040, + "packages/core/tests/document-output-api.test.ts": 1599, + "packages/core/tests/document-target-execution.test.ts": 6903, + "packages/core/tests/document-targets.test.ts": 4015, + "packages/core/tests/document-validation.test.ts": 5103, + "packages/core/tests/documentation-index.test.ts": 3778, + "packages/core/tests/each.test.ts": 3989, + "packages/core/tests/elicit-component.test.ts": 4489, + "packages/core/tests/ephemeral-service.test.ts": 4501, + "packages/core/tests/eval-bindings.test.ts": 3925, + "packages/core/tests/eval-context.test.ts": 2255, + "packages/core/tests/eval-durable.test.ts": 3923, + "packages/core/tests/eval-error-mode.test.ts": 4218, + "packages/core/tests/eval-interpolate.test.ts": 1567, + "packages/core/tests/eval-middleware.test.ts": 3585, + "packages/core/tests/eval-persist.test.ts": 4058, + "packages/core/tests/eval-return.test.ts": 3920, + "packages/core/tests/eval-scope.test.ts": 3832, + "packages/core/tests/eval-timeout.test.ts": 3944, + "packages/core/tests/eval-transform.test.ts": 3571, + "packages/core/tests/evaluate-component.test.ts": 5863, + "packages/core/tests/evaluate-loaded-copy.test.ts": 3999, + "packages/core/tests/evaluate-provider-lifetime.test.ts": 4135, + "packages/core/tests/evaluation-profile.test.ts": 3834, + "packages/core/tests/exec-timeout.test.ts": 4030, + "packages/core/tests/execute.test.ts": 4522, + "packages/core/tests/execution-protocol.test.ts": 5308, + "packages/core/tests/expand.test.ts": 4333, + "packages/core/tests/expansion-identity.test.ts": 4620, + "packages/core/tests/expansion-metadata.test.ts": 3889, + "packages/core/tests/expression-props.test.ts": 4421, + "packages/core/tests/fail-component.test.ts": 4143, + "packages/core/tests/failure-printing.test.ts": 4130, + "packages/core/tests/fatal-cause.test.ts": 3787, + "packages/core/tests/fetch-component.test.ts": 5288, + "packages/core/tests/file-component.test.ts": 5932, + "packages/core/tests/file-delete-component.test.ts": 4166, + "packages/core/tests/files-fatal.test.ts": 4877, + "packages/core/tests/foreground-exec.test.ts": 5000, + "packages/core/tests/frontmatter.test.ts": 3613, + "packages/core/tests/function-components.test.ts": 4479, + "packages/core/tests/generated-composition.test.ts": 4454, + "packages/core/tests/generated-xmd.test.ts": 5983, + "packages/core/tests/glob-api.test.ts": 1979, + "packages/core/tests/glob-component.test.ts": 4670, + "packages/core/tests/guarded-journal.test.ts": 3993, + "packages/core/tests/has-content.test.ts": 3816, + "packages/core/tests/heal.test.ts": 3820, + "packages/core/tests/if.test.ts": 4470, + "packages/core/tests/inline-root.test.ts": 4076, + "packages/core/tests/invocation-failures.test.ts": 3650, + "packages/core/tests/invocation-identity.test.ts": 4405, + "packages/core/tests/invocation-scope.test.ts": 4052, + "packages/core/tests/journal-source-position.test.ts": 4189, + "packages/core/tests/json-component.test.ts": 4258, + "packages/core/tests/json.test.ts": 3602, + "packages/core/tests/let.test.ts": 3982, + "packages/core/tests/loaded-copy-files.test.ts": 3919, + "packages/core/tests/loop.test.ts": 4810, + "packages/core/tests/named-slots.test.ts": 4782, + "packages/core/tests/output-error-mode.test.ts": 4908, + "packages/core/tests/output-normalize.test.ts": 1595, + "packages/core/tests/output-terminal.test.ts": 1705, + "packages/core/tests/parse-components.test.ts": 4038, + "packages/core/tests/plan-response.test.ts": 1617, + "packages/core/tests/props-binding.test.ts": 4083, + "packages/core/tests/protected-content.test.ts": 3573, + "packages/core/tests/registered-printed-errors.test.ts": 3729, + "packages/core/tests/replay-stream.test.ts": 1565, + "packages/core/tests/retain.test.ts": 4042, + "packages/core/tests/root-props.test.ts": 4143, + "packages/core/tests/root-provider.test.ts": 4159, + "packages/core/tests/sample-component.test.ts": 4963, + "packages/core/tests/scanner.test.ts": 3681, + "packages/core/tests/scope-local.test.ts": 1562, + "packages/core/tests/secret-detection.test.ts": 4964, + "packages/core/tests/secret-files.test.ts": 2103, + "packages/core/tests/secret-rules.test.ts": 2107, + "packages/core/tests/secret-scanner-baseline.test.ts": 1724, + "packages/core/tests/secret-scanner.test.ts": 1952, + "packages/core/tests/source-position.test.ts": 3789, + "packages/core/tests/state-ownership.test.ts": 3842, + "packages/core/tests/streaming-emission.test.ts": 3818, + "packages/core/tests/switch.test.ts": 4390, + "packages/core/tests/syntax-catalog.test.ts": 4345, + "packages/core/tests/syntax-component.test.ts": 5218, + "packages/core/tests/syntax-loaded-copy.test.ts": 4043, + "packages/core/tests/temp-dir.test.ts": 6449, + "packages/core/tests/temp-file-compiler.test.ts": 2223, + "packages/core/tests/terminal-grid-structure.test.ts": 3756, + "packages/core/tests/text-interpolation.test.ts": 3759, + "packages/core/tests/try-content.test.ts": 3750, + "packages/core/tests/unused-in-diff.test.ts": 3989, + "packages/core/tests/validate.test.ts": 3698, + "packages/core/tests/validation-integration.test.ts": 3843, + "packages/core/tests/workflow-component-bundle.test.ts": 4153, + "packages/durable-streams/tests/context.test.ts": 1804, + "packages/durable-streams/tests/deterministic-id.test.ts": 1856, + "packages/durable-streams/tests/divergence-api.test.ts": 1831, + "packages/durable-streams/tests/divergence.test.ts": 1901, + "packages/durable-streams/tests/durable-each.test.ts": 1902, + "packages/durable-streams/tests/durable-position.test.ts": 1843, + "packages/durable-streams/tests/durable-run.test.ts": 1861, + "packages/durable-streams/tests/ephemeral.test.ts": 1833, + "packages/durable-streams/tests/fail-stop.test.ts": 1849, + "packages/durable-streams/tests/guard-stream.test.ts": 1913, + "packages/durable-streams/tests/live-coordinator.test.ts": 1872, + "packages/durable-streams/tests/parse.test.ts": 1859, + "packages/durable-streams/tests/replay-guard.test.ts": 1959, + "packages/durable-streams/tests/replay-index.test.ts": 1647, + "packages/durable-streams/tests/retained.test.ts": 1707, + "packages/durable-streams/tests/serialize-event.test.ts": 1890, + "packages/durable-streams/tests/smoke.test.ts": 1822, + "packages/durable-streams/tests/structured-concurrency.test.ts": 2020, + "packages/durable-streams/tests/terminal-boundary.test.ts": 1881, + "packages/durable-streams/tests/types.test.ts": 1543, + "packages/runtime/tests/agent-session-coordinator.test.ts": 2238, + "packages/runtime/tests/duration.test.ts": 1558, + "packages/runtime/tests/executable-observer.test.ts": 1936, + "packages/runtime/tests/fetch.test.ts": 2440, + "packages/runtime/tests/fs.test.ts": 1776, + "packages/runtime/tests/host-files.test.ts": 2640, + "packages/runtime/tests/native-launcher.test.ts": 4007, + "packages/runtime/tests/process.test.ts": 1789, + "packages/runtime/tests/service.test.ts": 1907, + "packages/test-agent/tests/acp-server.test.ts": 1699, + "packages/test-agent/tests/behavior-engine.test.ts": 4358, + "packages/test-agent/tests/bridge.test.ts": 3772, + "packages/test-agent/tests/command-lazy.test.ts": 8022, + "packages/test-agent/tests/components.test.ts": 61161, + "packages/test-agent/tests/controller.test.ts": 3022, + "packages/test-agent/tests/cross-package-resolution.test.ts": 6168, + "packages/test-agent/tests/native-launch.test.ts": 30671, + "packages/test-agent/tests/net.test.ts": 1673, + "packages/test-agent/tests/profile.test.ts": 3959, + "packages/test-agent/tests/protocol.test.ts": 2581, + "packages/test-agent/tests/provider.test.ts": 4325, + "packages/test-agent/tests/public-api.test.ts": 5187, + "packages/test-agent/tests/route-slot.test.ts": 1580, + "packages/test-agent/tests/smoke.test.ts": 21034, + "packages/test-agent/tests/template.test.ts": 4048, + "packages/test-agent/tests/worker-lifecycle.test.ts": 13294, + "packages/test-support/tests/journal.test.ts": 1845, + "packages/testing/tests/agent-composition.test.ts": 4328, + "packages/testing/tests/assert-throws.test.ts": 5525, + "packages/testing/tests/assert.test.ts": 1585, + "packages/testing/tests/assertions.test.ts": 6154, + "packages/testing/tests/boundary-contract.test.ts": 5112, + "packages/testing/tests/cli.test.ts": 7178, + "packages/testing/tests/execution-harness.test.ts": 8919, + "packages/testing/tests/replay.test.ts": 5468, + "packages/testing/tests/smoke.test.ts": 5639, + "packages/testing/tests/test-component.test.ts": 6120, + "packages/testing/tests/testing-activation.test.ts": 5796, + "packages/testing/tests/testing-boundary.test.ts": 4667, + "packages/testing/tests/testing-mode.test.ts": 6442, + "packages/testing/tests/use-testing.test.ts": 5298, + "packages/web/tests/assets.test.ts": 1643, + "packages/web/tests/client-logic.test.ts": 1700, + "packages/web/tests/compile.test.ts": 4732, + "packages/web/tests/component.test.ts": 5277, + "packages/web/tests/declaration.test.ts": 4430, + "packages/web/tests/document.test.ts": 4682, + "packages/web/tests/elicitation.test.ts": 4341, + "packages/web/tests/live-form.test.ts": 4294, + "packages/web/tests/markdown.test.ts": 1793, + "packages/web/tests/opener.test.ts": 4309, + "packages/web/tests/page.test.ts": 1625, + "packages/web/tests/responder.test.ts": 4558, + "packages/web/tests/server-lifecycle.test.ts": 4450, + "packages/web/tests/server.test.ts": 4767, + "packages/workflow/tests/ambient-authentication.test.ts": 27268, + "packages/workflow/tests/credential-helper.test.ts": 5686, + "packages/workflow/tests/generated-agent-component.test.ts": 9729, + "packages/workflow/tests/generated-observations.test.ts": 4129, + "packages/workflow/tests/git-add-crash.test.ts": 7401, + "packages/workflow/tests/git-add-durability.test.ts": 26908, + "packages/workflow/tests/git-add.test.ts": 36233, + "packages/workflow/tests/git-commit-crash.test.ts": 7714, + "packages/workflow/tests/git-commit-durability.test.ts": 35424, + "packages/workflow/tests/git-commit.test.ts": 42345, + "packages/workflow/tests/git-host-effect.test.ts": 5176, + "packages/workflow/tests/git-push-crash.test.ts": 10630, + "packages/workflow/tests/git-push-durability.test.ts": 43607, + "packages/workflow/tests/git-push.test.ts": 53362, + "packages/workflow/tests/git-switch-crash.test.ts": 7308, + "packages/workflow/tests/git-switch-durability.test.ts": 22701, + "packages/workflow/tests/git-switch.test.ts": 24683, + "packages/workflow/tests/git.test.ts": 1928, + "packages/workflow/tests/issue-github.test.ts": 4314, + "packages/workflow/tests/issue-markdown.test.ts": 11688, + "packages/workflow/tests/issue-records.test.ts": 4026, + "packages/workflow/tests/materialization.test.ts": 5747, + "packages/workflow/tests/public-entrypoint.test.ts": 6990, + "packages/workflow/tests/pull-request-crash.test.ts": 9215, + "packages/workflow/tests/pull-request-durability.test.ts": 48666, + "packages/workflow/tests/pull-request-github.test.ts": 4168, + "packages/workflow/tests/pull-request-read.test.ts": 8330, + "packages/workflow/tests/pull-request-records.test.ts": 4163, + "packages/workflow/tests/pull-request.test.ts": 75205, + "packages/workflow/tests/repository-components.test.ts": 13308, + "packages/workflow/tests/repository-control-plane.test.ts": 11944, + "packages/workflow/tests/repository-materialization.test.ts": 8655, + "packages/workflow/tests/repository-replay.test.ts": 16215, + "packages/workflow/tests/repository-storage.test.ts": 19455, + "packages/workflow/tests/retained-run.test.ts": 4793, + "packages/workflow/tests/run-composition-ambient.test.ts": 12903, + "packages/workflow/tests/run-composition-managed.test.ts": 15191, + "packages/workflow/tests/run-composition-remote.test.ts": 14670, + "packages/workflow/tests/selection-authentication.test.ts": 1824, + "packages/workflow/tests/service-denial.test.ts": 1869, + "packages/workflow/tests/workflow-agent-checkpoints.test.ts": 6585, + "packages/workflow/tests/workflow-agent-sessions.test.ts": 5447, + "packages/workflow/tests/workflow-bundle.test.ts": 4590, + "packages/workflow/tests/workflow-checkpoint.test.ts": 6096, + "packages/workflow/tests/workflow-definition.test.ts": 4317, + "packages/workflow/tests/workflow-export.test.ts": 7932, + "packages/workflow/tests/workflow-fork.test.ts": 4298, + "packages/workflow/tests/workflow-lifecycle-authority.test.ts": 6430, + "packages/workflow/tests/workflow-lifecycle-control.test.ts": 5658, + "packages/workflow/tests/workflow-lifecycle-inspection.test.ts": 11174, + "packages/workflow/tests/workflow-run-journal.test.ts": 7803, + "packages/workflow/tests/workflow-run-storage.test.ts": 8223, + "packages/workflow/tests/workflow-run.test.ts": 4655, + "packages/workflow/tests/workflow-suspension-answer.test.ts": 6529, + "packages/workflow/tests/workflow-suspension.test.ts": 6030, + "packages/workflow/tests/workspace-crash-recovery.test.ts": 8406, + "packages/workflow/tests/workspace-effect-loaded-copy.test.ts": 4675, + "packages/workflow/tests/workspace-effect-transaction.test.ts": 6131, + "packages/workflow/tests/workspace-effect.test.ts": 6881, + "packages/workflow/tests/workspace-files.test.ts": 13225, + "packages/workflow/tests/workspace-root-restoration.test.ts": 7259, + "packages/workflow/tests/workspace-root.test.ts": 5556, + "packages/workflow/tests/workspace-transaction.test.ts": 5580, + "packages/workflow/tests/worktree-replay.test.ts": 6891, + "packages/workflow/tests/xmd-artifact.test.ts": 7282, + "scripts/tests/acpx-vendor.test.ts": 2145, + "scripts/tests/adapter-distribution.test.ts": 4456, + "scripts/tests/adapter-npm-package.test.ts": 32561, + "scripts/tests/adapter-vendor.test.ts": 4005, + "scripts/tests/bootstrap-npm-package.test.ts": 11117, + "scripts/tests/build-npm.test.ts": 7676, + "scripts/tests/build-web-client.test.ts": 30330, + "scripts/tests/bump-version.test.ts": 1695, + "scripts/tests/changed-paths.test.ts": 1610, + "scripts/tests/ci-workflow.test.ts": 3344, + "scripts/tests/cli-npm-bin.test.ts": 150877, + "scripts/tests/cloudflare-dofs-vendor.test.ts": 4399, + "scripts/tests/consumer-cycle.test.ts": 1664, + "scripts/tests/documentation-validation.test.ts": 5904, + "scripts/tests/filesystem-contract-workflow.test.ts": 1567, + "scripts/tests/frozen-entry.test.ts": 8436, + "scripts/tests/jsr-consumer-documentation.test.ts": 17639, + "scripts/tests/main-green.test.ts": 1943, + "scripts/tests/main-health.test.ts": 1700, + "scripts/tests/measure-test-weights.test.ts": 2016, + "scripts/tests/no-module-scoped-registry.test.ts": 2388, + "scripts/tests/no-redundant-test-scope.test.ts": 6548, + "scripts/tests/no-sync-filesystem.test.ts": 6411, + "scripts/tests/no-yield-in-finally.test.ts": 2415, + "scripts/tests/oxlint-policy.test.ts": 12343, + "scripts/tests/packaged-document.test.ts": 1586, + "scripts/tests/prefer-effection-operation.test.ts": 7361, + "scripts/tests/prefer-effection-result.test.ts": 5705, + "scripts/tests/prepared-state.test.ts": 2845, + "scripts/tests/publish-workflow-generator.test.ts": 6247, + "scripts/tests/publish-workflow-membership.test.ts": 1604, + "scripts/tests/readme-targets.test.ts": 19289, + "scripts/tests/release-targets.test.ts": 1673, + "scripts/tests/review-infrastructure.test.ts": 6112, + "scripts/tests/runtime-exclusions.test.ts": 2113, + "scripts/tests/runtime-tests.test.ts": 1733, + "scripts/tests/scope-bound-event-registration.test.ts": 6435, + "scripts/tests/session-rendering.test.ts": 15713, + "scripts/tests/shard-execution.test.ts": 11483, + "scripts/tests/staged-write.test.ts": 1587, + "scripts/tests/test-file-discovery.test.ts": 1804, + "scripts/tests/test-shards.test.ts": 1618, + "scripts/tests/test-weights.test.ts": 1910, + "scripts/tests/tracked.test.ts": 1577, + "scripts/tests/verify-adapter.test.ts": 7958, + "scripts/tests/verify-clean.test.ts": 1825, + "scripts/tests/verify-coordinator.test.ts": 1918, + "scripts/tests/web-client-module.test.ts": 1579, + "scripts/tests/workspace.test.ts": 1569 }, "node": { - "packages/acp/tests/acceptance.test.ts": 2110, - "packages/acp/tests/acpx-checkpoint-meta.test.ts": 4910, - "packages/acp/tests/acpx-materialization.test.ts": 7162, - "packages/acp/tests/acpx-transient-env.test.ts": 873, - "packages/acp/tests/adapter-materialization.test.ts": 75221, - "packages/acp/tests/adapter-protocol.test.ts": 38157, - "packages/acp/tests/native-launch.test.ts": 2018, - "packages/acp/tests/permission-bridge.test.ts": 1215, - "packages/acp/tests/provider.test.ts": 1747, - "packages/acp/tests/serial-queue.test.ts": 516, - "packages/acp/tests/session-key.test.ts": 547, - "packages/cli/tests/agent-adapters.test.ts": 2910, - "packages/cli/tests/agent-cli.test.ts": 26388, - "packages/cli/tests/agent-config.test.ts": 485, - "packages/cli/tests/agent-session-coordinator.test.ts": 1329, - "packages/cli/tests/cli-help.test.ts": 28686, - "packages/cli/tests/command.test.ts": 14928, - "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 3749, - "packages/cli/tests/document-suites/props/props-markdown.test.ts": 3266, - "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 9851, - "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 5047, - "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 17677, - "packages/cli/tests/fetch-cli.test.ts": 4738, - "packages/cli/tests/file-stream.test.ts": 541, - "packages/cli/tests/inline-cli.test.ts": 59512, - "packages/cli/tests/launch-timeout.test.ts": 20558, - "packages/cli/tests/packaged-document.test.ts": 1683, - "packages/cli/tests/plan-args.test.ts": 652, - "packages/cli/tests/plan-cli.test.ts": 48057, - "packages/cli/tests/plan-command-document.test.ts": 2152, - "packages/cli/tests/plan-component.test.ts": 5086, - "packages/cli/tests/plan-host-acts.test.ts": 2634, - "packages/cli/tests/plan.test.ts": 23344, - "packages/cli/tests/process-retention.test.ts": 4686, - "packages/cli/tests/props-cli.test.ts": 60160, - "packages/cli/tests/props-schema.test.ts": 1315, - "packages/cli/tests/props-sources.test.ts": 684, - "packages/cli/tests/run-composition.test.ts": 4213, - "packages/cli/tests/run-deadline.test.ts": 3800, - "packages/cli/tests/run-timeouts.test.ts": 19440, - "packages/cli/tests/secret-detection-cli.test.ts": 36835, - "packages/cli/tests/service-document.test.ts": 2570, - "packages/cli/tests/service-host.test.ts": 2346, - "packages/cli/tests/session-launch-cli.test.ts": 10714, - "packages/cli/tests/stdout-delivery.test.ts": 500, - "packages/cli/tests/syntax-cli.test.ts": 32184, - "packages/cli/tests/targets-cli.test.ts": 49189, - "packages/cli/tests/test-target.test.ts": 76268, - "packages/cli/tests/testing-activation.test.ts": 1478, - "packages/cli/tests/testing-execution-host.test.ts": 54491, - "packages/cli/tests/upgrade-cli.test.ts": 43799, - "packages/cli/tests/upgrade-command-document.test.ts": 5273, - "packages/cli/tests/upgrade-output.test.ts": 1813, - "packages/cli/tests/value-root.test.ts": 30041, - "packages/cli/tests/verbose-component.test.ts": 2031, - "packages/cli/tests/workflow-declaration.test.ts": 1253, - "packages/cli/tests/workflow-host.test.ts": 10928, - "packages/code-review-agent/tests/doctor.test.ts": 481, - "packages/code-review-agent/tests/parse-diagnostics.test.ts": 519, - "packages/code-review-agent/tests/parse-diff.test.ts": 505, - "packages/code-review-agent/tests/parse-doctor.test.ts": 489, - "packages/code-review-agent/tests/parse-oxlint.test.ts": 481, - "packages/code-review-agent/tests/policy.test.ts": 490, - "packages/core/tests/agent-api.test.ts": 518, - "packages/core/tests/agent-components.test.ts": 1951, - "packages/core/tests/agent-function-components.test.ts": 2637, - "packages/core/tests/agent-session-launch.test.ts": 2999, - "packages/core/tests/agent-stack.test.ts": 1499, - "packages/core/tests/answers-component.test.ts": 2311, - "packages/core/tests/answers-expansion-recursion.test.ts": 952, - "packages/core/tests/capture-errors.test.ts": 1234, - "packages/core/tests/capture-props.test.ts": 960, - "packages/core/tests/cli-journal.test.ts": 21029, - "packages/core/tests/code-block-component.test.ts": 2963, - "packages/core/tests/compiler-boundary.test.ts": 1120, - "packages/core/tests/component-api.test.ts": 555, - "packages/core/tests/component-registration.test.ts": 2005, - "packages/core/tests/component-returns.test.ts": 2676, - "packages/core/tests/component-schema-conformance.test.ts": 1106, - "packages/core/tests/config-api.test.ts": 1227, - "packages/core/tests/construct-error-observation.test.ts": 1336, - "packages/core/tests/contextual-cwd.test.ts": 2442, - "packages/core/tests/daemon-integration.test.ts": 1837, - "packages/core/tests/daemon.test.ts": 579, - "packages/core/tests/declared-markdown-component.test.ts": 2132, - "packages/core/tests/document-output-api.test.ts": 527, - "packages/core/tests/document-target-execution.test.ts": 4414, - "packages/core/tests/document-targets.test.ts": 1134, - "packages/core/tests/document-validation.test.ts": 2361, - "packages/core/tests/each.test.ts": 1227, - "packages/core/tests/elicit-component.test.ts": 1813, - "packages/core/tests/ephemeral-service.test.ts": 1779, - "packages/core/tests/eval-bindings.test.ts": 1204, - "packages/core/tests/eval-context.test.ts": 612, - "packages/core/tests/eval-durable.test.ts": 1286, - "packages/core/tests/eval-error-mode.test.ts": 1657, - "packages/core/tests/eval-interpolate.test.ts": 526, - "packages/core/tests/eval-middleware.test.ts": 598, - "packages/core/tests/eval-persist.test.ts": 1372, - "packages/core/tests/eval-return.test.ts": 1249, - "packages/core/tests/eval-scope.test.ts": 1146, - "packages/core/tests/eval-timeout.test.ts": 1256, - "packages/core/tests/eval-transform.test.ts": 590, - "packages/core/tests/exec-timeout.test.ts": 1278, - "packages/core/tests/execute.test.ts": 1923, - "packages/core/tests/execution-protocol.test.ts": 2629, - "packages/core/tests/expand.test.ts": 1566, - "packages/core/tests/expansion-identity.test.ts": 2024, - "packages/core/tests/expansion-metadata.test.ts": 1014, - "packages/core/tests/expression-props.test.ts": 1905, - "packages/core/tests/fail-component.test.ts": 1654, - "packages/core/tests/failure-printing.test.ts": 1477, - "packages/core/tests/fatal-cause.test.ts": 875, - "packages/core/tests/fetch-component.test.ts": 3013, - "packages/core/tests/file-component.test.ts": 3444, - "packages/core/tests/file-delete-component.test.ts": 1485, - "packages/core/tests/files-fatal.test.ts": 2434, - "packages/core/tests/foreground-exec.test.ts": 2300, - "packages/core/tests/frontmatter.test.ts": 579, - "packages/core/tests/function-components.test.ts": 2056, - "packages/core/tests/generated-xmd.test.ts": 2603, - "packages/core/tests/glob-api.test.ts": 595, - "packages/core/tests/glob-component.test.ts": 2093, - "packages/core/tests/guarded-journal.test.ts": 1339, - "packages/core/tests/has-content.test.ts": 927, - "packages/core/tests/heal.test.ts": 930, - "packages/core/tests/if.test.ts": 1911, - "packages/core/tests/inline-root.test.ts": 1354, - "packages/core/tests/invocation-failures.test.ts": 631, - "packages/core/tests/invocation-identity.test.ts": 1808, - "packages/core/tests/invocation-scope.test.ts": 1257, - "packages/core/tests/journal-source-position.test.ts": 1451, - "packages/core/tests/json-component.test.ts": 1557, - "packages/core/tests/json.test.ts": 517, - "packages/core/tests/let.test.ts": 1326, + "packages/acp/tests/acceptance.test.ts": 2186, + "packages/acp/tests/acpx-checkpoint-meta.test.ts": 4887, + "packages/acp/tests/acpx-materialization.test.ts": 7113, + "packages/acp/tests/acpx-transient-env.test.ts": 838, + "packages/acp/tests/adapter-materialization.test.ts": 74016, + "packages/acp/tests/adapter-protocol.test.ts": 42641, + "packages/acp/tests/native-launch.test.ts": 2039, + "packages/acp/tests/permission-bridge.test.ts": 1226, + "packages/acp/tests/provider.test.ts": 1764, + "packages/acp/tests/serial-queue.test.ts": 498, + "packages/acp/tests/session-key.test.ts": 527, + "packages/cli/tests/agent-adapters.test.ts": 2824, + "packages/cli/tests/agent-cli.test.ts": 26778, + "packages/cli/tests/agent-config.test.ts": 481, + "packages/cli/tests/agent-session-coordinator.test.ts": 1346, + "packages/cli/tests/cli-help.test.ts": 30156, + "packages/cli/tests/command.test.ts": 14660, + "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 3685, + "packages/cli/tests/document-suites/plan/plan-markdown.test.ts": 170363, + "packages/cli/tests/document-suites/props/props-markdown.test.ts": 3345, + "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 9999, + "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 5402, + "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 18656, + "packages/cli/tests/evaluate-component.test.ts": 15997, + "packages/cli/tests/fetch-cli.test.ts": 5021, + "packages/cli/tests/file-stream.test.ts": 557, + "packages/cli/tests/inline-cli.test.ts": 66722, + "packages/cli/tests/launch-timeout.test.ts": 20535, + "packages/cli/tests/packaged-document.test.ts": 1649, + "packages/cli/tests/plan-args.test.ts": 514, + "packages/cli/tests/plan-cli.test.ts": 108778, + "packages/cli/tests/plan-command-document.test.ts": 8152, + "packages/cli/tests/plan-component.test.ts": 11282, + "packages/cli/tests/plan-host-acts.test.ts": 2563, + "packages/cli/tests/plan.test.ts": 18700, + "packages/cli/tests/process-retention.test.ts": 4844, + "packages/cli/tests/props-cli.test.ts": 63394, + "packages/cli/tests/props-schema.test.ts": 1338, + "packages/cli/tests/props-sources.test.ts": 702, + "packages/cli/tests/run-composition.test.ts": 4361, + "packages/cli/tests/run-deadline.test.ts": 3889, + "packages/cli/tests/run-timeouts.test.ts": 20086, + "packages/cli/tests/secret-detection-cli.test.ts": 38318, + "packages/cli/tests/service-document.test.ts": 2685, + "packages/cli/tests/service-host.test.ts": 2425, + "packages/cli/tests/session-launch-cli.test.ts": 11008, + "packages/cli/tests/stdin-cli.test.ts": 61265, + "packages/cli/tests/stdout-delivery.test.ts": 518, + "packages/cli/tests/syntax-cli.test.ts": 64419, + "packages/cli/tests/targets-cli.test.ts": 49866, + "packages/cli/tests/test-target.test.ts": 80161, + "packages/cli/tests/testing-activation.test.ts": 1540, + "packages/cli/tests/testing-execution-host.test.ts": 92870, + "packages/cli/tests/upgrade-cli.test.ts": 47315, + "packages/cli/tests/upgrade-command-document.test.ts": 6154, + "packages/cli/tests/upgrade-output.test.ts": 1977, + "packages/cli/tests/value-root.test.ts": 31848, + "packages/cli/tests/verbose-component.test.ts": 2168, + "packages/cli/tests/workflow-declaration.test.ts": 1274, + "packages/cli/tests/workflow-host.test.ts": 11502, + "packages/code-review-agent/tests/doctor.test.ts": 508, + "packages/code-review-agent/tests/parse-diagnostics.test.ts": 534, + "packages/code-review-agent/tests/parse-diff.test.ts": 514, + "packages/code-review-agent/tests/parse-doctor.test.ts": 506, + "packages/code-review-agent/tests/parse-oxlint.test.ts": 485, + "packages/code-review-agent/tests/policy.test.ts": 524, + "packages/core/tests/agent-api.test.ts": 504, + "packages/core/tests/agent-components.test.ts": 2007, + "packages/core/tests/agent-function-components.test.ts": 2740, + "packages/core/tests/agent-session-launch.test.ts": 3130, + "packages/core/tests/agent-stack.test.ts": 1583, + "packages/core/tests/answer-identity.test.ts": 543, + "packages/core/tests/answers-component.test.ts": 2521, + "packages/core/tests/answers-expansion-recursion.test.ts": 992, + "packages/core/tests/capture-errors.test.ts": 1293, + "packages/core/tests/capture-props.test.ts": 1024, + "packages/core/tests/cli-journal.test.ts": 21883, + "packages/core/tests/code-block-component.test.ts": 3206, + "packages/core/tests/compiler-boundary.test.ts": 1219, + "packages/core/tests/component-api.test.ts": 571, + "packages/core/tests/component-registration.test.ts": 2062, + "packages/core/tests/component-returns.test.ts": 2982, + "packages/core/tests/component-schema-conformance.test.ts": 1163, + "packages/core/tests/config-api.test.ts": 1334, + "packages/core/tests/construct-error-observation.test.ts": 1433, + "packages/core/tests/contextual-cwd.test.ts": 2477, + "packages/core/tests/daemon-integration.test.ts": 1930, + "packages/core/tests/daemon.test.ts": 578, + "packages/core/tests/declared-markdown-component.test.ts": 2606, + "packages/core/tests/document-output-api.test.ts": 532, + "packages/core/tests/document-target-execution.test.ts": 4919, + "packages/core/tests/document-targets.test.ts": 1231, + "packages/core/tests/document-validation.test.ts": 2706, + "packages/core/tests/documentation-index.test.ts": 848, + "packages/core/tests/each.test.ts": 1323, + "packages/core/tests/elicit-component.test.ts": 1885, + "packages/core/tests/ephemeral-service.test.ts": 1883, + "packages/core/tests/eval-bindings.test.ts": 1254, + "packages/core/tests/eval-context.test.ts": 609, + "packages/core/tests/eval-durable.test.ts": 1323, + "packages/core/tests/eval-error-mode.test.ts": 1737, + "packages/core/tests/eval-interpolate.test.ts": 532, + "packages/core/tests/eval-middleware.test.ts": 604, + "packages/core/tests/eval-persist.test.ts": 1413, + "packages/core/tests/eval-return.test.ts": 1306, + "packages/core/tests/eval-scope.test.ts": 1197, + "packages/core/tests/eval-timeout.test.ts": 1274, + "packages/core/tests/eval-transform.test.ts": 603, + "packages/core/tests/evaluate-component.test.ts": 3750, + "packages/core/tests/evaluate-loaded-copy.test.ts": 1366, + "packages/core/tests/evaluate-provider-lifetime.test.ts": 1448, + "packages/core/tests/evaluation-profile.test.ts": 911, + "packages/core/tests/exec-timeout.test.ts": 1352, + "packages/core/tests/execute.test.ts": 2020, + "packages/core/tests/execution-protocol.test.ts": 2819, + "packages/core/tests/expand.test.ts": 1629, + "packages/core/tests/expansion-identity.test.ts": 2046, + "packages/core/tests/expansion-metadata.test.ts": 1058, + "packages/core/tests/expression-props.test.ts": 1959, + "packages/core/tests/fail-component.test.ts": 1693, + "packages/core/tests/failure-printing.test.ts": 1525, + "packages/core/tests/fatal-cause.test.ts": 913, + "packages/core/tests/fetch-component.test.ts": 3088, + "packages/core/tests/file-component.test.ts": 3407, + "packages/core/tests/file-delete-component.test.ts": 1521, + "packages/core/tests/files-fatal.test.ts": 2483, + "packages/core/tests/foreground-exec.test.ts": 2345, + "packages/core/tests/frontmatter.test.ts": 551, + "packages/core/tests/function-components.test.ts": 2057, + "packages/core/tests/generated-composition.test.ts": 2114, + "packages/core/tests/generated-xmd.test.ts": 3635, + "packages/core/tests/glob-api.test.ts": 603, + "packages/core/tests/glob-component.test.ts": 2111, + "packages/core/tests/guarded-journal.test.ts": 1374, + "packages/core/tests/has-content.test.ts": 957, + "packages/core/tests/heal.test.ts": 950, + "packages/core/tests/if.test.ts": 1877, + "packages/core/tests/inline-root.test.ts": 1359, + "packages/core/tests/invocation-failures.test.ts": 600, + "packages/core/tests/invocation-identity.test.ts": 1787, + "packages/core/tests/invocation-scope.test.ts": 1239, + "packages/core/tests/journal-source-position.test.ts": 1492, + "packages/core/tests/json-component.test.ts": 1570, + "packages/core/tests/json.test.ts": 512, + "packages/core/tests/let.test.ts": 1317, "packages/core/tests/loop.test.ts": 2373, - "packages/core/tests/named-slots.test.ts": 2468, - "packages/core/tests/output-error-mode.test.ts": 2544, - "packages/core/tests/output-normalize.test.ts": 535, - "packages/core/tests/output-terminal.test.ts": 680, - "packages/core/tests/parse-components.test.ts": 1413, - "packages/core/tests/props-binding.test.ts": 1401, - "packages/core/tests/registered-printed-errors.test.ts": 847, - "packages/core/tests/replay-stream.test.ts": 509, - "packages/core/tests/retain.test.ts": 1150, - "packages/core/tests/root-props.test.ts": 1405, - "packages/core/tests/root-provider.test.ts": 1311, - "packages/core/tests/sample-component.test.ts": 2389, - "packages/core/tests/scanner.test.ts": 610, - "packages/core/tests/scope-local.test.ts": 511, - "packages/core/tests/secret-detection.test.ts": 2067, - "packages/core/tests/secret-files.test.ts": 745, - "packages/core/tests/secret-rules.test.ts": 854, - "packages/core/tests/secret-scanner-baseline.test.ts": 743, - "packages/core/tests/secret-scanner.test.ts": 725, - "packages/core/tests/source-position.test.ts": 1088, - "packages/core/tests/state-ownership.test.ts": 1146, - "packages/core/tests/streaming-emission.test.ts": 1136, - "packages/core/tests/switch.test.ts": 1880, - "packages/core/tests/syntax-catalog.test.ts": 1700, - "packages/core/tests/temp-dir.test.ts": 3702, - "packages/core/tests/temp-file-compiler.test.ts": 545, - "packages/core/tests/text-interpolation.test.ts": 883, - "packages/core/tests/try-content.test.ts": 893, - "packages/core/tests/unused-in-diff.test.ts": 1373, - "packages/core/tests/validate.test.ts": 815, - "packages/core/tests/validation-integration.test.ts": 1131, - "packages/core/tests/workflow-component-bundle.test.ts": 1509, - "packages/durable-streams/tests/context.test.ts": 523, - "packages/durable-streams/tests/deterministic-id.test.ts": 562, - "packages/durable-streams/tests/divergence-api.test.ts": 549, - "packages/durable-streams/tests/divergence.test.ts": 559, - "packages/durable-streams/tests/durable-each.test.ts": 575, - "packages/durable-streams/tests/durable-position.test.ts": 547, - "packages/durable-streams/tests/durable-run.test.ts": 565, - "packages/durable-streams/tests/ephemeral.test.ts": 544, - "packages/durable-streams/tests/fail-stop.test.ts": 606, - "packages/durable-streams/tests/guard-stream.test.ts": 619, - "packages/durable-streams/tests/live-coordinator.test.ts": 564, - "packages/durable-streams/tests/parse.test.ts": 589, - "packages/durable-streams/tests/replay-guard.test.ts": 585, - "packages/durable-streams/tests/replay-index.test.ts": 561, - "packages/durable-streams/tests/retained.test.ts": 530, - "packages/durable-streams/tests/serialize-event.test.ts": 529, - "packages/durable-streams/tests/smoke.test.ts": 531, - "packages/durable-streams/tests/structured-concurrency.test.ts": 595, - "packages/durable-streams/tests/terminal-boundary.test.ts": 575, - "packages/durable-streams/tests/types.test.ts": 502, - "packages/runtime/tests/duration.test.ts": 498, - "packages/runtime/tests/fetch.test.ts": 1110, - "packages/runtime/tests/fs.test.ts": 549, - "packages/runtime/tests/host-files.test.ts": 1285, - "packages/runtime/tests/native-launcher.test.ts": 2858, - "packages/runtime/tests/process.test.ts": 549, - "packages/runtime/tests/service.test.ts": 524, - "packages/test-agent/tests/acp-server.test.ts": 721, - "packages/test-agent/tests/behavior-engine.test.ts": 1536, - "packages/test-agent/tests/bridge.test.ts": 525, - "packages/test-agent/tests/command-lazy.test.ts": 6427, - "packages/test-agent/tests/components.test.ts": 103438, - "packages/test-agent/tests/controller.test.ts": 798, - "packages/test-agent/tests/cross-package-resolution.test.ts": 3040, - "packages/test-agent/tests/native-launch.test.ts": 52218, - "packages/test-agent/tests/net.test.ts": 589, - "packages/test-agent/tests/profile.test.ts": 1162, - "packages/test-agent/tests/protocol.test.ts": 582, - "packages/test-agent/tests/provider.test.ts": 1331, - "packages/test-agent/tests/public-api.test.ts": 1527, - "packages/test-agent/tests/route-slot.test.ts": 515, - "packages/test-agent/tests/smoke.test.ts": 27717, - "packages/test-agent/tests/template.test.ts": 1162, - "packages/test-agent/tests/worker-lifecycle.test.ts": 22495, - "packages/test-support/tests/journal.test.ts": 488, - "packages/testing/tests/agent-composition.test.ts": 1454, - "packages/testing/tests/assert-throws.test.ts": 3055, - "packages/testing/tests/assert.test.ts": 521, - "packages/testing/tests/assertions.test.ts": 3770, - "packages/testing/tests/boundary-contract.test.ts": 2498, - "packages/testing/tests/cli.test.ts": 11015, - "packages/testing/tests/execution-harness.test.ts": 7363, - "packages/testing/tests/replay.test.ts": 3046, - "packages/testing/tests/smoke.test.ts": 3167, - "packages/testing/tests/test-component.test.ts": 3835, - "packages/testing/tests/testing-activation.test.ts": 3363, - "packages/testing/tests/testing-boundary.test.ts": 1985, - "packages/testing/tests/testing-mode.test.ts": 4044, - "packages/testing/tests/use-testing.test.ts": 2691, - "packages/web/tests/assets.test.ts": 517, - "packages/web/tests/client-logic.test.ts": 548, - "packages/web/tests/compile.test.ts": 1937, - "packages/web/tests/component.test.ts": 2426, - "packages/web/tests/declaration.test.ts": 1639, - "packages/web/tests/document.test.ts": 1771, - "packages/web/tests/elicitation.test.ts": 1563, - "packages/web/tests/live-form.test.ts": 1454, - "packages/web/tests/markdown.test.ts": 702, - "packages/web/tests/opener.test.ts": 1460, - "packages/web/tests/page.test.ts": 494, - "packages/web/tests/responder.test.ts": 1779, - "packages/web/tests/server-lifecycle.test.ts": 1544, - "packages/web/tests/server.test.ts": 2000, - "packages/workflow/tests/generated-observations.test.ts": 1388, - "packages/workflow/tests/git-host-effect.test.ts": 2443, - "packages/workflow/tests/git.test.ts": 524, - "packages/workflow/tests/issue-github.test.ts": 1197, - "packages/workflow/tests/issue-markdown.test.ts": 9804, - "packages/workflow/tests/issue-records.test.ts": 1169, - "packages/workflow/tests/pull-request-github.test.ts": 604, - "packages/workflow/tests/pull-request-records.test.ts": 1205, - "packages/workflow/tests/retained-run.test.ts": 2115, - "packages/workflow/tests/selection-authentication.test.ts": 489, - "packages/workflow/tests/service-denial.test.ts": 526, - "packages/workflow/tests/workflow-bundle.test.ts": 1639, - "packages/workflow/tests/workflow-definition.test.ts": 1246, - "packages/workflow/tests/workflow-fork.test.ts": 1235, - "packages/workflow/tests/workflow-run.test.ts": 1909, - "packages/workflow/tests/workspace-effect.test.ts": 3228, - "packages/workflow/tests/xmd-artifact.test.ts": 3708, - "scripts/tests/adapter-vendor.test.ts": 732, - "scripts/tests/bootstrap-npm-package.test.ts": 8010, - "scripts/tests/bump-version.test.ts": 602, - "scripts/tests/changed-paths.test.ts": 538, - "scripts/tests/ci-workflow.test.ts": 2100, - "scripts/tests/consumer-cycle.test.ts": 676, - "scripts/tests/filesystem-contract-workflow.test.ts": 581, - "scripts/tests/main-green.test.ts": 797, - "scripts/tests/main-health.test.ts": 618, - "scripts/tests/no-module-scoped-registry.test.ts": 1323, - "scripts/tests/no-redundant-test-scope.test.ts": 5347, - "scripts/tests/no-sync-filesystem.test.ts": 5517, - "scripts/tests/no-yield-in-finally.test.ts": 1355, - "scripts/tests/oxlint-policy.test.ts": 10991, - "scripts/tests/packaged-document.test.ts": 492, - "scripts/tests/prefer-effection-operation.test.ts": 6084, - "scripts/tests/prefer-effection-result.test.ts": 4590, - "scripts/tests/publish-workflow-membership.test.ts": 552, - "scripts/tests/review-infrastructure.test.ts": 3229, - "scripts/tests/runtime-exclusions.test.ts": 992, - "scripts/tests/runtime-tests.test.ts": 550, - "scripts/tests/staged-write.test.ts": 544, - "scripts/tests/test-file-discovery.test.ts": 804, - "scripts/tests/test-shards.test.ts": 585, - "scripts/tests/test-weights.test.ts": 706, - "scripts/tests/tracked.test.ts": 511, - "scripts/tests/verify-coordinator.test.ts": 731, - "scripts/tests/web-client-module.test.ts": 544, - "scripts/tests/workspace.test.ts": 509 + "packages/core/tests/named-slots.test.ts": 2380, + "packages/core/tests/output-error-mode.test.ts": 2731, + "packages/core/tests/output-normalize.test.ts": 518, + "packages/core/tests/output-terminal.test.ts": 710, + "packages/core/tests/parse-components.test.ts": 1495, + "packages/core/tests/plan-response.test.ts": 627, + "packages/core/tests/props-binding.test.ts": 1528, + "packages/core/tests/protected-content.test.ts": 568, + "packages/core/tests/registered-printed-errors.test.ts": 910, + "packages/core/tests/replay-stream.test.ts": 519, + "packages/core/tests/retain.test.ts": 1215, + "packages/core/tests/root-props.test.ts": 1509, + "packages/core/tests/root-provider.test.ts": 1392, + "packages/core/tests/sample-component.test.ts": 2519, + "packages/core/tests/scanner.test.ts": 615, + "packages/core/tests/scope-local.test.ts": 521, + "packages/core/tests/secret-detection.test.ts": 2211, + "packages/core/tests/secret-files.test.ts": 757, + "packages/core/tests/secret-rules.test.ts": 876, + "packages/core/tests/secret-scanner-baseline.test.ts": 801, + "packages/core/tests/secret-scanner.test.ts": 744, + "packages/core/tests/source-position.test.ts": 1168, + "packages/core/tests/state-ownership.test.ts": 1245, + "packages/core/tests/streaming-emission.test.ts": 1223, + "packages/core/tests/switch.test.ts": 1919, + "packages/core/tests/syntax-catalog.test.ts": 1745, + "packages/core/tests/syntax-component.test.ts": 2866, + "packages/core/tests/temp-dir.test.ts": 3819, + "packages/core/tests/temp-file-compiler.test.ts": 586, + "packages/core/tests/terminal-grid-structure.test.ts": 936, + "packages/core/tests/text-interpolation.test.ts": 952, + "packages/core/tests/try-content.test.ts": 952, + "packages/core/tests/unused-in-diff.test.ts": 1422, + "packages/core/tests/validate.test.ts": 870, + "packages/core/tests/validation-integration.test.ts": 1253, + "packages/core/tests/workflow-component-bundle.test.ts": 1645, + "packages/durable-streams/tests/context.test.ts": 568, + "packages/durable-streams/tests/deterministic-id.test.ts": 573, + "packages/durable-streams/tests/divergence-api.test.ts": 569, + "packages/durable-streams/tests/divergence.test.ts": 586, + "packages/durable-streams/tests/durable-each.test.ts": 576, + "packages/durable-streams/tests/durable-position.test.ts": 562, + "packages/durable-streams/tests/durable-run.test.ts": 624, + "packages/durable-streams/tests/ephemeral.test.ts": 560, + "packages/durable-streams/tests/fail-stop.test.ts": 614, + "packages/durable-streams/tests/guard-stream.test.ts": 638, + "packages/durable-streams/tests/live-coordinator.test.ts": 588, + "packages/durable-streams/tests/parse.test.ts": 600, + "packages/durable-streams/tests/replay-guard.test.ts": 623, + "packages/durable-streams/tests/replay-index.test.ts": 564, + "packages/durable-streams/tests/retained.test.ts": 556, + "packages/durable-streams/tests/serialize-event.test.ts": 562, + "packages/durable-streams/tests/smoke.test.ts": 550, + "packages/durable-streams/tests/structured-concurrency.test.ts": 636, + "packages/durable-streams/tests/terminal-boundary.test.ts": 607, + "packages/durable-streams/tests/types.test.ts": 518, + "packages/runtime/tests/duration.test.ts": 555, + "packages/runtime/tests/fetch.test.ts": 1154, + "packages/runtime/tests/fs.test.ts": 600, + "packages/runtime/tests/host-files.test.ts": 1349, + "packages/runtime/tests/native-launcher.test.ts": 2937, + "packages/runtime/tests/process.test.ts": 589, + "packages/runtime/tests/service.test.ts": 571, + "packages/test-agent/tests/acp-server.test.ts": 710, + "packages/test-agent/tests/behavior-engine.test.ts": 1680, + "packages/test-agent/tests/bridge.test.ts": 534, + "packages/test-agent/tests/command-lazy.test.ts": 6735, + "packages/test-agent/tests/components.test.ts": 106694, + "packages/test-agent/tests/controller.test.ts": 831, + "packages/test-agent/tests/cross-package-resolution.test.ts": 3012, + "packages/test-agent/tests/native-launch.test.ts": 54773, + "packages/test-agent/tests/net.test.ts": 623, + "packages/test-agent/tests/profile.test.ts": 1213, + "packages/test-agent/tests/protocol.test.ts": 583, + "packages/test-agent/tests/provider.test.ts": 1375, + "packages/test-agent/tests/public-api.test.ts": 1578, + "packages/test-agent/tests/route-slot.test.ts": 519, + "packages/test-agent/tests/smoke.test.ts": 28926, + "packages/test-agent/tests/template.test.ts": 1242, + "packages/test-agent/tests/worker-lifecycle.test.ts": 23816, + "packages/test-support/tests/journal.test.ts": 512, + "packages/testing/tests/agent-composition.test.ts": 1537, + "packages/testing/tests/assert-throws.test.ts": 3212, + "packages/testing/tests/assert.test.ts": 533, + "packages/testing/tests/assertions.test.ts": 3877, + "packages/testing/tests/boundary-contract.test.ts": 2560, + "packages/testing/tests/cli.test.ts": 11678, + "packages/testing/tests/execution-harness.test.ts": 7880, + "packages/testing/tests/replay.test.ts": 3174, + "packages/testing/tests/smoke.test.ts": 3418, + "packages/testing/tests/test-component.test.ts": 3971, + "packages/testing/tests/testing-activation.test.ts": 3523, + "packages/testing/tests/testing-boundary.test.ts": 2021, + "packages/testing/tests/testing-mode.test.ts": 4224, + "packages/testing/tests/use-testing.test.ts": 2849, + "packages/web/tests/assets.test.ts": 510, + "packages/web/tests/client-logic.test.ts": 547, + "packages/web/tests/compile.test.ts": 2027, + "packages/web/tests/component.test.ts": 2607, + "packages/web/tests/declaration.test.ts": 1710, + "packages/web/tests/document.test.ts": 1827, + "packages/web/tests/elicitation.test.ts": 1626, + "packages/web/tests/live-form.test.ts": 1545, + "packages/web/tests/markdown.test.ts": 714, + "packages/web/tests/opener.test.ts": 1534, + "packages/web/tests/page.test.ts": 515, + "packages/web/tests/responder.test.ts": 1835, + "packages/web/tests/server-lifecycle.test.ts": 1666, + "packages/web/tests/server.test.ts": 2076, + "packages/workflow/tests/generated-observations.test.ts": 1473, + "packages/workflow/tests/git-host-effect.test.ts": 2649, + "packages/workflow/tests/git.test.ts": 539, + "packages/workflow/tests/issue-github.test.ts": 1239, + "packages/workflow/tests/issue-markdown.test.ts": 10923, + "packages/workflow/tests/issue-records.test.ts": 1216, + "packages/workflow/tests/pull-request-github.test.ts": 638, + "packages/workflow/tests/pull-request-records.test.ts": 1302, + "packages/workflow/tests/retained-run.test.ts": 2202, + "packages/workflow/tests/selection-authentication.test.ts": 521, + "packages/workflow/tests/service-denial.test.ts": 541, + "packages/workflow/tests/workflow-bundle.test.ts": 1707, + "packages/workflow/tests/workflow-definition.test.ts": 1417, + "packages/workflow/tests/workflow-fork.test.ts": 1287, + "packages/workflow/tests/workflow-run.test.ts": 2114, + "packages/workflow/tests/workspace-effect.test.ts": 3426, + "packages/workflow/tests/xmd-artifact.test.ts": 3991, + "scripts/tests/adapter-vendor.test.ts": 768, + "scripts/tests/bootstrap-npm-package.test.ts": 8812, + "scripts/tests/bump-version.test.ts": 649, + "scripts/tests/changed-paths.test.ts": 545, + "scripts/tests/ci-workflow.test.ts": 2297, + "scripts/tests/consumer-cycle.test.ts": 707, + "scripts/tests/filesystem-contract-workflow.test.ts": 612, + "scripts/tests/main-green.test.ts": 794, + "scripts/tests/main-health.test.ts": 632, + "scripts/tests/no-module-scoped-registry.test.ts": 1370, + "scripts/tests/no-redundant-test-scope.test.ts": 5571, + "scripts/tests/no-sync-filesystem.test.ts": 5810, + "scripts/tests/no-yield-in-finally.test.ts": 1383, + "scripts/tests/oxlint-policy.test.ts": 11311, + "scripts/tests/packaged-document.test.ts": 543, + "scripts/tests/prefer-effection-operation.test.ts": 6347, + "scripts/tests/prefer-effection-result.test.ts": 4695, + "scripts/tests/publish-workflow-membership.test.ts": 596, + "scripts/tests/review-infrastructure.test.ts": 3397, + "scripts/tests/runtime-exclusions.test.ts": 1018, + "scripts/tests/runtime-tests.test.ts": 584, + "scripts/tests/scope-bound-event-registration.test.ts": 5557, + "scripts/tests/staged-write.test.ts": 561, + "scripts/tests/test-file-discovery.test.ts": 858, + "scripts/tests/test-shards.test.ts": 564, + "scripts/tests/test-weights.test.ts": 777, + "scripts/tests/tracked.test.ts": 547, + "scripts/tests/verify-coordinator.test.ts": 774, + "scripts/tests/web-client-module.test.ts": 530, + "scripts/tests/workspace.test.ts": 518 }, "bun": { - "packages/acp/tests/acceptance.test.ts": 764, - "packages/acp/tests/acpx-checkpoint-meta.test.ts": 4306, - "packages/acp/tests/acpx-materialization.test.ts": 6502, - "packages/acp/tests/acpx-transient-env.test.ts": 251, - "packages/acp/tests/adapter-materialization.test.ts": 69745, - "packages/acp/tests/adapter-protocol.test.ts": 36552, - "packages/acp/tests/native-launch.test.ts": 895, - "packages/acp/tests/permission-bridge.test.ts": 351, - "packages/acp/tests/provider.test.ts": 774, - "packages/acp/tests/serial-queue.test.ts": 66, - "packages/acp/tests/session-key.test.ts": 77, - "packages/cli/tests/agent-adapters.test.ts": 1485, - "packages/cli/tests/agent-cli.test.ts": 12007, - "packages/cli/tests/agent-config.test.ts": 29, - "packages/cli/tests/agent-session-coordinator.test.ts": 378, - "packages/cli/tests/cli-help.test.ts": 10485, - "packages/cli/tests/command.test.ts": 7822, - "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 2352, - "packages/cli/tests/document-suites/props/props-markdown.test.ts": 1890, - "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 4856, - "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 3841, - "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 8433, - "packages/cli/tests/fetch-cli.test.ts": 2186, - "packages/cli/tests/file-stream.test.ts": 57, - "packages/cli/tests/inline-cli.test.ts": 27163, - "packages/cli/tests/launch-timeout.test.ts": 10098, - "packages/cli/tests/packaged-document.test.ts": 469, - "packages/cli/tests/plan-args.test.ts": 84, - "packages/cli/tests/plan-cli.test.ts": 26713, - "packages/cli/tests/plan-command-document.test.ts": 930, - "packages/cli/tests/plan-component.test.ts": 3482, - "packages/cli/tests/plan-host-acts.test.ts": 1461, - "packages/cli/tests/plan.test.ts": 22521, - "packages/cli/tests/process-retention.test.ts": 2326, - "packages/cli/tests/props-cli.test.ts": 27671, - "packages/cli/tests/props-schema.test.ts": 451, - "packages/cli/tests/props-sources.test.ts": 133, - "packages/cli/tests/run-composition.test.ts": 3210, - "packages/cli/tests/run-deadline.test.ts": 2540, - "packages/cli/tests/run-timeouts.test.ts": 11094, - "packages/cli/tests/secret-detection-cli.test.ts": 18587, - "packages/cli/tests/service-document.test.ts": 1570, - "packages/cli/tests/service-host.test.ts": 1452, - "packages/cli/tests/session-launch-cli.test.ts": 5353, - "packages/cli/tests/stdout-delivery.test.ts": 52, - "packages/cli/tests/syntax-cli.test.ts": 17431, - "packages/cli/tests/targets-cli.test.ts": 20355, - "packages/cli/tests/test-target.test.ts": 40330, - "packages/cli/tests/testing-activation.test.ts": 563, - "packages/cli/tests/testing-execution-host.test.ts": 30494, - "packages/cli/tests/upgrade-cli.test.ts": 17333, - "packages/cli/tests/upgrade-command-document.test.ts": 3516, - "packages/cli/tests/upgrade-output.test.ts": 777, - "packages/cli/tests/value-root.test.ts": 15182, - "packages/cli/tests/verbose-component.test.ts": 889, - "packages/cli/tests/workflow-declaration.test.ts": 305, - "packages/cli/tests/workflow-host.test.ts": 4039, - "packages/code-review-agent/tests/doctor.test.ts": 29, - "packages/code-review-agent/tests/parse-diagnostics.test.ts": 42, - "packages/code-review-agent/tests/parse-diff.test.ts": 36, - "packages/code-review-agent/tests/parse-doctor.test.ts": 29, - "packages/code-review-agent/tests/parse-oxlint.test.ts": 29, - "packages/code-review-agent/tests/policy.test.ts": 31, - "packages/core/tests/agent-api.test.ts": 30, - "packages/core/tests/agent-components.test.ts": 1187, - "packages/core/tests/agent-function-components.test.ts": 1944, - "packages/core/tests/agent-session-launch.test.ts": 2051, - "packages/core/tests/agent-stack.test.ts": 691, - "packages/core/tests/answers-component.test.ts": 1342, - "packages/core/tests/answers-expansion-recursion.test.ts": 317, - "packages/core/tests/capture-errors.test.ts": 556, - "packages/core/tests/capture-props.test.ts": 329, - "packages/core/tests/cli-journal.test.ts": 9573, - "packages/core/tests/code-block-component.test.ts": 2278, - "packages/core/tests/compiler-boundary.test.ts": 312, - "packages/core/tests/component-api.test.ts": 65, - "packages/core/tests/component-registration.test.ts": 1035, - "packages/core/tests/component-returns.test.ts": 1560, - "packages/core/tests/component-schema-conformance.test.ts": 561, + "packages/acp/tests/acceptance.test.ts": 879, + "packages/acp/tests/acpx-checkpoint-meta.test.ts": 4327, + "packages/acp/tests/acpx-materialization.test.ts": 6529, + "packages/acp/tests/acpx-transient-env.test.ts": 278, + "packages/acp/tests/adapter-materialization.test.ts": 71439, + "packages/acp/tests/adapter-protocol.test.ts": 41733, + "packages/acp/tests/native-launch.test.ts": 949, + "packages/acp/tests/permission-bridge.test.ts": 382, + "packages/acp/tests/provider.test.ts": 809, + "packages/acp/tests/serial-queue.test.ts": 68, + "packages/acp/tests/session-key.test.ts": 66, + "packages/cli/tests/agent-adapters.test.ts": 1374, + "packages/cli/tests/agent-cli.test.ts": 13127, + "packages/cli/tests/agent-config.test.ts": 31, + "packages/cli/tests/agent-session-coordinator.test.ts": 405, + "packages/cli/tests/cli-help.test.ts": 11535, + "packages/cli/tests/command.test.ts": 8001, + "packages/cli/tests/document-suites/inline/inline-markdown.test.ts": 2464, + "packages/cli/tests/document-suites/plan/plan-markdown.test.ts": 103960, + "packages/cli/tests/document-suites/props/props-markdown.test.ts": 1975, + "packages/cli/tests/document-suites/syntax/syntax-markdown.test.ts": 5024, + "packages/cli/tests/document-suites/targets/targets-markdown.test.ts": 4147, + "packages/cli/tests/document-suites/verbose/verbose-markdown.test.ts": 9074, + "packages/cli/tests/evaluate-component.test.ts": 8030, + "packages/cli/tests/fetch-cli.test.ts": 2370, + "packages/cli/tests/file-stream.test.ts": 60, + "packages/cli/tests/inline-cli.test.ts": 31469, + "packages/cli/tests/launch-timeout.test.ts": 10099, + "packages/cli/tests/packaged-document.test.ts": 473, + "packages/cli/tests/plan-args.test.ts": 37, + "packages/cli/tests/plan-cli.test.ts": 50345, + "packages/cli/tests/plan-command-document.test.ts": 5649, + "packages/cli/tests/plan-component.test.ts": 9407, + "packages/cli/tests/plan-host-acts.test.ts": 1374, + "packages/cli/tests/plan.test.ts": 15815, + "packages/cli/tests/process-retention.test.ts": 2413, + "packages/cli/tests/props-cli.test.ts": 27872, + "packages/cli/tests/props-schema.test.ts": 421, + "packages/cli/tests/props-sources.test.ts": 127, + "packages/cli/tests/run-composition.test.ts": 3221, + "packages/cli/tests/run-deadline.test.ts": 2560, + "packages/cli/tests/run-timeouts.test.ts": 11125, + "packages/cli/tests/secret-detection-cli.test.ts": 18895, + "packages/cli/tests/service-document.test.ts": 1525, + "packages/cli/tests/service-host.test.ts": 1425, + "packages/cli/tests/session-launch-cli.test.ts": 5536, + "packages/cli/tests/stdin-cli.test.ts": 28816, + "packages/cli/tests/stdout-delivery.test.ts": 53, + "packages/cli/tests/syntax-cli.test.ts": 35264, + "packages/cli/tests/targets-cli.test.ts": 21387, + "packages/cli/tests/test-target.test.ts": 42557, + "packages/cli/tests/testing-activation.test.ts": 578, + "packages/cli/tests/testing-execution-host.test.ts": 50835, + "packages/cli/tests/upgrade-cli.test.ts": 18252, + "packages/cli/tests/upgrade-command-document.test.ts": 3812, + "packages/cli/tests/upgrade-output.test.ts": 866, + "packages/cli/tests/value-root.test.ts": 16026, + "packages/cli/tests/verbose-component.test.ts": 960, + "packages/cli/tests/workflow-declaration.test.ts": 311, + "packages/cli/tests/workflow-host.test.ts": 4141, + "packages/code-review-agent/tests/doctor.test.ts": 30, + "packages/code-review-agent/tests/parse-diagnostics.test.ts": 44, + "packages/code-review-agent/tests/parse-diff.test.ts": 37, + "packages/code-review-agent/tests/parse-doctor.test.ts": 31, + "packages/code-review-agent/tests/parse-oxlint.test.ts": 32, + "packages/code-review-agent/tests/policy.test.ts": 32, + "packages/core/tests/agent-api.test.ts": 33, + "packages/core/tests/agent-components.test.ts": 1292, + "packages/core/tests/agent-function-components.test.ts": 2028, + "packages/core/tests/agent-session-launch.test.ts": 2259, + "packages/core/tests/agent-stack.test.ts": 726, + "packages/core/tests/answer-identity.test.ts": 43, + "packages/core/tests/answers-component.test.ts": 1466, + "packages/core/tests/answers-expansion-recursion.test.ts": 324, + "packages/core/tests/capture-errors.test.ts": 575, + "packages/core/tests/capture-props.test.ts": 335, + "packages/core/tests/cli-journal.test.ts": 10249, + "packages/core/tests/code-block-component.test.ts": 2348, + "packages/core/tests/compiler-boundary.test.ts": 345, + "packages/core/tests/component-api.test.ts": 58, + "packages/core/tests/component-registration.test.ts": 1074, + "packages/core/tests/component-returns.test.ts": 1654, + "packages/core/tests/component-schema-conformance.test.ts": 562, "packages/core/tests/config-api.test.ts": 348, - "packages/core/tests/construct-error-observation.test.ts": 704, - "packages/core/tests/contextual-cwd.test.ts": 1516, - "packages/core/tests/daemon-integration.test.ts": 1005, - "packages/core/tests/daemon.test.ts": 73, - "packages/core/tests/declared-markdown-component.test.ts": 1296, - "packages/core/tests/document-output-api.test.ts": 38, - "packages/core/tests/document-target-execution.test.ts": 3484, - "packages/core/tests/document-targets.test.ts": 409, - "packages/core/tests/document-validation.test.ts": 1405, - "packages/core/tests/each.test.ts": 394, - "packages/core/tests/elicit-component.test.ts": 881, - "packages/core/tests/ephemeral-service.test.ts": 770, - "packages/core/tests/eval-bindings.test.ts": 376, - "packages/core/tests/eval-context.test.ts": 75, - "packages/core/tests/eval-durable.test.ts": 406, - "packages/core/tests/eval-error-mode.test.ts": 646, - "packages/core/tests/eval-interpolate.test.ts": 38, - "packages/core/tests/eval-middleware.test.ts": 74, - "packages/core/tests/eval-persist.test.ts": 471, - "packages/core/tests/eval-return.test.ts": 403, - "packages/core/tests/eval-scope.test.ts": 322, - "packages/core/tests/eval-timeout.test.ts": 401, - "packages/core/tests/eval-transform.test.ts": 65, - "packages/core/tests/exec-timeout.test.ts": 466, - "packages/core/tests/execute.test.ts": 981, - "packages/core/tests/execution-protocol.test.ts": 1511, - "packages/core/tests/expand.test.ts": 866, - "packages/core/tests/expansion-identity.test.ts": 1210, + "packages/core/tests/construct-error-observation.test.ts": 699, + "packages/core/tests/contextual-cwd.test.ts": 1556, + "packages/core/tests/daemon-integration.test.ts": 1034, + "packages/core/tests/daemon.test.ts": 71, + "packages/core/tests/declared-markdown-component.test.ts": 1645, + "packages/core/tests/document-output-api.test.ts": 41, + "packages/core/tests/document-target-execution.test.ts": 3721, + "packages/core/tests/document-targets.test.ts": 446, + "packages/core/tests/document-validation.test.ts": 1917, + "packages/core/tests/documentation-index.test.ts": 178, + "packages/core/tests/each.test.ts": 457, + "packages/core/tests/elicit-component.test.ts": 999, + "packages/core/tests/ephemeral-service.test.ts": 883, + "packages/core/tests/eval-bindings.test.ts": 415, + "packages/core/tests/eval-context.test.ts": 87, + "packages/core/tests/eval-durable.test.ts": 450, + "packages/core/tests/eval-error-mode.test.ts": 728, + "packages/core/tests/eval-interpolate.test.ts": 39, + "packages/core/tests/eval-middleware.test.ts": 82, + "packages/core/tests/eval-persist.test.ts": 521, + "packages/core/tests/eval-return.test.ts": 455, + "packages/core/tests/eval-scope.test.ts": 363, + "packages/core/tests/eval-timeout.test.ts": 441, + "packages/core/tests/eval-transform.test.ts": 90, + "packages/core/tests/evaluate-component.test.ts": 2713, + "packages/core/tests/evaluate-loaded-copy.test.ts": 529, + "packages/core/tests/evaluate-provider-lifetime.test.ts": 620, + "packages/core/tests/evaluation-profile.test.ts": 187, + "packages/core/tests/exec-timeout.test.ts": 503, + "packages/core/tests/execute.test.ts": 1113, + "packages/core/tests/execution-protocol.test.ts": 1646, + "packages/core/tests/expand.test.ts": 848, + "packages/core/tests/expansion-identity.test.ts": 1239, "packages/core/tests/expansion-metadata.test.ts": 354, - "packages/core/tests/expression-props.test.ts": 830, - "packages/core/tests/fail-component.test.ts": 734, - "packages/core/tests/failure-printing.test.ts": 674, - "packages/core/tests/fatal-cause.test.ts": 172, - "packages/core/tests/fetch-component.test.ts": 1624, - "packages/core/tests/file-component.test.ts": 2347, - "packages/core/tests/file-delete-component.test.ts": 601, - "packages/core/tests/files-fatal.test.ts": 1583, - "packages/core/tests/foreground-exec.test.ts": 1271, - "packages/core/tests/frontmatter.test.ts": 52, - "packages/core/tests/function-components.test.ts": 898, - "packages/core/tests/generated-xmd.test.ts": 1432, - "packages/core/tests/glob-api.test.ts": 93, - "packages/core/tests/glob-component.test.ts": 1237, - "packages/core/tests/guarded-journal.test.ts": 438, - "packages/core/tests/has-content.test.ts": 258, - "packages/core/tests/heal.test.ts": 248, - "packages/core/tests/if.test.ts": 834, - "packages/core/tests/inline-root.test.ts": 480, - "packages/core/tests/invocation-failures.test.ts": 105, - "packages/core/tests/invocation-identity.test.ts": 789, - "packages/core/tests/invocation-scope.test.ts": 531, - "packages/core/tests/journal-source-position.test.ts": 558, - "packages/core/tests/json-component.test.ts": 2439, + "packages/core/tests/expression-props.test.ts": 888, + "packages/core/tests/fail-component.test.ts": 754, + "packages/core/tests/failure-printing.test.ts": 690, + "packages/core/tests/fatal-cause.test.ts": 196, + "packages/core/tests/fetch-component.test.ts": 1733, + "packages/core/tests/file-component.test.ts": 2417, + "packages/core/tests/file-delete-component.test.ts": 639, + "packages/core/tests/files-fatal.test.ts": 1476, + "packages/core/tests/foreground-exec.test.ts": 1253, + "packages/core/tests/frontmatter.test.ts": 51, + "packages/core/tests/function-components.test.ts": 915, + "packages/core/tests/generated-composition.test.ts": 1138, + "packages/core/tests/generated-xmd.test.ts": 2289, + "packages/core/tests/glob-api.test.ts": 101, + "packages/core/tests/glob-component.test.ts": 1262, + "packages/core/tests/guarded-journal.test.ts": 453, + "packages/core/tests/has-content.test.ts": 283, + "packages/core/tests/heal.test.ts": 268, + "packages/core/tests/if.test.ts": 820, + "packages/core/tests/inline-root.test.ts": 484, + "packages/core/tests/invocation-failures.test.ts": 163, + "packages/core/tests/invocation-identity.test.ts": 790, + "packages/core/tests/invocation-scope.test.ts": 533, + "packages/core/tests/journal-source-position.test.ts": 575, + "packages/core/tests/json-component.test.ts": 2438, "packages/core/tests/json.test.ts": 34, - "packages/core/tests/let.test.ts": 404, - "packages/core/tests/loop.test.ts": 1188, - "packages/core/tests/named-slots.test.ts": 1336, - "packages/core/tests/output-error-mode.test.ts": 1530, - "packages/core/tests/output-normalize.test.ts": 42, - "packages/core/tests/output-terminal.test.ts": 167, - "packages/core/tests/parse-components.test.ts": 593, - "packages/core/tests/props-binding.test.ts": 549, - "packages/core/tests/registered-printed-errors.test.ts": 206, - "packages/core/tests/replay-stream.test.ts": 39, - "packages/core/tests/retain.test.ts": 459, - "packages/core/tests/root-props.test.ts": 557, - "packages/core/tests/root-provider.test.ts": 530, - "packages/core/tests/sample-component.test.ts": 1131, - "packages/core/tests/scanner.test.ts": 77, + "packages/core/tests/let.test.ts": 424, + "packages/core/tests/loop.test.ts": 1263, + "packages/core/tests/named-slots.test.ts": 1275, + "packages/core/tests/output-error-mode.test.ts": 1770, + "packages/core/tests/output-normalize.test.ts": 46, + "packages/core/tests/output-terminal.test.ts": 163, + "packages/core/tests/parse-components.test.ts": 612, + "packages/core/tests/plan-response.test.ts": 79, + "packages/core/tests/props-binding.test.ts": 561, + "packages/core/tests/protected-content.test.ts": 49, + "packages/core/tests/registered-printed-errors.test.ts": 216, + "packages/core/tests/replay-stream.test.ts": 38, + "packages/core/tests/retain.test.ts": 488, + "packages/core/tests/root-props.test.ts": 599, + "packages/core/tests/root-provider.test.ts": 597, + "packages/core/tests/sample-component.test.ts": 1143, + "packages/core/tests/scanner.test.ts": 79, "packages/core/tests/scope-local.test.ts": 36, - "packages/core/tests/secret-detection.test.ts": 1073, - "packages/core/tests/secret-files.test.ts": 133, - "packages/core/tests/secret-rules.test.ts": 163, - "packages/core/tests/secret-scanner-baseline.test.ts": 154, - "packages/core/tests/secret-scanner.test.ts": 100, - "packages/core/tests/source-position.test.ts": 318, - "packages/core/tests/state-ownership.test.ts": 408, - "packages/core/tests/streaming-emission.test.ts": 316, - "packages/core/tests/switch.test.ts": 809, - "packages/core/tests/syntax-catalog.test.ts": 829, - "packages/core/tests/temp-dir.test.ts": 2781, - "packages/core/tests/temp-file-compiler.test.ts": 78, - "packages/core/tests/text-interpolation.test.ts": 233, - "packages/core/tests/try-content.test.ts": 254, - "packages/core/tests/unused-in-diff.test.ts": 456, - "packages/core/tests/validate.test.ts": 302, - "packages/core/tests/validation-integration.test.ts": 368, - "packages/core/tests/workflow-component-bundle.test.ts": 673, + "packages/core/tests/secret-detection.test.ts": 1140, + "packages/core/tests/secret-files.test.ts": 136, + "packages/core/tests/secret-rules.test.ts": 170, + "packages/core/tests/secret-scanner-baseline.test.ts": 159, + "packages/core/tests/secret-scanner.test.ts": 104, + "packages/core/tests/source-position.test.ts": 339, + "packages/core/tests/state-ownership.test.ts": 399, + "packages/core/tests/streaming-emission.test.ts": 323, + "packages/core/tests/switch.test.ts": 871, + "packages/core/tests/syntax-catalog.test.ts": 775, + "packages/core/tests/syntax-component.test.ts": 1769, + "packages/core/tests/temp-dir.test.ts": 2800, + "packages/core/tests/temp-file-compiler.test.ts": 87, + "packages/core/tests/terminal-grid-structure.test.ts": 202, + "packages/core/tests/text-interpolation.test.ts": 243, + "packages/core/tests/try-content.test.ts": 267, + "packages/core/tests/unused-in-diff.test.ts": 511, + "packages/core/tests/validate.test.ts": 325, + "packages/core/tests/validation-integration.test.ts": 370, + "packages/core/tests/workflow-component-bundle.test.ts": 707, "packages/durable-streams/tests/context.test.ts": 36, - "packages/durable-streams/tests/deterministic-id.test.ts": 72, - "packages/durable-streams/tests/divergence-api.test.ts": 47, - "packages/durable-streams/tests/divergence.test.ts": 58, - "packages/durable-streams/tests/durable-each.test.ts": 68, - "packages/durable-streams/tests/durable-position.test.ts": 54, - "packages/durable-streams/tests/durable-run.test.ts": 65, + "packages/durable-streams/tests/deterministic-id.test.ts": 71, + "packages/durable-streams/tests/divergence-api.test.ts": 49, + "packages/durable-streams/tests/divergence.test.ts": 57, + "packages/durable-streams/tests/durable-each.test.ts": 74, + "packages/durable-streams/tests/durable-position.test.ts": 55, + "packages/durable-streams/tests/durable-run.test.ts": 66, "packages/durable-streams/tests/ephemeral.test.ts": 62, - "packages/durable-streams/tests/fail-stop.test.ts": 74, - "packages/durable-streams/tests/guard-stream.test.ts": 99, - "packages/durable-streams/tests/live-coordinator.test.ts": 58, - "packages/durable-streams/tests/parse.test.ts": 49, - "packages/durable-streams/tests/replay-guard.test.ts": 75, - "packages/durable-streams/tests/replay-index.test.ts": 47, - "packages/durable-streams/tests/retained.test.ts": 45, - "packages/durable-streams/tests/serialize-event.test.ts": 43, - "packages/durable-streams/tests/smoke.test.ts": 36, - "packages/durable-streams/tests/structured-concurrency.test.ts": 160, - "packages/durable-streams/tests/terminal-boundary.test.ts": 81, - "packages/durable-streams/tests/types.test.ts": 28, + "packages/durable-streams/tests/fail-stop.test.ts": 79, + "packages/durable-streams/tests/guard-stream.test.ts": 103, + "packages/durable-streams/tests/live-coordinator.test.ts": 62, + "packages/durable-streams/tests/parse.test.ts": 50, + "packages/durable-streams/tests/replay-guard.test.ts": 74, + "packages/durable-streams/tests/replay-index.test.ts": 100, + "packages/durable-streams/tests/retained.test.ts": 50, + "packages/durable-streams/tests/serialize-event.test.ts": 41, + "packages/durable-streams/tests/smoke.test.ts": 34, + "packages/durable-streams/tests/structured-concurrency.test.ts": 96, + "packages/durable-streams/tests/terminal-boundary.test.ts": 79, + "packages/durable-streams/tests/types.test.ts": 29, "packages/runtime/tests/duration.test.ts": 30, - "packages/runtime/tests/fetch.test.ts": 610, - "packages/runtime/tests/fs.test.ts": 73, - "packages/runtime/tests/host-files.test.ts": 733, - "packages/runtime/tests/native-launcher.test.ts": 2396, - "packages/runtime/tests/process.test.ts": 91, - "packages/runtime/tests/service.test.ts": 65, - "packages/test-agent/tests/acp-server.test.ts": 109, - "packages/test-agent/tests/behavior-engine.test.ts": 658, - "packages/test-agent/tests/bridge.test.ts": 68, - "packages/test-agent/tests/command-lazy.test.ts": 3260, - "packages/test-agent/tests/components.test.ts": 51444, - "packages/test-agent/tests/controller.test.ts": 211, - "packages/test-agent/tests/cross-package-resolution.test.ts": 1807, - "packages/test-agent/tests/native-launch.test.ts": 23663, - "packages/test-agent/tests/net.test.ts": 83, - "packages/test-agent/tests/profile.test.ts": 304, + "packages/runtime/tests/fetch.test.ts": 613, + "packages/runtime/tests/fs.test.ts": 80, + "packages/runtime/tests/host-files.test.ts": 726, + "packages/runtime/tests/native-launcher.test.ts": 2405, + "packages/runtime/tests/process.test.ts": 89, + "packages/runtime/tests/service.test.ts": 68, + "packages/test-agent/tests/acp-server.test.ts": 110, + "packages/test-agent/tests/behavior-engine.test.ts": 680, + "packages/test-agent/tests/bridge.test.ts": 67, + "packages/test-agent/tests/command-lazy.test.ts": 3232, + "packages/test-agent/tests/components.test.ts": 51983, + "packages/test-agent/tests/controller.test.ts": 203, + "packages/test-agent/tests/cross-package-resolution.test.ts": 2053, + "packages/test-agent/tests/native-launch.test.ts": 23840, + "packages/test-agent/tests/net.test.ts": 112, + "packages/test-agent/tests/profile.test.ts": 301, "packages/test-agent/tests/protocol.test.ts": 59, - "packages/test-agent/tests/provider.test.ts": 406, - "packages/test-agent/tests/public-api.test.ts": 468, - "packages/test-agent/tests/route-slot.test.ts": 58, - "packages/test-agent/tests/smoke.test.ts": 15313, - "packages/test-agent/tests/template.test.ts": 300, - "packages/test-agent/tests/worker-lifecycle.test.ts": 9013, - "packages/test-support/tests/journal.test.ts": 43, - "packages/testing/tests/agent-composition.test.ts": 647, - "packages/testing/tests/assert-throws.test.ts": 2226, - "packages/testing/tests/assert.test.ts": 57, - "packages/testing/tests/assertions.test.ts": 2970, - "packages/testing/tests/boundary-contract.test.ts": 1636, - "packages/testing/tests/cli.test.ts": 5466, - "packages/testing/tests/execution-harness.test.ts": 6964, - "packages/testing/tests/replay.test.ts": 2384, - "packages/testing/tests/smoke.test.ts": 1920, - "packages/testing/tests/test-component.test.ts": 3161, - "packages/testing/tests/testing-activation.test.ts": 2784, - "packages/testing/tests/testing-boundary.test.ts": 1217, - "packages/testing/tests/testing-mode.test.ts": 3289, - "packages/testing/tests/use-testing.test.ts": 2005, - "packages/web/tests/assets.test.ts": 33, - "packages/web/tests/client-logic.test.ts": 59, - "packages/web/tests/compile.test.ts": 1011, - "packages/web/tests/component.test.ts": 1564, - "packages/web/tests/declaration.test.ts": 695, - "packages/web/tests/document.test.ts": 851, - "packages/web/tests/elicitation.test.ts": 559, - "packages/web/tests/live-form.test.ts": 500, - "packages/web/tests/markdown.test.ts": 144, - "packages/web/tests/opener.test.ts": 514, - "packages/web/tests/page.test.ts": 33, - "packages/web/tests/responder.test.ts": 813, - "packages/web/tests/server-lifecycle.test.ts": 625, - "packages/web/tests/server.test.ts": 1125, - "packages/workflow/tests/generated-observations.test.ts": 546, - "packages/workflow/tests/git-host-effect.test.ts": 1558, + "packages/test-agent/tests/provider.test.ts": 426, + "packages/test-agent/tests/public-api.test.ts": 481, + "packages/test-agent/tests/route-slot.test.ts": 59, + "packages/test-agent/tests/smoke.test.ts": 15562, + "packages/test-agent/tests/template.test.ts": 297, + "packages/test-agent/tests/worker-lifecycle.test.ts": 9227, + "packages/test-support/tests/journal.test.ts": 45, + "packages/testing/tests/agent-composition.test.ts": 648, + "packages/testing/tests/assert-throws.test.ts": 2474, + "packages/testing/tests/assert.test.ts": 58, + "packages/testing/tests/assertions.test.ts": 3296, + "packages/testing/tests/boundary-contract.test.ts": 1697, + "packages/testing/tests/cli.test.ts": 5502, + "packages/testing/tests/execution-harness.test.ts": 7006, + "packages/testing/tests/replay.test.ts": 2332, + "packages/testing/tests/smoke.test.ts": 1916, + "packages/testing/tests/test-component.test.ts": 3085, + "packages/testing/tests/testing-activation.test.ts": 2644, + "packages/testing/tests/testing-boundary.test.ts": 1124, + "packages/testing/tests/testing-mode.test.ts": 3344, + "packages/testing/tests/use-testing.test.ts": 1961, + "packages/web/tests/assets.test.ts": 37, + "packages/web/tests/client-logic.test.ts": 87, + "packages/web/tests/compile.test.ts": 953, + "packages/web/tests/component.test.ts": 1436, + "packages/web/tests/declaration.test.ts": 674, + "packages/web/tests/document.test.ts": 787, + "packages/web/tests/elicitation.test.ts": 577, + "packages/web/tests/live-form.test.ts": 504, + "packages/web/tests/markdown.test.ts": 150, + "packages/web/tests/opener.test.ts": 511, + "packages/web/tests/page.test.ts": 35, + "packages/web/tests/responder.test.ts": 891, + "packages/web/tests/server-lifecycle.test.ts": 652, + "packages/web/tests/server.test.ts": 1195, + "packages/workflow/tests/generated-observations.test.ts": 556, + "packages/workflow/tests/git-host-effect.test.ts": 1615, "packages/workflow/tests/git.test.ts": 69, - "packages/workflow/tests/issue-github.test.ts": 314, - "packages/workflow/tests/issue-markdown.test.ts": 8942, - "packages/workflow/tests/issue-records.test.ts": 302, - "packages/workflow/tests/pull-request-github.test.ts": 84, - "packages/workflow/tests/pull-request-records.test.ts": 316, - "packages/workflow/tests/retained-run.test.ts": 1202, - "packages/workflow/tests/selection-authentication.test.ts": 39, - "packages/workflow/tests/service-denial.test.ts": 61, - "packages/workflow/tests/workflow-bundle.test.ts": 738, - "packages/workflow/tests/workflow-definition.test.ts": 356, - "packages/workflow/tests/workflow-fork.test.ts": 308, - "packages/workflow/tests/workflow-run.test.ts": 1103, - "packages/workflow/tests/workspace-effect.test.ts": 1841, - "scripts/tests/adapter-vendor.test.ts": 164, - "scripts/tests/bootstrap-npm-package.test.ts": 5508, + "packages/workflow/tests/issue-github.test.ts": 298, + "packages/workflow/tests/issue-markdown.test.ts": 9015, + "packages/workflow/tests/issue-records.test.ts": 306, + "packages/workflow/tests/pull-request-github.test.ts": 87, + "packages/workflow/tests/pull-request-records.test.ts": 326, + "packages/workflow/tests/retained-run.test.ts": 1272, + "packages/workflow/tests/selection-authentication.test.ts": 41, + "packages/workflow/tests/service-denial.test.ts": 71, + "packages/workflow/tests/workflow-bundle.test.ts": 772, + "packages/workflow/tests/workflow-definition.test.ts": 342, + "packages/workflow/tests/workflow-fork.test.ts": 328, + "packages/workflow/tests/workflow-run.test.ts": 1075, + "packages/workflow/tests/workspace-effect.test.ts": 1767, + "scripts/tests/adapter-vendor.test.ts": 160, + "scripts/tests/bootstrap-npm-package.test.ts": 5560, "scripts/tests/bump-version.test.ts": 81, - "scripts/tests/changed-paths.test.ts": 42, - "scripts/tests/ci-workflow.test.ts": 1319, + "scripts/tests/changed-paths.test.ts": 41, + "scripts/tests/ci-workflow.test.ts": 1357, "scripts/tests/consumer-cycle.test.ts": 105, - "scripts/tests/filesystem-contract-workflow.test.ts": 85, - "scripts/tests/main-green.test.ts": 284, - "scripts/tests/main-health.test.ts": 111, - "scripts/tests/no-module-scoped-registry.test.ts": 924, - "scripts/tests/no-redundant-test-scope.test.ts": 5114, - "scripts/tests/no-sync-filesystem.test.ts": 4621, - "scripts/tests/no-yield-in-finally.test.ts": 900, + "scripts/tests/filesystem-contract-workflow.test.ts": 80, + "scripts/tests/main-green.test.ts": 291, + "scripts/tests/main-health.test.ts": 115, + "scripts/tests/no-module-scoped-registry.test.ts": 927, + "scripts/tests/no-redundant-test-scope.test.ts": 5143, + "scripts/tests/no-sync-filesystem.test.ts": 4690, + "scripts/tests/no-yield-in-finally.test.ts": 920, "scripts/tests/oxlint-policy.test.ts": 10652, - "scripts/tests/packaged-document.test.ts": 39, - "scripts/tests/prefer-effection-operation.test.ts": 5674, - "scripts/tests/prefer-effection-result.test.ts": 4193, - "scripts/tests/publish-workflow-membership.test.ts": 55, - "scripts/tests/review-infrastructure.test.ts": 1971, - "scripts/tests/runtime-exclusions.test.ts": 289, - "scripts/tests/runtime-tests.test.ts": 78, - "scripts/tests/staged-write.test.ts": 67, - "scripts/tests/test-file-discovery.test.ts": 232, - "scripts/tests/test-shards.test.ts": 47, - "scripts/tests/test-weights.test.ts": 211, - "scripts/tests/tracked.test.ts": 42, + "scripts/tests/packaged-document.test.ts": 64, + "scripts/tests/prefer-effection-operation.test.ts": 5790, + "scripts/tests/prefer-effection-result.test.ts": 4177, + "scripts/tests/publish-workflow-membership.test.ts": 74, + "scripts/tests/review-infrastructure.test.ts": 1864, + "scripts/tests/runtime-exclusions.test.ts": 306, + "scripts/tests/runtime-tests.test.ts": 82, + "scripts/tests/scope-bound-event-registration.test.ts": 4539, + "scripts/tests/staged-write.test.ts": 70, + "scripts/tests/test-file-discovery.test.ts": 242, + "scripts/tests/test-shards.test.ts": 46, + "scripts/tests/test-weights.test.ts": 206, + "scripts/tests/tracked.test.ts": 40, "scripts/tests/verify-coordinator.test.ts": 224, - "scripts/tests/web-client-module.test.ts": 81, - "scripts/tests/workspace.test.ts": 76 + "scripts/tests/web-client-module.test.ts": 51, + "scripts/tests/workspace.test.ts": 78 } } }