Files
reverse-engineering-anything/tests/fixtures/environmentStateServing.ts
T
Edgar ArakelyanandClaude Opus 5.5 6d21b62e84 fix(environment): refuse writes the state could not hold or reload
Served writes now refuse, before changing the state:
- a document write with members or JSON types its plan did not accept
  (the same body check entity writes use), or at a path other than the
  one the state holds the document at;
- a body or resulting value data/add would refuse (a number inexact as
  data/get writes it, a __proto__ member, nesting past the limit), so
  data/get output always loads back, increments included;
- a create, update or document write that would take the state past the
  32 MiB data/add intake limit (resource_constraint), with the state's
  serialized size kept incrementally rather than reserialized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 13:10:22 -07:00

47 lines
1.9 KiB
TypeScript

import type { ReplayArguments } from "../../src/application/environment/environmentReplay.js";
import { EnvironmentStateStore } from "../../src/application/environment/environmentStateStore.js";
import { environmentToolAnswer } from "../../src/application/environment/environmentToolAnswer.js";
import { projectAnalysisError } from "../../src/domain/analysisErrorProjection.js";
import { timedCaptureEvidence, type TimedCaptureRow } from "./analysisView.js";
import {
environmentStateServeFixture,
environmentStateServeInputs,
} from "./environmentServe.js";
import { BOOK_ROWS } from "./environmentStateWrites.js";
/** A served environment over the state derived from a capture of `rows`, answering tool calls as the server does. */
export const servedFrom = (rows: readonly TimedCaptureRow[] = BOOK_ROWS) => {
const { source, state } = environmentStateServeInputs(
environmentStateServeFixture(timedCaptureEvidence(rows)),
);
const store = new EnvironmentStateStore(state);
const respond = environmentToolAnswer(source, store);
const call = (name: string, args: ReplayArguments) => {
const tool = source.manifest.tools.find(
(candidate) => candidate.name === name,
);
if (tool === undefined) throw new Error(`The manifest lacks ${name}`);
return respond(tool, args);
};
return {
source,
state,
store,
call,
answer: (name: string, args: ReplayArguments = {}) => {
const result = call(name, args);
if (!result.ok) throw result.error;
return result.value;
},
refusal: (name: string, args: ReplayArguments = {}) => {
const result = call(name, args);
if (result.ok) throw new Error(`Expected ${name} to be refused`);
return projectAnalysisError(result.error);
},
/** What data/get reports, as text, so whole states compare byte for byte. */
snapshot: () => JSON.stringify(store.snapshot()),
};
};
export type Served = ReturnType<typeof servedFrom>;