11/**
22 * End-to-end scenario harness: full agent-loop runs against the production
3- * stack — live tool dispatch, chat director, posix tools plus permission
4- * middleware, git-backed context store, production compactor — with only
5- * inference scripted by @intx/inference-testing. `e2e/integration-harness.ts` owns
6- * the assembly; this layer adds fixture-repo seeding and small scenario
7- * conveniences so e2e files stay declarative.
3+ * stack (tools, director, permissions, context store, compactor) with only
4+ * inference scripted by @intx/inference-testing.
85 *
9- * Deliberate boundary: no TUI and no process spawn here — a scenario drives
10- * `agent.send` through the same seam the runners use. PTY-level coverage is
11- * a separate layer and out of scope for this harness.
6+ * Layer split: `integration-harness.ts` owns the assembly; this file adds
7+ * fixture-repo seeding and scenario conveniences so e2e files stay
8+ * declarative. No TUI or process spawn: scenarios drive `agent.send` through
9+ * the seam the runners use.
1210 */
1311
1412import { cpSync , mkdirSync , writeFileSync } from "node:fs" ;
@@ -46,15 +44,14 @@ export type E2ESession = IntegrationSession;
4644
4745export interface OpenE2ESessionOpts extends OpenIntegrationSessionOpts {
4846 /**
49- * Name of a `fixtures/<name>` directory copied into the session cwd
50- * before the scenario runs. `node_modules` and `.git` are skipped: fixture
51- * deps install into the real repo, and the repo marker belongs to the
52- * `git` option, not to whatever the fixture happens to contain.
47+ * Name of a `fixtures/<name>` directory copied into the session cwd.
48+ * `node_modules` and `.git` are skipped: fixture deps install into the
49+ * real repo, and the repo marker belongs to the `git` option.
5350 */
5451 fixture ?: string ;
5552 /**
56- * Initialize the session cwd as a git repository. Defaults to true — a
57- * " fixture-repo run" should look like one to worktree-aware permission
53+ * Initialize the session cwd as a git repository; defaults to true.
54+ * A fixture-repo run should look like one to worktree-aware permission
5855 * and trust checks. Pass false only when the scenario asserts on
5956 * non-repo behavior.
6057 */
@@ -85,7 +82,7 @@ export function e2ePermissionGate(): PermissionGate {
8582 } ) ;
8683}
8784
88- /** Write (or overwrite) a file inside the session cwd mid-scenario. */
85+ /** Write a file inside the session cwd mid-scenario. */
8986export function seedFile (
9087 session : E2ESession ,
9188 relativePath : string ,
@@ -100,16 +97,15 @@ export interface OperatorTurn {
10097 /** The exact message sent — recovery flows key on its identity. */
10198 message : InboundMessage ;
10299 events : ReactorEmittedEvent [ ] ;
103- /** The raw send result — a terminally-failed turn is not asserted here . */
100+ /** The raw send result; failures are returned, not thrown . */
104101 outcome : SendOutcome | unknown ;
105102}
106103
107104/**
108105 * Send one operator message and pump the harness until the send settles,
109- * whatever the outcome. Unlike runUntilDone this never asserts a reply —
110- * scenarios that script a terminal failure (credential recovery, provider
111- * outage) need the failure's event stream plus the send outcome, not a
112- * thrown expectation.
106+ * whatever the outcome. Never asserts a reply (unlike `runUntilDone`):
107+ * terminal-failure scenarios need the failure's event stream plus the send
108+ * outcome.
113109 */
114110export async function sendOperatorTurn (
115111 session : E2ESession ,
@@ -130,10 +126,9 @@ export async function sendOperatorTurn(
130126 } ;
131127 const events : ReactorEmittedEvent [ ] = [ ] ;
132128 const continuationGate = createContinuationGate ( ) ;
133- // The collector outlives the send: recovery scenarios deliver a follow-up
134- // turn after this returns, and its events keep appending to `events`. The
135- // catch mirrors runUntilSuspended — a stream error must not become an
136- // unhandled rejection in the shared test process.
129+ // The collector outlives the send so recovery follow-up events keep
130+ // appending; the catch keeps stream errors from becoming unhandled
131+ // rejections in the shared test process.
137132 void ( async ( ) => {
138133 for await ( const event of session . agent . stream ( ) ) {
139134 events . push ( event ) ;
@@ -161,9 +156,9 @@ export interface ScriptedReply {
161156
162157/**
163158 * Queue one model response per inference request, in order — the common
164- * "model calls tools, then answers" scenario spine. Thin sugar over
165- * `scenario.replyOnce`; reach for ` whenRequestBodyMatches`/`createStream`
166- * directly when a reply must key on request content or timing.
159+ * "model calls tools, then answers" spine. Use
160+ * `whenRequestBodyMatches`/`createStream` directly when a reply must key on
161+ * request content or timing.
167162 */
168163export function scriptReplies (
169164 session : E2ESession ,
0 commit comments