@basein/runner 0.2.10 → 0.2.12
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 +41 -1
- package/dist/bin/bir-scenario.d.ts +29 -2
- package/dist/bin/bir-scenario.js +484 -16
- package/dist/bin/bir.d.ts +10 -0
- package/dist/bin/bir.js +143 -43
- package/dist/bin/investigate.js +2 -2
- package/dist/bin/scenario-edit.d.ts +200 -0
- package/dist/bin/scenario-edit.js +950 -0
- package/dist/config/generate.d.ts +21 -0
- package/dist/config/generate.js +16 -0
- package/dist/control/server.js +18 -5
- package/dist/record/housekeeping.d.ts +71 -0
- package/dist/record/housekeeping.js +417 -0
- package/dist/replay/controller.d.ts +3 -1
- package/dist/replay/controller.js +17 -12
- package/docs/calculatedReplay.md +115 -4
- package/docs/calculatedReplayGuide.md +528 -10
- package/docs/quickstart.md +44 -2
- package/package.json +1 -1
package/dist/bin/bir.js
CHANGED
|
@@ -12,6 +12,16 @@
|
|
|
12
12
|
* bir login | logout
|
|
13
13
|
* bir --version
|
|
14
14
|
*
|
|
15
|
+
* bir scenario list | show <runId|scnId> [--step <n>] | calc <runId|scnId> [--force [--discard-edits]]
|
|
16
|
+
* bir scenario check|edit <runId|scnId> --step <n> --input-logic <file|-> … ← fix one step
|
|
17
|
+
* bir scenario edits | undo <runId|scnId> [--edit <sedit_id> | --step <n>] [--force --note "why"]
|
|
18
|
+
* bir scenario editing on|off|status ← may this project's `bir` MCP server change a scenario?
|
|
19
|
+
* bir scenario replay <scnId> --prompt "…" [--dry] | bir replay status|on|off|allow …
|
|
20
|
+
* bir investigate [<id>] | list | executions
|
|
21
|
+
*
|
|
22
|
+
* The `scenario` words that read or change one step live in scenario-edit.ts
|
|
23
|
+
* (editSteps.md in the BaseIn repository); `investigate` in investigate.ts.
|
|
24
|
+
*
|
|
15
25
|
* `bir install` is reversible by construction: every file it edits is stashed
|
|
16
26
|
* verbatim first, so `bir uninstall` restores it byte-for-byte unless somebody
|
|
17
27
|
* else edited it in the meantime (in which case it repairs the entries and says
|
|
@@ -20,7 +30,7 @@
|
|
|
20
30
|
* from `serverInfo`, which must stay the upstream's (Phase 3).
|
|
21
31
|
*/
|
|
22
32
|
import { randomBytes } from "node:crypto";
|
|
23
|
-
import { existsSync, realpathSync, writeFileSync } from "node:fs";
|
|
33
|
+
import { existsSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
24
34
|
import { dirname, join, resolve as resolvePath } from "node:path";
|
|
25
35
|
import { fileURLToPath } from "node:url";
|
|
26
36
|
import { ControlClient } from "../control/client.js";
|
|
@@ -37,6 +47,7 @@ import { DEFAULT_CONTROL_PORT } from "../control/server.js";
|
|
|
37
47
|
import { errText } from "../util/log.js";
|
|
38
48
|
import { journalPath, readJournal } from "../util/journal.js";
|
|
39
49
|
import { investigateCommand } from "./investigate.js";
|
|
50
|
+
import { SCENARIO_EDIT_SUBCOMMANDS, scenarioEditCommand } from "./scenario-edit.js";
|
|
40
51
|
import { loadCredentials } from "../auth/client.js";
|
|
41
52
|
import { packageVersion } from "../util/version.js";
|
|
42
53
|
const VERSION = packageVersion();
|
|
@@ -59,8 +70,22 @@ Commands:
|
|
|
59
70
|
logout revoke this machine's session and forget it
|
|
60
71
|
|
|
61
72
|
scenario list recorded runs and their calculated scenarios
|
|
62
|
-
scenario show <runId>
|
|
63
|
-
|
|
73
|
+
scenario show <runId|scnId> [--step <n>]
|
|
74
|
+
a scenario: intent, params, steps (--step: just that one)
|
|
75
|
+
scenario calc <runId|scnId> [--force [--discard-edits]]
|
|
76
|
+
calculate (or re-derive) a run's scenario; a scn_ id
|
|
77
|
+
(a sub-task's too) is recalculated in place, with --force
|
|
78
|
+
scenario check <runId|scnId> --step <n> [--input-logic <file|->] [--output-logic <file|->] [--unfreeze]
|
|
79
|
+
try a change to one step against the recording; saves nothing
|
|
80
|
+
scenario edit <runId|scnId> --step <n> [--input-logic <file|->] [--output-logic <file|->]
|
|
81
|
+
[--freeze | --unfreeze] [--note "why"] [--force --note "why"] [--revision <n>]
|
|
82
|
+
the same check, and save the change if it passes
|
|
83
|
+
scenario edits <runId|scnId> a scenario's hand edits, newest first
|
|
84
|
+
scenario undo <runId|scnId> [--edit <sedit_id> | --step <n>] [--force --note "why"]
|
|
85
|
+
take back the newest edit (of step n); run it again to go
|
|
86
|
+
one further back; undo an undo's sedit_ id to redo
|
|
87
|
+
scenario editing on|off|status whether this project's bir MCP server offers the tools
|
|
88
|
+
that change a scenario (restart Claude Code after)
|
|
64
89
|
scenario replay <scnId> --prompt "…" [--dry]
|
|
65
90
|
replay --scenario <scnId> --prompt "…" [--dry]
|
|
66
91
|
replay status | on | off | allow <a,b> | allow all
|
|
@@ -83,8 +108,21 @@ Options:
|
|
|
83
108
|
--replay install/remove the scenario server, enabling calculated replay
|
|
84
109
|
--port <n> install/setup: control-server port to write into the hook URLs
|
|
85
110
|
(default: this project's, else the lowest free one from ${DEFAULT_CONTROL_PORT})
|
|
86
|
-
--json machine-readable output for status / doctor
|
|
111
|
+
--json machine-readable output for status / doctor / scenario / investigate
|
|
112
|
+
(scenario check|edit|edits|undo: the service's answer, unchanged)
|
|
87
113
|
--dry replay against recorded outputs only; run no real tools
|
|
114
|
+
--force scenario calc: recalculate in place · scenario edit: save although
|
|
115
|
+
the check refused it (needs --note; only for a recording that was wrong)
|
|
116
|
+
· scenario undo: undo although a later step or the answer would break
|
|
117
|
+
--step <n> scenario show|check|edit|undo: the step, by the stepIndex \`show\` prints
|
|
118
|
+
--input-logic <file|-> scenario check|edit: the new input logic, from a file or stdin (-)
|
|
119
|
+
--output-logic <file|-> scenario check|edit: the new output logic, from a file or stdin (-)
|
|
120
|
+
--freeze scenario edit: mark the step "needs a judgement" (runs hand over before it)
|
|
121
|
+
--unfreeze scenario check|edit: ask to remove that mark; the check decides
|
|
122
|
+
--note <text> scenario edit|undo: why, kept in the history (required with --force)
|
|
123
|
+
--revision <n> scenario edit|undo: only if the plan is still at this chainRevision
|
|
124
|
+
--edit <id> scenario undo: the sedit_ id to undo (default: the newest edit that can be)
|
|
125
|
+
--discard-edits scenario calc --force: recalculate a plan with hand edits, replacing them
|
|
88
126
|
--no-browser login: print the link and code, open nothing (SSH, headless)
|
|
89
127
|
--token <value> login: redeem a one-time setup token from the console (no browser)
|
|
90
128
|
--password login: use the old email/password prompt (deprecated)
|
|
@@ -118,6 +156,9 @@ function parseArgs(argv) {
|
|
|
118
156
|
noDaemon: false,
|
|
119
157
|
restart: false,
|
|
120
158
|
portExplicit: false,
|
|
159
|
+
freeze: false,
|
|
160
|
+
unfreeze: false,
|
|
161
|
+
discardEdits: false,
|
|
121
162
|
};
|
|
122
163
|
for (let i = 1; i < argv.length; i += 1) {
|
|
123
164
|
const arg = argv[i];
|
|
@@ -214,6 +255,53 @@ function parseArgs(argv) {
|
|
|
214
255
|
args.limit = n;
|
|
215
256
|
break;
|
|
216
257
|
}
|
|
258
|
+
case "--step": {
|
|
259
|
+
// Digits only: `Number("")` is 0 and `Number("0x4")` is 4, and a step
|
|
260
|
+
// index nobody typed is a step nobody meant to change.
|
|
261
|
+
const raw = argv[++i] ?? "";
|
|
262
|
+
if (!/^\d+$/.test(raw))
|
|
263
|
+
usage(2);
|
|
264
|
+
args.step = Number(raw);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case "--input-logic":
|
|
268
|
+
// A value flag, so a bare `-` (stdin) is taken here and never reaches
|
|
269
|
+
// the default branch, which refuses anything that starts with a dash.
|
|
270
|
+
args.inputLogic = argv[++i];
|
|
271
|
+
if (!args.inputLogic)
|
|
272
|
+
usage(2);
|
|
273
|
+
break;
|
|
274
|
+
case "--output-logic":
|
|
275
|
+
args.outputLogic = argv[++i];
|
|
276
|
+
if (!args.outputLogic)
|
|
277
|
+
usage(2);
|
|
278
|
+
break;
|
|
279
|
+
case "--freeze":
|
|
280
|
+
args.freeze = true;
|
|
281
|
+
break;
|
|
282
|
+
case "--unfreeze":
|
|
283
|
+
args.unfreeze = true;
|
|
284
|
+
break;
|
|
285
|
+
case "--note":
|
|
286
|
+
args.note = argv[++i];
|
|
287
|
+
if (args.note === undefined)
|
|
288
|
+
usage(2);
|
|
289
|
+
break;
|
|
290
|
+
case "--edit":
|
|
291
|
+
args.edit = argv[++i];
|
|
292
|
+
if (!args.edit)
|
|
293
|
+
usage(2);
|
|
294
|
+
break;
|
|
295
|
+
case "--revision": {
|
|
296
|
+
const raw = argv[++i] ?? "";
|
|
297
|
+
if (!/^\d+$/.test(raw) || Number(raw) <= 0)
|
|
298
|
+
usage(2);
|
|
299
|
+
args.revision = Number(raw);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "--discard-edits":
|
|
303
|
+
args.discardEdits = true;
|
|
304
|
+
break;
|
|
217
305
|
default:
|
|
218
306
|
if (arg.startsWith("-"))
|
|
219
307
|
usage(2);
|
|
@@ -221,6 +309,10 @@ function parseArgs(argv) {
|
|
|
221
309
|
args.positionals.push(arg);
|
|
222
310
|
}
|
|
223
311
|
}
|
|
312
|
+
if (args.freeze && args.unfreeze) {
|
|
313
|
+
process.stderr.write("[bir] --freeze and --unfreeze are mutually exclusive\n");
|
|
314
|
+
process.exit(2);
|
|
315
|
+
}
|
|
224
316
|
return args;
|
|
225
317
|
}
|
|
226
318
|
/** Absolute path to this package's built `bir-proxy.js`, for `--local`. */
|
|
@@ -960,51 +1052,59 @@ async function scenarioCommand(args) {
|
|
|
960
1052
|
}
|
|
961
1053
|
return 0;
|
|
962
1054
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
out("That run already has a scenario. Re-derive it in place with --force.");
|
|
993
|
-
return 1;
|
|
994
|
-
}
|
|
995
|
-
if (status === 503) {
|
|
996
|
-
out("The service has no Anthropic configuration, so it cannot calculate scenarios.");
|
|
997
|
-
return 1;
|
|
998
|
-
}
|
|
999
|
-
out(`Could not start calculation (HTTP ${status}): ${JSON.stringify(body)}`);
|
|
1000
|
-
return 1;
|
|
1055
|
+
// show, calc, and everything that reads or changes one step (editSteps.md).
|
|
1056
|
+
if (SCENARIO_EDIT_SUBCOMMANDS.has(sub)) {
|
|
1057
|
+
return scenarioEditCommand({
|
|
1058
|
+
positionals: args.positionals,
|
|
1059
|
+
json: args.json,
|
|
1060
|
+
force: args.force,
|
|
1061
|
+
step: args.step,
|
|
1062
|
+
inputLogic: args.inputLogic,
|
|
1063
|
+
outputLogic: args.outputLogic,
|
|
1064
|
+
freeze: args.freeze,
|
|
1065
|
+
unfreeze: args.unfreeze,
|
|
1066
|
+
note: args.note,
|
|
1067
|
+
edit: args.edit,
|
|
1068
|
+
revision: args.revision,
|
|
1069
|
+
discardEdits: args.discardEdits,
|
|
1070
|
+
}, {
|
|
1071
|
+
cwd: process.cwd(),
|
|
1072
|
+
out,
|
|
1073
|
+
service: async (method, path, body) => {
|
|
1074
|
+
try {
|
|
1075
|
+
return await service(method, path, body);
|
|
1076
|
+
}
|
|
1077
|
+
catch (err) {
|
|
1078
|
+
return { error: errText(err) };
|
|
1079
|
+
}
|
|
1080
|
+
},
|
|
1081
|
+
readFile: (path) => readFileSync(resolvePath(process.cwd(), path)),
|
|
1082
|
+
readStdin,
|
|
1083
|
+
});
|
|
1001
1084
|
}
|
|
1002
1085
|
if (sub === "replay") {
|
|
1003
1086
|
return replayCommand({ ...args, scenarioId: args.scenarioId ?? target });
|
|
1004
1087
|
}
|
|
1005
|
-
out("usage: bir scenario <list|show|calc|replay> …");
|
|
1088
|
+
out("usage: bir scenario <list|show|calc|check|edit|edits|undo|editing|replay> …");
|
|
1006
1089
|
return 2;
|
|
1007
1090
|
}
|
|
1091
|
+
/**
|
|
1092
|
+
* All of stdin, for `--input-logic -`. A person at a terminal gets told how to
|
|
1093
|
+
* end it; a pipe never sees the line (it goes to stderr, and only on a TTY).
|
|
1094
|
+
*/
|
|
1095
|
+
function readStdin() {
|
|
1096
|
+
if (process.stdin.isTTY) {
|
|
1097
|
+
process.stderr.write("[bir] reading the logic from stdin — end it with Ctrl-D (Ctrl-Z, Enter on Windows)\n");
|
|
1098
|
+
}
|
|
1099
|
+
return new Promise((resolve, reject) => {
|
|
1100
|
+
const chunks = [];
|
|
1101
|
+
process.stdin.on("data", (chunk) => {
|
|
1102
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk);
|
|
1103
|
+
});
|
|
1104
|
+
process.stdin.on("end", () => resolve(Buffer.concat(chunks)));
|
|
1105
|
+
process.stdin.on("error", reject);
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1008
1108
|
/**
|
|
1009
1109
|
* `--dry` evaluates the scenario's stored logic against the **source run's
|
|
1010
1110
|
* recorded outputs**, server-side: no real tools, no side effects, one Haiku
|
package/dist/bin/investigate.js
CHANGED
|
@@ -179,11 +179,11 @@ export const DECLINES = {
|
|
|
179
179
|
},
|
|
180
180
|
known_bad_first_step: {
|
|
181
181
|
cause: "the chain's first step is parked after repeated failures.",
|
|
182
|
-
fix: "wait: the service retries it once an hour for a day, then repairs the plan from the next run of the prompt. To repair now: `bir scenario calc <
|
|
182
|
+
fix: "wait: the service retries it once an hour for a day, then repairs the plan from the next run of the prompt — unless the plan has steps edited by hand, or is a sub-task, which it does not repair on its own. To repair now: `bir scenario calc <scnId> --force` (add --discard-edits to drop hand edits), or fix the step: `bir scenario edit <scnId> --step 0 --input-logic <file>`. `bir investigate <scnId>` names the scenario id.",
|
|
183
183
|
},
|
|
184
184
|
nondeterministic_first_step: {
|
|
185
185
|
cause: "the chain's first step needs a judgement the calculation could not write code for, so the plan cannot start.",
|
|
186
|
-
fix: "the
|
|
186
|
+
fix: "if its code only has a slip, fix the step yourself: read it with `bir scenario show <scnId> --step 0`, write the input logic to a file, and run `bir scenario edit <scnId> --step 0 --input-logic <file>`; the service checks it against the recording before it saves it. A real judgement — a choice with no fixed rule — stays with the agent until a model step exists (plan-services.md W3.1).",
|
|
187
187
|
},
|
|
188
188
|
unusable_first_step: {
|
|
189
189
|
cause: "the first step calls a sub-task that is gone, switched off or stale.",
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scenario-edit — read, check, change and undo one step of a calculated
|
|
3
|
+
* scenario (editSteps.md in the BaseIn repository; docs/calculatedReplayGuide.md §9.2).
|
|
4
|
+
*
|
|
5
|
+
* bir scenario show <runId|scnId> [--step <n>]
|
|
6
|
+
* bir scenario check <runId|scnId> --step <n> [--input-logic <file|->] [--output-logic <file|->] [--unfreeze]
|
|
7
|
+
* bir scenario edit <runId|scnId> --step <n> [--input-logic <file|->] [--output-logic <file|->]
|
|
8
|
+
* [--freeze | --unfreeze] [--note "why"] [--force --note "why"] [--revision <n>]
|
|
9
|
+
* bir scenario edits <runId|scnId>
|
|
10
|
+
* bir scenario undo <runId|scnId> [--edit <sedit_id> | --step <n>] [--force --note "why"]
|
|
11
|
+
* bir scenario calc <runId|scnId> [--force [--discard-edits]]
|
|
12
|
+
* bir scenario editing on|off|status
|
|
13
|
+
*
|
|
14
|
+
* WHY THIS IS A CLIENT AND NOTHING MORE. Whether a change may be saved is
|
|
15
|
+
* decided on the service, against the recording, by the calculation's own
|
|
16
|
+
* check (D3) — and `check` and `edit` are the same function there (D11). A
|
|
17
|
+
* runner-side pre-check would be a second opinion that can disagree with the
|
|
18
|
+
* one that counts, so this module reads logic from files, sends it, and says
|
|
19
|
+
* in words what the service answered. `--json` prints the answer unchanged,
|
|
20
|
+
* which is what the `bir` MCP server hands the model.
|
|
21
|
+
*
|
|
22
|
+
* Logic never comes from the command line itself. A JavaScript body is full
|
|
23
|
+
* of quotes, braces and `$`, and every shell mangles a different subset of
|
|
24
|
+
* them; a file, or stdin with `-`, arrives byte for byte.
|
|
25
|
+
*
|
|
26
|
+
* Everything the commands touch is injected ({@link ScenarioEditDeps}), as in
|
|
27
|
+
* `investigate.ts`, so all of it is tested in-process against a fake service.
|
|
28
|
+
* The exception is `editing`, which writes the install sidecar — tests point
|
|
29
|
+
* `BIR_HOME` at a temporary directory for that.
|
|
30
|
+
*/
|
|
31
|
+
export type InputStatus = "reproduces" | "differs" | "throws" | "copy" | "not_checked";
|
|
32
|
+
export interface EditReport {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
stepIndex: number;
|
|
35
|
+
toolName: string | null;
|
|
36
|
+
/** The recording the change was checked against. */
|
|
37
|
+
sourceRunId: string;
|
|
38
|
+
verifiable: boolean;
|
|
39
|
+
input: {
|
|
40
|
+
changed: boolean;
|
|
41
|
+
before: InputStatus;
|
|
42
|
+
after: InputStatus;
|
|
43
|
+
computed?: unknown;
|
|
44
|
+
recorded?: unknown;
|
|
45
|
+
firstDifference?: {
|
|
46
|
+
at: number;
|
|
47
|
+
computed: string;
|
|
48
|
+
recorded: string;
|
|
49
|
+
};
|
|
50
|
+
error?: string;
|
|
51
|
+
};
|
|
52
|
+
output: {
|
|
53
|
+
changed: boolean;
|
|
54
|
+
status: "runs" | "throws" | "not_object" | "unchanged";
|
|
55
|
+
emittedKeys?: string[];
|
|
56
|
+
error?: string;
|
|
57
|
+
};
|
|
58
|
+
later: Array<{
|
|
59
|
+
stepIndex: number;
|
|
60
|
+
toolName: string | null;
|
|
61
|
+
before: InputStatus;
|
|
62
|
+
after: InputStatus;
|
|
63
|
+
regressed: boolean;
|
|
64
|
+
}>;
|
|
65
|
+
answer: {
|
|
66
|
+
informativeBefore: boolean;
|
|
67
|
+
informativeAfter: boolean;
|
|
68
|
+
} | null;
|
|
69
|
+
mark: {
|
|
70
|
+
before: MarkState;
|
|
71
|
+
after: MarkState;
|
|
72
|
+
};
|
|
73
|
+
/** The logic and mark asked for are what the step already has (rule 10). */
|
|
74
|
+
noChange?: boolean;
|
|
75
|
+
/** The check stopped at the service's sandbox-time budget: *too costly to check* (rule 11). */
|
|
76
|
+
budgetExceeded?: boolean;
|
|
77
|
+
problems: string[];
|
|
78
|
+
}
|
|
79
|
+
interface MarkState {
|
|
80
|
+
marked: boolean;
|
|
81
|
+
why: string | null;
|
|
82
|
+
}
|
|
83
|
+
export interface StepState {
|
|
84
|
+
toolInputLogic: string | null;
|
|
85
|
+
toolOutputLogic: string | null;
|
|
86
|
+
nondeterministic: boolean;
|
|
87
|
+
nondeterministicWhy: string | null;
|
|
88
|
+
editedAt: string | null;
|
|
89
|
+
editForced: boolean;
|
|
90
|
+
}
|
|
91
|
+
export interface EditEntry {
|
|
92
|
+
id: string;
|
|
93
|
+
scenarioId: string;
|
|
94
|
+
stepIndex: number;
|
|
95
|
+
kind: "edit" | "freeze" | "revert";
|
|
96
|
+
revertsEditId: string | null;
|
|
97
|
+
note: string | null;
|
|
98
|
+
forced: boolean;
|
|
99
|
+
chainRevisionBefore: number;
|
|
100
|
+
chainRevisionAfter: number;
|
|
101
|
+
before: StepState;
|
|
102
|
+
after: StepState;
|
|
103
|
+
report: EditReport | null;
|
|
104
|
+
createdAt: string;
|
|
105
|
+
/** A later undo put this one back. */
|
|
106
|
+
revertedAt: string | null;
|
|
107
|
+
/** A recalculation replaced the chain; the entry is history now. */
|
|
108
|
+
replacedAt: string | null;
|
|
109
|
+
}
|
|
110
|
+
export type ServiceReply = {
|
|
111
|
+
status: number;
|
|
112
|
+
body: unknown;
|
|
113
|
+
} | {
|
|
114
|
+
error: string;
|
|
115
|
+
};
|
|
116
|
+
export interface ScenarioEditDeps {
|
|
117
|
+
cwd: string;
|
|
118
|
+
out: (line?: string) => void;
|
|
119
|
+
/** An authenticated call to the service; a failure to reach it is `{ error }`, never a throw. */
|
|
120
|
+
service: (method: string, path: string, body?: unknown) => Promise<ServiceReply>;
|
|
121
|
+
/** A logic file's bytes. Relative paths are the caller's to resolve. */
|
|
122
|
+
readFile: (path: string) => Buffer;
|
|
123
|
+
/** All of stdin, for `--input-logic -` / `--output-logic -`. */
|
|
124
|
+
readStdin: () => Promise<Buffer>;
|
|
125
|
+
}
|
|
126
|
+
export interface ScenarioEditArgs {
|
|
127
|
+
/** The words after `bir scenario`: `[sub, target | on|off|status, …]`. */
|
|
128
|
+
positionals: string[];
|
|
129
|
+
json: boolean;
|
|
130
|
+
force: boolean;
|
|
131
|
+
step?: number;
|
|
132
|
+
/** A path, or `-` for stdin. */
|
|
133
|
+
inputLogic?: string;
|
|
134
|
+
outputLogic?: string;
|
|
135
|
+
freeze: boolean;
|
|
136
|
+
unfreeze: boolean;
|
|
137
|
+
note?: string;
|
|
138
|
+
/** `undo --edit`: the `sedit_` id to put back. `undo --step` is {@link step}. */
|
|
139
|
+
edit?: string;
|
|
140
|
+
/** `--revision`: save only if the plan is still at this `chainRevision`. */
|
|
141
|
+
revision?: number;
|
|
142
|
+
discardEdits: boolean;
|
|
143
|
+
}
|
|
144
|
+
/** The `bir scenario` words this module answers; `list` and `replay` stay in bir.ts. */
|
|
145
|
+
export declare const SCENARIO_EDIT_SUBCOMMANDS: ReadonlySet<string>;
|
|
146
|
+
/** The `bir` MCP server's tools that only read: always offered (D2). */
|
|
147
|
+
export declare const READ_TOOLS: readonly ["scenario_show", "scenario_edits", "investigate"];
|
|
148
|
+
/** The ones that change a scenario: offered only after `bir scenario editing on` (D2). */
|
|
149
|
+
export declare const EDIT_TOOLS: readonly ["scenario_check", "scenario_edit", "scenario_undo"];
|
|
150
|
+
export declare function scenarioEditCommand(args: ScenarioEditArgs, deps: ScenarioEditDeps): Promise<number>;
|
|
151
|
+
/**
|
|
152
|
+
* A logic file's text. UTF-8, with a byte-order mark dropped — and UTF-16 with
|
|
153
|
+
* its mark decoded, because that is what `"…" > step.js` writes in Windows
|
|
154
|
+
* PowerShell 5.1, and a service answering "SyntaxError" to a file that looks
|
|
155
|
+
* fine in every editor is a riddle nobody should have to solve.
|
|
156
|
+
*/
|
|
157
|
+
export declare function decodeLogic(bytes: Buffer): string;
|
|
158
|
+
/**
|
|
159
|
+
* The report in the lines editSteps.md "What a person sees" shows:
|
|
160
|
+
* `input`, `output` (when the output logic changed), `later`, `answer` (when
|
|
161
|
+
* the final answer read anything before) and `mark`.
|
|
162
|
+
*
|
|
163
|
+
* `check` prints every line: it is where a person explores a change, and "step
|
|
164
|
+
* 5 still reproduces" is an answer there. `edit` and `undo` are acts, and print
|
|
165
|
+
* `brief`ly — what changed and what went wrong: `input` always, `output` when
|
|
166
|
+
* it changed, `later` only for a step that broke, `answer` only when it lost its
|
|
167
|
+
* values, `mark` only when it moves. The report is the same one either way (D11);
|
|
168
|
+
* only the lines that say "nothing to see" are left out.
|
|
169
|
+
*
|
|
170
|
+
* An `undo` does not judge the step itself — its code and mark go back exactly
|
|
171
|
+
* as they were (editSteps.md, "Undo") — so its report's input status is
|
|
172
|
+
* `not_checked` by design, and printing the usual reason for that ("the
|
|
173
|
+
* recorded call is plain text") would be false. It says what happened instead.
|
|
174
|
+
*/
|
|
175
|
+
export declare function renderReport(out: (line?: string) => void, r: EditReport, opts?: {
|
|
176
|
+
brief?: boolean;
|
|
177
|
+
undo?: boolean;
|
|
178
|
+
}): void;
|
|
179
|
+
/**
|
|
180
|
+
* About {@link CONTEXT} characters either side of `at`. A text already that
|
|
181
|
+
* short — a window the service cut itself, or a small call — is printed whole.
|
|
182
|
+
*/
|
|
183
|
+
export declare function around(text: string, at: number): string;
|
|
184
|
+
/**
|
|
185
|
+
* What `undo` without `--edit` takes back (D9): the newest **edit** — never an
|
|
186
|
+
* undo entry — that nothing has put back and no recalculation replaced; of
|
|
187
|
+
* step `step` when it is given.
|
|
188
|
+
*
|
|
189
|
+
* Undo entries are skipped on purpose. They used to be picked like any other,
|
|
190
|
+
* so a second `undo` redid the first one, and a step edited twice toggled
|
|
191
|
+
* between its two edits for ever and never got back to the calculation's code
|
|
192
|
+
* (C12). Now a second `undo` goes one further back; a redo is asked for by
|
|
193
|
+
* name, `--edit <the undo's id>`, which the undo prints.
|
|
194
|
+
*
|
|
195
|
+
* Whether the step is still exactly as that edit left it is the service's
|
|
196
|
+
* question, not this list's: it answers `not_latest_edit` when it is not.
|
|
197
|
+
*/
|
|
198
|
+
export declare function newestUndoable(edits: EditEntry[], step?: number): EditEntry | undefined;
|
|
199
|
+
export {};
|
|
200
|
+
//# sourceMappingURL=scenario-edit.d.ts.map
|