feat(browser): reuse saved response values across scenario steps (#7267)

Save typed response fields and reuse generated IDs or authentication values across browser scenario requests, UI observations and navigation through the shared CLI/MCP workflow.

Preserve exact numbers, retained Evidence, explicit source/coverage limits and prospective page-value semantics. Bound response decoding, retained spellings and request serialization before allocation, and protect marked response values across source records, follow-up text and planned screenshots.

Integrates Edgar Arakelyan's #7162, including follow-ups through 9f5191ab0. Final local validation: 560 feature-branch tests and 561 current-main integration tests, static/build/docs checks and real PocketBase CLI/MCP privacy workflows. Whole-task comparison and verification limits are recorded in docs/verification/browser-saved-values-2026-10-26.md.

Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com>
This commit is contained in:
gensokyo-devandEdgar Arakelyan authored and GitHub committed 2026-10-27 08:15:52 +08:00
1 parent 60822e0702
commit 3fcbabe593
54 files changed
+7287 -370

No files matched your search

@@ -37,6 +37,7 @@ import {
import { updatedFields } from "./environmentStateWriteApply.js";
import {
retainFixed,
retainCreateExemplar,
type EffectContext,
} from "./environmentStateWriteEffects.js";
@@ -3113,6 +3114,61 @@ it("learns omitted fields using the raw ID resolved by the item owner", () => {
});
});
describe("create exemplar retention", () => {
const facts = () => {
const snapshot = { id: "held", payload: "p".repeat(1_000_000) };
const held = Array.from({ length: 1000 }, () => snapshot);
return {
entity: { id: "new", url: "/new" },
call: {
path: "/items",
pathValues: new Map<string, string>(),
body: { payload: "x".repeat(10_000) },
},
idField: "id",
startMs: undefined,
collection: held,
type: held,
};
};
it("charges temporary request facts and shared snapshot references without rebilling owned entity payloads", () => {
let retained = 0;
const context = {
io: {
retain: (bytes: number) => {
retained += bytes;
},
},
} as unknown as EffectContext;
const input = facts();
expect(retainCreateExemplar(context, input, [])).toBe(input);
expect(retained).toBeGreaterThan(28_000);
expect(retained).toBeLessThan(40_000);
});
it("retains no exemplar when every string field is already explained", () => {
const retain = vi.fn();
const context = { io: { retain } } as unknown as EffectContext;
expect(
retainCreateExemplar(context, facts(), [
{ field: "id", rule: "echo" },
{ field: "url", rule: "echo" },
]),
).toBeUndefined();
expect(retain).not.toHaveBeenCalled();
});
it("does not adopt request facts when the retained budget refuses them", () => {
const context = {
io: {
retain: () => {
throw new Error("budget exhausted");
},
},
} as unknown as EffectContext;
expect(() => retainCreateExemplar(context, facts(), [])).toThrow(
"budget exhausted",
);
});
});
it.each([
{
label: "point read with simultaneous unknown action",