@basein/runner 0.3.17 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/bin/bir-scenario.d.ts +5 -1
  2. package/dist/bin/bir-scenario.js +155 -5
  3. package/dist/bin/bir.js +2 -2
  4. package/dist/bin/scenario-edit.d.ts +7 -0
  5. package/dist/bin/scenario-edit.js +9 -2
  6. package/dist/bin/scenario-liveness.d.ts +12 -1
  7. package/dist/bin/scenario-liveness.js +8 -4
  8. package/dist/bin/setup.js +3 -3
  9. package/dist/control/client.d.ts +5 -0
  10. package/dist/control/client.js +7 -0
  11. package/dist/control/ensure-hook.d.ts +14 -3
  12. package/dist/control/ensure-hook.js +18 -5
  13. package/dist/control/server.d.ts +165 -2
  14. package/dist/control/server.js +719 -21
  15. package/dist/control/transcript.d.ts +19 -0
  16. package/dist/control/transcript.js +57 -0
  17. package/dist/proxy/intercept.js +13 -0
  18. package/dist/proxy/session.d.ts +23 -0
  19. package/dist/proxy/session.js +71 -3
  20. package/dist/record/recorder.d.ts +146 -0
  21. package/dist/record/recorder.js +9 -0
  22. package/dist/record/remote-recorder.d.ts +59 -1
  23. package/dist/record/remote-recorder.js +297 -20
  24. package/dist/record/switchable-recorder.js +6 -0
  25. package/dist/replay/bundle.d.ts +8 -0
  26. package/dist/replay/bundle.js +20 -6
  27. package/dist/replay/controller.d.ts +33 -1
  28. package/dist/replay/controller.js +137 -12
  29. package/dist/replay/derive.d.ts +15 -0
  30. package/dist/replay/derive.js +5 -0
  31. package/dist/replay/plan.d.ts +90 -1
  32. package/dist/replay/plan.js +232 -10
  33. package/dist/replay/source-run.d.ts +2 -2
  34. package/dist/replay/source-run.js +3 -3
  35. package/dist/replay/targets.d.ts +40 -1
  36. package/dist/replay/targets.js +105 -3
  37. package/dist/replay/types.d.ts +6 -5
  38. package/package.json +1 -1
@@ -21,20 +21,27 @@ import { bashCommandFor } from "./bash-channel.js";
21
21
  import { BuiltinNotRunnable, BuiltinTimeout, parseBashAllow, parseBuiltinTools, runBuiltin, } from "./builtins.js";
22
22
  import { BASH_CHANNEL_MAX, MAX_REPLAY_REASON, testWords, truncate } from "./bundle.js";
23
23
  import { coverageOf, modeFor, reachOf } from "./coverage.js";
24
- import { deriveParameters, } from "./derive.js";
24
+ import { deriveParameters, localDay, } from "./derive.js";
25
25
  import { buildHandoverNote, MAX_HANDOVER_NOTE, } from "./handover.js";
26
26
  import { NO_PROXY, NoSessionProxyError, ProxyWorkQueue, QUEUE_CLOSED } from "./executor.js";
27
27
  import { logicTimeoutMs, MAX_LOGIC_TIMEOUT_MS } from "./logic.js";
28
- import { PREVIEW_BUDGET_MS, ScenarioReplayPlan, StepRunError, } from "./plan.js";
28
+ import { PREVIEW_BUDGET_MS, RecordedValueError, ScenarioReplayPlan, StepRunError, } from "./plan.js";
29
29
  import { PRICING_VERSION } from "./pricing.js";
30
30
  import { hasShellStep, sinkOf, sinkOfPlan, unsafeParameter } from "./safety.js";
31
31
  import { SourceRunOutputs } from "./source-run.js";
32
32
  import { clampToFrameStart, flattenChain, frameEdges, } from "./flatten.js";
33
- import { blockingTargets } from "./targets.js";
33
+ import { blockingTargets, testedOnlyTargets } from "./targets.js";
34
34
  import { isNoResult, toolResultError } from "./tool-error.js";
35
35
  import { OUTCOME_RANK, hasTargets, isReadyScenario, } from "./types.js";
36
36
  /** The first-party tool a `direct` plan is delivered through (§6.3). */
37
37
  export const DIRECT_TOOL_NAME = "mcp__bir__run_scenario";
38
+ /**
39
+ * `bir`'s own tool for saying a replay's results do not answer the request
40
+ * (bin/bir-scenario.ts; the service's review of calcscenarioautocorrect.md,
41
+ * item 19): the one call a finished bundle lets the agent make, where the
42
+ * session has it ({@link ReplayState.reportTool}).
43
+ */
44
+ export const REPORT_TOOL_NAME = "mcp__bir__report_wrong_result";
38
45
  /** How long a `/proxy/poll` is held open before it answers empty. */
39
46
  export const POLL_HOLD_MS = 25_000;
40
47
  /**
@@ -113,6 +120,19 @@ const DIRECT_RUN_MARGIN_MS = 5_000;
113
120
  * Each is bounded by `logicTimeoutMs()` (logic.ts).
114
121
  */
115
122
  const LOGIC_BODIES_OUTSIDE_PLAN = 6;
123
+ /**
124
+ * The agent's day as a system prompt said it, and only then (issue 1212): a
125
+ * line that says a day, written out or in words. Claude Code's own date
126
+ * reminder is this machine's day, which the runner knows better itself.
127
+ */
128
+ function systemDay(day) {
129
+ if (!day || day.source !== "system")
130
+ return undefined;
131
+ if (day.day)
132
+ return day;
133
+ const words = /\b(jan(uary)?|feb(ruary)?|mar(ch)?|apr(il)?|may|june?|july?|aug(ust)?|sep(t(ember)?)?|oct(ober)?|nov(ember)?|dec(ember)?)\b/i;
134
+ return words.test(day.line) && /\b\d{4}\b/.test(day.line) ? day : undefined;
135
+ }
116
136
  /** A derivation wait longer than this is not a budget a direct run can keep. */
117
137
  const MAX_DIRECT_DERIVE_MS = 60_000;
118
138
  /** However a direct run is squeezed, its plan keeps at least this. */
@@ -506,7 +526,7 @@ export class ReplayController {
506
526
  // command nobody asked for.
507
527
  let deriveCtx = ctx;
508
528
  if (ctx.recentResults?.length && sinkOfPlan(planned, host?.sinks) === "command") {
509
- deriveCtx = { liveCall: ctx.liveCall };
529
+ deriveCtx = { liveCall: ctx.liveCall, agentDay: ctx.agentDay };
510
530
  logLine("replay.derive_context", {
511
531
  scenario: scenario.id,
512
532
  shell: hasShellStep(planned, host?.sinks) || undefined,
@@ -515,11 +535,27 @@ export class ReplayController {
515
535
  });
516
536
  }
517
537
  const derivation = this.startDerivation(scenario, prompt, state, deriveCtx);
538
+ // The agent's own day shows in the session only after the prompt hook
539
+ // (issue 1212): the plan's start looks again, and reads the values once
540
+ // more when the day is another one.
541
+ state.agentDayNow = deriveCtx.agentDay;
542
+ state.rederive = (day) => this.startDerivation(scenario, prompt, state, { ...deriveCtx, agentDay: () => day });
518
543
  // Whether the derivation has answered yet — read, never waited on, when the
519
544
  // directive is written (below).
520
545
  let deriveAnswered = false;
521
546
  derivation.then(() => (deriveAnswered = true), () => (deriveAnswered = true));
522
- const params = derivation.then((r) => r.params);
547
+ // The targets only one half of this plan reads (the service's review of
548
+ // calcscenarioautocorrect.md, item 11; targets.ts, `testedOnlyTargets`):
549
+ // the plan holds each as a mark when the request does not give it. A
550
+ // reading that did not answer carries every target at its recorded
551
+ // sample (derive.ts), and one of these must be the mark there too — never
552
+ // last week's task name under a step that would create the task.
553
+ const oneHalf = hasTargets(scenario.paramsObject)
554
+ ? testedOnlyTargets(targetKeys(scenario.paramsObject), scenario.paramsObject, planned, scenario.paramsLogic)
555
+ : [];
556
+ const params = derivation.then((r) => r.derived || oneHalf.length === 0
557
+ ? r.params
558
+ : { ...r.params, ...Object.fromEntries(oneHalf.map((key) => [key, null])) });
523
559
  // `params` is awaited by the plan, and by gate 7 below when there is a
524
560
  // target. Without this, the losing race in gate 7 leaves `derivation`
525
561
  // rejected and unhandled, which takes the process down on an unhandled
@@ -578,11 +614,22 @@ export class ReplayController {
578
614
  // Worth a line of its own: this is the difference between a scenario
579
615
  // that never runs and one that does, and it is the first thing to look
580
616
  // at when a replay acts on the wrong thing.
581
- logLine("replay.targets_found_by_chain", {
582
- scenario: scenario.id,
583
- unnamed: result.missing.join(","),
584
- why: "the chain computes these from its own steps; none is read from the caller",
585
- });
617
+ const forOneHalf = result.missing.filter((key) => oneHalf.includes(key));
618
+ const byChain = result.missing.filter((key) => !oneHalf.includes(key));
619
+ if (byChain.length > 0) {
620
+ logLine("replay.targets_found_by_chain", {
621
+ scenario: scenario.id,
622
+ unnamed: byChain.join(","),
623
+ why: "the chain computes these from its own steps; none is read from the caller",
624
+ });
625
+ }
626
+ if (forOneHalf.length > 0) {
627
+ logLine("replay.targets_for_one_half", {
628
+ scenario: scenario.id,
629
+ unnamed: forOneHalf.join(","),
630
+ why: "only steps that run under a test read these: the plan runs, and a step that needs one stops in front of its call for the agent",
631
+ });
632
+ }
586
633
  }
587
634
  // The values are in hand: one this plan must not template into its
588
635
  // command (safety.ts) declines here, before any directive is injected,
@@ -1058,10 +1105,12 @@ export class ReplayController {
1058
1105
  // a note, delivered in place of this call.
1059
1106
  const step = plan.currentStep();
1060
1107
  if (step) {
1108
+ // A value only the recording holds (issue 1212) is no fault of the step.
1109
+ const recorded = err instanceof RecordedValueError;
1061
1110
  this.recordStep(state, {
1062
1111
  step,
1063
1112
  entry: plan.currentEntry(),
1064
- outcome: "failed",
1113
+ outcome: recorded ? "skipped" : "failed",
1065
1114
  stage: "tool_input_logic",
1066
1115
  error: errText(err),
1067
1116
  });
@@ -1071,6 +1120,7 @@ export class ReplayController {
1071
1120
  position: plan.currentStepIndex,
1072
1121
  error: errText(err),
1073
1122
  delivery: "above",
1123
+ ...(recorded ? { stopReason: "not_run" } : {}),
1074
1124
  });
1075
1125
  const note = this.takeNote(state);
1076
1126
  if (note)
@@ -1772,7 +1822,7 @@ export class ReplayController {
1772
1822
  const deadline = Date.now() + this.budgets.planMs;
1773
1823
  let result;
1774
1824
  try {
1775
- result = await plan.runToCompletion(this.executeStep(state, { deadline }), this.recordedSource(state), this.observeStep(state), deadline, MAX_REPLAY_REASON, { stopOnFailure: true, recordedFallback: this.recordedFallback, signal });
1825
+ result = await plan.runToCompletion(this.executeStep(state, { deadline }), this.recordedSource(state), this.observeStep(state), deadline, MAX_REPLAY_REASON, { stopOnFailure: true, recordedFallback: this.recordedFallback, signal, reportTool: this.reportToolFor(state) });
1776
1826
  }
1777
1827
  catch (err) {
1778
1828
  // The scenario's own logic failed. Retire and let the model do the work.
@@ -2233,8 +2283,18 @@ export class ReplayController {
2233
2283
  const service = this.deriveService(scenario.id);
2234
2284
  const hasSchema = Object.keys(scenario.paramsObject ?? {}).length > 0;
2235
2285
  state.deriveOnService = !apiKey && service !== undefined && hasSchema;
2286
+ // The day a system prompt told the agent it is — a benchmark's keeps its
2287
+ // agent on 2023-11-30 for ever — and else this machine's (issue 1212).
2288
+ // Never Claude Code's own date reminder: that is this machine's day, and
2289
+ // on a new day's first prompt still yesterday's.
2290
+ const agent = systemDay(ctx.agentDay?.());
2291
+ const today = agent?.day ?? localDay();
2292
+ state.deriveDay = today;
2293
+ state.deriveLine = agent?.line;
2236
2294
  return derive({
2237
2295
  prompt,
2296
+ today,
2297
+ ...(agent?.line ? { todaySaid: agent.line } : {}),
2238
2298
  intent: scenario.intent ?? "",
2239
2299
  paramsObject: scenario.paramsObject,
2240
2300
  apiKey,
@@ -2252,6 +2312,9 @@ export class ReplayController {
2252
2312
  })
2253
2313
  .then((r) => {
2254
2314
  state.deriveCostUsd += r.costUsd;
2315
+ // The day the service read from: a plan on a fixed date reads its own.
2316
+ if (r.dayUsed)
2317
+ state.deriveDay = r.dayUsed;
2255
2318
  logLine("replay.derived", {
2256
2319
  scenario: scenario.id,
2257
2320
  params: Object.keys(r.params).length,
@@ -2333,6 +2396,7 @@ export class ReplayController {
2333
2396
  recordedFallback: this.recordedFallback,
2334
2397
  deadline,
2335
2398
  signal,
2399
+ reportTool: this.reportToolFor(state),
2336
2400
  });
2337
2401
  }
2338
2402
  catch (err) {
@@ -2768,6 +2832,21 @@ export class ReplayController {
2768
2832
  }
2769
2833
  return serializeCapped(redact(result));
2770
2834
  }
2835
+ /**
2836
+ * The report tool a bundle may name, when this plan's session has it
2837
+ * ({@link ReplayState.reportTool}); undefined leaves the bundle's words as
2838
+ * they always were. Never for another host: its adapter reads no bundle.
2839
+ */
2840
+ reportToolFor(state) {
2841
+ if (state.host || !state.reportTool)
2842
+ return undefined;
2843
+ try {
2844
+ return state.reportTool() ? REPORT_TOOL_NAME : undefined;
2845
+ }
2846
+ catch {
2847
+ return undefined;
2848
+ }
2849
+ }
2771
2850
  /** Where recorded outputs come from, when they may stand in at all. */
2772
2851
  recordedSource(state, force = false) {
2773
2852
  if (!force && !this.recordedFallback)
@@ -2801,6 +2880,37 @@ export class ReplayController {
2801
2880
  // carries the verdict, so the recording page says why it never runs.
2802
2881
  blame: true,
2803
2882
  });
2883
+ // The agent's own day may show only now (issue 1212): its host writes a
2884
+ // system prompt's "Today's date is …" just after the prompt hook. Values
2885
+ // read for another day are read again, before the first step runs.
2886
+ if (!opts.adHoc && state.rederive && state.agentDayNow && plan.currentStepIndex === 0) {
2887
+ const now = systemDay(state.agentDayNow());
2888
+ // A new line, unless it says the very day the values were read for. A
2889
+ // line with the day in words is read by the service.
2890
+ if (now && now.line !== state.deriveLine && (now.day === undefined || now.day !== state.deriveDay)) {
2891
+ logLine("replay.rederive", {
2892
+ scenario: state.scenarioId ?? undefined,
2893
+ from: state.deriveDay,
2894
+ to: now.day ?? "said in words",
2895
+ });
2896
+ state.deriveLine = now.line;
2897
+ if (now.day)
2898
+ state.deriveDay = now.day;
2899
+ const targets = targetKeys(plan.paramsSchema);
2900
+ // A reading that did not answer names no target, as at the prompt
2901
+ // (gate 7): never the recorded person or date in its place.
2902
+ const again = state.rederive(now).then((r) => {
2903
+ if (r.derived)
2904
+ return r;
2905
+ const params = { ...r.params };
2906
+ for (const key of targets)
2907
+ params[key] = null;
2908
+ return { ...r, params, missing: [...targets] };
2909
+ });
2910
+ again.then((r) => (state.rederivedMissing = r.missing), () => (state.rederivedMissing = [...targets]));
2911
+ plan.resetParams(again.then((r) => r.params));
2912
+ }
2913
+ }
2804
2914
  if (!plan.parametersSettled) {
2805
2915
  let failure;
2806
2916
  const settled = plan.ready().then(() => true, (err) => {
@@ -2839,6 +2949,21 @@ export class ReplayController {
2839
2949
  }
2840
2950
  }
2841
2951
  }
2952
+ // The second reading left a value unnamed that this plan would act on.
2953
+ const missingAgain = state.rederivedMissing;
2954
+ state.rederivedMissing = undefined;
2955
+ if (missingAgain && !opts.adHoc) {
2956
+ const planned = plan.allEntries().slice(0, plan.stepCount);
2957
+ const blocked = blockingTargets(missingAgain, plan.paramsSchema, planned, plan.paramsLogic);
2958
+ if (blocked.length > 0) {
2959
+ return {
2960
+ ok: false,
2961
+ error: `the value of ${blocked[0]} could not be read from this request for ${state.deriveDay}`,
2962
+ stage: "derive_params",
2963
+ blame: false,
2964
+ };
2965
+ }
2966
+ }
2842
2967
  const sink = opts.adHoc
2843
2968
  ? undefined
2844
2969
  : sinkOfPlan(plan.allEntries().slice(0, plan.stepCount), state.host?.sinks);
@@ -38,10 +38,21 @@ export interface LiveCall {
38
38
  /** Redacted and capped, exactly as the probe sent it. */
39
39
  toolInput: string;
40
40
  }
41
+ /** The day the agent was told it is (control/transcript.ts `agentDayOf`; issue 1212). */
42
+ export interface AgentDay {
43
+ line: string;
44
+ day?: string;
45
+ source: "system" | "host";
46
+ }
41
47
  /** What a turn can tell derivation beyond its prompt (segmented.md R-PARAM-2). */
42
48
  export interface DeriveContext {
43
49
  liveCall?: LiveCall;
44
50
  recentResults?: string[];
51
+ /**
52
+ * The agent's own day, read again each time it is asked: its host writes it
53
+ * into the session only after the prompt hook (issue 1212).
54
+ */
55
+ agentDay?: () => AgentDay | undefined;
45
56
  }
46
57
  /**
47
58
  * The service, which derives when this runner has no key of its own
@@ -62,6 +73,8 @@ export interface DeriveOptions extends DeriveContext {
62
73
  paramsObject: ParamsSchema | null;
63
74
  /** The day on this machine. Injected by tests; defaults to {@link localDay}. */
64
75
  today?: string;
76
+ /** The words that told the agent its day, when its host showed it any (issue 1212). */
77
+ todaySaid?: string;
65
78
  /** An override that keeps the reading on this machine. Absent → the service. */
66
79
  apiKey?: string;
67
80
  /** Used when there is no `apiKey`. Absent too → recorded samples. */
@@ -91,6 +104,8 @@ export interface DeriveResult {
91
104
  missing: string[];
92
105
  /** Settings filled from their recorded sample (R-PARAM-2). */
93
106
  sampled: string[];
107
+ /** The day the service read the turn's dates from, when it said (issue 1212). */
108
+ dayUsed?: string;
94
109
  }
95
110
  /**
96
111
  * The day on this machine, `YYYY-MM-DD`, in its own time zone.
@@ -343,6 +343,10 @@ async function deriveViaService(opts, service, schema, keys) {
343
343
  // What "tomorrow" is counted from. A service that does not know the
344
344
  // field ignores it.
345
345
  today: opts.today ?? localDay(),
346
+ // The words that told the agent its day ("Today's date is Thursday,
347
+ // 2023-11-30 …"), which the service turns into the day it reads from
348
+ // (issue 1212). Older services ignore it.
349
+ ...(opts.todaySaid ? { todaySaid: opts.todaySaid } : {}),
346
350
  }),
347
351
  signal: opts.signal ?? timeoutSignal(),
348
352
  });
@@ -402,6 +406,7 @@ async function deriveViaService(opts, service, schema, keys) {
402
406
  model: body.model,
403
407
  missing,
404
408
  sampled,
409
+ ...(typeof body.today === "string" ? { dayUsed: body.today } : {}),
405
410
  };
406
411
  }
407
412
  //# sourceMappingURL=derive.js.map
@@ -24,6 +24,48 @@ import { type FlatEntry } from "./flatten.js";
24
24
  import type { ReplayMode } from "./coverage.js";
25
25
  import type { HandoverStopReason } from "./handover.js";
26
26
  import type { ExecutionStage, FallbackKind, ParamsSchema, SerializedScenario, SerializedScenarioStep } from "./types.js";
27
+ /**
28
+ * A value a step of the recording worked out — an address the directory
29
+ * returned, the id a search found; the service labels it `from: "step"` —
30
+ * is never replayed from the recording (issue 1212). The plan holds this mark
31
+ * in its place. A step whose input still holds it, because its earlier steps
32
+ * did not return the value and its code fell back on the parameter, stops the
33
+ * plan in front of it, for the agent; a summary that holds it is left out.
34
+ * Never the recorded e-mail address, never the recorded lead.
35
+ */
36
+ export declare const FROM_STEP_MARK = "\u2063bir-from-step:";
37
+ /**
38
+ * A value the request did not give, which only the steps of one half of an
39
+ * "if \u2026 otherwise" read (the service's review of calcscenarioautocorrect.md,
40
+ * item 11; targets.ts, `testedOnlyTargets`). The plan arms without it \u2014 the
41
+ * other half needs nothing it lacks \u2014 and holds this mark in its place, never
42
+ * `null` and never the recorded value. A step whose input reads or holds it
43
+ * stops in front of its call, and the agent does that half; a test that reads
44
+ * it decides nothing; a summary that reads it is left out.
45
+ */
46
+ export declare const MISSING_VALUE_MARK = "\u2063bir-missing:";
47
+ /**
48
+ * A step's code read a value a step works out, which here only the recording
49
+ * holds (issue 1212). Not a fault of the step: its earlier steps did not
50
+ * return the value this time. The plan stops in front of it, the step counts
51
+ * as not run, and the agent does the rest.
52
+ */
53
+ export declare class RecordedValueError extends Error {
54
+ readonly key: string;
55
+ constructor(key: string, message?: string);
56
+ }
57
+ /**
58
+ * A step's code read a value the request did not give ({@link
59
+ * MISSING_VALUE_MARK}). The same stop as {@link RecordedValueError} \u2014 not a
60
+ * fault of the step: it counts as not run, nothing is parked or repaired, and
61
+ * the agent does the rest \u2014 so it is one, and every place that tells that
62
+ * stop apart tells this one apart too. Its words name the value.
63
+ */
64
+ export declare class MissingValueError extends RecordedValueError {
65
+ constructor(key: string);
66
+ }
67
+ /** The value a mark stands for, when `value` holds one anywhere \u2014 either kind. */
68
+ export declare function markedKey(value: unknown): string | undefined;
27
69
  /**
28
70
  * Runs one step's tool and returns its output as a string.
29
71
  *
@@ -76,6 +118,14 @@ export interface DriveOptions {
76
118
  * so what the run reports about it is the truth.
77
119
  */
78
120
  signal?: AbortSignal;
121
+ /**
122
+ * The tool the model may call although the bundle says to call none: `bir`'s
123
+ * own `mcp__bir__report_wrong_result`, when the session has it (the service's
124
+ * review of calcscenarioautocorrect.md, item 19). Set by the caller only
125
+ * where the `bir` server is connected; absent, the bundle's words are as
126
+ * they always were (bundle.ts, `AssembleOptions.reportTool`).
127
+ */
128
+ reportTool?: string;
79
129
  }
80
130
  /**
81
131
  * Supplies a step's recorded output when its tool cannot run here (§8.1).
@@ -289,7 +339,17 @@ export declare class ScenarioReplayPlan {
289
339
  private readonly scenario;
290
340
  /** The flat list this plan walks. One entry per step that will really run. */
291
341
  private readonly entries;
292
- private readonly paramsPromise;
342
+ private paramsPromise;
343
+ /** The values a step worked out in the recording ({@link FROM_STEP_MARK}). */
344
+ private readonly fromStep;
345
+ /**
346
+ * The targets only the steps of one half read (targets.ts,
347
+ * `testedOnlyTargets`): each held as {@link MISSING_VALUE_MARK} when the
348
+ * request does not give it.
349
+ */
350
+ private readonly oneHalf;
351
+ /** Of {@link oneHalf}, the ones the request did not give: held as the mark now. */
352
+ private missingMarked;
293
353
  private params;
294
354
  /** The derivation's own answer, before `paramsLogic`. What safety.ts judges. */
295
355
  private derivedParams;
@@ -385,6 +445,12 @@ export declare class ScenarioReplayPlan {
385
445
  * throws.
386
446
  */
387
447
  useFallbackParams(): void;
448
+ /**
449
+ * The values read again, before any step ran (issue 1212): the agent's own
450
+ * day showed in the session only after the first reading. False once a step
451
+ * has run, when the values the steps ran on are the ones that stand.
452
+ */
453
+ resetParams(params: Promise<Record<string, unknown>>): boolean;
388
454
  /** Whether the parameters are final. */
389
455
  get parametersSettled(): boolean;
390
456
  /** The derivation's own values, before `paramsLogic`. Empty until settled. */
@@ -409,6 +475,21 @@ export declare class ScenarioReplayPlan {
409
475
  currentEntry(): FlatEntry | undefined;
410
476
  /** The parameters in force. Empty until {@link ready} resolves. */
411
477
  get parameters(): Readonly<Record<string, unknown>>;
478
+ /**
479
+ * The values a body may not use: a value a step works out ({@link
480
+ * FROM_STEP_MARK}) and a value the request did not give ({@link
481
+ * MISSING_VALUE_MARK}). A read of one is the stop {@link valueError} names.
482
+ */
483
+ private watchedKeys;
484
+ /** The stop a read of `key` means: a value the request did not give, or one only the recording had. */
485
+ private valueError;
486
+ /**
487
+ * `parameters` for one body, with every read of a value a step works out
488
+ * noted (issue 1212): a read is the recorded value used, however the code
489
+ * changes it afterwards — upper-cased, encoded, sliced or counted. A value
490
+ * the request did not give is watched the same way (review item 11).
491
+ */
492
+ private watched;
412
493
  /** Everything the steps have accumulated so far. */
413
494
  get accumulated(): Readonly<Record<string, unknown>>;
414
495
  /** The scenario's parameter schema — what the target and safety checks judge. */
@@ -439,6 +520,14 @@ export declare class ScenarioReplayPlan {
439
520
  * a throw as divergence.
440
521
  */
441
522
  toolInputForCurrentStep(): Record<string, unknown>;
523
+ /**
524
+ * A step's input, refused when it holds a value only the recording had: its
525
+ * code fell back on a parameter a step works out, and the earlier steps did
526
+ * not return it (issue 1212). The caller stops the plan in front of it. So
527
+ * is one that reads, or holds, a value the request did not give (review
528
+ * item 11): {@link MissingValueError}.
529
+ */
530
+ private inputOf;
442
531
  /** Whether the plan's cursor rests in front of the step it is parked before. */
443
532
  atStop(): boolean;
444
533
  /**