@basein/runner 0.3.26 → 0.3.28

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.
@@ -11,7 +11,7 @@
11
11
  * degrades to "run the turn normally" or returns something the session can
12
12
  * ignore. Nothing throws at a hook.
13
13
  */
14
- import type { ExecutionReport } from "../record/recorder.js";
14
+ import type { ExecutionReport, ExecutionTurn, TurnUsage } from "../record/recorder.js";
15
15
  import { type ReplayMode, type StepReach } from "./coverage.js";
16
16
  import { deriveParameters, type AgentDay, type DeriveContext, type DeriveResult } from "./derive.js";
17
17
  import { type HandoverStopReason } from "./handover.js";
@@ -92,6 +92,13 @@ export interface PreToolOptions {
92
92
  * route's deadline guard spoke first. No further step is started.
93
93
  */
94
94
  signal?: AbortSignal;
95
+ /**
96
+ * The call only looks and changes nothing (replay/reads-only.ts), as the
97
+ * control server judged it with what the tool's server says of it. A direct
98
+ * plan the model has not asked for yet lets such a call through and waits
99
+ * for `run_scenario` (B2 is11.md); nothing runs in its place.
100
+ */
101
+ readsOnly?: boolean;
95
102
  }
96
103
  /**
97
104
  * What the caller knows about how a pinned call ended, beyond its error text
@@ -353,6 +360,15 @@ export interface Handover {
353
360
  error?: string;
354
361
  /** For a `step_failed`: where the stopped step stood ({@link stopOf}). */
355
362
  stop?: string;
363
+ /**
364
+ * Why it stopped, as a code: for a `step_failed` the stop's own reason
365
+ * (`budget`, `cancelled`, `test_failed`, `concurrent`, `host_rejected`, …),
366
+ * `failed` for a plain failure; for another kind the kind itself. Only the
367
+ * report reads it (the service's learningPhase.md LP11): {@link stop}
368
+ * folds the stops in front of a step into `not_run`, and that is all the
369
+ * service needs to continue one, not to tell why a plan stopped.
370
+ */
371
+ reason?: string;
356
372
  /** What the model is told. Always built, even when delivery fails. */
357
373
  note: string;
358
374
  /** Set once the note reached the model, so it is never delivered twice. */
@@ -461,6 +477,16 @@ export interface ReplayState {
461
477
  bashCwd?: string;
462
478
  /** Set when the plan handed the task to the model part-way (fallbk.md). */
463
479
  handover?: Handover;
480
+ /**
481
+ * Characters this plan handed the agent to read so far — `run_scenario`'s
482
+ * answer, a divergence's bundle, the notes told in place of a call or
483
+ * beside its result — for the report's `turn` (the service's
484
+ * learningPhase.md LP11). Counted where the text leaves for the agent,
485
+ * never where it is built: a note made and never delivered was not read.
486
+ */
487
+ handedChars?: number;
488
+ /** The bundle this plan handed the agent, when it handed one: brief (0.3.25), or the full one. */
489
+ bundleKind?: "brief" | "full";
464
490
  /**
465
491
  * Every planned step ran and the model was handed the results to answer
466
492
  * from: a steered plan whose last step threaded, a direct run that ran to
@@ -514,6 +540,12 @@ export interface ReplayState {
514
540
  running?: Promise<RunArmedResult>;
515
541
  /** The model called `run_scenario` for this plan (its `PreToolUse` was seen). */
516
542
  directRequested?: boolean;
543
+ /**
544
+ * Calls that only look, made while this direct plan waited for
545
+ * `run_scenario` (B2 is11.md): each ran as the model wrote it, and the plan
546
+ * stayed announced. The first is told the plan still waits, once.
547
+ */
548
+ readsWaited?: number;
517
549
  /**
518
550
  * The direct run's caller went away mid-run — Esc on `run_scenario`, or its
519
551
  * client timing out. The turn it cut short is no measurement of the task, so
@@ -677,7 +709,23 @@ export type DeclineCode = "replay_disabled" | "not_ready" | "known_bad_first_ste
677
709
  * failed on this request, so none of its steps could be computed. Set by
678
710
  * the control server.
679
711
  */
680
- | "params_failed";
712
+ | "params_failed"
713
+ /**
714
+ * A direct plan announced to the model, which made a call that may change
715
+ * something before it called `run_scenario`: the plan retired running
716
+ * nothing, because run after the model's own change it could do the same
717
+ * work twice. Calls that only look before it do not count (B2 is11.md).
718
+ * Set by the control server (runners after 0.3.26; up to it, such a plan
719
+ * was retired at any first call, and reported no reason).
720
+ */
721
+ | "changed_first"
722
+ /**
723
+ * A direct plan whose `run_scenario` call never reached the runner: the
724
+ * person refused it, a rule denied it, or it failed on the way. Refused
725
+ * means refused: the plan retired running nothing. Set by the control
726
+ * server (runners after 0.3.26; up to it, reported with no reason).
727
+ */
728
+ | "run_refused";
681
729
  /**
682
730
  * What a continuation continues (the service's fallbk.md Part 3): the plan
683
731
  * that handed over, the step it stopped in front of, and the recording of the
@@ -696,6 +744,14 @@ export interface ContinuationOf {
696
744
  * user's request: it ends with the answer.
697
745
  */
698
746
  export declare function isSubTask(state: Pick<ReplayState, "armedBy" | "continuation">): boolean;
747
+ /**
748
+ * The report's `turn` (the service's learningPhase.md LP11): what this plan
749
+ * did in the turn, from its state, and the window's tokens and model calls,
750
+ * which only the control server can read (`usage`; undefined when it could
751
+ * not). Every value is null when it is not known, and nothing here throws: a
752
+ * state it cannot read is a `turn` of nulls, never a report lost.
753
+ */
754
+ export declare function turnOf(state: ReplayState, usage?: TurnUsage): ExecutionTurn;
699
755
  /** What `PreToolUse` should do about this call. */
700
756
  export type PreToolAction =
701
757
  /** Pin the arguments and let the real tool run. */
@@ -874,6 +930,13 @@ export declare class ReplayController {
874
930
  * Returns it once and marks it delivered; undefined when there is none.
875
931
  */
876
932
  takeNote(state: ReplayState | undefined): string | undefined;
933
+ /**
934
+ * The hand-over note `run_scenario` answers with: claimed when it is still
935
+ * to tell ({@link takeNote}), and told again when it was told already — the
936
+ * same text the run always answered (`takeNote(state) ?? the note`), now
937
+ * counted as read either way.
938
+ */
939
+ private runNote;
877
940
  /** Whether a note about this plan is still to be told to the model: a hand-over's, or the unseen results'. */
878
941
  hasUndeliveredNote(state: ReplayState | undefined): boolean;
879
942
  /**
@@ -1091,6 +1154,12 @@ export declare class ReplayController {
1091
1154
  * own baseline, so the turn's saving is booked somewhere.
1092
1155
  */
1093
1156
  booksOwnSaving?: boolean;
1157
+ /**
1158
+ * The model calls and tokens of the window `sessionCostUsd` was read
1159
+ * for, for the report's `turn` (the service's learningPhase.md LP11).
1160
+ * Only the control server holds the transcript; absent, they are null.
1161
+ */
1162
+ usage?: TurnUsage;
1094
1163
  }): ExecutionReport | undefined;
1095
1164
  /**
1096
1165
  * The step a failed replay is fairly blamed on: the first whose own logic
@@ -221,6 +221,10 @@ export function sentACall(state) {
221
221
  }
222
222
  return false;
223
223
  }
224
+ /** {@link Handover.reason}: a stopped step's own reason, `failed` for a plain failure, else the kind. */
225
+ function handoverReason(kind, stopReason) {
226
+ return kind === "step_failed" ? (stopReason ?? "failed") : kind;
227
+ }
224
228
  /**
225
229
  * How long a call waits for the previous pin to thread before it is judged to
226
230
  * be running beside it: the control server's hook-view fallback
@@ -255,6 +259,59 @@ const TURN_CALLS_MAX_CHARS = 8 * 1024 * 1024;
255
259
  export function isSubTask(state) {
256
260
  return state.armedBy === "intent" && state.continuation === undefined;
257
261
  }
262
+ /**
263
+ * Count text the plan hands the agent to read ({@link ReplayState.handedChars}),
264
+ * where it leaves for the agent. Adds a length and nothing else.
265
+ */
266
+ function handed(state, text) {
267
+ if (!state || typeof text !== "string" || text.length === 0)
268
+ return;
269
+ state.handedChars = (state.handedChars ?? 0) + text.length;
270
+ }
271
+ /** Longest `stop` or `reason` a report's `turn` carries: they are codes, and a code is short. */
272
+ const TURN_CODE_MAX = 64;
273
+ const turnCode = (value) => typeof value === "string" && value !== "" ? value.slice(0, TURN_CODE_MAX) : null;
274
+ /**
275
+ * The report's `turn` (the service's learningPhase.md LP11): what this plan
276
+ * did in the turn, from its state, and the window's tokens and model calls,
277
+ * which only the control server can read (`usage`; undefined when it could
278
+ * not). Every value is null when it is not known, and nothing here throws: a
279
+ * state it cannot read is a `turn` of nulls, never a report lost.
280
+ */
281
+ export function turnOf(state, usage) {
282
+ const count = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0 ? Math.round(n) : null;
283
+ try {
284
+ const armed = state.mode === "direct" || state.mode === "steer";
285
+ const h = state.handover;
286
+ return {
287
+ mode: armed ? state.mode : null,
288
+ modelCalls: count(usage?.modelCalls),
289
+ inputTokens: count(usage?.inputTokens),
290
+ outputTokens: count(usage?.outputTokens),
291
+ cacheReadTokens: count(usage?.cacheReadTokens),
292
+ cacheWriteTokens: count(usage?.cacheWriteTokens),
293
+ bundleChars: armed ? count(state.handedChars ?? 0) : null,
294
+ brief: state.bundleKind === "brief" ? true : state.bundleKind === "full" ? false : null,
295
+ // Read by the control server after the turn, when it reads the answer (AC11).
296
+ answerChars: null,
297
+ handover: h ? { stop: turnCode(h.stop), reason: turnCode(h.reason) } : null,
298
+ };
299
+ }
300
+ catch {
301
+ return {
302
+ mode: null,
303
+ modelCalls: null,
304
+ inputTokens: null,
305
+ outputTokens: null,
306
+ cacheReadTokens: null,
307
+ cacheWriteTokens: null,
308
+ bundleChars: null,
309
+ brief: null,
310
+ answerChars: null,
311
+ handover: null,
312
+ };
313
+ }
314
+ }
258
315
  export class ReplayController {
259
316
  enabled;
260
317
  work = new ProxyWorkQueue();
@@ -700,21 +757,24 @@ export class ReplayController {
700
757
  stopAt,
701
758
  subTask: isSubTask(state),
702
759
  });
703
- if (mode === "steer") {
704
- // A steer directive shows the arguments the steps will run with, so the
705
- // call the model writes is one the pin guard accepts (plan.ts,
706
- // `steeringDirective`). That needs the parameters settled — which costs
707
- // nothing when the derivation has already answered: gate 7 waited for
708
- // it, or there was nothing to derive. One turn of the loop lets an answer
709
- // that is already in hand through; one still on its way is not waited
710
- // for here, and the directive simply leaves the arguments to the system,
711
- // as it always did. A `paramsLogic` that throws is not judged here: the
712
- // first call that needs the parameters meets the same failure, as before.
713
- if (!deriveAnswered)
714
- await new Promise((resolve) => setImmediate(resolve));
715
- if (deriveAnswered)
716
- await state.plan.ready().catch(() => undefined);
717
- }
760
+ // A steer directive shows the arguments the steps will run with, so the
761
+ // call the model writes is one the pin guard accepts (plan.ts,
762
+ // `steeringDirective`). A direct one says which of this request's values
763
+ // the steps take, and puts this request's values where the recording's
764
+ // stand in its intent (B2 is11.md): "set Olga up" under a request for
765
+ // Carlos made a careful model check first, and that check retired the
766
+ // plan. Both need the parameters settled — which costs nothing when the
767
+ // derivation has already answered: gate 7 waited for it, or there was
768
+ // nothing to derive. One turn of the loop lets an answer that is already
769
+ // in hand through; one still on its way is not waited for here, and the
770
+ // directive leaves the values out (a direct one names each recorded value
771
+ // by its role instead). A `paramsLogic` that throws is not judged here:
772
+ // the first call that needs the parameters meets the same failure, as
773
+ // before.
774
+ if (!deriveAnswered)
775
+ await new Promise((resolve) => setImmediate(resolve));
776
+ if (deriveAnswered)
777
+ await state.plan.ready().catch(() => undefined);
718
778
  state.mode = mode;
719
779
  state.stepsPlanned = steps.length;
720
780
  // The chain this plan was served at: what its own calls are marked with
@@ -967,6 +1027,7 @@ export class ReplayController {
967
1027
  scenario: state.scenarioId ?? undefined,
968
1028
  bytes: h.note.length,
969
1029
  });
1030
+ handed(state, h.note);
970
1031
  return h.note;
971
1032
  }
972
1033
  // A plan that ran to its end with nobody there to read it has no
@@ -975,10 +1036,25 @@ export class ReplayController {
975
1036
  if (u && !u.delivered) {
976
1037
  u.delivered = true;
977
1038
  logDetail("replay.unseen_delivered", { scenario: state.scenarioId ?? undefined, bytes: u.note.length });
1039
+ handed(state, u.note);
978
1040
  return u.note;
979
1041
  }
980
1042
  return undefined;
981
1043
  }
1044
+ /**
1045
+ * The hand-over note `run_scenario` answers with: claimed when it is still
1046
+ * to tell ({@link takeNote}), and told again when it was told already — the
1047
+ * same text the run always answered (`takeNote(state) ?? the note`), now
1048
+ * counted as read either way.
1049
+ */
1050
+ runNote(state) {
1051
+ const note = this.takeNote(state);
1052
+ if (note !== undefined)
1053
+ return note;
1054
+ const again = state.handover?.note;
1055
+ handed(state, again);
1056
+ return again;
1057
+ }
982
1058
  /** Whether a note about this plan is still to be told to the model: a hand-over's, or the unseen results'. */
983
1059
  hasUndeliveredNote(state) {
984
1060
  return Boolean((state?.handover && !state.handover.delivered) || (state?.unseen && !state.unseen.delivered));
@@ -1055,6 +1131,16 @@ export class ReplayController {
1055
1131
  });
1056
1132
  return { kind: "passthrough" };
1057
1133
  }
1134
+ // A CALL THAT ONLY LOOKS DOES NOT END A DIRECT PLAN (B2 is11.md). Asked
1135
+ // for `run_scenario` first, the model looked at something first instead —
1136
+ // in is11 its own notes, after the note had named another request's
1137
+ // person. Read as a divergence, this call would run every step here,
1138
+ // unattended; read as the model leaving the plan, it retired a plan that
1139
+ // would have done the task right. It is neither: it runs as written,
1140
+ // nothing runs in its place, and the plan waits for `run_scenario`. The
1141
+ // control server retires it at the first call that may change something.
1142
+ if (state.mode === "direct" && hook.readsOnly === true)
1143
+ return { kind: "passthrough" };
1058
1144
  // Everything below — the wait for the parameters, and a divergence that
1059
1145
  // executes the rest of the plan — happens inside this one hook, which the
1060
1146
  // host waits on for a bounded time. One deadline covers all of it — and
@@ -1142,6 +1228,7 @@ export class ReplayController {
1142
1228
  if (skip && toolName !== plan.expectedTool() && skip.tools.has(toolName) && (skip.refused ?? 0) < 2) {
1143
1229
  skip.delivered = true;
1144
1230
  skip.refused = (skip.refused ?? 0) + 1;
1231
+ handed(state, skip.text);
1145
1232
  return this.deliverInstead(skip.text, toolName, otherHost);
1146
1233
  }
1147
1234
  // A call to the next step's tool: a note the model has read is done
@@ -1673,6 +1760,7 @@ export class ReplayController {
1673
1760
  if (!skip || skip.delivered)
1674
1761
  return undefined;
1675
1762
  skip.delivered = true;
1763
+ handed(state, skip.text);
1676
1764
  return skip.text;
1677
1765
  }
1678
1766
  /**
@@ -1686,6 +1774,7 @@ export class ReplayController {
1686
1774
  if (!skip || skip.delivered || !skip.tools.has(toolName))
1687
1775
  return undefined;
1688
1776
  skip.delivered = true;
1777
+ handed(state, skip.text);
1689
1778
  return skip.text;
1690
1779
  }
1691
1780
  /**
@@ -1874,7 +1963,7 @@ export class ReplayController {
1874
1963
  delivery: "none",
1875
1964
  stopReason: "not_run",
1876
1965
  });
1877
- return handedOver(this.takeNote(state) ?? state.handover?.note) ?? { ok: false, why: ready.error };
1966
+ return handedOver(this.runNote(state)) ?? { ok: false, why: ready.error };
1878
1967
  }
1879
1968
  const deadline = Date.now() + this.budgets.planMs;
1880
1969
  let result;
@@ -1968,12 +2057,15 @@ export class ReplayController {
1968
2057
  ? { ok: true, text: `${note}\n\n${result.text}`, responseModel: {}, steps: result.executed + result.recorded, partial: true }
1969
2058
  : (handedOver(note) ?? { ok: false, why: note });
1970
2059
  }
1971
- const note = this.takeNote(state) ?? state.handover?.note ?? "";
2060
+ const note = this.runNote(state) ?? "";
1972
2061
  if (!live) {
1973
2062
  // Nothing ran: the tool answers with an error that says so, which is
1974
2063
  // what a model reacts to best.
1975
2064
  return handedOver(note) ?? { ok: false, why: note };
1976
2065
  }
2066
+ // The note in front was counted as it was claimed; the rest of the answer here.
2067
+ handed(state, `\n\n${result.text}`);
2068
+ state.bundleKind = result.brief ? "brief" : "full";
1977
2069
  return {
1978
2070
  ok: true,
1979
2071
  text: `${note}\n\n${result.text}`,
@@ -1993,7 +2085,7 @@ export class ReplayController {
1993
2085
  ran: 0,
1994
2086
  noneNeeded: true,
1995
2087
  });
1996
- return handedOver(this.takeNote(state) ?? state.handover?.note) ?? { ok: false, why: "" };
2088
+ return handedOver(this.runNote(state)) ?? { ok: false, why: "" };
1997
2089
  }
1998
2090
  if (result.executed === 0) {
1999
2091
  // Every step stood on its recorded output (BIR_REPLAY_RECORDED_OUTPUTS):
@@ -2008,7 +2100,7 @@ export class ReplayController {
2008
2100
  stopReason: "not_run",
2009
2101
  ran: 0,
2010
2102
  });
2011
- return handedOver(this.takeNote(state) ?? state.handover?.note) ?? { ok: false, why: "" };
2103
+ return handedOver(this.runNote(state)) ?? { ok: false, why: "" };
2012
2104
  }
2013
2105
  // Live steps only, as above: a recorded stand-in did no work here.
2014
2106
  state.stepsPinned += result.executed;
@@ -2074,6 +2166,19 @@ export class ReplayController {
2074
2166
  why: "the caller went away during the last step — every step ran and nobody read the results",
2075
2167
  });
2076
2168
  }
2169
+ else {
2170
+ // What `run_scenario` hands the agent: the bundle, and the response
2171
+ // model `bir-scenario` puts under it when there is one.
2172
+ handed(state, result.text);
2173
+ try {
2174
+ if (Object.keys(responseModel).length > 0)
2175
+ handed(state, JSON.stringify(responseModel));
2176
+ }
2177
+ catch {
2178
+ // A model no JSON can carry reaches the agent as nothing: nothing to count.
2179
+ }
2180
+ state.bundleKind = result.brief ? "brief" : "full";
2181
+ }
2077
2182
  return {
2078
2183
  ok: true,
2079
2184
  text: result.text,
@@ -2189,6 +2294,10 @@ export class ReplayController {
2189
2294
  d.cutShort === true
2190
2295
  ? false
2191
2296
  : undefined,
2297
+ // How the plan ran, what the turn's model calls and tokens were, what
2298
+ // the agent was handed to read, and why it handed over (LP11). Only
2299
+ // facts the runner already had; an older service drops the field.
2300
+ turn: turnOf(state, d.usage),
2192
2301
  };
2193
2302
  }
2194
2303
  /**
@@ -2569,12 +2678,14 @@ export class ReplayController {
2569
2678
  // done its work, and the model must know before it does the task itself.
2570
2679
  if (stop?.reason === "uncertain" && stop.position !== undefined) {
2571
2680
  const note = this.stopNote(state, plan, stop, "none", composed.left);
2681
+ handed(state, note);
2572
2682
  return this.deliverInstead(note, toolName, state.host !== undefined);
2573
2683
  }
2574
2684
  // The rest is the other half (AC5): the model is told so, in place of
2575
2685
  // its call, before it does any of the plan's remaining steps.
2576
2686
  if (stop?.kind === "other_branch" && stop.position !== undefined) {
2577
2687
  const note = this.stopNote(state, plan, stop, "none", composed.left);
2688
+ handed(state, note);
2578
2689
  return this.deliverInstead(note, toolName, state.host !== undefined);
2579
2690
  }
2580
2691
  // Every remaining step was left out by its test: the steps the session
@@ -2602,6 +2713,7 @@ export class ReplayController {
2602
2713
  kind: stopKind,
2603
2714
  stepIndex: parked.stepIndex,
2604
2715
  toolName: parked.toolName ?? undefined,
2716
+ reason: stopKind,
2605
2717
  note: this.noteFor(state, {
2606
2718
  kind: stopKind,
2607
2719
  step: parked,
@@ -2625,6 +2737,10 @@ export class ReplayController {
2625
2737
  // reason is read as adversarial interception.
2626
2738
  const action = this.deliverInstead(text, toolName, state.host !== undefined);
2627
2739
  logDetail("replay.inject", { channel: action.kind, bytes: text.length });
2740
+ // What the agent reads of it: the whole text as a refusal's reason, as
2741
+ // much as the channel carries as a command's output.
2742
+ handed(state, action.kind === "bash" ? text.slice(0, BASH_CHANNEL_MAX) : text);
2743
+ state.bundleKind = "full";
2628
2744
  return action;
2629
2745
  }
2630
2746
  /**
@@ -2662,6 +2778,7 @@ export class ReplayController {
2662
2778
  ...(stop.kind === "step_failed"
2663
2779
  ? { stop: stopOf({ ranThisStep: stop.stage === "tool_output_logic", stopReason: stop.reason }) }
2664
2780
  : {}),
2781
+ reason: handoverReason(stop.kind, stop.reason),
2665
2782
  note,
2666
2783
  delivered: true,
2667
2784
  };
@@ -2686,6 +2803,7 @@ export class ReplayController {
2686
2803
  toolName: h.step?.toolName ?? undefined,
2687
2804
  error: h.error,
2688
2805
  ...(h.kind === "step_failed" ? { stop: stopOf(h) } : {}),
2806
+ reason: handoverReason(h.kind, h.stopReason),
2689
2807
  note: this.noteFor(state, h),
2690
2808
  delivered: false,
2691
2809
  };
@@ -514,6 +514,47 @@ export declare class ScenarioReplayPlan {
514
514
  * body gets at most `bodyMs` ({@link PREVIEW_LOGIC_MS}) of it.
515
515
  */
516
516
  private previewArguments;
517
+ /**
518
+ * This request's value of `key`, as a directive may show it, or undefined
519
+ * (B2 is11.md): once the reading has settled, a plain value the reading
520
+ * took from the request — never a mark, and never a value a step works out
521
+ * (`from: "step"`): before the run nobody has that one, and the recorded one
522
+ * is another request's (issue 1212).
523
+ */
524
+ private shownValueOf;
525
+ /**
526
+ * A text written from the recording — the intent, a step's reasoning — put
527
+ * right for this request, for a directive to show (B2 is11.md).
528
+ *
529
+ * Both name the recording's values: "set Olga up", "moves each lead to
530
+ * Olga". Shown beside a request for Carlos, the name tells the model the
531
+ * plan is for someone else. A careful model then checks before it runs
532
+ * anything, and a direct plan's first call that was not `run_scenario`
533
+ * retired it — so the replay was lost on exactly the turn replay is for: the
534
+ * same task with a new value. The steps never read the text: they take
535
+ * Carlos from the request.
536
+ *
537
+ * Each recorded value of a parameter found in the text, as a whole word, is
538
+ * replaced by this request's own value where the plan has one it may show
539
+ * ({@link shownValueOf}), and else by the parameter's role (`<assignee
540
+ * name>`): a target the request did not name, a value a step works out, or
541
+ * any value while the reading has not settled. A value the same as the
542
+ * recorded one stays as it is. One pass, longest value first, so nothing put
543
+ * in is replaced again.
544
+ */
545
+ forThisRequest(text: string): string;
546
+ /** {@link forThisRequest} as one function, built once for a directive's many texts. */
547
+ private rewriter;
548
+ /**
549
+ * This request's own values, for the direct directive's line that says the
550
+ * steps take them (B2 is11.md): what the reading took from the request.
551
+ * The values the request names in words come first — a name, a title: what
552
+ * a reader holds the note against — those unlike the recording's first;
553
+ * then the values worked out from the day ("tomorrow" as a date). Targets
554
+ * only: never a setting, never a value a step works out, never a mark.
555
+ * Undefined until the reading has settled, or when it named none.
556
+ */
557
+ requestValues(): string | undefined;
517
558
  /**
518
559
  * The directive injected via `UserPromptSubmit`'s `additionalContext`.
519
560
  *