@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
package/dist/replay/types.js
CHANGED
|
@@ -50,13 +50,9 @@ export function isReadyScenario(value) {
|
|
|
50
50
|
s.steps.every(readyStep));
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
* One step of a ready chain
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* and a string `toolInputLogic` — would decline every chain that contains one.
|
|
57
|
-
* A call is ready when it says it cannot run (the plan stops in front of it and
|
|
58
|
-
* the agent takes over there) or when it carries a segment whose own steps pass
|
|
59
|
-
* this same test. A call row with neither is a payload we cannot run.
|
|
53
|
+
* One step of a ready chain: a tool and the logic that computes its input.
|
|
54
|
+
* Anything else — a row with no tool, as an older service could send — is a
|
|
55
|
+
* payload this runner cannot run, and the plan is not armed.
|
|
60
56
|
*/
|
|
61
57
|
function readyStep(step) {
|
|
62
58
|
if (!step)
|
|
@@ -65,15 +61,6 @@ function readyStep(step) {
|
|
|
65
61
|
// not armed rather than run with the step always in, or always out.
|
|
66
62
|
if (step.when !== undefined && step.when !== null && !isStepTest(step.when))
|
|
67
63
|
return false;
|
|
68
|
-
if (step.kind === "segment") {
|
|
69
|
-
if (step.unusable)
|
|
70
|
-
return true;
|
|
71
|
-
const segment = step.segment;
|
|
72
|
-
return (!!segment &&
|
|
73
|
-
Array.isArray(segment.steps) &&
|
|
74
|
-
segment.steps.length > 0 &&
|
|
75
|
-
segment.steps.every(readyStep));
|
|
76
|
-
}
|
|
77
64
|
return typeof step.toolName === "string" && typeof step.toolInputLogic === "string";
|
|
78
65
|
}
|
|
79
66
|
//# sourceMappingURL=types.js.map
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - **1** — stops in front of a step that carries `stop`, and reads
|
|
7
7
|
* `withheld: "runner_update_required"` on a match.
|
|
8
|
-
* - **2** — runs a step
|
|
9
|
-
* says so: leaves it out (`not_taken`) or stops in front of it
|
|
8
|
+
* - **2** — runs a step only when its test, `when`, says so: leaves it out (`not_taken`) or stops in front of it
|
|
10
9
|
* (`other_branch`) when the test says no, and stops when the test cannot
|
|
11
10
|
* answer (stage `when_logic`). The service's autocorrect.md AC5: a plan
|
|
12
11
|
* holding a test is handed only to a runner that names contract 2 or newer,
|
|
@@ -22,8 +22,7 @@ import { packageVersion } from "./version.js";
|
|
|
22
22
|
*
|
|
23
23
|
* - **1** — stops in front of a step that carries `stop`, and reads
|
|
24
24
|
* `withheld: "runner_update_required"` on a match.
|
|
25
|
-
* - **2** — runs a step
|
|
26
|
-
* says so: leaves it out (`not_taken`) or stops in front of it
|
|
25
|
+
* - **2** — runs a step only when its test, `when`, says so: leaves it out (`not_taken`) or stops in front of it
|
|
27
26
|
* (`other_branch`) when the test says no, and stops when the test cannot
|
|
28
27
|
* answer (stage `when_logic`). The service's autocorrect.md AC5: a plan
|
|
29
28
|
* holding a test is handed only to a runner that names contract 2 or newer,
|
package/docs/calculatedReplay.md
CHANGED
|
@@ -45,7 +45,7 @@ this design has a ladder whose cheapest rung is free — and the more of a stack
|
|
|
45
45
|
|---|---|---|
|
|
46
46
|
| Runs MCP tools itself | No (`replay.md` §12: *"rrepeat never executes tools — not even MCP"*) | **Yes**, on the connection it already owns |
|
|
47
47
|
| Divergence fallback | A second Agent SDK session — the dominant cost | Direct `tools/call` through the proxies — **$0** |
|
|
48
|
-
| Reaches built-ins (`Bash`, `Read`) | Only by steering the live session | `Read`, `Glob`, `Grep`, `Edit`, `Write` and `Bash` run on the runner itself,
|
|
48
|
+
| Reaches built-ins (`Bash`, `Read`) | Only by steering the live session | `Read`, `Glob`, `Grep`, `Edit`, `Write` and `Bash` run on the runner itself, on any path the agent could reach unless `BIR_PATH_ALLOW` names folders (`BIR_BUILTIN_TOOLS`, `BIR_BASH_ALLOW`, `BIR_PATH_ALLOW`); any other built-in is steered. In a host that is not Claude Code a tool with one of these names is the application's own, and the runner runs none of them (§7.4) |
|
|
49
49
|
| Needs `@anthropic-ai/*` at runtime | Yes | No (§16.3) |
|
|
50
50
|
|
|
51
51
|
---
|
|
@@ -231,8 +231,8 @@ more than one score — a same-request question under its threshold, and a secon
|
|
|
231
231
|
prompt's task line. Re-scoring that on this side declined matches the server had made (a checked
|
|
232
232
|
0.85, a task line at 0.91). **A match is the decision to use the scenario**, so every hand-out
|
|
233
233
|
steers; what a plan cannot do — a parked first step, a tool nothing reaches, a target the prompt
|
|
234
|
-
never named — the gates after it still stop. `BIR_MIN_STEER_SIMILARITY`
|
|
235
|
-
|
|
234
|
+
never named — the gates after it still stop. `BIR_MIN_STEER_SIMILARITY` is
|
|
235
|
+
ignored.
|
|
236
236
|
|
|
237
237
|
`not_steered` as the floor is not a failure code. It is the **control group**: the prompt matched,
|
|
238
238
|
the agent ran the task the ordinary way, and the cost of doing so is a fresh measurement of what this
|
|
@@ -265,7 +265,7 @@ export function modeFor(steps: SerializedScenarioStep[], wrapped: ReadonlySet<st
|
|
|
265
265
|
|
|
266
266
|
| Every step | Mode | Where the tools run | Model spend |
|
|
267
267
|
|---|---|---|---|
|
|
268
|
-
| a wrapped MCP tool, or a built-in on `BIR_BUILTIN_TOOLS` | **`direct`** (§6) | The proxies, on connections already open; allow-listed built-ins on the runner itself,
|
|
268
|
+
| a wrapped MCP tool, or a built-in on `BIR_BUILTIN_TOOLS` | **`direct`** (§6) | The proxies, on connections already open; allow-listed built-ins on the runner itself, from the session's project directory (replay/builtins.ts) | one Haiku derivation + one turn that reads the results |
|
|
269
269
|
| anything else, or mixed | **`steer`** (§7) | The live session, inputs pinned | one Haiku derivation + the live turn |
|
|
270
270
|
| — | `none` | nowhere | declines at gate 5 |
|
|
271
271
|
|
|
@@ -275,11 +275,17 @@ so `Task`, `WebFetch`; up to 0.3.7 also `Bash`, `Edit`, `Write`), an MCP server
|
|
|
275
275
|
`claude-in-chrome` — which is `scope: "dynamic"`, appears in no config file, and therefore can never
|
|
276
276
|
be wrapped (v1 design §1). None of them can be reached except through the session.
|
|
277
277
|
|
|
278
|
-
A built-in **on** the allow-list runs on the runner,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
278
|
+
A built-in **on** the allow-list runs on the runner, from the session's own project directory: a
|
|
279
|
+
relative path resolves against it, as the host's tools resolve it, and an absolute path is taken
|
|
280
|
+
as it is, inside the project or not — the agent's own tools reach any folder its session allows,
|
|
281
|
+
and the recorded call was one of them (up to 0.3.20 every path was confined to the project, and a
|
|
282
|
+
plan that read the agent's memory file under `~/.claude` handed the whole task back). The file
|
|
283
|
+
tools have a switch of their own (`BIR_PATH_ALLOW`, folders; unset means any, `project` brings
|
|
284
|
+
back the confinement, `project,~/.claude` adds a folder, `none` keeps them in the session); under
|
|
285
|
+
a list, a path outside it, symlinks included, is refused and the step is `not_run`, the clean
|
|
286
|
+
hand-over. `Bash` has its switch too (`BIR_BASH_ALLOW`, command prefixes; unset means any command,
|
|
287
|
+
`none` keeps `Bash` in the session), because a runner-side step never reaches the host's
|
|
288
|
+
permission prompts. The
|
|
283
289
|
results mimic the hook's view of each tool, which is what the recorder stored for built-in steps
|
|
284
290
|
and what their `toolOutputLogic` was authored against; they pass through the same
|
|
285
291
|
`serializeCapped(redact(…))` as every recorded payload. Bash keeps the host's own semantics a
|
|
@@ -748,30 +754,6 @@ about it:
|
|
|
748
754
|
It ends with the remaining planned steps and the parameters derived for this request, within 4 000
|
|
749
755
|
characters.
|
|
750
756
|
|
|
751
|
-
**A plan's decision (0.3.19)** has a note of its own. The service serves a step with
|
|
752
|
-
`stop: {kind: "decision"}` where the task has an "if … otherwise" (its segmentsbreakdown.md). The
|
|
753
|
-
plan runs only the steps before it, in steer and direct mode and when a divergence's bundle runs up
|
|
754
|
-
to it, and hands the task back. The note opens *"[BaseInstRunner calculated replay] The calculated
|
|
755
|
-
scenario for this request ran the steps before a decision, and stopped there."*, says which steps
|
|
756
|
-
ran as above, and ends *"This request asks for a decision: “…”. Decide from the results above
|
|
757
|
-
which way applies, then continue the task, calling tools as needed."* (*below* in a direct run's
|
|
758
|
-
answer, *above and below* after a divergence; *"This task has a decision to make here."* when the
|
|
759
|
-
request has no such sentence). The quote is the live request's own sentences with a word for a
|
|
760
|
-
condition, found with the service's word list (`if`, `otherwise`, `else`, `unless`, `only when`,
|
|
761
|
-
`only if`, `in case`, `whether`, and the Hebrew ones), at most 600 characters
|
|
762
|
-
([`condition-words.ts`](../src/replay/condition-words.ts)). The note has no intent line, no
|
|
763
|
-
remaining planned steps and no parameters, and never the condition the service keeps (`stop.why`):
|
|
764
|
-
each names, or hints at, the half the recording took. The directive at the prompt leaves the intent
|
|
765
|
-
out for the same reason, and says the task comes back *"at a decision"*. The report is `fell_back`
|
|
766
|
-
(`failed` when no step ran) with `fallbackKind: "decision"`; the decision step has no verdict, so
|
|
767
|
-
nothing counts against it. A runner up to 0.3.18 reads the unknown kind as `known_bad_step`.
|
|
768
|
-
|
|
769
|
-
A plan whose chain has a decision keeps these protections when it stops *earlier* for another
|
|
770
|
-
reason — a parked or failed step, a judgement, the budget. Its note is the ordinary one above, but
|
|
771
|
-
with no intent line and no parameters, and its remaining planned steps end before the decision. Its
|
|
772
|
-
directive leaves the intent out too. An agent sent on to the recorded half's steps would start that
|
|
773
|
-
half's segment, and the plan would have decided after all.
|
|
774
|
-
|
|
775
757
|
With `BIR_REPLAY_RECORDED_OUTPUTS=1`, a step that could not be *sent* (a built-in, no proxy, off the
|
|
776
758
|
allowlist) is served its **recorded output** instead (§8.1), marked `(recorded)` in the bundle so the
|
|
777
759
|
model is never told a stale result is fresh. A timeout or an upstream error never is.
|
|
@@ -910,8 +892,7 @@ requests* — which is what §7.3's ordering rule protects.
|
|
|
910
892
|
Built 2026-10-23 for the service's autocorrect.md AC5; not yet released. A task can have two
|
|
911
893
|
halves: "if engaged users went over the threshold, book a meeting; otherwise send a note". A
|
|
912
894
|
recording shows one half, so its plan knows one half. The service's correction adds the other half
|
|
913
|
-
and a test on each step that belongs to only one of them. A served step
|
|
914
|
-
row, may carry:
|
|
895
|
+
and a test on each step that belongs to only one of them. A served step may carry:
|
|
915
896
|
|
|
916
897
|
```ts
|
|
917
898
|
when?: { logic: string; otherwise: "skip" | "hand_over"; text?: string | null } | null
|
|
@@ -920,16 +901,12 @@ when?: { logic: string; otherwise: "skip" | "hand_over"; text?: string | null }
|
|
|
920
901
|
|
|
921
902
|
The test runs in the same sandbox as the other logic (`evalWhenLogic`, `src/replay/logic.ts`). It is
|
|
922
903
|
decided when its step comes due, with what is known then: the request's values and the results of
|
|
923
|
-
the steps before it.
|
|
924
|
-
starts — where its first step *or its callee's* is: a sub-task whose chain begins with a call
|
|
925
|
-
begins with that call's steps, so nothing of it runs before its test says it is needed. A sub-task
|
|
926
|
-
is entered there too, before its callee, whose mapping reads its parameters, and left after the
|
|
927
|
-
last step of it or its callee (`frameEdges`, `src/replay/flatten.ts`).
|
|
904
|
+
the steps before it.
|
|
928
905
|
|
|
929
906
|
| The test says | What happens |
|
|
930
907
|
|---|---|
|
|
931
908
|
| `true` | The step runs. |
|
|
932
|
-
| `false`, `otherwise: "skip"` | Nothing is sent. The step is reported `not_taken` and the plan goes on.
|
|
909
|
+
| `false`, `otherwise: "skip"` | Nothing is sent. The step is reported `not_taken` and the plan goes on. |
|
|
933
910
|
| `false`, `otherwise: "hand_over"` | The plan stops in front of the step and hands the rest of the task to the model, saying the steps from here are only for when `text` (`fallbackKind: other_branch`). |
|
|
934
911
|
| throws, or not exactly `true` or `false` | The plan stops: the step is `failed` at stage `when_logic` (`fallbackKind: step_failed`). The model is told the plan could not tell whether this request needs the step, and decides itself. Nothing is guessed. |
|
|
935
912
|
|
|
@@ -937,24 +914,18 @@ A plan whose tests left out every step it came to, and ran none, hands the whole
|
|
|
937
914
|
(`other_branch`, step 0). Its report is `failed` with `fallbackKind: other_branch`, and it is sent
|
|
938
915
|
although it cost nothing: it tells the service the request took the half the plan does not know.
|
|
939
916
|
|
|
940
|
-
A step left out that is the last of a sub-task still hands the sub-task's results back to its
|
|
941
|
-
caller. When the body that maps them throws, the plan stops there: the call row is `failed` at stage
|
|
942
|
-
`tool_output_logic`, and the note says the sub-task could not hand back its results — never that
|
|
943
|
-
the step left out ran.
|
|
944
|
-
|
|
945
917
|
- **Direct mode** decides the tests in its loop. The bundle gives a left-out step its own heading,
|
|
946
918
|
`--- Step 5: tool (not needed) ---`, and says it is only for when `text`, so the model does not run
|
|
947
919
|
it itself.
|
|
948
920
|
- **Steer mode** settles the tests after each call. The `PostToolUse` answer names the next step
|
|
949
|
-
this request does not need, and the step to call instead. A call to a left-out tool
|
|
950
|
-
of a sub-task left out whole — is answered in its place with the same words, at most twice, and
|
|
921
|
+
this request does not need, and the step to call instead. A call to a left-out tool is answered in its place with the same words, at most twice, and
|
|
951
922
|
does not end the plan. When the left-out step and the next one share a tool and the note has not
|
|
952
923
|
reached the model yet, a call the pin guard (§7) finds is not the next step gets the note in its
|
|
953
924
|
place too, so the step left out never runs because the note was late. A note naming a step to call
|
|
954
925
|
next is dropped when the plan retires — a divergence, a hand-over — since the plan no longer has
|
|
955
926
|
that step; only "the sequence is complete" outlives a plan that finished.
|
|
956
|
-
- **The divergence bundle** (§8) decides the tests the same way, going on from
|
|
957
|
-
cursor is
|
|
927
|
+
- **The divergence bundle** (§8) decides the tests the same way, going on from where the
|
|
928
|
+
cursor is, with what the plan made so far. A `hand_over` stop ends the bundle there,
|
|
958
929
|
and the turn is booked `fell_back` when a step did its work (`failed` when none did) — a hand-over,
|
|
959
930
|
as in the other modes, never `diverged`, so the service takes the agent's work after it as that
|
|
960
931
|
half's evidence.
|
|
@@ -1034,16 +1005,10 @@ note replaces the call, in direct mode `run_scenario` answers with it). The deri
|
|
|
1034
1005
|
itself times out after max(`BIR_SERVICE_TIMEOUT_MS`, `BIR_DERIVE_BUDGET_MS`). None of these waits
|
|
1035
1006
|
happens while the service is cooling down after a failure: the turn simply runs normally.
|
|
1036
1007
|
|
|
1037
|
-
**Intent arming mid-turn is
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
(and no `BIR_INTENT_ARM=1`), or `BIR_INTENT_ARM=0`, it is never waited on. Up to 0.3.18 arming was
|
|
1042
|
-
opt-in: a segment runs only mid-task, and a plan that stops at its decision hands the rest of the
|
|
1043
|
-
task to segments of its halves, so 0.3.19 turns it on. A probe asks the service to hand segments out
|
|
1044
|
-
(`acceptSegments`) only where one can arm: segment and intent arming on, in Claude Code. Any other
|
|
1045
|
-
probe — `BIR_INTENT_ARM=0`, or a session of another host — gets what would have armed instead, and
|
|
1046
|
-
it is logged (`replay.segment_would_arm`).
|
|
1008
|
+
**Intent arming mid-turn is opt-in.** With `BIR_INTENT_ARM=1`, a `PreToolUse` whose call the agent
|
|
1009
|
+
explained sends an intent probe, and a whole plan it matches may arm in that call's place; the hook
|
|
1010
|
+
waits at most `BIR_INTENT_ARM_BUDGET_MS` (**500**) for the probe and 1.5 s for arming. Unset (or
|
|
1011
|
+
`0`), no probe is sent and nothing arms mid-turn.
|
|
1047
1012
|
|
|
1048
1013
|
`UserPromptSubmit` must stay non-`async`: an async hook is fire-and-forget and cannot return
|
|
1049
1014
|
`additionalContext` at all.
|
|
@@ -1075,8 +1040,7 @@ stopped at a step that broke (a logic failure, a tool error, a call sent and nev
|
|
|
1075
1040
|
recorded stand-in (`BIR_REPLAY_RECORDED_OUTPUTS=1`) is never work done: it counts toward neither
|
|
1076
1041
|
`stepsPinned` nor the upgrade, and a direct run that used one is `diverged` at best. A call that ran
|
|
1077
1042
|
beside a pinned one hands over as `fell_back` or `failed` (§7), and so does a divergence whose
|
|
1078
|
-
bundle stops in front of the other half of an "if … otherwise" (§9.2)
|
|
1079
|
-
decision (§8). A direct run cancelled by its caller
|
|
1043
|
+
bundle stops in front of the other half of an "if … otherwise" (§9.2). A direct run cancelled by its caller
|
|
1080
1044
|
(Esc, or `bir-scenario`'s own timeout) books `fell_back` or `failed` with `measured: false`, never
|
|
1081
1045
|
`diverged`: that turn's cost says nothing about what the task costs.
|
|
1082
1046
|
|
|
@@ -1185,10 +1149,6 @@ a replay that sent 3600.
|
|
|
1185
1149
|
has no output, and neither has a call the host says failed without a result. The exception is a
|
|
1186
1150
|
step its host stopped itself (§7.4): its verdict keeps what the host handed back, and after a
|
|
1187
1151
|
changed call it has no input, because only the host knows the arguments that call ran with.
|
|
1188
|
-
- **Only for the reported scenario's own steps.** A step inside a called segment is reported with
|
|
1189
|
-
its verdict and its `scenarioId`, without payloads: the console still files verdicts by step
|
|
1190
|
-
number alone (the service's plan-services.md, W1.9), and a called segment numbers its steps from
|
|
1191
|
-
zero too.
|
|
1192
1152
|
|
|
1193
1153
|
`ok` and `recorded` are passes (`recorded` with an asterisk: the values came from the source run,
|
|
1194
1154
|
which happens only with `BIR_REPLAY_RECORDED_OUTPUTS=1` and in `bir replay`). `skipped` produced no
|
|
@@ -1216,8 +1176,7 @@ nothing knows which step the stack trace belonged to. In steer mode there is no
|
|
|
1216
1176
|
the controller records the verdict at both hooks: `PreToolUse` for an input-logic throw, `PostToolUse`
|
|
1217
1177
|
for the pass or the output-logic throw — and keeps the pinned arguments on the pin, so the verdict
|
|
1218
1178
|
`PostToolUse` writes can say what the call ran with. `ReplayState.stepResults` is keyed by the
|
|
1219
|
-
|
|
1220
|
-
called segment's step 0 never replaces the caller's.
|
|
1179
|
+
step's index, so the second word on a step replaces the first.
|
|
1221
1180
|
|
|
1222
1181
|
One consequence for the rule that a costless decline is not worth sending (`buildReport`, and the
|
|
1223
1182
|
service's matching `202 { recorded: false }`): it now *is* worth sending when a step broke. No cost
|
|
@@ -1287,15 +1246,6 @@ tokens and every model in the list has a price; with no usage at all, the line s
|
|
|
1287
1246
|
`why="the host sent no usage"`. Such a host hands over one number for the whole run, so with more
|
|
1288
1247
|
than one plan in one run none of them is measured.
|
|
1289
1248
|
|
|
1290
|
-
**A plan stopped at its decision is billed up to the stop (0.3.19).** When a step of it ran, its
|
|
1291
|
-
hand-over takes a usage mark, and its report's window ends there: the agent's decision and the half
|
|
1292
|
-
it took are the agent's own, not the plan's (the service's segmentsbreakdown.md SB-26). This holds
|
|
1293
|
-
for a plan the prompt started, which gets a way to take a mark only when its stop is a decision, and
|
|
1294
|
-
for one an intent match started, whose window already ended at its own retire. Every other plan
|
|
1295
|
-
keeps its window — a plan of the prompt is billed for the whole turn up to the next plan, so the
|
|
1296
|
-
answer it was asked for stays on its bill — and every other hand-over still takes no mark. A
|
|
1297
|
-
decision reached before any step ran takes no mark either: its report is a sample of the whole turn.
|
|
1298
|
-
|
|
1299
1249
|
---
|
|
1300
1250
|
|
|
1301
1251
|
## 12. What the replayed turn records
|
|
@@ -1780,12 +1730,12 @@ bir replay status|on|off|allow <a,b>|allow all
|
|
|
1780
1730
|
|
|
1781
1731
|
bir scenario list GET /recordings/runs runs, iterations, scenario state
|
|
1782
1732
|
bir scenario show <runId> GET /recordings/runs/:id/scenario intent, params, steps, logic
|
|
1783
|
-
bir scenario show <scnId> GET /scenarios/:id the same, by scenario id
|
|
1733
|
+
bir scenario show <scnId> GET /scenarios/:id the same, by scenario id
|
|
1784
1734
|
[--step <n>: one step, with scenarioId and chainRevision first]
|
|
1785
1735
|
bir scenario calc <runId> POST /recordings/runs/:id/calculate [--force to re-derive in place]
|
|
1786
1736
|
[--force --discard-edits: re-derive a plan with hand edits]
|
|
1787
1737
|
bir scenario calc <scnId> --force
|
|
1788
|
-
POST /scenarios/:id/recalculate recalculate in place
|
|
1738
|
+
POST /scenarios/:id/recalculate recalculate in place
|
|
1789
1739
|
[--discard-edits: sends {discardEdits: true}]
|
|
1790
1740
|
bir scenario replay <scnId> --prompt "…" [--dry]
|
|
1791
1741
|
|
|
@@ -1811,8 +1761,7 @@ are where `bir` changes a scenario by hand, so the rules are strict:
|
|
|
1811
1761
|
`--force --note "<why>"`. `check` and `edit` run the same check; `check` never writes. When the
|
|
1812
1762
|
check had any problem, a forced save is recorded as forced, and `bir investigate` keeps saying so.
|
|
1813
1763
|
- `<id>` is a `run_` id, resolved to its whole-run scenario with `GET /recordings/runs/:id/scenario`,
|
|
1814
|
-
or a `scn_` id, used as it is.
|
|
1815
|
-
sub-task scenarios, `bir` lists their `scn_` ids. Logic goes in with `--input-logic` /
|
|
1764
|
+
or a `scn_` id, used as it is. Logic goes in with `--input-logic` /
|
|
1816
1765
|
`--output-logic` from a file, or `-` for stdin — never inline, because shell quoting mangles
|
|
1817
1766
|
JavaScript. `edit` also takes `--freeze`, `--unfreeze`, `--note` and `--revision <n>` (the
|
|
1818
1767
|
`expectedRevision` of the body).
|
|
@@ -158,8 +158,7 @@ Calculation is a background job. Poll `show` until `state` leaves `calculating`:
|
|
|
158
158
|
`409 scenario_exists` means this run already has one. Re-derive it in place — keeping the id and its
|
|
159
159
|
replay history — with `bir scenario calc run_… --force`. A `run_` id reaches only the run's
|
|
160
160
|
whole-run scenario. From the next version (not yet released), `bir scenario calc scn_… --force`
|
|
161
|
-
does the same by the scenario's own id
|
|
162
|
-
recalculate a sub-task scenario from `bir`.
|
|
161
|
+
does the same by the scenario's own id.
|
|
163
162
|
|
|
164
163
|
To change one step instead, without recalculating, see §9.2. A plan with steps edited by hand is
|
|
165
164
|
not rebuilt unless you add `--discard-edits`, which replaces those edits. They stay in
|
|
@@ -241,8 +240,10 @@ When replay arms:
|
|
|
241
240
|
§7) — and never in plan mode.
|
|
242
241
|
- **Direct steps are not visible to the permission system at all.** They are dispatched straight to a
|
|
243
242
|
`bir-proxy`, which calls the upstream on a connection it already holds — or, for Claude Code's own
|
|
244
|
-
`Read`, `Glob`, `Grep`, `Edit`, `Write` and `Bash`, run by the recorder itself
|
|
245
|
-
folder, any
|
|
243
|
+
`Read`, `Glob`, `Grep`, `Edit`, `Write` and `Bash`, run by the recorder itself from the project
|
|
244
|
+
folder, on any file the agent could reach (from 0.3.21; up to 0.3.20 only files inside the
|
|
245
|
+
project) and any `Bash` command included (`BIR_BUILTIN_TOOLS`, `BIR_PATH_ALLOW`,
|
|
246
|
+
`BIR_BASH_ALLOW`; up to 0.3.7 only the
|
|
246
247
|
first three). Claude Code never sees them.
|
|
247
248
|
The `run_scenario` call that starts them is answered `allow` too, while the runner has announced a
|
|
248
249
|
direct plan; your own deny or ask rules for it still apply.
|
|
@@ -253,7 +254,8 @@ That is what makes replay fast, and it is the whole risk. Two things follow:
|
|
|
253
254
|
2. Run `bir replay allow <servers>` (§5.3). An allowlist of the servers you are comfortable having
|
|
254
255
|
called unattended is cheap insurance, and it is the difference between "replay reads a dashboard"
|
|
255
256
|
and "replay can do anything any wrapped server can do". The same goes for built-ins:
|
|
256
|
-
`BIR_BUILTIN_TOOLS=Read,Glob,Grep` keeps writes and commands with the model,
|
|
257
|
+
`BIR_BUILTIN_TOOLS=Read,Glob,Grep` keeps writes and commands with the model,
|
|
258
|
+
`BIR_PATH_ALLOW=project` keeps the file tools inside the project folder, and
|
|
257
259
|
`BIR_BASH_ALLOW=git,npm test` (for example) limits the commands the recorder runs itself.
|
|
258
260
|
|
|
259
261
|
Nothing else is approved on your behalf. Outside a matched scenario's own steps, a wrapped MCP call
|
|
@@ -327,7 +329,6 @@ Recording : yes
|
|
|
327
329
|
· the recorder runs in the background (pid 41820); its audit log is ~/.baseinstrunner/logs/<key>.log
|
|
328
330
|
· the BaseIn service last answered the recorder 12 s ago
|
|
329
331
|
· wrapped MCP calls are not approved by the runner: Claude Code asks as it would without it. For headless runs (`claude -p`) allow them in permissions.allow or --allowedTools, or set BIR_CORRELATION_DECISION=allow where the recorder starts
|
|
330
|
-
· segments run mid-task — recurring sub-tasks, and the halves after a plan's decision — and so may whole plans (the default; BIR_SEGMENT_ARM=0 turns this off)
|
|
331
332
|
|
|
332
333
|
No problems found.
|
|
333
334
|
```
|
|
@@ -368,10 +369,10 @@ so there is exactly one switch and it cannot get out of step with itself.
|
|
|
368
369
|
| `BIR_STEP_TIMEOUT_MS` | `60000` | Per-step ceiling for one direct `tools/call`, clipped to what the plan has left |
|
|
369
370
|
| `BIR_LOGIC_TIMEOUT_MS` | `1000` | How long one scenario logic body may run before it is stopped. At most 10 000 |
|
|
370
371
|
| `BIR_REPLAY_RECORDED_OUTPUTS` | *(unset)* | `1` lets a step that could not be sent (a built-in off `BIR_BUILTIN_TOOLS`, no proxy, a server off the allowlist) stand on its recorded output instead of stopping the plan. Never for a timeout or an upstream error |
|
|
371
|
-
| `BIR_BUILTIN_TOOLS` | `Read,Glob,Grep,Edit,Write,Bash` | Built-ins the runner executes itself during a replay,
|
|
372
|
+
| `BIR_BUILTIN_TOOLS` | `Read,Glob,Grep,Edit,Write,Bash` | Built-ins the runner executes itself during a replay, from the session's own project directory (which folders the file tools may touch: `BIR_PATH_ALLOW`). A chain whose only non-MCP steps are on this list arms `direct`. A runner-side step never reaches the host's permission prompts, so leave off any tool you want the model to call itself; `Read,Glob,Grep` is the read-only set (the default up to 0.3.7). `none`: every built-in step is steered in the session. Claude Code sessions only: in a LangChain application a tool with one of these names is the application's own, and the runner runs none (§6.5) |
|
|
372
373
|
| `BIR_BASH_ALLOW` | *(unset: any command)* | Command prefixes a runner-side `Bash` step may run (`*` for all). Unset means any command; `none` means no command, and `Bash` steps are steered in the session. A plan's Bash steps share a working directory, exactly as the host's own Bash tool does — variables and functions do not persist, also as the host's. A call with `run_in_background`, or with its own `timeout` longer than the step's clock (`BIR_STEP_TIMEOUT_MS`), is never started on the runner: the plan hands over in front of it |
|
|
373
|
-
| `
|
|
374
|
-
| `BIR_INTENT_ARM` | *(unset)* | `1` lets a
|
|
374
|
+
| `BIR_PATH_ALLOW` | *(unset: any folder, from 0.3.21)* | Folders a runner-side `Read`, `Glob`, `Grep`, `Edit` or `Write` may touch (`*` for all). Unset means any path, as the agent's own tools reach it — a plan that reads the agent's memory file under `~/.claude` runs. `project` is the session's project folder alone (the rule up to 0.3.20); add folders after a comma, `~` for the home folder: `project,~/.claude`. Under a list, a path outside it, symlinks included, is refused and the plan hands over in front of it. `none` means no folder, and the file steps are steered in the session. `Bash` is `BIR_BASH_ALLOW`'s |
|
|
375
|
+
| `BIR_INTENT_ARM` | *(unset: off)* | `1` lets a whole plan whose intent matches the agent's reasoning mid-turn arm in the calling tool's place, which means waiting for it (`BIR_INTENT_ARM_BUDGET_MS`, 500). Unset or `0`: off — no probe is sent and nothing arms mid-turn, as up to 0.3.18 |
|
|
375
376
|
| `BIR_VERBOSE` | *(unset)* | `1` adds per-step `replay.*` detail lines |
|
|
376
377
|
|
|
377
378
|
The `bir` server reads its own, from the environment Claude Code starts it with:
|
|
@@ -494,11 +495,7 @@ Everything replay decides is one line. `grep` for these:
|
|
|
494
495
|
| `replay.step` | One direct step executed |
|
|
495
496
|
| `replay.step_not_taken` | A step's test said this request does not need it, and nothing was sent for it ([calculatedReplay.md](calculatedReplay.md) §9.2). `plan.armed … tests=` lists the tested steps by their place in the plan: `4:hand_over,11:skip` |
|
|
496
497
|
| `replay.diverge` / `replay.compose` | Off-script, and the recovery |
|
|
497
|
-
| `replay.handover` | The plan stopped and handed the rest of the task to the model; `kind=` and `step=` say where
|
|
498
|
-
| `run.fragment … decision=true` / `run.fragment_dropped` | After a plan's decision: the agent's own work from its next call is recorded as a fragment, from which the service makes a calculated scenario of that way / a plan the intent check armed, or a next scenario, took that call instead, so nothing is recorded as the agent's own |
|
|
499
|
-
| `replay.next_ready` / `replay.next_hit` / `replay.next_miss` | 0.3.20: the calculated scenarios that can follow a plan's decision, armed while the agent decided / the agent's call was one's first step, value for value, so it runs in the call's place / none was used: `reason=other_values` (the same first tool with other values), `own_way` (a call that may change something and starts none of them), `not_ready` (the one that starts with that tool was not armed in time), `calls_limit` (5 calls started none), `turn_ended`. A call that only reads ends nothing |
|
|
500
|
-
| `run.fragment_closed` | 0.3.20: a scenario that follows the decision took over after the agent's own looks had opened the fragment; the fragment ends there, with what the agent did itself |
|
|
501
|
-
| `replay.decision … code=would_repeat` | 0.3.20: a plan an intent match armed after the agent's call would have made that call again (the same tool that may change something, or for a shell the same command), so it was not started (never twice) |
|
|
498
|
+
| `replay.handover` | The plan stopped and handed the rest of the task to the model; `kind=` and `step=` say where |
|
|
502
499
|
| `replay.vetoed` | A direct plan retired without running anything: `run_scenario` was not the first call, or never arrived |
|
|
503
500
|
| `replay.run_ambiguous` | Two sessions had `run_scenario` pending and the request named neither; nothing ran |
|
|
504
501
|
| `replay.cancelled` / `replay.note_kept` | A direct run's caller went away (Esc); no further step started, and the note is kept for the model's next call |
|
|
@@ -583,11 +580,6 @@ A recorded output that stood in for a step (`BIR_REPLAY_RECORDED_OUTPUTS=1`) is
|
|
|
583
580
|
work done. A direct run you cancel (Esc) is booked `fell_back` or `failed` with `measured: false`:
|
|
584
581
|
a turn cut short says nothing about what the task costs.
|
|
585
582
|
|
|
586
|
-
A plan that stops at its decision (runner 0.3.19 or newer) is booked `fell_back` with
|
|
587
|
-
`fallbackKind: decision`, or `failed` when no step ran. Nothing is counted against its steps, and
|
|
588
|
-
when a step ran its cost ends at the stop: the agent's decision and the half it took are not on the
|
|
589
|
-
plan's bill.
|
|
590
|
-
|
|
591
583
|
A turn's cost is **measured** only when its tokens were found and every model of the turn has a
|
|
592
584
|
price in the runner's table. A model with no price used to count as $0, and that zero was called
|
|
593
585
|
measured. Now such a turn is not measured, in Claude Code as in any host, and a `run.unmeasured`
|
|
@@ -666,14 +658,12 @@ Code's pool, as before.
|
|
|
666
658
|
| `run_scenario` answers "The prepared results are not available for this request. Do the task normally with your tools." | The plan could not be delivered — a recorder that does not answer, a timeout, an HTTP error — and the model does the task itself | The `scenario.answered` line on the `bir` server's stderr has the real reason. `BIR_SCENARIO_DEBUG=1` in that server's environment hands the raw reason to the model as an error, for debugging |
|
|
667
659
|
| A hand-over note says a step "was sent but did not answer … may or may not have completed" | The step timed out, or its upstream went away mid-call; nothing after it ran | Check whether its work happened before running it again — the model is told the same. Repeats: look at that upstream, or raise `BIR_STEP_TIMEOUT_MS` |
|
|
668
660
|
| A hand-over note says "a step never runs on another session's upstream" | Two Claude Code sessions are open in the project, and this one has not yet made a call of its own to that server, so bir cannot tell its proxy from the other session's. A direct plan is told apart by the process that started both the `bir` server and the session's proxies, so for one this means an older proxy or `bir` server (restart the session after an update), or a server started through a wrapper such as a shell or `npx` | Expected: the model calls the tool itself. Once the session's own call to the server has gone through, later replays use its proxy |
|
|
669
|
-
| A hand-over note says the plan "ran the steps before a decision, and stopped there" | The service split the plan at its "if … otherwise" (runner 0.3.19 or newer): the plan runs the steps both ways need, then the agent decides which way applies. The note quotes the request's own sentences with the condition | Expected. The agent's next step may start a segment of the way it chose (`replay.intent_armed … kind=segment`); with `BIR_SEGMENT_ARM=0` it does that part itself. `bir investigate` shows the run as `fell_back · decision` |
|
|
670
|
-
| A hand-over note says a step "did not run: it has failed before", and the step never failed | A runner up to 0.3.18 met a plan's decision, a stop it does not know. It stops there too, but its note names a failure and lists the remaining steps | Update the runner (`bir update`, then `bir up --restart`) |
|
|
671
661
|
| A hand-over note says a step "was not run by the host", or "ran with arguments a person chose, not the scenario's" | A LangChain application (§6.5). A person said no to the step, or answered in the tool's place, or a call limit blocked the call (`host_rejected`); or a person changed the call before it ran (`host_edited`) | Expected, and no fault of the plan: the step is booked `skipped`, the plan stops there and the model takes over. It is told not to run the step again — after a refusal, unless the user asks. §7 has what the report says |
|
|
672
662
|
| `recorder.send_failed … error="HTTP 409 … invalid_ticket"` | The execution report's ticket was already redeemed, or belongs to another scenario. Or the report came more than an hour after its plan was handed out | Harmless if the body says `duplicate: true`. Otherwise a rollover raced `SessionEnd`; the server books once. A report that came too late is not booked; the service as built (not deployed yet) takes a report for 24 hours |
|
|
673
663
|
| `recorder.send_failed … error="HTTP 429 …"` | The account is over one of the service's limits, and the answer is `429` with `Retry-After`. The limits are built on the service and not deployed yet; each is a setting there. By default: 120 runs a minute · 3,000 steps a minute (a tool call is two steps) · 10 title requests a minute · 20 requests in any one hour for Calculate, Prefer and Recalculate together (`bir scenario calc` then prints a line that begins `Could not start calculation (HTTP 429`) | What it costs: a create, a step or a report is sent once more, at most 2 s later, then dropped. A dropped step is a hole in its recording. A run whose create got the 429 runs without its plan. A 429 that the second try did not cure counts as the service being unwell: for 5 to 60 seconds no prompt of that recorder waits for a match. An intent probe over its own limit (1,500 a minute) is answered with no match, never with `429` |
|
|
674
664
|
| `savedUsd` looks impossible | Pricing drift between the runner's table and the server's | Compare `PRICING_VERSION` on both sides. Design §11.3 documents a known live drift between two existing copies |
|
|
675
665
|
| The hand-over note says a step "did not run: its input needs a judgement" | The service marked the step non-deterministic when it calculated the plan: the generated logic could not compute its input from the prompt or from earlier outputs, so the recorded value was a copy (the service's plan-services design, D8 kind 3 — it lives in the BaseIn repository, not this one). `nondeterministicWhy: by_hand` means someone marked it with `bir scenario edit --freeze` | If the code only has a slip, fix the step yourself: `bir scenario show scn_… --step <n>`, write the input logic to a file, then `bir scenario edit scn_… --step <n> --input-logic <file>` — the service checks it against the recording before it saves it (§9.2, not yet released). Of the edits, only `--unfreeze` lifts a mark made by hand (`by_hand`); a code edit, even a forced one, leaves it in place. A real judgement — a choice with no fixed rule — cannot be written as code: the agent makes that choice and finishes the task; a model step for it is planned (W3.1). The journal's `plan.armed` line lists the step under `stops=` |
|
|
676
|
-
| A parked step ran again after an hour, or a plan was recalculated by itself | The service's grace period (D8): a parked step is served with `stop: null` once an hour for a day and a success clears its count; if it keeps failing, or its tool is gone, the next repeat of the prompt is recorded in full and the plan is calculated again from it | Nothing: that is the repair. `bir investigate` says which it is — a step still being retried, a parked step whose repair is due, or a plan being calculated again. To repair now by hand: `bir scenario calc <runId> --force` for a whole-run plan; from the next version, `bir scenario calc <scnId> --force` works
|
|
666
|
+
| A parked step ran again after an hour, or a plan was recalculated by itself | The service's grace period (D8): a parked step is served with `stop: null` once an hour for a day and a success clears its count; if it keeps failing, or its tool is gone, the next repeat of the prompt is recorded in full and the plan is calculated again from it | Nothing: that is the repair. `bir investigate` says which it is — a step still being retried, a parked step whose repair is due, or a plan being calculated again. To repair now by hand: `bir scenario calc <runId> --force` for a whole-run plan; from the next version, `bir scenario calc <scnId> --force` works by the plan's own id. A plan with steps edited by hand is not repaired by itself: the parked step stays parked, and `bir investigate` says the repair was skipped. Then fix the step (§9.2); or take the edits back with `bir scenario undo`, once per edit, and it is repaired as usual; or recalculate now and drop the edits: `bir scenario calc <scnId> --force --discard-edits` |
|
|
677
667
|
| `sessionCostUsd` grows every prompt in a session | The per-run usage watermark is missing or not taken | Design §11.4. Reports without a mark must carry `measured: false` |
|
|
678
668
|
| `run.unmeasured` in the log, and `bir investigate` shows the report as `UNMEASURED` | The turn's cost is not measured. The run opened before any hook carried a transcript path, or the runner has no price for a model of the turn (`models=` names it). In a LangChain application: the adapter sent no usage, the run made no model call, or a model has no price | Update the runner when it has no price for the model. The report is booked as not measured. A model with no price used to count as $0 and measured (§7) |
|
|
679
669
|
| Everything works, nothing is saved | A replayed turn is deliberately not recorded (design §12) | Correct. The matched run stays canonical and its `iterations` is bumped |
|
|
@@ -799,8 +789,7 @@ bir scenario editing on|off|status
|
|
|
799
789
|
```
|
|
800
790
|
|
|
801
791
|
A `run_` id finds the run's whole-run scenario. A `scn_` id (what `bir investigate` prints) is used
|
|
802
|
-
as it is.
|
|
803
|
-
lists their `scn_` ids instead of guessing. `--step` is the `stepIndex` that `show` prints; it
|
|
792
|
+
as it is. `--step` is the `stepIndex` that `show` prints; it
|
|
804
793
|
starts at 0. `--revision <n>` saves only if the plan is still at revision `n`: the `chainRevision`
|
|
805
794
|
at the top of `show --step`. `--json` on `check`, `edit`, `edits` or `undo` prints the service's
|
|
806
795
|
answer unchanged. Exit codes: `0` checked OK, saved or undone · `1` refused, not found, or a
|
|
@@ -829,8 +818,7 @@ code in its own process, with the global scope and only a time limit, where `fet
|
|
|
829
818
|
do exist. So read every change before it is saved — yours and Claude's.
|
|
830
819
|
|
|
831
820
|
**Only a step's code and its mark can be changed — and a parameter's kind (below, *A value no prompt names*).**
|
|
832
|
-
Not the parameters' sample values, not the logic that builds the final answer.
|
|
833
|
-
sub-task call row belongs to the service.
|
|
821
|
+
Not the parameters' sample values, not the logic that builds the final answer.
|
|
834
822
|
|
|
835
823
|
#### The fix, step by step
|
|
836
824
|
|
|
@@ -1027,8 +1015,6 @@ call with a mistake you do not want repeated. Then no correct code can reproduce
|
|
|
1027
1015
|
as a `warn`.
|
|
1028
1016
|
- A forced save removes a mark **the calculation** set, unless you also pass `--freeze`. A mark
|
|
1029
1017
|
made **by hand** (`--freeze`) stays. A save lifts it only with `--unfreeze`.
|
|
1030
|
-
- A step after a sub-task call row can only be saved with `--force`: the check cannot rebuild the
|
|
1031
|
-
outputs that step reads.
|
|
1032
1018
|
|
|
1033
1019
|
#### Mark or unmark a step by hand
|
|
1034
1020
|
|
|
@@ -1166,13 +1152,11 @@ Not recalculated: steps 3, 4 were edited by hand, and a recalculation rebuilds e
|
|
|
1166
1152
|
```
|
|
1167
1153
|
|
|
1168
1154
|
A `run_` id reaches only the run's whole-run scenario. `bir scenario calc <scnId> --force`
|
|
1169
|
-
recalculates any scenario in place, by its own id
|
|
1155
|
+
recalculates any scenario in place, by its own id. Add
|
|
1170
1156
|
`--discard-edits` when it has hand edits. A `scn_` id without `--force` is refused before anything
|
|
1171
1157
|
is sent: a scenario that exists can only be recalculated.
|
|
1172
1158
|
|
|
1173
|
-
The
|
|
1174
|
-
edits; the console does not discard them. The service's own rebuilds — the repair of a parked step
|
|
1175
|
-
(§9) and the adoption of a sub-task — skip a plan with hand edits. `bir investigate` says that the
|
|
1159
|
+
The service's own rebuild — the repair of a parked step (§9) — skips a plan with hand edits. `bir investigate` says that the
|
|
1176
1160
|
service does not rebuild the plan on its own, and warns when it skipped a repair
|
|
1177
1161
|
(`repair_skipped_edits`). After `--discard-edits` the old edits stay readable, but they cannot be
|
|
1178
1162
|
undone (`edit_replaced`).
|
|
@@ -1344,12 +1328,11 @@ Parameter database: target → setting (revision 4). Undo: bir scenario undo scn
|
|
|
1344
1328
|
| A `later` step no longer reproduces | The change broke a step after it — usually output logic that stopped keeping a value a later step reads | Keep every key the later steps read |
|
|
1345
1329
|
| `too costly to check` | The check used up its 5 seconds of sandbox time (`EDIT_CHECK_BUDGET_MS`). Usually code that reads or keeps a great many values, so the check has to run it very many times | Make the code cheaper to run, then check again |
|
|
1346
1330
|
| `Nothing to change: the step already has this code and this mark.` | The code and the mark you gave are what the step already has (`nothing_to_change`) | Nothing to do. `check` says `Nothing would change` for the same case |
|
|
1347
|
-
| `not_a_tool_step` | The index is a sub-task call row, not a tool step | Call rows cannot be edited; the service writes them |
|
|
1348
1331
|
| `note_required` | `--force` without `--note` | Add `--note "why"` |
|
|
1349
1332
|
| `revision_changed` | The plan changed since you read it: another edit, or a recalculation | `show` it again, check again, save again |
|
|
1350
1333
|
| `not_ready` or `scenario_calculating` | The scenario is not `ready`, or a recalculation is running | Wait for it to finish |
|
|
1351
1334
|
| `undo_refused` | The undo would stop a later step from giving its recorded call, or leave the final answer without its values | Fix that later step first. Or undo it on purpose: `--force --note "why"` |
|
|
1352
|
-
| `not_latest_edit` | The step has changed since the edit you named: a newer entry changed it. For a correction: the plan has changed since it
|
|
1335
|
+
| `not_latest_edit` | The step has changed since the edit you named: a newer entry changed it. For a correction: the plan has changed since it | `bir` prints two commands: undo the newer one first, then yours |
|
|
1353
1336
|
| `already_undone` | That edit was undone already | To redo it, undo the undo. `bir` prints the command |
|
|
1354
1337
|
| `edit_replaced` | A recalculation replaced the plan after that edit | Nothing to undo; the edit is history now |
|
|
1355
1338
|
| `logic_sandbox_unavailable` | The service could not run step code just now (HTTP 503). Nothing was checked, saved or undone | Try again in a minute |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basein/runner",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.22",
|
|
4
4
|
"description": "A recording MCP proxy: sits between any MCP client and its MCP servers, executes each call on the client's behalf, and records the run as a reusable BaseIn scenario.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|