swarm-orchestrator 13.1.4 → 13.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +25 -4
  3. package/dist/agent-run.js +39 -1
  4. package/dist/agent-run.js.map +1 -1
  5. package/dist/cli-options.js +9 -8
  6. package/dist/cli-options.js.map +1 -1
  7. package/dist/cli.js +262 -10
  8. package/dist/cli.js.map +1 -1
  9. package/dist/core/loop.js +4 -2
  10. package/dist/core/loop.js.map +1 -1
  11. package/dist/evidence/dag.js +24 -0
  12. package/dist/evidence/dag.js.map +1 -1
  13. package/dist/evidence/ledger-record.js +1 -0
  14. package/dist/evidence/ledger-record.js.map +1 -1
  15. package/dist/evidence/review-page.js +198 -0
  16. package/dist/evidence/review-page.js.map +1 -1
  17. package/dist/gates/git-workspace.js +32 -41
  18. package/dist/gates/git-workspace.js.map +1 -1
  19. package/dist/gates/scratch-index.js +50 -0
  20. package/dist/gates/scratch-index.js.map +1 -0
  21. package/dist/gates/turn-baseline.js +98 -0
  22. package/dist/gates/turn-baseline.js.map +1 -0
  23. package/dist/select/model-fallback.js +89 -0
  24. package/dist/select/model-fallback.js.map +1 -0
  25. package/dist/tui/key-dispatcher.js +37 -0
  26. package/dist/tui/key-dispatcher.js.map +1 -1
  27. package/dist/tui/screen-model.js +47 -6
  28. package/dist/tui/screen-model.js.map +1 -1
  29. package/dist/tui/screen.js +14 -0
  30. package/dist/tui/screen.js.map +1 -1
  31. package/dist/tui/session-interface.js +120 -4
  32. package/dist/tui/session-interface.js.map +1 -1
  33. package/dist/tui/session-store.js +6 -0
  34. package/dist/tui/session-store.js.map +1 -1
  35. package/dist/tui/session-view.js +2 -0
  36. package/dist/tui/session-view.js.map +1 -1
  37. package/dist/tui/verify-bundle.js +30 -6
  38. package/dist/tui/verify-bundle.js.map +1 -1
  39. package/dist/tui/view-state.js +95 -0
  40. package/dist/tui/view-state.js.map +1 -1
  41. package/docs/build-guide.md +1 -1
  42. package/docs/claims.md +2 -0
  43. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # Changelog
2
2
 
3
+ ## 13.1.6
4
+
5
+ A session, and the evidence a person reads.
6
+
7
+ ### Added
8
+
9
+ - **`swarm` with no task opens a session.** One process, one ledger, tasks typed one after
10
+ another, each continuing the conversation the last one left. The screen keeps what each
11
+ finished turn came to, so it does not forget between them. `swarm "task"` is unchanged.
12
+ - **Each turn is measured on its own.** A turn ends by recording where it left the tree, so the
13
+ next turn's gates see that turn's changes and not the ones before it. Without it the second
14
+ turn is charged with the first's diff and the file-set check calls the first turn's files
15
+ out-of-set.
16
+ - **The review page says what happened.** The header carries the tasks, the model, whether the
17
+ loop completed, how long it took and what it cost, above the identifiers it used to open with.
18
+ - **The gate table is in the bundle.** It was printed to a terminal and never written into the
19
+ page, where the gates had been indistinguishable cards among the model calls.
20
+ - **The change itself is recorded and shown.** Nothing recorded a patch, so the question the
21
+ page exists to answer, what did this do to my code, meant leaving the evidence and running git.
22
+
23
+ ### Fixed
24
+
25
+ - **A run that changed nothing reported `DONE`.** The gates run after the loop and each gate
26
+ event rewrote the status, so the last gate to pass over an empty diff became the last word on
27
+ a run that built nothing. The stop reason is now its own field, and a cycle that measured no
28
+ changed files says so before the table.
29
+ - **A second turn measured its own edits as deletions.** `git diff <base>` from the person's
30
+ index calls a file that is in the base and untracked here deleted. Changes are now measured
31
+ through a scratch index, which makes the comparison tree to tree and counts a file the agent
32
+ just wrote as added.
33
+ - **`q` did not leave the view.** It set a flag that three things read after the fact; nothing
34
+ unmounted the screen, which kept painting. It now comes down and the run reports the way it
35
+ does off a terminal.
36
+ - **A refused bundle named nothing.** The failing check was read off stderr and the verifier
37
+ reports through stdout, so every real refusal said "no detail given" at the one moment the
38
+ panel exists for.
39
+ - Six record types rendered as their own bare name on the page, including the one holding what
40
+ the run cost.
41
+
42
+ ## 13.1.5
43
+
44
+ Three fixes, all found by running the tool rather than by reading it.
45
+
46
+ ### Fixed
47
+
48
+ - **A routed model the backend does not serve reached dispatch.** The router picks from what a
49
+ calibration measured, and a calibration is a record of a machine at a moment; the backend
50
+ answering today is a separate fact, and the two drift. A model pulled into Ollama, discovery
51
+ preferring rapid-mlx, and the router handed over a name that endpoint had never heard of. It
52
+ answered `Not Found` three times and the run stopped at zero steps. The served list is now
53
+ asked before dispatch, and a served local model, then a frontier provider whose key is set,
54
+ answers instead. Substitutions are announced and recorded.
55
+ - **A run that built nothing reported `DONE`.** The gates run after the loop and every gate
56
+ event rewrote the status line, so the last gate to pass became the last word on the run. A
57
+ loop that stopped at step zero displayed `DONE gate diff-budget: passed` in the success
58
+ colour, over an empty diff. The stop reason is now its own field and the outcome leads with it.
59
+ - **`git diff` outside a repository printed its whole option list.** One line of diagnosis
60
+ followed by a hundred lines about `--dirstat`, with the sentence saying what to do at the
61
+ bottom. Now one line, and it says to run `git init`.
62
+
3
63
  ## 13.1.4
4
64
 
5
65
  ### Fixed
package/README.md CHANGED
@@ -31,11 +31,11 @@ a workspace it had never seen, recorded in a real terminal:
31
31
 
32
32
  npm install -g swarm-orchestrator
33
33
 
34
- That is **13.1.4**, and it leaves `swarm` on your path.
34
+ That is **13.1.6**, and it leaves `swarm` on your path.
35
35
 
36
36
  Installing from a tag works too, but only into a project rather than globally:
37
37
 
38
- npm install github:moonrunnerkc/swarm-orchestrator#v13.1.4
38
+ npm install github:moonrunnerkc/swarm-orchestrator#v13.1.6
39
39
 
40
40
  `dist/` is not committed, so a git ref builds itself on install and needs this package's
41
41
  devDependencies to do it. npm does not install those when a git ref is installed with `-g`: it
@@ -55,6 +55,7 @@ option, so on anything older that measurement does not happen.
55
55
 
56
56
  swarm "make slugify collapse whitespace and strip punctuation"
57
57
 
58
+ swarm # a session: type tasks, one after another
58
59
  swarm gates # run the gates over a workspace, no model
59
60
  swarm select # probe this machine, recommend a local model
60
61
  swarm calibrate # measure candidate models on the golden set
@@ -83,6 +84,25 @@ what it has learned.
83
84
  Settings live in one optional `swarm.toml`: providers and endpoints, gate definitions, budgets,
84
85
  model pins, and the `[interface]`, `[theme]` and `[keys]` tables. Flags win over the file.
85
86
 
87
+ ## A session, or a single task
88
+
89
+ Run `swarm` with no task and it opens a session: one process, one ledger, and tasks typed one
90
+ after another, each continuing the conversation the last one left.
91
+
92
+ ```
93
+ › create calculator.js exporting add and multiply, and calculator.test.js covering both
94
+ 8 gate(s) passed, 8 step(s)
95
+
96
+ › add a divide function that throws on division by zero, and cover both cases
97
+ ```
98
+
99
+ Each turn is measured on its own. A turn ends by recording where it left the tree, so the next
100
+ one's gates see that turn's changes and not the ones before it. Three turns of this, with the
101
+ bundle verified from outside and the page it produced, are in
102
+ [`session.md`](docs/evidence/2026-08-24/session.md).
103
+
104
+ `swarm "task"` still runs one task and exits, exactly as before.
105
+
86
106
  ## Watching it work
87
107
 
88
108
  On a terminal, a run draws a single screen you can drive. Off one, it writes the same plain
@@ -108,8 +128,9 @@ j scroll enter expand tab pane / filter e evidence ? help q detach ctrl+c
108
128
  ```
109
129
 
110
130
  `?` lists every key. `enter` expands a row to its whole payload and the ledger record it came
111
- from. `q` leaves the view and lets the run finish; `ctrl+c` cancels the run. There is no
112
- progress bar, because an agent run has no denominator.
131
+ from. `q` leaves the view: the screen comes down and the run keeps going, reporting the plain
132
+ lines it writes off a terminal. `ctrl+c` cancels the run. There is no progress bar, because an
133
+ agent run has no denominator.
113
134
 
114
135
  When the run ends, the screen lists what it produced, says how many claims the harness
115
136
  verified and how many it refused, and offers to open the review page. It says the bundle
package/dist/agent-run.js CHANGED
@@ -2,6 +2,7 @@ import { resolve } from "node:path";
2
2
  import { runAgentLoop } from "./core/loop.js";
3
3
  import { runGatesEngine } from "./gates/engine.js";
4
4
  import { createAmendFileSetTool, createDeclareFileSetTool } from "./gates/file-set-tool.js";
5
+ import { diffAgainstBase } from "./gates/scratch-index.js";
5
6
  import { createToolChokepoint } from "./tools/chokepoint.js";
6
7
  import { createLedgerChokepointRecorder } from "./tools/chokepoint-record.js";
7
8
  import { createClaimTool } from "./tools/claim-tool.js";
@@ -85,7 +86,10 @@ export async function runAgentTask(options) {
85
86
  maxOutputTokens: 8192,
86
87
  retryPolicy: { attempts: 3, baseDelayMs: 500, maxJitterRatio: 0.5 },
87
88
  };
88
- const loop = await runAgentLoop(options.task, loopDependencies);
89
+ const loop = await runAgentLoop(options.task, {
90
+ ...loopDependencies,
91
+ ...(options.history === undefined ? {} : { history: options.history }),
92
+ });
89
93
  await options.evidence.record({
90
94
  type: "session-stopped",
91
95
  actor: "harness",
@@ -116,12 +120,46 @@ export async function runAgentTask(options) {
116
120
  ? {}
117
121
  : { singleFileTestCommand: options.singleFileTestCommand }),
118
122
  });
123
+ // What the task did to the tree, as a patch, recorded once the gates have settled so it is
124
+ // the state that was judged. Nothing else in the ledger answers "what did it change to my
125
+ // code?": the file-set record names files, the diff budget counts lines, and the tool calls
126
+ // hold fragments, so a reviewer had to leave the evidence and run git themselves.
127
+ await recordWorkspaceDiff(options);
119
128
  return {
120
129
  loop,
121
130
  gates,
122
131
  green: loop.stopReason === "completed" && gates.outcome.settled === "green",
123
132
  };
124
133
  }
134
+ /** A patch is only worth reading up to a point, past which it is a file to open, not a page to read. */
135
+ const diffCharacterCap = 200_000;
136
+ async function recordWorkspaceDiff(options) {
137
+ let patch;
138
+ try {
139
+ patch = await diffAgainstBase({
140
+ workspaceRoot: options.workspace,
141
+ baseRef: options.baseRef,
142
+ });
143
+ }
144
+ catch {
145
+ // A tree the diff cannot be taken from is a fact about the workspace, and one the gates
146
+ // have already reported on. It is not a reason to lose the run's evidence.
147
+ return;
148
+ }
149
+ const truncated = patch.length > diffCharacterCap;
150
+ await options.evidence.record({
151
+ type: "workspace-diff",
152
+ actor: "harness",
153
+ // The patch is the harness's reading of the tree, and the tree is what the model wrote.
154
+ provenance: ["model"],
155
+ payload: {
156
+ baseRef: options.baseRef,
157
+ truncated,
158
+ characters: patch.length,
159
+ patch: truncated ? `${patch.slice(0, diffCharacterCap)}\n... truncated` : patch,
160
+ },
161
+ });
162
+ }
125
163
  /**
126
164
  * One attempt at fixing what a gate reported. A fresh loop rather than a continued one: the
127
165
  * gate output is the whole brief, and starting clean keeps an attempt from inheriting the
@@ -1 +1 @@
1
- {"version":3,"file":"agent-run.js","sourceRoot":"","sources":["../src/agent-run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-run.js","sourceRoot":"","sources":["../src/agent-run.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,9 @@ import { resolve } from "node:path";
2
2
  import { bundledShortlistKeyword } from "./select/shortlist-source.js";
3
3
  export const usage = [
4
4
  "swarm [--model <provider:id>] [--workspace <dir>] [--bundle <dir>] [--base <ref>]",
5
- ' [--attempts <n>] [--max-steps <n>] [--local-endpoint <url>] "<task>"',
5
+ ' [--attempts <n>] [--max-steps <n>] [--local-endpoint <url>] ["<task>"]',
6
+ "",
7
+ " swarm a session: type tasks, one after another",
6
8
  "",
7
9
  " swarm gates [--workspace <dir>] [--base <ref>] run the gates, no model",
8
10
  " swarm select [--shortlist <file|url|bundled>] probe this machine, recommend a model",
@@ -145,13 +147,7 @@ export function parseCommandLine(argv, context) {
145
147
  bundleDirectory,
146
148
  };
147
149
  }
148
- const task = words.join(" ").trim();
149
- if (task.length === 0) {
150
- throw new InvalidCommandLineError("nothing to do");
151
- }
152
- return {
153
- command: "run",
154
- task,
150
+ const shared = {
155
151
  modelSpec: flags.get("model") ?? null,
156
152
  workspace,
157
153
  maxSteps: parseFlagCount(flags.get("max-steps"), "--max-steps"),
@@ -161,6 +157,11 @@ export function parseCommandLine(argv, context) {
161
157
  localEndpoint: parseLocalEndpoint(flags.get("local-endpoint")),
162
158
  interfaceFlags: parseInterfaceFlags(flags),
163
159
  };
160
+ const task = words.join(" ").trim();
161
+ if (task.length === 0) {
162
+ return { command: "session", ...shared };
163
+ }
164
+ return { command: "run", task, ...shared };
164
165
  }
165
166
  /** Both halves of a pair named at once is a contradiction, so it is an error rather than an order. */
166
167
  function parseInterfaceFlags(flags) {
@@ -1 +1 @@
1
- {"version":3,"file":"cli-options.js","sourceRoot":"","sources":["../src/cli-options.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-options.js","sourceRoot":"","sources":["../src/cli-options.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -22,6 +22,7 @@ import { createFileSetRegistry } from "./gates/file-set.js";
22
22
  import { citedRecords, outstandingJustifications } from "./gates/gate-runner.js";
23
23
  import { createNodeCommandRunner } from "./gates/node-command-runner.js";
24
24
  import { summarizeRatchet } from "./gates/ratchet-summary.js";
25
+ import { recordTurnBaseline } from "./gates/turn-baseline.js";
25
26
  import { localEndpointRecord, resolveLocalEndpoint, } from "./providers/endpoint-resolution.js";
26
27
  import { discoverLocalEndpoints } from "./providers/local-discovery.js";
27
28
  import { parseModelSpec } from "./providers/model-spec.js";
@@ -35,6 +36,7 @@ import { renderCalibrationReport } from "./select/calibration-report.js";
35
36
  import { appendCalibrationCase, defaultGoldenSetPath, readGoldenSet } from "./select/golden-set.js";
36
37
  import { probeHardware } from "./select/hardware-probe.js";
37
38
  import { createOllamaMemoryProbe } from "./select/memory-probe.js";
39
+ import { chooseUsableModel } from "./select/model-fallback.js";
38
40
  import { describePreflight, preflightLocalModels, preflightRecord, } from "./select/model-preflight.js";
39
41
  import { defaultPickPath, readCalibrationPick, writeCalibrationPick } from "./select/pick-store.js";
40
42
  import { loadPricing } from "./select/pricing-source.js";
@@ -154,7 +156,7 @@ async function select(options) {
154
156
  async function chooseModel(task, home, random) {
155
157
  const calibrated = await readCalibrationPick(defaultPickPath(home));
156
158
  if (calibrated?.model == null) {
157
- return { modelSpec: null, assignment: "pinned", decision: null };
159
+ return { modelSpec: null, assignment: "pinned", decision: null, candidates: [] };
158
160
  }
159
161
  const log = await openRoutingLog({ path: defaultRoutingLogPath(home) });
160
162
  const decision = routeModel({
@@ -165,7 +167,192 @@ async function chooseModel(task, home, random) {
165
167
  random,
166
168
  });
167
169
  process.stdout.write(`routing: ${decision.model} (${decision.assignment}) - ${decision.reason}\n`);
168
- return { modelSpec: decision.model, assignment: decision.assignment, decision };
170
+ return {
171
+ modelSpec: decision.model,
172
+ assignment: decision.assignment,
173
+ decision,
174
+ candidates: calibrated.candidates,
175
+ };
176
+ }
177
+ /**
178
+ * A session: one process, one ledger, many tasks, each typed rather than passed.
179
+ *
180
+ * Everything expensive is built once, which is the point of a session over repeated runs: the
181
+ * settings, the provider registry, the sandbox and its tool definitions, the evidence chain and
182
+ * the screen all outlive a turn. What is rebuilt per turn is what carries state that a second
183
+ * task must not inherit, and each of those is a decision rather than an oversight:
184
+ *
185
+ * - the abort controller, because a signal is one-shot and a reused aborted one would make
186
+ * the next turn stop before it started;
187
+ * - the file-set registry, because declaring a set twice is an error and the check walks the
188
+ * whole chain when it decides what was edited before it was authorised;
189
+ * - the base commit, because the previous turn's edits are still uncommitted, and measuring
190
+ * against the start of the session would charge this turn with the last one's diff;
191
+ * - the routed model, because routing reads the task, and a different task may deserve a
192
+ * different arm.
193
+ *
194
+ * The conversation is what carries across, so a follow-up can say "now make it throw" and mean
195
+ * the file the previous turn wrote.
196
+ */
197
+ async function session(options) {
198
+ if (!statSync(options.workspace).isDirectory()) {
199
+ throw new Error(`${options.workspace} is not a directory to work in`);
200
+ }
201
+ const settings = await settingsFor(options.workspace, {
202
+ model: options.modelSpec,
203
+ maxSteps: options.maxSteps,
204
+ attempts: options.attempts,
205
+ localEndpoint: options.localEndpoint,
206
+ interfaceFlags: options.interfaceFlags,
207
+ });
208
+ const clock = createSystemClock();
209
+ const random = createSystemRandom();
210
+ const evidence = await openEvidenceSession({
211
+ root: defaultSessionRoot(homedir()),
212
+ sessionId: createSessionId(clock, random),
213
+ clock,
214
+ });
215
+ const ui = startInterface({ task: "", workspace: options.workspace, settings, clock });
216
+ let baseRef = options.baseRef;
217
+ let history = [];
218
+ let turns = 0;
219
+ let lastGreen = true;
220
+ try {
221
+ for (;;) {
222
+ const task = await ui.readTask();
223
+ if (task === null) {
224
+ break;
225
+ }
226
+ turns += 1;
227
+ ui.beginTurn(task);
228
+ const outcome = await runOneTurn({
229
+ task,
230
+ history,
231
+ baseRef,
232
+ options,
233
+ settings,
234
+ evidence,
235
+ ui,
236
+ clock,
237
+ random,
238
+ });
239
+ history = outcome.messages;
240
+ lastGreen = outcome.green;
241
+ // Where this turn ended is where the next one starts being measured from. A repository
242
+ // with no commit yet has nothing to hang one off, and the base stays where it was.
243
+ const recorded = await recordTurnBaseline({
244
+ workspaceRoot: options.workspace,
245
+ label: `turn ${turns}`,
246
+ previousBase: baseRef,
247
+ });
248
+ if (recorded !== null) {
249
+ baseRef = recorded;
250
+ }
251
+ }
252
+ }
253
+ finally {
254
+ if (turns > 0) {
255
+ const written = await writeBundle(evidence, options.bundleDirectory, clock, ui.note);
256
+ announceBundle(written.directory, ui.note);
257
+ }
258
+ await ui.stop();
259
+ taskReader?.close();
260
+ taskReader = null;
261
+ taskLines = null;
262
+ }
263
+ if (turns === 0) {
264
+ process.stdout.write("nothing was asked for, so nothing ran.\n");
265
+ return 0;
266
+ }
267
+ return lastGreen ? 0 : 1;
268
+ }
269
+ /** One turn of a session, from a typed task to a settled set of gates. */
270
+ async function runOneTurn(input) {
271
+ const { task, options, settings, evidence, ui, clock, random } = input;
272
+ const routed = settings.modelPinned
273
+ ? {
274
+ modelSpec: null,
275
+ assignment: "pinned",
276
+ decision: null,
277
+ candidates: [],
278
+ }
279
+ : await chooseModel(task, homedir(), random);
280
+ const modelSpec = routed.modelSpec ?? settings.modelSpec;
281
+ const spec = parseModelSpec(modelSpec);
282
+ const localBackend = await resolveLocalBackend(settings, [spec]);
283
+ if (localBackend !== null) {
284
+ await evidence.record(localEndpointRecord(localBackend));
285
+ }
286
+ if (routed.decision !== null) {
287
+ await evidence.record(routingDecisionRecord(routed.decision));
288
+ }
289
+ const usable = spec.provider === "local" && localBackend !== null
290
+ ? chooseUsableModel({
291
+ requested: modelSpec,
292
+ preflight: await preflightAll(evidence, localBackend.url, [modelSpec]),
293
+ keys: settings.providerKeys,
294
+ candidates: routed.candidates,
295
+ })
296
+ : { outcome: "as-requested", modelSpec, reason: "not a local model" };
297
+ if (usable.outcome === "substituted") {
298
+ ui.note(`model: ${usable.modelSpec} instead of ${usable.requested}, ${usable.reason}`);
299
+ }
300
+ const registry = createProviderRegistry(registrySettingsFrom(settings, localBackend));
301
+ const model = createRecordingModelClient(registry.create(parseModelSpec(usable.modelSpec)), evidence);
302
+ const fileSet = createFileSetRegistry(evidence);
303
+ const interruption = new AbortController();
304
+ const onInterrupt = () => {
305
+ interruption.abort();
306
+ };
307
+ process.on("SIGINT", onInterrupt);
308
+ void ui.cancelled().then(onInterrupt);
309
+ const startedAt = clock.now();
310
+ const gateOptions = gateOptionsFrom(settings);
311
+ const diffBudget = diffBudgetFrom(settings);
312
+ try {
313
+ const { loop, gates } = await runAgentTask({
314
+ task,
315
+ workspace: options.workspace,
316
+ baseRef: input.baseRef,
317
+ maxSteps: settings.maxSteps,
318
+ attempts: settings.attempts,
319
+ model,
320
+ evidence,
321
+ fileSet,
322
+ clock,
323
+ random,
324
+ emit: (event) => {
325
+ ui.emit(event);
326
+ },
327
+ confirm: ui.confirm,
328
+ abortSignal: interruption.signal,
329
+ homeDir: homedir(),
330
+ history: input.history,
331
+ ...(gateOptions === undefined ? {} : { gateOptions }),
332
+ ...(diffBudget === undefined ? {} : { diffBudget }),
333
+ });
334
+ reportGates(gates.outcome, evidence, ui.note);
335
+ await logReward({
336
+ evidence,
337
+ home: homedir(),
338
+ task,
339
+ modelSpec: usable.modelSpec,
340
+ assignment: routed.assignment,
341
+ ratchet: summarizeRatchet(gates.outcome),
342
+ changedFiles: gates.outcome.finalCycle.measures.changedFiles ?? null,
343
+ latencyMs: clock.now() - startedAt,
344
+ recordedAt: clock.now(),
345
+ cost: await priceTask(usable.modelSpec, evidence),
346
+ note: ui.note,
347
+ });
348
+ return {
349
+ messages: loop.messages,
350
+ green: loop.stopReason === "completed" && gates.outcome.settled === "green",
351
+ };
352
+ }
353
+ finally {
354
+ process.off("SIGINT", onInterrupt);
355
+ }
169
356
  }
170
357
  /**
171
358
  * Everything ambient the screen needs, gathered here so nothing below the composition root
@@ -195,11 +382,35 @@ function startInterface(input) {
195
382
  }),
196
383
  bindings: resolveKeyBindings(ui.keys),
197
384
  ...(isTty ? { askOnTerminal } : {}),
385
+ readLine: readTaskLine,
198
386
  openEvidence: ui.openEvidence,
199
387
  spawnOpen: spawnOpener,
200
388
  platform: platform(),
201
389
  });
202
390
  }
391
+ /**
392
+ * One readline for the whole session, opened when the first task is asked for.
393
+ *
394
+ * Kept open rather than opened per question, because a fresh interface per line loses whatever
395
+ * is already buffered from a pipe, and a piped session is a list of tasks somebody wrote down.
396
+ * Null at end of input is what ends the session.
397
+ */
398
+ let taskReader = null;
399
+ let taskLines = null;
400
+ async function readTaskLine(prompt) {
401
+ if (taskReader === null) {
402
+ taskReader = createInterface({ input: process.stdin, output: process.stderr });
403
+ taskLines = taskReader[Symbol.asyncIterator]();
404
+ }
405
+ if (process.stdin.isTTY === true) {
406
+ process.stderr.write(prompt);
407
+ }
408
+ const next = await taskLines?.next();
409
+ if (next === undefined || next.done === true) {
410
+ return null;
411
+ }
412
+ return next.value;
413
+ }
203
414
  /** Readline, on the plain path only. Ink owns stdin whenever the screen is up. */
204
415
  async function askOnTerminal(question) {
205
416
  const prompt = createInterface({ input: process.stdin, output: process.stderr });
@@ -275,7 +486,12 @@ async function run(options) {
275
486
  });
276
487
  const random = createSystemRandom();
277
488
  const routed = settings.modelPinned
278
- ? { modelSpec: null, assignment: "pinned", decision: null }
489
+ ? {
490
+ modelSpec: null,
491
+ assignment: "pinned",
492
+ decision: null,
493
+ candidates: [],
494
+ }
279
495
  : await chooseModel(options.task, homedir(), random);
280
496
  const modelSpec = routed.modelSpec ?? settings.modelSpec;
281
497
  const spec = parseModelSpec(modelSpec);
@@ -297,8 +513,23 @@ async function run(options) {
297
513
  // before the session exists. What it names is still the decision that ran this task.
298
514
  await evidence.record(routingDecisionRecord(routed.decision));
299
515
  }
516
+ // What the backend is serving decides, rather than what a calibration measured on some
517
+ // earlier day. Without this a routed model the endpoint has never heard of reaches dispatch
518
+ // and answers Not Found, which names neither the endpoint nor the model that was missing.
519
+ const usable = spec.provider === "local" && localBackend !== null
520
+ ? chooseUsableModel({
521
+ requested: modelSpec,
522
+ preflight: await preflightAll(evidence, localBackend.url, [modelSpec]),
523
+ keys: settings.providerKeys,
524
+ candidates: routed.candidates,
525
+ })
526
+ : { outcome: "as-requested", modelSpec, reason: "not a local model" };
527
+ if (usable.outcome === "substituted") {
528
+ process.stdout.write(`model: ${usable.modelSpec} instead of ${usable.requested}, ${usable.reason}\n`);
529
+ }
530
+ const runSpec = parseModelSpec(usable.modelSpec);
300
531
  const registry = createProviderRegistry(registrySettingsFrom(settings, localBackend));
301
- const model = createRecordingModelClient(registry.create(spec), evidence);
532
+ const model = createRecordingModelClient(registry.create(runSpec), evidence);
302
533
  const fileSet = createFileSetRegistry(evidence);
303
534
  const ui = startInterface({
304
535
  task: options.task,
@@ -345,7 +576,7 @@ async function run(options) {
345
576
  evidence,
346
577
  home: homedir(),
347
578
  task: options.task,
348
- modelSpec,
579
+ modelSpec: usable.modelSpec,
349
580
  assignment: routed.assignment,
350
581
  ratchet: summarizeRatchet(gates.outcome),
351
582
  // The diff-budget gate's own measure, merged into the cycle. Read from there rather
@@ -353,7 +584,7 @@ async function run(options) {
353
584
  changedFiles: gates.outcome.finalCycle.measures.changedFiles ?? null,
354
585
  latencyMs: clock.now() - startedAt,
355
586
  recordedAt: clock.now(),
356
- cost: await priceTask(modelSpec, evidence),
587
+ cost: await priceTask(usable.modelSpec, evidence),
357
588
  note: ui.note,
358
589
  });
359
590
  const written = await writeBundle(evidence, options.bundleDirectory, clock, ui.note);
@@ -377,6 +608,16 @@ function describeCycle(cycle) {
377
608
  }
378
609
  /** Written through `note`, so an interactive screen holds them until it comes down. */
379
610
  function reportGates(outcome, evidence, note) {
611
+ // Said before the gate table rather than after it, because a table of passes over a tree
612
+ // nothing touched is the most misleading thing this tool can print. A model that answered in
613
+ // prose, or emitted its tool calls as text the protocol never parsed, reaches here having
614
+ // done nothing, stops for the honest reason "completed", and every gate then passes over an
615
+ // empty diff. A task can legitimately change nothing, so this states the fact rather than
616
+ // calling it a failure.
617
+ if (outcome.finalCycle.measures.changedFiles === 0) {
618
+ note("\nno files were changed. The gates below measured an unchanged workspace, so they say " +
619
+ "nothing about work being done.");
620
+ }
380
621
  note(`\ngates:\n${describeCycle(outcome.finalCycle)}`);
381
622
  for (const attempt of outcome.attempts) {
382
623
  note(`attempt ${attempt.attempt}: ${attempt.decision.accepted ? "accepted" : "REJECTED"} - ` +
@@ -679,6 +920,17 @@ const servedModelsTimeoutMs = 2_000;
679
920
  * serving nothing, and treating it as one would drop every model on no evidence at all.
680
921
  */
681
922
  async function preflight(evidence, backendUrl, models) {
923
+ const checked = await preflightAll(evidence, backendUrl, models);
924
+ // Calibration's own account of the probe: which models it will not create runs for, and
925
+ // how many of the ones asked for survive. A single run says something else, because it
926
+ // goes on to substitute one and needs to name the substitution rather than the shortfall.
927
+ for (const line of describePreflight(checked)) {
928
+ process.stdout.write(`${line}\n`);
929
+ }
930
+ return checked.runnable;
931
+ }
932
+ /** The whole answer rather than the runnable subset, for the caller that has to choose. */
933
+ async function preflightAll(evidence, backendUrl, models) {
682
934
  const checked = preflightLocalModels({
683
935
  requested: models,
684
936
  backendUrl,
@@ -689,10 +941,7 @@ async function preflight(evidence, backendUrl, models) {
689
941
  }),
690
942
  });
691
943
  await evidence.record(preflightRecord(checked));
692
- for (const line of describePreflight(checked)) {
693
- process.stdout.write(`${line}\n`);
694
- }
695
- return checked.runnable;
944
+ return checked;
696
945
  }
697
946
  /** Turns a task that went wrong into a case the golden set will measure against forever. */
698
947
  async function addCase(options) {
@@ -848,6 +1097,9 @@ async function main() {
848
1097
  if (options.command === "parallel") {
849
1098
  return parallel(options);
850
1099
  }
1100
+ if (options.command === "session") {
1101
+ return session(options);
1102
+ }
851
1103
  return options.command === "gates" ? gates(options) : run(options);
852
1104
  }
853
1105
  main().then((code) => {