@basein/runner 0.3.21 → 0.3.23

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 (50) hide show
  1. package/dist/bin/bir-hooks.d.ts +12 -16
  2. package/dist/bin/bir-hooks.js +12 -16
  3. package/dist/bin/bir-scenario.js +1 -1
  4. package/dist/bin/bir.js +1 -21
  5. package/dist/bin/investigate.d.ts +0 -9
  6. package/dist/bin/investigate.js +14 -42
  7. package/dist/bin/scenario-edit.js +13 -44
  8. package/dist/control/pin-guard.d.ts +16 -0
  9. package/dist/control/pin-guard.js +36 -0
  10. package/dist/control/recorder-main.d.ts +0 -15
  11. package/dist/control/recorder-main.js +7 -39
  12. package/dist/control/server.d.ts +81 -131
  13. package/dist/control/server.js +460 -968
  14. package/dist/record/recorder.d.ts +47 -138
  15. package/dist/record/recorder.js +0 -3
  16. package/dist/record/remote-recorder.d.ts +1 -9
  17. package/dist/record/remote-recorder.js +11 -49
  18. package/dist/record/switchable-recorder.js +0 -2
  19. package/dist/replay/bundle.d.ts +2 -2
  20. package/dist/replay/bundle.js +3 -3
  21. package/dist/replay/controller.d.ts +75 -124
  22. package/dist/replay/controller.js +207 -529
  23. package/dist/replay/derive.d.ts +0 -10
  24. package/dist/replay/derive.js +0 -3
  25. package/dist/replay/handover.d.ts +2 -37
  26. package/dist/replay/handover.js +38 -106
  27. package/dist/replay/logic.d.ts +0 -11
  28. package/dist/replay/logic.js +0 -24
  29. package/dist/replay/plan.d.ts +43 -163
  30. package/dist/replay/plan.js +144 -556
  31. package/dist/replay/safety.d.ts +4 -5
  32. package/dist/replay/safety.js +7 -7
  33. package/dist/replay/source-run.d.ts +15 -24
  34. package/dist/replay/source-run.js +25 -58
  35. package/dist/replay/targets.d.ts +11 -21
  36. package/dist/replay/targets.js +30 -69
  37. package/dist/replay/types.d.ts +9 -96
  38. package/dist/replay/types.js +3 -16
  39. package/dist/util/service-headers.d.ts +1 -2
  40. package/dist/util/service-headers.js +1 -2
  41. package/docs/calculatedReplay.md +17 -74
  42. package/docs/calculatedReplayGuide.md +10 -30
  43. package/package.json +1 -1
  44. package/production.md +5 -35
  45. package/dist/replay/condition-words.d.ts +0 -28
  46. package/dist/replay/condition-words.js +0 -59
  47. package/dist/replay/flatten.d.ts +0 -161
  48. package/dist/replay/flatten.js +0 -222
  49. package/dist/replay/reads-only.d.ts +0 -29
  50. package/dist/replay/reads-only.js +0 -261
@@ -272,19 +272,25 @@ export interface ControlServerOptions {
272
272
  */
273
273
  onStopRequested?: () => void;
274
274
  /**
275
- * Whether an intent probe may arm a plan inside the `PreToolUse` that sent it
276
- * (fallbk.md §Runner 4).
275
+ * Whether a match found mid-turn may arm a plan in the place of the call
276
+ * that found it (fallbk.md §Runner 4).
277
277
  *
278
278
  * Arming there means *waiting* there, on every unsteered tool call, for a
279
- * service round trip. It waits (at most `BIR_INTENT_ARM_BUDGET_MS`, 500 ms,
280
- * and never while the service is failing) when segment arming is on — the
281
- * recorder's default from 0.3.19, `BIR_SEGMENT_ARM` unset or `1` — or when
282
- * `BIR_INTENT_ARM=1` asks for whole-scenario intent arming. `BIR_INTENT_ARM=0`
283
- * never waits. Otherwise, as in a server built with neither (a test, an
284
- * embedder), the probe is sent without waiting, for hit counting only, and
285
- * nothing arms mid-turn.
279
+ * service round trip — so it is off by default: no probe is sent and nothing
280
+ * arms mid-turn. `BIR_INTENT_ARM=1` turns it on, and then each call waits at
281
+ * most `BIR_INTENT_ARM_BUDGET_MS` (500 ms), and never while the service is
282
+ * failing. Unset or `BIR_INTENT_ARM=0` is off.
286
283
  */
287
284
  intentArm?: boolean;
285
+ /**
286
+ * Whether the model's first call after a plan handed over asks the service
287
+ * for the plan of the work recorded after an earlier hand-over at that step,
288
+ * and runs it when that call is its first step (the service's fallbk.md
289
+ * Part 3). On by default: it is one request per hand-over, never per call.
290
+ * `BIR_CONTINUATIONS=0` turns it off; so does `BIR_INTENT_MATCH=0`, which
291
+ * turns off every mid-turn request.
292
+ */
293
+ continuations?: boolean;
288
294
  /**
289
295
  * The verdict hot paths consult before they wait on the service. Defaults to
290
296
  * the process-wide one every service call reports to; tests pass their own.
@@ -441,8 +447,8 @@ export declare class ControlServer {
441
447
  private readonly deriveRecentResults;
442
448
  /**
443
449
  * Which rungs of R-INTENT-1 the runner may send (`BIR_INTENT_SOURCES`). It
444
- * governs only what is *sent*: with every source off, the probe still goes out
445
- * with an empty text and the server builds the tool line (R-HIT-4).
450
+ * governs only what is *sent*: with every source off, a step goes out with no
451
+ * text, and no intent probe is sent for it.
446
452
  */
447
453
  private readonly intentSources;
448
454
  constructor(opts: ControlServerOptions);
@@ -1144,154 +1150,98 @@ export declare class ControlServer {
1144
1150
  */
1145
1151
  private replayOverran;
1146
1152
  /**
1147
- * Recordings this turn must not count a step hit against (segmented.md
1148
- * R-HIT-7).
1149
- *
1150
- * A repeat of a recording's own prompt is *prompt* recurrence, counted as
1151
- * `iterations`, never step recurrence. Without this, three prompt repeats
1152
- * would reach `SEGMENT_MIN_HITS` on every step of the whole recording and the
1153
- * detector would build a whole-run-sized segment beside the whole-run
1154
- * scenario.
1155
- */
1156
- private excludeRunsFor;
1157
- /**
1158
- * Per plan of this turn, its recording and how far the plan got in its own
1159
- * chain (segmented.md R-OUT-6).
1160
- *
1161
- * The server uses it to refuse a segment that starts *before* where this turn
1162
- * already is: re-running steps the turn has just done is worse than not
1163
- * replaying at all. The position is the plan's own: the step it handed over
1164
- * at (its decision included), or its last step when it ran to its end. The
1165
- * server maps it onto the recording — a segment's first position, a
1166
- * decision's step before it — and takes the largest per recording (the
1167
- * service's segmentsbreakdown.md D18). One entry per plan, so that two plans
1168
- * of one recording, whose own positions are on different scales, never
1169
- * hide each other. A plan declined for anything but a known-bad first step
1170
- * reports nothing — it ran none of the recording, so it blocks none of it.
1171
- *
1172
- * Rebuilt on every probe rather than cached: a plan that hands over between
1173
- * two calls changes the answer.
1174
- */
1175
- private ranThroughFor;
1176
- /**
1177
- * Intent matching in the ReAct loop (fallbk.md §Runner 4, segmented.md 10.3).
1153
+ * Intent matching in the ReAct loop (fallbk.md §Runner 4).
1178
1154
  *
1179
- * Called only while the model is driving. Every unsteered, non-housekeeping
1180
- * tool call is sent: the service counts it as a hit on whatever recorded step
1181
- * it matches, and may hand back a scenario or a segment to run in its place.
1155
+ * Called only while the model is driving, and only when a match may arm a
1156
+ * plan in the call's place ({@link intentArming}, off unless
1157
+ * `BIR_INTENT_ARM=1`): the reasoning the call was made with is sent, and the
1158
+ * service may hand back a whole scenario whose intent it matches. A call made
1159
+ * with no reasoning sends nothing — there is no intent to match. Every
1160
+ * failure is a miss.
1182
1161
  *
1183
- * A call made with **no reasoning at all** still probes (R-HIT-4): the server
1184
- * builds an intent from the tool name and arguments, and a step the agent took
1185
- * without narrating it is exactly as much a recurrence as one it explained.
1186
- * Every failure is a miss.
1187
- *
1188
- * THE PROBE IS NOT WAITED ON unless it may arm ({@link intentArming}). Hit
1189
- * counting needs no answer at all, and waiting for one put a service round
1190
- * trip — 70-450 ms healthy, the whole 4 s budget on a hung service — in front
1191
- * of every Read, Grep, Edit and Bash of every signed-in user. When it may arm,
1192
- * the wait is {@link intentArmBudgetMs} at most, and none while the service is
1162
+ * The probe sits in front of the call, so it is waited on
1163
+ * {@link intentArmBudgetMs} at most, and not at all while the service is
1193
1164
  * failing. Delivering a match on a *later* call instead is not an option: the
1194
1165
  * matched call has run by then, and the plan's first step would repeat it.
1195
1166
  */
1196
1167
  private tryIntentMatch;
1197
1168
  /**
1198
- * Whether the model's call is plausibly `state`'s first step: its tool, and
1199
- * arguments the pin guard would pin to that step's input. The input is
1200
- * computed only for a step of the plan's own frame (a called segment's first
1201
- * step would build that segment's parameters here); anything that cannot be
1202
- * computed is "no" — the directive then rides on the call's PostToolUse.
1203
- */
1204
- private isFirstStep;
1205
- /**
1206
- * The agent's call against `state`'s first step, value for value (the
1207
- * service's offer1.md O5): `hit` when every argument is the step's own,
1208
- * `missing` when the only differences are values the plan does not have
1209
- * (a target the reading left empty, which the agent's call may hold), and
1210
- * `other` otherwise.
1211
- */
1212
- private firstStepVerdict;
1213
- /**
1214
- * Whether `state`'s plan calls `toolName` in a step it would run: what makes
1215
- * a plan started after a call of that tool make it a second time (the
1216
- * service's offer1.md O8). A tool that only reads never counts — reading
1217
- * twice changes nothing — by the service's own rule ({@link readsOnly}): a
1218
- * `crm_search_customers` mid-task never keeps a plan that searches later from
1219
- * starting.
1220
- */
1221
- private planCallsTool;
1222
- /**
1223
- * A plan of this turn stopped at its decision: ask the service, once per
1224
- * plan, which calculated scenarios can follow it, and arm each in the
1225
- * background while the agent reads the note and decides (offer1.md O3, O4).
1226
- * Called wherever a hand-over is first seen; a second call for the same plan
1227
- * does nothing.
1228
- */
1229
- private noteDecision;
1230
- /**
1231
- * Ask for a decision's next scenarios (offer1.md O3): each is checkable as
1232
- * soon as the service answers, and armed in the background, each on its own
1233
- * (O4). Resolves when the service has answered, not when the arms have.
1234
- * Never rejects.
1169
+ * A continuation (the service's fallbk.md Part 3), on the model's first call
1170
+ * after a plan handed over.
1171
+ *
1172
+ * The model's work after an earlier hand-over of the same plan at the same
1173
+ * step was recorded once, as a fragment, and the service may have calculated
1174
+ * it into a plan. Until 0.3.23 nothing asked for that plan: the only way a
1175
+ * plan started mid-task was a match of the model's words against plan
1176
+ * intents ({@link tryIntentMatch}, off by default), and a one-line note
1177
+ * after a hand-over does not read like a plan's intent paragraph. Here the
1178
+ * hand-over itself is the question — the plan and the step — so the service
1179
+ * names one recording and matches no words.
1180
+ *
1181
+ * It arms only when the call the model is making is that plan's first step —
1182
+ * its tool, and arguments the pin guard would pin to the step's input — and
1183
+ * is then answered in that call's place, as an intent plan whose first step
1184
+ * the call is. The plan before it stopped because the next step needed a
1185
+ * judgement. This call is the model's judgement; a plan that starts with
1186
+ * another call is a way the model did not take, and must not run.
1187
+ *
1188
+ * Its values are read from the turn's own request — the rest of the task is
1189
+ * the one the user asked for — with the model's words, the call it was about
1190
+ * to make and this turn's tool results beside it, as for any plan started at
1191
+ * a tool call.
1192
+ *
1193
+ * Asked once per hand-over, waited on {@link CONTINUATION_PROBE_MS} and
1194
+ * {@link CONTINUATION_ARM_MS} at most, and not at all while the service is
1195
+ * failing. Every way it does not arm leaves the turn as it was: the model's
1196
+ * call runs, and its work is recorded as the fragment. A plan handed out and
1197
+ * not armed is reported for its ticket, with the reason.
1235
1198
  */
1236
- private fetchNext;
1199
+ private tryContinuation;
1237
1200
  /**
1238
- * Arm one next scenario in the background (offer1.md O4): its values read
1239
- * from the turn's request and its results so far — or, once more, with the
1240
- * agent's own call (O5) — and settled, so a call is compared with the first
1241
- * step as it would really run. Never rejects.
1201
+ * A continuation handed out and not armed: kept, retired, for its ticket's
1202
+ * report at the seal (`not_steered`, with the reason, unmeasured). `code`
1203
+ * says why when no gate did.
1242
1204
  */
1243
- private armNext;
1205
+ private keepDeclinedContinuation;
1206
+ /** A continuation request's answer that came after the call it was for went ahead. */
1207
+ private noteLateContinuation;
1244
1208
  /**
1245
- * The agent's call after a decision, against the scenarios that can follow
1246
- * it (offer1.md O5, O6). A hit — the call is a scenario's first step, value
1247
- * for value — is answered in the call's place with that scenario's directive:
1248
- * the agent calls `run_scenario`, and the scenario runs every step, this one
1249
- * included, once. Undefined otherwise: the call runs as the agent wrote it.
1209
+ * Every scenario this turn was handed and armed or declined: never handed
1210
+ * out again in it. A plan that handed over is among them, so its own
1211
+ * continuation request can never return it.
1250
1212
  */
1251
- private tryNextScenarios;
1252
- /** A next scenario's hit: bookkeeping as for any plan armed mid-task, then its directive in the call's place. */
1253
- private nextHit;
1213
+ private armedScenarioIds;
1254
1214
  /**
1255
- * A next scenario hit after the agent's own calls — looks — opened the
1256
- * fragment of its work after the decision: the fragment ends here, with what
1257
- * the agent did itself, and nothing more of this turn is recorded into it.
1258
- * The scenario's own calls, pinned in steer mode or run in direct mode, are
1259
- * not the agent's work, and would make the fragment a copy of that scenario
1260
- * (offer1.md O7). A fragment still due is dropped instead
1261
- * ({@link dropDecisionFragment}).
1215
+ * Whether the model's call is a continuation's first step: its tool, and
1216
+ * the step's own input in every argument the two share (pin-guard.ts
1217
+ * `sameFirstCall`). Anything that cannot be computed is "no".
1262
1218
  */
1263
- private closeDecisionFragment;
1219
+ private isContinuationFirstCall;
1220
+ /** Whether continuations are asked for: on unless `BIR_CONTINUATIONS=0`. */
1221
+ private continuationsOn;
1264
1222
  /**
1265
- * End this turn's next scenarios (offer1.md O6): every one but the hit is
1266
- * never announced, so never runs and is never reported.
1223
+ * Whether the model's call is plausibly `state`'s first step: its tool, and
1224
+ * arguments the pin guard would pin to that step's input. Anything that
1225
+ * cannot be computed is "no" — the directive then rides on the call's
1226
+ * PostToolUse.
1267
1227
  */
1268
- private endNext;
1228
+ private isFirstStep;
1269
1229
  /**
1270
- * Whether an intent probe may arm a plan in its own `PreToolUse` — and so
1271
- * whether that hook waits for it. See {@link ControlServerOptions.intentArm}.
1230
+ * Whether a match found mid-turn may arm a plan in its own `PreToolUse` — and
1231
+ * so whether a probe is sent and waited for at all. Off unless
1232
+ * `BIR_INTENT_ARM=1`. See {@link ControlServerOptions.intentArm}.
1272
1233
  */
1273
1234
  private intentArming;
1274
1235
  /** How long an arming probe is waited on: `BIR_INTENT_ARM_BUDGET_MS`, never past the probe's own budget. */
1275
1236
  private intentArmBudgetMs;
1276
- /** The bookkeeping half of a probe's answer: what `/health` and the log show. */
1237
+ /** A probe's answer, for the log. Never throws: a malformed answer is a log line. */
1277
1238
  private noteProbe;
1278
- private noteProbeUnsafe;
1279
1239
  /**
1280
1240
  * Schedule a fragment once a matched turn's plan has handed over (fallbk.md
1281
1241
  * D7). Only a turn that is not already recording needs one: an unmatched turn
1282
1242
  * whose intent-armed plan handed over is recording the model's work anyway.
1283
1243
  */
1284
1244
  private noteHandover;
1285
- /**
1286
- * Drop a fragment scheduled at a decision (the service's
1287
- * segmentsbreakdown.md SB-16) when a plan the intent check armed takes the
1288
- * agent's next call: what follows is that plan's half, not the other one,
1289
- * and recorded as the other half it would become a wrong segment C. Cleared
1290
- * rather than ended, so a later hand-over of that plan schedules its own
1291
- * fragment, as any plan's does in a turn with none. Any other fragment is
1292
- * left as it is.
1293
- */
1294
- private dropDecisionFragment;
1295
1245
  /**
1296
1246
  * Open the fragment run and record from this call on (fallbk.md D7).
1297
1247
  *