@basein/runner 0.3.27 → 0.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -423,6 +423,19 @@ bir scenario edit scn_… --param database --kind setting --note "why" # use
423
423
  bir scenario undo scn_… --param database # take that back
424
424
  ```
425
425
 
426
+ **The learning phase.** Not yet released. A new plan is in its learning phase
427
+ until 10 of its runs were evaluated (1 to 50, per plan). In it the service tries
428
+ one change at a time and keeps it only when the plan got better: successful
429
+ runs first, then cost, then speed. `bir scenario show` ends with where it
430
+ stands; `bir scenario edits` lists its changes under their `simp_` ids
431
+ ([the guide's §9.3](docs/calculatedReplayGuide.md)):
432
+
433
+ ```bash
434
+ bir scenario learning scn_… # runs evaluated, the measures now, the changes tried
435
+ bir scenario learning scn_… --runs 20 # learn for 20 runs; --stop ends it, --again starts anew
436
+ bir scenario undo scn_… --edit simp_… # take back a change the learning phase made
437
+ ```
438
+
426
439
  ---
427
440
 
428
441
  ## Two things to know before you turn it on
@@ -596,7 +596,8 @@ const SCENARIO_TOOLS = [
596
596
  description: "List a calculated scenario's hand edits, newest first — step edits and parameter kind changes: step or " +
597
597
  "parameter, note, revision, and whether each was forced, undone or replaced by a recalculation — and the " +
598
598
  "corrections the service made from a run the agent redid (scor_ ids): what each added, tested or changed, " +
599
- "and whether it is used.",
599
+ "and whether it is used — and the changes its learning phase made (simp_ ids): what each changed and why, " +
600
+ "and whether it is on trial, kept or taken back.",
600
601
  inputSchema: {
601
602
  type: "object",
602
603
  properties: { target: TARGET },
@@ -746,14 +747,15 @@ const SCENARIO_TOOLS = [
746
747
  "one further back. The service checks a step's undo like a save and refuses it when a later step or the final " +
747
748
  "answer would break — `force` with a `note` undoes it anyway. To redo, undo the undo: pass its id as `edit` (the " +
748
749
  "answer names it). A scor_ id takes back a correction the service made: the plan goes back exactly as it was " +
749
- "before it, and is held — not used — until it is corrected again or let go on the recording page.",
750
+ "before it, and is held — not used — until it is corrected again or let go on the recording page. A simp_ id " +
751
+ "takes back a change the plan's learning phase made, by its id only: the plan goes back exactly as it was before it.",
750
752
  inputSchema: {
751
753
  type: "object",
752
754
  properties: {
753
755
  target: TARGET,
754
756
  edit: {
755
757
  type: "string",
756
- description: "The sedit_, pedit_ or scor_ id to undo, as scenario_edits lists it. Not with `step` or `param`.",
758
+ description: "The sedit_, pedit_, scor_ or simp_ id to undo, as scenario_edits lists it. Not with `step` or `param`.",
757
759
  },
758
760
  step: {
759
761
  ...STEP,
@@ -779,8 +781,8 @@ const SCENARIO_TOOLS = [
779
781
  throw new BadArguments("`edit`, `step` and `param` each pick what to undo; give one of them");
780
782
  }
781
783
  if (a.edit !== undefined && a.edit !== null) {
782
- if (typeof a.edit !== "string" || !/^(sedit|pedit|scor)_[\w-]+$/.test(a.edit)) {
783
- throw new BadArguments("`edit` must be a sedit_…, pedit_… or scor_… id");
784
+ if (typeof a.edit !== "string" || !/^(sedit|pedit|scor|simp)_[\w-]+$/.test(a.edit)) {
785
+ throw new BadArguments("`edit` must be a sedit_…, pedit_… or scor_… id, or a learning change's simp_… id");
784
786
  }
785
787
  if (a.step !== undefined && a.step !== null) {
786
788
  throw new BadArguments("`edit` names one entry and `step` picks one; give one of them");
package/dist/bin/bir.js CHANGED
@@ -123,10 +123,16 @@ Commands:
123
123
  a target must be named by the prompt or the plan is
124
124
  declined; a setting uses its recorded value when the
125
125
  prompt names none (needs --note)
126
- scenario edits <runId|scnId> a scenario's hand edits, newest first
126
+ scenario edits <runId|scnId> a scenario's hand edits, corrections and learning changes,
127
+ newest first
127
128
  scenario undo <runId|scnId> [--edit <id> | --step <n> | --param <name>] [--force --note "why"]
128
129
  take back the newest edit (of step n, or parameter name);
129
130
  run it again to go one further back; undo an undo's id to redo
131
+ scenario learning <runId|scnId> [--runs <n>] [--stop] [--again]
132
+ a plan's learning phase: runs evaluated, the measures of its
133
+ revision now, what the last run showed, the changes tried
134
+ (--runs: how many runs it lasts, 1–50; --stop: end it now;
135
+ --again: start a new one)
130
136
  scenario editing on|off|status whether this project's bir MCP server offers the tools
131
137
  that read and change a scenario (restart Claude Code after);
132
138
  \`bir setup\` turns it on, and an off stays off
@@ -159,7 +165,7 @@ Options:
159
165
  --port <n> install/setup: control-server port to write into the hook URLs
160
166
  (default: this project's, else the lowest free one from ${DEFAULT_CONTROL_PORT})
161
167
  --json machine-readable output for status / doctor / scenario / investigate
162
- (scenario check|edit|edits|undo: the service's answer, unchanged)
168
+ (scenario check|edit|edits|undo|learning: the service's answer, unchanged)
163
169
  --dry replay against recorded outputs only; run no real tools
164
170
  --force scenario calc: recalculate in place · scenario edit: save although
165
171
  the check refused it (needs --note; only for a recording that was wrong)
@@ -171,12 +177,17 @@ Options:
171
177
  --unfreeze scenario check|edit: ask to remove that mark; the check decides
172
178
  --note <text> scenario edit|undo: why, kept in the history (required with --force)
173
179
  --revision <n> scenario edit|undo: only if the plan is still at this chainRevision
174
- --edit <id> scenario undo: the sedit_, pedit_ or scor_ id to undo (default: the newest
175
- that can be); a scor_ id puts back the plan from before that correction
180
+ --edit <id> scenario undo: the sedit_, pedit_, scor_ or simp_ id to undo (default: the newest
181
+ that can be); a scor_ id puts back the plan from before that correction,
182
+ a simp_ id the plan from before that learning change
176
183
  --param <name> scenario edit: the parameter whose kind changes · scenario undo: its newest change
177
184
  --kind <kind> scenario edit --param: target (a prompt must name it) or setting (its
178
185
  recorded value is used when a prompt names none; needs --note)
179
186
  --discard-edits scenario calc --force: recalculate a plan with hand edits, replacing them
187
+ --runs <n> scenario learning: how many evaluated runs the learning phase lasts (1–50);
188
+ with --again, how many the new one lasts
189
+ --stop scenario learning: end the learning phase now
190
+ --again scenario learning: start a new learning phase
180
191
  --no-browser login: print the link and code, open nothing (SSH, headless)
181
192
  --token <value> login: redeem a one-time setup token from the console (no browser)
182
193
  --password login: use the old email/password prompt (deprecated)
@@ -222,6 +233,8 @@ function parseArgs(argv) {
222
233
  freeze: false,
223
234
  unfreeze: false,
224
235
  discardEdits: false,
236
+ stop: false,
237
+ again: false,
225
238
  here: false,
226
239
  all: false,
227
240
  quick: false,
@@ -402,6 +415,21 @@ function parseArgs(argv) {
402
415
  if (!args.kind)
403
416
  usage(2);
404
417
  break;
418
+ case "--runs": {
419
+ // Digits only, as --step: the range (1–50) is scenario-edit.ts's to
420
+ // explain in words.
421
+ const raw = argv[++i] ?? "";
422
+ if (!/^\d+$/.test(raw))
423
+ usage(2);
424
+ args.runs = Number(raw);
425
+ break;
426
+ }
427
+ case "--stop":
428
+ args.stop = true;
429
+ break;
430
+ case "--again":
431
+ args.again = true;
432
+ break;
405
433
  case "--here":
406
434
  args.here = true;
407
435
  break;
@@ -3622,6 +3650,9 @@ async function scenarioCommand(args) {
3622
3650
  discardEdits: args.discardEdits,
3623
3651
  param: args.param,
3624
3652
  kind: args.kind,
3653
+ runs: args.runs,
3654
+ stop: args.stop,
3655
+ again: args.again,
3625
3656
  }, {
3626
3657
  cwd: process.cwd(),
3627
3658
  out,
@@ -3640,7 +3671,7 @@ async function scenarioCommand(args) {
3640
3671
  if (sub === "replay") {
3641
3672
  return replayCommand({ ...args, scenarioId: args.scenarioId ?? target });
3642
3673
  }
3643
- out("usage: bir scenario <list|show|calc|check|edit|edits|undo|editing|replay> …");
3674
+ out("usage: bir scenario <list|show|calc|check|edit|edits|undo|editing|learning|replay> …");
3644
3675
  return 2;
3645
3676
  }
3646
3677
  /**
@@ -8,8 +8,9 @@
8
8
  * [--freeze | --unfreeze] [--note "why"] [--force --note "why"] [--revision <n>]
9
9
  * bir scenario edit <runId|scnId> --param <name> --kind target|setting [--note "why"] [--revision <n>]
10
10
  * bir scenario edits <runId|scnId>
11
- * bir scenario undo <runId|scnId> [--edit <sedit_id|pedit_id> | --step <n> | --param <name>] [--force --note "why"]
11
+ * bir scenario undo <runId|scnId> [--edit <sedit_id|pedit_id|scor_id|simp_id> | --step <n> | --param <name>] [--force --note "why"]
12
12
  * bir scenario calc <runId|scnId> [--force [--discard-edits]]
13
+ * bir scenario learning <runId|scnId> [--runs <n>] [--stop] [--again]
13
14
  * bir scenario editing on|off|status
14
15
  *
15
16
  * WHY THIS IS A CLIENT AND NOTHING MORE. Whether a change may be saved is
@@ -214,6 +215,12 @@ export interface ScenarioEditArgs {
214
215
  param?: string;
215
216
  /** `edit --kind target|setting`, with `--param`. Checked here, so any word reaches the usage line. */
216
217
  kind?: string;
218
+ /** `learning --runs <n>`: how many evaluated runs the plan's learning phase lasts (1–50). */
219
+ runs?: number;
220
+ /** `learning --stop`: end the learning phase now. */
221
+ stop?: boolean;
222
+ /** `learning --again`: start a new learning phase (of `runs`, when given). */
223
+ again?: boolean;
217
224
  }
218
225
  /** The `bir scenario` words this module answers; `list` and `replay` stay in bir.ts. */
219
226
  export declare const SCENARIO_EDIT_SUBCOMMANDS: ReadonlySet<string>;
@@ -295,5 +302,99 @@ export declare function newestUndoableParam(paramEdits: ParamEditEntry[], param?
295
302
  * when `--step` or `--param` narrows the undo to a step or a parameter.
296
303
  */
297
304
  export declare function newestUndoableCorrection(corrections: CorrectionEntry[]): CorrectionEntry | undefined;
305
+ /** What a learning-phase change aims to make better (the service's learningPhase.md). */
306
+ export type LearningAim = "successful" | "cost" | "speed";
307
+ /** The three measures of one revision of a plan: successful runs, cost, speed. */
308
+ export interface LearningMeasures {
309
+ evaluated: number;
310
+ successful: number;
311
+ successShare: number | null;
312
+ /** Median cost ÷ the original cost, over the successful measured runs. */
313
+ costRatio: number | null;
314
+ /** Median time ÷ the original time, over the successful runs. */
315
+ speedRatio: number | null;
316
+ }
317
+ /** A problem the service's rules found in a run (P1–P10). */
318
+ export interface LearningProblem {
319
+ code: string;
320
+ aim: LearningAim | string;
321
+ /** One plain sentence. */
322
+ text: string;
323
+ step: number | null;
324
+ }
325
+ /** One change of a plan in its learning phase: `simp_` + uuid. Only what is printed is read. */
326
+ export interface LearningChange {
327
+ id: string;
328
+ createdAt: string;
329
+ aim: LearningAim | string;
330
+ /** One sentence: what changed and why. */
331
+ summary: string;
332
+ state: "proposed" | "trial" | "kept" | "taken_back" | "failed_check" | "dismissed" | "replaced" | string;
333
+ revisionBefore?: number;
334
+ revisionAfter?: number | null;
335
+ /** One sentence with the numbers, once it was kept or taken back. */
336
+ decision?: string | null;
337
+ }
338
+ /** `GET /scenarios/:id/learning`'s `learning`: the phase, its measures, its problems and its changes. */
339
+ export interface LearningView {
340
+ scenarioId?: string;
341
+ /** Null: the plan never had a learning phase. */
342
+ state: "learning" | "done" | "stopped" | null;
343
+ mode?: "off" | "count" | "observe" | "on" | string;
344
+ phase?: number;
345
+ runs: number;
346
+ evaluated: number;
347
+ revision?: number;
348
+ trial: {
349
+ changeId: string;
350
+ needed: number;
351
+ done: number;
352
+ } | null;
353
+ measures?: {
354
+ current: LearningMeasures | null;
355
+ start: LearningMeasures | null;
356
+ };
357
+ changes?: LearningChange[];
358
+ problems?: LearningProblem[];
359
+ }
360
+ /** A scenario's `learning`, as `GET /scenarios/:id` serves it beside the plan. */
361
+ export interface LearningBrief {
362
+ state: "learning" | "done" | "stopped";
363
+ runs: number;
364
+ evaluated: number;
365
+ trial: {
366
+ changeId: string;
367
+ needed: number;
368
+ done: number;
369
+ } | null;
370
+ /** Changes proposed and waiting for the owner. */
371
+ waiting: number;
372
+ }
373
+ /** A learning-phase change in `GET /scenarios/:id/edits`'s `learning`. */
374
+ export interface LearningEditEntry {
375
+ id: string;
376
+ createdAt: string;
377
+ state: LearningChange["state"];
378
+ aim: LearningAim | string;
379
+ summary: string;
380
+ revisionBefore: number;
381
+ revisionAfter: number | null;
382
+ }
383
+ /**
384
+ * The learning phase in one line (the service's learningPhase.md LP1, LP9):
385
+ * "Learning: 4 of 10 runs evaluated · change 2 on trial (1 of 2 runs)",
386
+ * "Learning done after 10 runs", "Learning stopped after 4 runs", or "No
387
+ * learning phase". `changes`, when known, give the change on trial its
388
+ * number, oldest first; `waiting`, the changes that wait for their owner.
389
+ */
390
+ export declare function learningLine(l: Partial<Pick<LearningView, "state" | "runs" | "evaluated" | "trial">> | null | undefined, changes?: ReadonlyArray<Partial<LearningChange>>, waiting?: number | null): string;
391
+ /**
392
+ * A revision's three measures in one line, leaving out what is not known:
393
+ * "Successful 4 of 6 · cost 40% under the original · time 35% under the
394
+ * original". Undefined when none is.
395
+ */
396
+ export declare function measuresLine(m: Partial<LearningMeasures> | null | undefined): string | undefined;
397
+ /** The second line of a learning change in `edits`: what it did, what for, and what became of it. */
398
+ export declare function learningEditSummary(c: LearningEditEntry): string;
298
399
  export {};
299
400
  //# sourceMappingURL=scenario-edit.d.ts.map