@lloyal-labs/dev-tools 0.4.2 → 0.5.0-alpha.2

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/dist/index.d.ts CHANGED
@@ -40,6 +40,11 @@ export interface DevControl {
40
40
  command: string;
41
41
  /** The command field carrying the selected value. */
42
42
  field: string;
43
+ /** How to draw the choice. `segmented` (default) is the button row;
44
+ * `slider` is the same ordered `values`, stepped — right when they form a
45
+ * scale rather than a set, so the ordering is the information. Both
46
+ * dispatch the identical command, so this changes the picture only. */
47
+ render?: 'segmented' | 'slider';
43
48
  /** One clause shown beside the control, e.g. `applies next run`. */
44
49
  note?: string;
45
50
  /** Read the current value out of the live config object. */
@@ -56,10 +61,20 @@ export interface ClarifyExchange {
56
61
  export interface AgentLane {
57
62
  agentId: number;
58
63
  parentAgentId: number | null;
59
- /** The run phase current at spawn — research's own markers (`plan:start`,
60
- * `research:start`, `synthesize:start`) when the template emits them;
61
- * null when the wire says nothing (basic). Never guessed. */
62
- role: 'planner' | 'research' | 'synth' | null;
64
+ /** The phase label current at spawn — from the harness's own
65
+ * {@link RunFraming} declaration; null when its wire marks nothing.
66
+ * Never guessed. */
67
+ role: string | null;
68
+ /** Agent ids whose completion gated this spawn — the DAG's dependency
69
+ * edges, from the orchestrator via `agent:spawn.after`. Never inferred. */
70
+ after?: number[];
71
+ /** Tokens already resident on this lane's prefix at its fork — snapshotted
72
+ * the moment the spawn folds, never reconstructed. Top-level: the trunk
73
+ * inheritance + spine growth so far. Recursive: the parent lane's own
74
+ * inheritance + what it had produced by then (its suffix is not counted —
75
+ * an honest undercount). Absent when the pane cannot attribute the fork
76
+ * (a pre-spine spawn such as a planner). */
77
+ inherited?: number;
63
78
  spawnedAt: number;
64
79
  doneAt: number | null;
65
80
  /** Terminal outcome, when known. `failed` carries the reason. */
@@ -218,10 +233,75 @@ export interface AbilityInfo {
218
233
  }
219
234
  /** The folded pane state. Everything optional is honestly absent until its
220
235
  * event arrives — the pane renders absence, never a placeholder value. */
236
+ /** The run's framing, declared by the HARNESS as data — the pane knows no
237
+ * pipeline's event names. `phases` maps a marker event to the label every
238
+ * agent spawned under it wears; `open` events reset the run (the timeline
239
+ * anchor); `close` events end it. A scaffold passes its own grammar beside
240
+ * the other DevPane wiring and EDITS it when a stage is added or renamed;
241
+ * the default covers the stock templates. */
242
+ export interface RunFraming {
243
+ phases: Record<string, string>;
244
+ /** The submission's start markers IN PIPELINE ORDER. Within one run they
245
+ * only advance (preflight → plan:start → query); a marker at or before
246
+ * the last one seen is a NEW submission superseding an unclosed run —
247
+ * the halt-and-resubmit path emits no close event. */
248
+ open: readonly string[];
249
+ close: readonly string[];
250
+ /** Where the user's instruction lives on THIS harness's wire — the event
251
+ * type and the field carrying its text (and optionally the field carrying
252
+ * its media descriptors). Declared, never guessed: undeclared harnesses
253
+ * get a spine row folded from runtime events alone, with no instruction
254
+ * shown. */
255
+ instruction?: {
256
+ event: string;
257
+ field: string;
258
+ attachments?: string;
259
+ };
260
+ }
261
+ export declare const DEFAULT_FRAMING: RunFraming;
262
+ /** One session-trunk turn (`branch:prefill role='warmDelta'` mirror) — the
263
+ * verbatim conversation delta the spine accreted, with what it cost. */
264
+ export interface TrunkTurn {
265
+ at: number;
266
+ /** Which conversation side — from the Session's own prefill call, never
267
+ * inferred from the text. `turn` is a committed whole exchange. */
268
+ speaker?: 'user' | 'assistant' | 'tool' | 'turn';
269
+ /** Verbatim prefilled text (the trunk conversation turn). */
270
+ content: string;
271
+ /** A committed exchange's halves (`speaker: 'turn'`) — never re-split
272
+ * from `content`. */
273
+ query?: string;
274
+ response?: string;
275
+ /** KV cells the prefill added. */
276
+ cells: number;
277
+ /** The trunk branch this turn accreted onto — the key the release fold
278
+ * deletes by when that branch leaves the KV. */
279
+ branchHandle?: number;
280
+ /** The images that entered with it — roots, resolvable to bytes through
281
+ * the bridge's `representationUrl` when the harness exposes one. */
282
+ attachments: {
283
+ digest: string;
284
+ mediaType?: string;
285
+ }[];
286
+ /** Wall time of the run this delta settled out of — folded from the run
287
+ * anchor at arrival. Absent when no run was open. */
288
+ wallMs?: number;
289
+ /** What the run's agents spent (sum of its lanes' cumulative counters) to
290
+ * produce this delta — the numerator of the distillation ratio whose
291
+ * denominator is `cells`. Absent with `wallMs`. */
292
+ agentTokens?: number;
293
+ }
221
294
  export interface PaneModel {
222
- /** The current run's phase cursor — set by the template's own phase events;
295
+ /** The current run's phase cursor — set by the framing's marker events;
223
296
  * tags each spawn with a role. */
224
- runPhase: 'planner' | 'research' | 'synth' | null;
297
+ runPhase: string | null;
298
+ /** A run is OPEN from its first open-marker until a close-marker ends it —
299
+ * the reset guard, replacing the old 1.5s timing window (recon can hold
300
+ * the start markers apart for minutes). */
301
+ runOpen: boolean;
302
+ /** Position (in `framing.open`) of the last open-marker seen — the
303
+ * supersede detector: a marker at or before it starts a NEW run. */
304
+ lastOpenIdx: number;
225
305
  /** When the current run began (`query` / `plan:start`) — the timeline's
226
306
  * anchor. Null before the first run. */
227
307
  runStartAt: number | null;
@@ -262,6 +342,53 @@ export interface PaneModel {
262
342
  * "applied for this session"). Undefined until a save happens. */
263
343
  lastSavedTo: string | null | undefined;
264
344
  lanes: Map<number, AgentLane>;
345
+ /** The RESIDENT conversation — the turns of the trunk the model can
346
+ * currently attend. Not cleared by `resetRun` (the next run rides the
347
+ * live trunk), but a released trunk's turns are REMOVED when its
348
+ * `branch:prune` folds: dead cells feed nothing, so the feed never
349
+ * shows them. History across trunks is the harness's concern. */
350
+ trunk: TrunkTurn[];
351
+ /** The run's SPINE, run-scoped: the shared root every agent forks from.
352
+ * Folded from runtime events alone (`branch:prefill role='spineHeader'`,
353
+ * `prompt:format role='spine'`) — universal to any pool harness — plus,
354
+ * when the harness DECLARES it ({@link RunFraming.instruction}), the
355
+ * user's instruction verbatim. This is the prompt's home in the pane
356
+ * even when a run later fails. Cleared by `resetRun`. */
357
+ spine: {
358
+ /** The user's instruction, as submitted — null until (unless) the
359
+ * harness's declared instruction event arrives. Never guessed. */
360
+ query: string | null;
361
+ attachments: {
362
+ digest: string;
363
+ }[];
364
+ /** First-seen moment (instruction arrival or first header prefill). */
365
+ at: number;
366
+ /** KV cells the spine header prefills added (outer + inner pools). */
367
+ spineCells: number;
368
+ /** The compiled spine header (system + tools), verbatim. */
369
+ headerText: string | null;
370
+ headerTokens: number;
371
+ spineAt: number | null;
372
+ /** Every moment the spine grew, with what it grew by — the seed first,
373
+ * then each extension (a chain step, a fanout widening). The bar's
374
+ * tick marks. */
375
+ growth: {
376
+ at: number;
377
+ tokens: number;
378
+ }[];
379
+ /** Positions inherited at fork — 0 on a cold start, the trunk's length
380
+ * on a warm one. From `branch:create role='spine'` position; first
381
+ * spine only (the inner pool's spine forks from the outer). */
382
+ inherited?: number;
383
+ /** Parsed from the STRUCTURED `tools` field the runtime emits on
384
+ * `prompt:format role='spine'` — reading data, not scraping markup. */
385
+ tools?: {
386
+ name: string;
387
+ description: string;
388
+ }[];
389
+ /** The system message text, from the structured `messages` field. */
390
+ systemText?: string | null;
391
+ } | null;
265
392
  retrievals: Retrieval[];
266
393
  pressure: PressurePoint[];
267
394
  /** Host samples (`host:resources`, dev-gated boots only): the harness
@@ -295,7 +422,7 @@ export interface PaneModel {
295
422
  eventCount: number;
296
423
  }
297
424
  export declare function createPaneModel(): PaneModel;
298
- export declare function foldEvent(m: PaneModel, ev: DevEvent, now: number): void;
425
+ export declare function foldEvent(m: PaneModel, ev: DevEvent, now: number, framing?: RunFraming): void;
299
426
  /** Live when any lane is still open — the run is producing and the pane's
300
427
  * clocks (elapsed, park countdowns) must keep advancing even between
301
428
  * events. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;4DAC4D;AAC5D,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElE;iFACiF;AACjF,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB;kCAC8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ;kFAC8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/D;AAED;8EAC8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;kEAE8D;IAC9D,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iEAAiE;IACjE,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;iEAC6D;IAC7D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC;IAC9C,uEAAuE;IACvE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;qCACiC;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC;;gEAE4D;IAC5D,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD;;;;;;qCAMiC;IACjC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;oEACgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6DAA6D;AAC7D;;mEAEmE;AACnE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB;qCACiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;kCAC8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd;;8CAE0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;wDAEwD;AACxD,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAEtD;AAED;;qDAEqD;AACrD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;yCACqC;IACrC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC;sDACkD;IAClD,aAAa,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IAChG;;iEAE6D;IAC7D,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChE;AAED;uCACuC;AACvC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;eAGe;AACf,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QAC3F,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;2EAC2E;AAC3E,MAAM,WAAW,SAAS;IACxB;uCACmC;IACnC,QAAQ,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC;IAClD;6CACyC;IACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;mEAE+D;IAC/D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;sEACkE;IAClE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;qDAEiD;IACjD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;mEAE+D;IAC/D,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;uDACmD;IACnD,GAAG,EAAE,OAAO,CAAC;IACb;uDACmD;IACnD,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QACzC,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,GAAG,IAAI,CAAC;IACT;mDAC+C;IAC/C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACjD;uEACmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC9B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B;;;8DAG0D;IAC1D,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjG,oEAAoE;IACpE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B;;oCAEgC;IAChC,SAAS,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAChC;gEAC4D;IAC5D,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD;2EACuE;IACvE,UAAU,EAAE,OAAO,CAAC;IACpB,yDAAyD;IACzD,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,IAAI,SAAS,CAwB3C;AA8DD,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAmXvE;AAED;;cAEc;AACd,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAI5C;AAED;kBACkB;AAClB,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;wEAEwE;AACxE,wBAAgB,aAAa,CAC3B,CAAC,EAAE,SAAS,EACZ,OAAO,EAAE,MAAM,GACd;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAkB/B;AAKD;2DAC2D;AAC3D,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED;gCACgC;AAChC,eAAO,MAAM,gBAAgB,EAAE,SAAS;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAOjF,CAAC;AAEF;kEACkE;AAClE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AACvD,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAU1D,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAQT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,9 +4,26 @@
4
4
  export function lanePpl(lane) {
5
5
  return lane.nllCount === 0 ? null : Math.exp(lane.nllSum / lane.nllCount);
6
6
  }
7
+ export const DEFAULT_FRAMING = {
8
+ phases: {
9
+ 'preflight:start': 'recon',
10
+ 'plan:start': 'planner',
11
+ 'research:start': 'research',
12
+ 'synthesize:start': 'synth',
13
+ },
14
+ // Declared in WIRE order: preflight (when it runs) precedes the query
15
+ // event, which the pipeline sends before the planner phase marker. An
16
+ // out-of-order declaration makes the supersede heuristic fire a second
17
+ // resetRun on every run (query idx > plan idx), wiping run-scoped state.
18
+ open: ['preflight:start', 'query', 'plan:start'],
19
+ close: ['complete', 'ui:error', 'ui:composer'],
20
+ instruction: { event: 'query', field: 'query', attachments: 'attachments' },
21
+ };
7
22
  export function createPaneModel() {
8
23
  return {
9
24
  runPhase: null,
25
+ runOpen: false,
26
+ lastOpenIdx: -1,
10
27
  runStartAt: null,
11
28
  runEndedAt: null,
12
29
  pausedAt: null,
@@ -18,6 +35,8 @@ export function createPaneModel() {
18
35
  origin: null,
19
36
  lastSavedTo: undefined,
20
37
  lanes: new Map(),
38
+ trunk: [],
39
+ spine: null,
21
40
  retrievals: [],
22
41
  pressure: [],
23
42
  host: [],
@@ -35,6 +54,7 @@ export function createPaneModel() {
35
54
  const MAX_PRESSURE_POINTS = 20_000;
36
55
  const MAX_RETRIEVALS = 500;
37
56
  const MAX_INTERVENTIONS = 200;
57
+ const MAX_TRUNK = 200;
38
58
  const MAX_EPISTEMICS = 4096;
39
59
  const MAX_HOST = 600;
40
60
  /**
@@ -45,35 +65,45 @@ const MAX_HOST = 600;
45
65
  /** A new run begins: the timeline shows THE RUN, not wall-clock since page
46
66
  * load — clear the run-scoped collections and anchor the axis. Idempotent
47
67
  * (research emits `plan:start` then `query` back-to-back). */
48
- function resetRun(m, now) {
49
- // A clarify answer re-enters planning WITHIN the same run: the planner
50
- // asked, the user answered, the cycle continues — mark the exchange
51
- // answered and keep everything.
52
- if (m.clarifying) {
53
- m.clarifying = false;
54
- m.runContinuedAt = now;
55
- for (const lane of m.lanes.values()) {
56
- if (lane.clarify && lane.clarify.answeredAt === null)
57
- lane.clarify.answeredAt = now;
58
- }
59
- return;
68
+ /** A clarify answer re-enters planning WITHIN the same run: the planner
69
+ * asked, the user answered, the cycle continues — mark the exchange
70
+ * answered and keep everything. */
71
+ function continueRun(m, now) {
72
+ m.clarifying = false;
73
+ m.runContinuedAt = now;
74
+ for (const lane of m.lanes.values()) {
75
+ if (lane.clarify && lane.clarify.answeredAt === null)
76
+ lane.clarify.answeredAt = now;
60
77
  }
61
- // Idempotent across the back-to-back run-start pair (research emits
62
- // `plan:start` then `query` within milliseconds) — one reset per run.
63
- if (m.runStartAt !== null && (now - m.runStartAt < 1500 ||
64
- (m.runContinuedAt !== null && now - m.runContinuedAt < 1500)))
78
+ }
79
+ function resetRun(m, now) {
80
+ // Idempotent across a run's OWN start markers — recon opens the run
81
+ // minutes before `plan:start`/`query` arrive, so this is a flag, not a
82
+ // timing window. A close-marker (or supersede) re-arms it.
83
+ if (m.runOpen)
65
84
  return;
85
+ m.runOpen = true;
66
86
  m.lanes = new Map();
67
87
  m.retrievals = [];
68
88
  m.pressure = [];
69
89
  m.host = [];
70
90
  m.interventions = [];
71
91
  m.plan = null;
92
+ m.spine = null;
72
93
  m.runStartAt = now;
73
94
  m.runEndedAt = null;
74
95
  m.pausedAt = null;
75
96
  m.windingDownAt = null;
76
97
  }
98
+ /** The spine record, created by whichever signal arrives first — the
99
+ * harness's declared instruction event or the runtime's own header
100
+ * prefill. Runtime-only harnesses still get a spine row. */
101
+ function ensureSpine(m, now) {
102
+ if (!m.spine) {
103
+ m.spine = { query: null, attachments: [], at: now, spineCells: 0, headerText: null, headerTokens: 0, spineAt: null, growth: [] };
104
+ }
105
+ return m.spine;
106
+ }
77
107
  /** The retrieval a mirrored trace event belongs to: by callId WITHIN the
78
108
  * agent (callIds are per-agent counters — call_0 exists in every agent, so
79
109
  * a global match attaches one agent's funnel to another's call), else the
@@ -88,29 +118,54 @@ function findRetrieval(m, callId, agentId) {
88
118
  }
89
119
  return undefined;
90
120
  }
91
- export function foldEvent(m, ev, now) {
121
+ export function foldEvent(m, ev, now, framing = DEFAULT_FRAMING) {
92
122
  m.eventCount++;
93
123
  if (m.t0 === null)
94
124
  m.t0 = now;
95
- switch (ev.type) {
96
- // ── run phases: the template's OWN markers tag spawns with roles ──
97
- case 'plan:start': {
98
- resetRun(m, now);
99
- m.runPhase = 'planner';
100
- return;
125
+ // ── run framing: the harness's OWN declared markers, as data ──
126
+ if (framing.close.includes(ev.type)) {
127
+ m.runOpen = false;
128
+ m.lastOpenIdx = -1;
129
+ }
130
+ const openIdx = framing.open.indexOf(ev.type);
131
+ if (openIdx !== -1) {
132
+ if (m.clarifying) {
133
+ // An answered clarify CONTINUES this run — never a reset.
134
+ continueRun(m, now);
101
135
  }
102
- case 'query': {
136
+ else {
137
+ // Same submission's markers only ADVANCE through `open`; at-or-before
138
+ // means a new submission superseded an unclosed run (halt-and-resubmit
139
+ // emits no close marker).
140
+ if (m.runOpen && openIdx <= m.lastOpenIdx)
141
+ m.runOpen = false;
103
142
  resetRun(m, now);
104
- return;
105
143
  }
106
- case 'research:start': {
107
- m.runPhase = 'research';
108
- return;
109
- }
110
- case 'synthesize:start': {
111
- m.runPhase = 'synth';
112
- return;
144
+ m.lastOpenIdx = openIdx;
145
+ }
146
+ const phaseLabel = framing.phases[ev.type];
147
+ if (phaseLabel !== undefined)
148
+ m.runPhase = phaseLabel;
149
+ // The user's instruction — read only where the harness DECLARED it lives
150
+ // (framing.instruction), never guessed from event shapes. First one per
151
+ // run wins: a re-plan re-emits the same event and must not reseed.
152
+ const instr = framing.instruction;
153
+ if (instr && ev.type === instr.event && (m.spine === null || m.spine.query === null)) {
154
+ const s = ensureSpine(m, now);
155
+ const q = ev[instr.field];
156
+ if (typeof q === 'string')
157
+ s.query = q;
158
+ if (instr.attachments) {
159
+ const a = ev[instr.attachments];
160
+ if (Array.isArray(a)) {
161
+ s.attachments = a.flatMap((x) => {
162
+ const r = x;
163
+ return typeof r.digest === 'string' ? [{ digest: r.digest }] : [];
164
+ });
165
+ }
113
166
  }
167
+ }
168
+ switch (ev.type) {
114
169
  case 'plan': {
115
170
  const intent = typeof ev.intent === 'string' ? ev.intent : 'research';
116
171
  if (intent === 'clarify') {
@@ -183,6 +238,21 @@ export function foldEvent(m, ev, now) {
183
238
  return;
184
239
  }
185
240
  case 'agent:spawn': {
241
+ const afterIds = Array.isArray(ev.after)
242
+ ? ev.after.filter((x) => typeof x === 'number')
243
+ : [];
244
+ // Inherited-at-fork, snapshotted NOW: a recursive fork carries its
245
+ // parent's attention state; a top-level fork carries trunk + the spine
246
+ // as grown so far. Pre-spine forks get nothing — no guessed parentage.
247
+ const parentLane = typeof ev.parentAgentId === 'number' ? m.lanes.get(ev.parentAgentId) : undefined;
248
+ let inheritedAtFork;
249
+ if (parentLane) {
250
+ inheritedAtFork = (parentLane.inherited ?? 0) + parentLane.tokenCount;
251
+ }
252
+ else if (m.spine && m.spine.spineAt !== null && now + 250 >= m.spine.spineAt) {
253
+ inheritedAtFork = (m.spine.inherited ?? 0)
254
+ + m.spine.growth.reduce((n2, g) => (g.at <= now + 250 ? n2 + g.tokens : n2), 0);
255
+ }
186
256
  if (typeof ev.agentId !== 'number')
187
257
  return; // type-only frame — never corrupt the lane map
188
258
  const id = ev.agentId;
@@ -194,6 +264,8 @@ export function foldEvent(m, ev, now) {
194
264
  doneAt: null,
195
265
  outcome: 'running',
196
266
  tokenCount: 0,
267
+ ...(afterIds.length > 0 ? { after: afterIds } : {}),
268
+ ...(inheritedAtFork !== undefined ? { inherited: inheritedAtFork } : {}),
197
269
  inflightTool: null,
198
270
  report: null,
199
271
  reportSource: null,
@@ -333,6 +405,78 @@ export function foldEvent(m, ev, now) {
333
405
  if (!te)
334
406
  return;
335
407
  switch (te.type) {
408
+ case 'branch:create': {
409
+ // Cold vs warm, from the run's own record: the FIRST spine's fork
410
+ // position. The inner pool's spine forks from the outer — skip it.
411
+ if (te.role !== 'spine')
412
+ return;
413
+ {
414
+ const s = ensureSpine(m, now);
415
+ if (s.inherited === undefined && typeof te.position === 'number')
416
+ s.inherited = te.position;
417
+ }
418
+ return;
419
+ }
420
+ case 'spine:extend': {
421
+ // A settled contribution committed onto the spine mid-run (chain
422
+ // steps). Later forks inherit it — the growth entry is what makes
423
+ // their inherited-at-fork snapshot and the paid-once sum honest.
424
+ const s = ensureSpine(m, now);
425
+ const grew = typeof te.deltaTokens === 'number' ? te.deltaTokens : 0;
426
+ s.spineCells += grew;
427
+ if (grew > 0)
428
+ s.growth.push({ at: now, tokens: grew });
429
+ return;
430
+ }
431
+ case 'branch:prefill': {
432
+ // The spine's seed — runtime truth, no harness assumption.
433
+ if (te.role === 'spineHeader') {
434
+ const s = ensureSpine(m, now);
435
+ const grew = typeof te.cells === 'number' ? te.cells : 0;
436
+ s.spineCells += grew;
437
+ if (grew > 0)
438
+ s.growth.push({ at: now, tokens: grew });
439
+ if (s.spineAt === null)
440
+ s.spineAt = now;
441
+ return;
442
+ }
443
+ // The session trunk's own turns (role warmDelta) — visible beside
444
+ // the runs they feed. Session-lived: resetRun leaves m.trunk alone.
445
+ if (te.role !== 'warmDelta')
446
+ return;
447
+ const speaker = te.speaker;
448
+ // Run-derived stats ride the response side: how long the run took
449
+ // and what its agents spent to produce what the trunk kept.
450
+ const responseSide = speaker === 'assistant' || speaker === 'turn' || speaker === undefined;
451
+ const stats = responseSide && m.runStartAt !== null
452
+ ? {
453
+ wallMs: Math.max(0, now - m.runStartAt),
454
+ agentTokens: [...m.lanes.values()].reduce((n, l) => n + l.tokenCount, 0),
455
+ }
456
+ : {};
457
+ m.trunk.push({
458
+ at: now,
459
+ ...stats,
460
+ ...(speaker === 'user' || speaker === 'assistant' || speaker === 'tool' || speaker === 'turn'
461
+ ? { speaker } : {}),
462
+ ...(typeof te.query === 'string' ? { query: te.query } : {}),
463
+ ...(typeof te.response === 'string' ? { response: te.response } : {}),
464
+ content: typeof te.content === 'string' ? te.content : '',
465
+ cells: typeof te.cells === 'number' ? te.cells : 0,
466
+ ...(typeof te.branchHandle === 'number' ? { branchHandle: te.branchHandle } : {}),
467
+ attachments: Array.isArray(te.attachments)
468
+ ? te.attachments.flatMap((a) => {
469
+ const r = a;
470
+ return typeof r.digest === 'string'
471
+ ? [{ digest: r.digest, ...(typeof r.mediaType === 'string' ? { mediaType: r.mediaType } : {}) }]
472
+ : [];
473
+ })
474
+ : [],
475
+ });
476
+ if (m.trunk.length > MAX_TRUNK)
477
+ m.trunk.shift();
478
+ return;
479
+ }
336
480
  case 'pool:agentNudge': {
337
481
  m.interventions.push({
338
482
  kind: typeof te.guard === 'string' ? 'guard' : 'nudge',
@@ -363,6 +507,40 @@ export function foldEvent(m, ev, now) {
363
507
  return;
364
508
  }
365
509
  case 'prompt:format': {
510
+ // The compiled spine header — what position 0 actually holds.
511
+ if (te.role === 'spine') {
512
+ const s = ensureSpine(m, now);
513
+ if (typeof te.promptText === 'string')
514
+ s.headerText = te.promptText;
515
+ if (typeof te.tokenCount === 'number')
516
+ s.headerTokens = te.tokenCount;
517
+ if (typeof te.tools === 'string') {
518
+ try {
519
+ const arr = JSON.parse(te.tools);
520
+ if (Array.isArray(arr)) {
521
+ s.tools = arr.flatMap((x) => {
522
+ const f = x.function ?? x;
523
+ const g = f;
524
+ return g && typeof g.name === 'string'
525
+ ? [{ name: g.name, description: typeof g.description === 'string' ? g.description : '' }]
526
+ : [];
527
+ });
528
+ }
529
+ }
530
+ catch { /* not JSON — leave unparsed */ }
531
+ }
532
+ if (typeof te.messages === 'string') {
533
+ try {
534
+ const ms = JSON.parse(te.messages);
535
+ if (Array.isArray(ms)) {
536
+ const sys = ms.find((mm) => mm && mm.role === 'system' && typeof mm.content === 'string');
537
+ s.systemText = sys ? sys.content : null;
538
+ }
539
+ }
540
+ catch { /* not JSON */ }
541
+ }
542
+ return;
543
+ }
366
544
  const lane = m.lanes.get(agentId);
367
545
  if (lane && typeof te.promptText === 'string') {
368
546
  lane.prompt = {
@@ -378,6 +556,13 @@ export function foldEvent(m, ev, now) {
378
556
  const lane = m.lanes.get(handle);
379
557
  if (lane)
380
558
  lane.prunedAt = now;
559
+ // The same prune, seen by the trunk feed: this handle's turns
560
+ // left the KV with it, so they leave the feed — the feed shows
561
+ // the resident conversation, nothing else. Handle-matched (never
562
+ // a blanket clear): an agent branch's prune must not touch the
563
+ // trunk, and the match is order-independent with the next
564
+ // generation's first commit.
565
+ m.trunk = m.trunk.filter((t) => t.branchHandle !== handle);
381
566
  return;
382
567
  }
383
568
  case 'tool:dispatch': {
@@ -548,6 +733,8 @@ export const KEY_TIERS = {
548
733
  'model.path': 'reload',
549
734
  'model.reranker': 'reload',
550
735
  'model.gpu': 'reload',
736
+ 'model.imageMinTokens': 'reload',
737
+ 'model.imageMaxTokens': 'reload',
551
738
  'model.nCtx': 'boot',
552
739
  'model.branches': 'boot',
553
740
  'model.kvCache': 'boot',