@basein/runner 0.3.20 → 0.3.22
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.
- package/README.md +6 -5
- package/dist/bin/bir-hooks.d.ts +17 -19
- package/dist/bin/bir-hooks.js +17 -19
- package/dist/bin/bir-scenario.js +1 -1
- package/dist/bin/bir.js +1 -21
- package/dist/bin/investigate.d.ts +0 -9
- package/dist/bin/investigate.js +15 -43
- package/dist/bin/scenario-edit.js +13 -44
- package/dist/control/recorder-main.d.ts +0 -15
- package/dist/control/recorder-main.js +22 -42
- package/dist/control/server.d.ts +24 -137
- package/dist/control/server.js +107 -1001
- package/dist/record/recorder.d.ts +11 -142
- package/dist/record/recorder.js +0 -3
- package/dist/record/remote-recorder.d.ts +1 -9
- package/dist/record/remote-recorder.js +3 -49
- package/dist/record/switchable-recorder.js +0 -2
- package/dist/replay/builtins.d.ts +45 -9
- package/dist/replay/builtins.js +131 -59
- package/dist/replay/bundle.d.ts +2 -2
- package/dist/replay/bundle.js +3 -3
- package/dist/replay/controller.d.ts +34 -125
- package/dist/replay/controller.js +171 -528
- package/dist/replay/derive.d.ts +0 -10
- package/dist/replay/derive.js +0 -3
- package/dist/replay/handover.d.ts +2 -37
- package/dist/replay/handover.js +38 -106
- package/dist/replay/logic.d.ts +0 -11
- package/dist/replay/logic.js +0 -24
- package/dist/replay/plan.d.ts +43 -163
- package/dist/replay/plan.js +144 -556
- package/dist/replay/safety.d.ts +4 -5
- package/dist/replay/safety.js +7 -7
- package/dist/replay/source-run.d.ts +15 -24
- package/dist/replay/source-run.js +25 -58
- package/dist/replay/targets.d.ts +11 -21
- package/dist/replay/targets.js +30 -69
- package/dist/replay/types.d.ts +9 -96
- package/dist/replay/types.js +3 -16
- package/dist/util/service-headers.d.ts +1 -2
- package/dist/util/service-headers.js +1 -2
- package/docs/calculatedReplay.md +30 -81
- package/docs/calculatedReplayGuide.md +17 -34
- package/package.json +1 -1
- package/production.md +7 -36
- package/dist/replay/condition-words.d.ts +0 -28
- package/dist/replay/condition-words.js +0 -59
- package/dist/replay/flatten.d.ts +0 -161
- package/dist/replay/flatten.js +0 -222
- package/dist/replay/reads-only.d.ts +0 -29
- package/dist/replay/reads-only.js +0 -261
|
@@ -26,7 +26,7 @@ import { DISCOVERY_CHECK_MS, HEARTBEAT_MS, pidAlive, readDiscovery, removeDiscov
|
|
|
26
26
|
import { DAEMON_CWD_ENV, DAEMON_ENV, DAEMON_LOG_ENV, DERIVE_KEY_ENV, DaemonLog, USE_API_KEY_ENV, clearPortProblem, compareVersions, probeHealth, projectEndpoint, rediscover, validPort, writePortProblem, } from "./daemon.js";
|
|
27
27
|
import { configDir, normalizePath, supersededLogPath } from "./paths.js";
|
|
28
28
|
import { RecorderKeeper } from "./recorder-keeper.js";
|
|
29
|
-
import { parseBashAllow, parseBuiltinTools } from "../replay/builtins.js";
|
|
29
|
+
import { FILE_BUILTINS, parseBashAllow, parseBuiltinTools, parsePathAllow } from "../replay/builtins.js";
|
|
30
30
|
import { parseAllowList } from "../replay/coverage.js";
|
|
31
31
|
import { sweepDeliveries } from "../replay/bash-channel.js";
|
|
32
32
|
import { exemptLoopbackFromProxy, isWrapped, projectRecord, projectToken, readSidecar, } from "../config/generate.js";
|
|
@@ -85,9 +85,8 @@ function wrappedServersFor(cwd) {
|
|
|
85
85
|
* `BIR_INTENT_SOURCES` — which text a step's intent may be read from
|
|
86
86
|
* (segmented.md R-INTENT-3). Unset or unparseable means all three.
|
|
87
87
|
*
|
|
88
|
-
* It governs only what is *sent*.
|
|
89
|
-
*
|
|
90
|
-
* line from the tool name and arguments (R-HIT-4).
|
|
88
|
+
* It governs only what is *sent*. With every source off, a step goes out with
|
|
89
|
+
* no text, and no intent probe is sent for it.
|
|
91
90
|
*/
|
|
92
91
|
function parseIntentSources(value) {
|
|
93
92
|
if (value === undefined)
|
|
@@ -152,33 +151,12 @@ export function derivationKey(daemon = process.env[DAEMON_ENV] === "1") {
|
|
|
152
151
|
}
|
|
153
152
|
return {};
|
|
154
153
|
}
|
|
155
|
-
/**
|
|
156
|
-
* `BIR_SEGMENT_ARM`: whether a segment the service hands out may run mid-task.
|
|
157
|
-
* On unless it is `0`, from runner 0.3.19 (the service's segmentsbreakdown.md
|
|
158
|
-
* SB-21): segments found by repeated work, and the halves after a plan's
|
|
159
|
-
* decision. `0` is observe-only: what would have armed is logged, and nothing
|
|
160
|
-
* is replaced. While it is on, whole plans may start mid-task by intent too:
|
|
161
|
-
* `BIR_INTENT_ARM` follows it unless that is set.
|
|
162
|
-
*/
|
|
163
|
-
export function segmentArmFromEnv(env = process.env) {
|
|
164
|
-
return env.BIR_SEGMENT_ARM !== "0";
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* What the `replay.enabled` startup line says segments do. A segment starts
|
|
168
|
-
* only where the probe is waited on, so `BIR_INTENT_ARM=0` starts nothing
|
|
169
|
-
* mid-task, segments included — the rule `bir doctor` words from /health.
|
|
170
|
-
*/
|
|
171
|
-
export function segmentsAtStartup(segmentArm, env = process.env) {
|
|
172
|
-
if (!segmentArm)
|
|
173
|
-
return "observed only (BIR_SEGMENT_ARM=0)";
|
|
174
|
-
return env.BIR_INTENT_ARM === "0" ? "observed only (BIR_INTENT_ARM=0)" : "run mid-task";
|
|
175
|
-
}
|
|
176
154
|
/**
|
|
177
155
|
* Assemble the replay configuration (docs/calculatedReplay.md §5.3 of the guide).
|
|
178
156
|
*
|
|
179
157
|
* There is no steer threshold: a match the service hands out is steered
|
|
180
158
|
* (controller.ts, gate 4). A recorder started with `BIR_MIN_STEER_SIMILARITY`
|
|
181
|
-
*
|
|
159
|
+
* set ignores it.
|
|
182
160
|
*/
|
|
183
161
|
function buildReplayOptions(keeper, policy, key) {
|
|
184
162
|
// The environment still wins — an operator at a terminal is the most
|
|
@@ -197,15 +175,18 @@ function buildReplayOptions(keeper, policy, key) {
|
|
|
197
175
|
: undefined;
|
|
198
176
|
// Which built-ins the runner may execute itself (replay/builtins.ts):
|
|
199
177
|
// all six by default, `BIR_BUILTIN_TOOLS` to narrow them, `BIR_BASH_ALLOW`
|
|
200
|
-
// to narrow the commands a `Bash` step may run
|
|
201
|
-
//
|
|
178
|
+
// to narrow the commands a `Bash` step may run, `BIR_PATH_ALLOW` the
|
|
179
|
+
// folders a file step may touch (unset: any, as the agent's own tools).
|
|
180
|
+
// Environment-only knobs, like `BIR_REPLAY_RECORDED_OUTPUTS`.
|
|
202
181
|
const builtinTools = parseBuiltinTools(process.env.BIR_BUILTIN_TOOLS);
|
|
203
182
|
const bashAllow = parseBashAllow(process.env.BIR_BASH_ALLOW);
|
|
183
|
+
const pathAllow = parsePathAllow(process.env.BIR_PATH_ALLOW);
|
|
204
184
|
const opts = {
|
|
205
185
|
enabled,
|
|
206
186
|
allowServers,
|
|
207
187
|
builtinTools,
|
|
208
188
|
bashAllow,
|
|
189
|
+
pathAllow,
|
|
209
190
|
budgets: {
|
|
210
191
|
// What a prompt may wait for its match (K5). Past it the prompt goes on
|
|
211
192
|
// without one; a service slower than this must not cost every prompt.
|
|
@@ -224,22 +205,14 @@ function buildReplayOptions(keeper, policy, key) {
|
|
|
224
205
|
// BIR_INTENT_MATCH=0 turns it off on its own.
|
|
225
206
|
intentMatch: {
|
|
226
207
|
enabled: process.env.BIR_INTENT_MATCH !== "0",
|
|
227
|
-
// The probe's own ceiling, not a wait on the hook's path:
|
|
228
|
-
//
|
|
229
|
-
// BIR_SEGMENT_ARM=0 or BIR_INTENT_ARM=0 — and then at most
|
|
208
|
+
// The probe's own ceiling, not a wait on the hook's path: a probe is sent
|
|
209
|
+
// only with BIR_INTENT_ARM=1, and `PreToolUse` waits for it at most
|
|
230
210
|
// BIR_INTENT_ARM_BUDGET_MS (500 ms), never while the service is failing
|
|
231
|
-
// (control/server.ts)
|
|
232
|
-
|
|
233
|
-
// not-clear band its one live question under the service's own 2 500 ms
|
|
234
|
-
// attempt (segmented.md R-HIT-11).
|
|
235
|
-
budgetMs: positiveInt(process.env.BIR_INTENT_MATCH_BUDGET_MS, 4_000),
|
|
211
|
+
// (control/server.ts).
|
|
212
|
+
budgetMs: positiveInt(process.env.BIR_INTENT_MATCH_BUDGET_MS, 1_500),
|
|
236
213
|
maxPerTurn: positiveInt(process.env.BIR_INTENT_MATCHES_PER_TURN, 3),
|
|
237
214
|
maxRequestsPerTurn: positiveInt(process.env.BIR_INTENT_REQUESTS_PER_TURN, 40),
|
|
238
215
|
},
|
|
239
|
-
// On by default from 0.3.19 (the service's segmentsbreakdown.md SB-21): a
|
|
240
|
-
// plan that stops at its decision hands the rest to segments of each half,
|
|
241
|
-
// and they run only mid-task. BIR_SEGMENT_ARM=0 brings back observe-only.
|
|
242
|
-
segmentArm: segmentArmFromEnv(),
|
|
243
216
|
// Both read live, never captured (C5). The recorder signs in after it
|
|
244
217
|
// listens, refreshes the token as the session outlives it, and may sign
|
|
245
218
|
// in or out while it runs; replay reads whatever holds *now*. The old
|
|
@@ -263,6 +236,15 @@ function buildReplayOptions(keeper, policy, key) {
|
|
|
263
236
|
// all — loud for the same reason as the rest of this line.
|
|
264
237
|
builtins: builtinTools.size > 0 ? [...builtinTools].join(",") : "(none)",
|
|
265
238
|
bashAllow: builtinTools.has("Bash") ? (bashAllow.length > 0 ? bashAllow.join(",") : "(none — Bash steps are steered)") : undefined,
|
|
239
|
+
// Where the file tools may reach: anywhere, as the agent's own, unless
|
|
240
|
+
// BIR_PATH_ALLOW names folders (up to 0.3.20 the project alone).
|
|
241
|
+
pathAllow: [...builtinTools].some((name) => FILE_BUILTINS.has(name))
|
|
242
|
+
? pathAllow.includes("*")
|
|
243
|
+
? "(any folder)"
|
|
244
|
+
: pathAllow.length > 0
|
|
245
|
+
? pathAllow.join(",")
|
|
246
|
+
: "(none — file steps are steered)"
|
|
247
|
+
: undefined,
|
|
266
248
|
// Who reads what this turn acts on (segmented.md R-PARAM-5). Named at
|
|
267
249
|
// startup because the third state is a replay that silently never runs.
|
|
268
250
|
derive: key.source ??
|
|
@@ -270,8 +252,6 @@ function buildReplayOptions(keeper, policy, key) {
|
|
|
270
252
|
? "the service"
|
|
271
253
|
: "recorded sample values — sign in, or a scenario with a target will not run"),
|
|
272
254
|
intentMatch: opts.intentMatch?.enabled ? "on" : "off",
|
|
273
|
-
// Whether a segment the service hands out runs, or is only logged.
|
|
274
|
-
segments: segmentsAtStartup(opts.segmentArm === true),
|
|
275
255
|
source,
|
|
276
256
|
why: "a prompt that matches a calculated scenario runs it: the scenario's own steps run without a " +
|
|
277
257
|
"permission prompt of their own (never in plan mode); every other tool call is asked about as " +
|
package/dist/control/server.d.ts
CHANGED
|
@@ -272,17 +272,14 @@ export interface ControlServerOptions {
|
|
|
272
272
|
*/
|
|
273
273
|
onStopRequested?: () => void;
|
|
274
274
|
/**
|
|
275
|
-
* Whether
|
|
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
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
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;
|
|
288
285
|
/**
|
|
@@ -441,8 +438,8 @@ export declare class ControlServer {
|
|
|
441
438
|
private readonly deriveRecentResults;
|
|
442
439
|
/**
|
|
443
440
|
* Which rungs of R-INTENT-1 the runner may send (`BIR_INTENT_SOURCES`). It
|
|
444
|
-
* governs only what is *sent*: with every source off,
|
|
445
|
-
*
|
|
441
|
+
* governs only what is *sent*: with every source off, a step goes out with no
|
|
442
|
+
* text, and no intent probe is sent for it.
|
|
446
443
|
*/
|
|
447
444
|
private readonly intentSources;
|
|
448
445
|
constructor(opts: ControlServerOptions);
|
|
@@ -1144,154 +1141,44 @@ export declare class ControlServer {
|
|
|
1144
1141
|
*/
|
|
1145
1142
|
private replayOverran;
|
|
1146
1143
|
/**
|
|
1147
|
-
*
|
|
1148
|
-
* R-HIT-7).
|
|
1144
|
+
* Intent matching in the ReAct loop (fallbk.md §Runner 4).
|
|
1149
1145
|
*
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1154
|
-
*
|
|
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).
|
|
1178
|
-
*
|
|
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.
|
|
1146
|
+
* Called only while the model is driving, and only when a match may arm a
|
|
1147
|
+
* plan in the call's place ({@link intentArming}, off unless
|
|
1148
|
+
* `BIR_INTENT_ARM=1`): the reasoning the call was made with is sent, and the
|
|
1149
|
+
* service may hand back a whole scenario whose intent it matches. A call made
|
|
1150
|
+
* with no reasoning sends nothing — there is no intent to match. Every
|
|
1151
|
+
* failure is a miss.
|
|
1182
1152
|
*
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
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
|
|
1153
|
+
* The probe sits in front of the call, so it is waited on
|
|
1154
|
+
* {@link intentArmBudgetMs} at most, and not at all while the service is
|
|
1193
1155
|
* failing. Delivering a match on a *later* call instead is not an option: the
|
|
1194
1156
|
* matched call has run by then, and the plan's first step would repeat it.
|
|
1195
1157
|
*/
|
|
1196
1158
|
private tryIntentMatch;
|
|
1197
1159
|
/**
|
|
1198
1160
|
* 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.
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
* computed is "no" — the directive then rides on the call's PostToolUse.
|
|
1161
|
+
* arguments the pin guard would pin to that step's input. Anything that
|
|
1162
|
+
* cannot be computed is "no" — the directive then rides on the call's
|
|
1163
|
+
* PostToolUse.
|
|
1203
1164
|
*/
|
|
1204
1165
|
private isFirstStep;
|
|
1205
1166
|
/**
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
* `
|
|
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.
|
|
1235
|
-
*/
|
|
1236
|
-
private fetchNext;
|
|
1237
|
-
/**
|
|
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.
|
|
1242
|
-
*/
|
|
1243
|
-
private armNext;
|
|
1244
|
-
/**
|
|
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.
|
|
1250
|
-
*/
|
|
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;
|
|
1254
|
-
/**
|
|
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}).
|
|
1262
|
-
*/
|
|
1263
|
-
private closeDecisionFragment;
|
|
1264
|
-
/**
|
|
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.
|
|
1267
|
-
*/
|
|
1268
|
-
private endNext;
|
|
1269
|
-
/**
|
|
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}.
|
|
1167
|
+
* Whether a match found mid-turn may arm a plan in its own `PreToolUse` — and
|
|
1168
|
+
* so whether a probe is sent and waited for at all. Off unless
|
|
1169
|
+
* `BIR_INTENT_ARM=1`. See {@link ControlServerOptions.intentArm}.
|
|
1272
1170
|
*/
|
|
1273
1171
|
private intentArming;
|
|
1274
1172
|
/** How long an arming probe is waited on: `BIR_INTENT_ARM_BUDGET_MS`, never past the probe's own budget. */
|
|
1275
1173
|
private intentArmBudgetMs;
|
|
1276
|
-
/**
|
|
1174
|
+
/** A probe's answer, for the log. Never throws: a malformed answer is a log line. */
|
|
1277
1175
|
private noteProbe;
|
|
1278
|
-
private noteProbeUnsafe;
|
|
1279
1176
|
/**
|
|
1280
1177
|
* Schedule a fragment once a matched turn's plan has handed over (fallbk.md
|
|
1281
1178
|
* D7). Only a turn that is not already recording needs one: an unmatched turn
|
|
1282
1179
|
* whose intent-armed plan handed over is recording the model's work anyway.
|
|
1283
1180
|
*/
|
|
1284
1181
|
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
1182
|
/**
|
|
1296
1183
|
* Open the fragment run and record from this call on (fallbk.md D7).
|
|
1297
1184
|
*
|