pi-supernova 0.8.1 → 0.9.0

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 (66) hide show
  1. package/README.md +244 -54
  2. package/docs/CHANGELOG.md +111 -1
  3. package/docs/TOKEN_COSTS.md +38 -0
  4. package/index.js +10 -175
  5. package/package.json +2 -1
  6. package/src/adapters/bash.js +23 -33
  7. package/src/adapters/errors.js +1 -9
  8. package/src/adapters/read-focus.js +98 -0
  9. package/src/adapters/read-image.js +51 -0
  10. package/src/adapters/read-json.js +42 -0
  11. package/src/adapters/read-text.js +71 -0
  12. package/src/adapters/read.js +66 -635
  13. package/src/bridge/catalog.js +3 -2
  14. package/src/bridge/host-bridge.js +35 -167
  15. package/src/bridge/tool-registry.js +104 -0
  16. package/src/bridge/trace.js +41 -0
  17. package/src/context/evidence-graph.js +249 -0
  18. package/src/context/evidence-rank.js +153 -0
  19. package/src/context/evidence.js +10 -424
  20. package/src/context/query.js +71 -0
  21. package/src/context/repo-index.js +8 -162
  22. package/src/context/search-files.js +19 -0
  23. package/src/context/search.js +2 -24
  24. package/src/context/snap-search.js +202 -0
  25. package/src/context/snap.js +5 -266
  26. package/src/context/source-entry.js +112 -0
  27. package/src/contract/bash.js +18 -2
  28. package/src/contract/program.js +36 -0
  29. package/src/contract/read.js +8 -53
  30. package/src/fs/check.js +1 -1
  31. package/src/fs/commit.js +161 -0
  32. package/src/fs/diff.js +11 -15
  33. package/src/fs/directory.js +79 -0
  34. package/src/fs/file-io.js +100 -0
  35. package/src/fs/glob.js +54 -0
  36. package/src/fs/json-size.js +54 -0
  37. package/src/fs/lines.js +117 -0
  38. package/src/fs/read-window.js +74 -0
  39. package/src/fs/session-resource.js +50 -0
  40. package/src/fs/text-ops.js +7 -242
  41. package/src/fs/vfs.js +5 -239
  42. package/src/fs/workspace.js +7 -2
  43. package/src/output/bottleneck.js +13 -67
  44. package/src/output/final.js +114 -0
  45. package/src/output/format.js +94 -5
  46. package/src/output/outcome.js +91 -0
  47. package/src/runtime/batch-input.js +68 -0
  48. package/src/runtime/guest-api.js +281 -0
  49. package/src/runtime/guest-worker.js +62 -333
  50. package/src/runtime/parallel.js +41 -39
  51. package/src/runtime/program-batch.js +35 -68
  52. package/src/runtime/program-file.js +3 -11
  53. package/src/runtime/program.js +141 -0
  54. package/src/runtime/reference.js +11 -10
  55. package/src/runtime/runtime.js +94 -261
  56. package/src/runtime/worker-pool.js +91 -0
  57. package/src/shared/decode.js +22 -8
  58. package/src/shared/image-worker.js +30 -0
  59. package/src/shared/image.js +78 -0
  60. package/src/shared/png.js +57 -0
  61. package/src/shared/result.js +77 -0
  62. package/src/shared/syntax-context.js +61 -3
  63. package/src/ui/host-render.js +104 -0
  64. package/src/ui/progress.js +51 -0
  65. package/src/ui/render.js +21 -421
  66. package/src/ui/trace.js +277 -0
package/README.md CHANGED
@@ -12,7 +12,99 @@ Ordinary JavaScript control flow remains available; the guest command bindings
12
12
  are only `read`, `edit`, `write`, and `bash`. Supernova supplies retrieval,
13
13
  transactional file operations, batching, bounded results and the grouped nova UI.
14
14
 
15
- ## What is new in 0.8.0
15
+ ## What is new in 0.9.0
16
+
17
+ - **Text clipping does not stop batches:** sequential and parallel programs keep
18
+ running when the combined display text exceeds its allowance. Results disclose
19
+ truncation; execution, deadline, host-call, log and image limits remain enforced.
20
+ - **Decoded image validation:** PNG/JPEG/GIF/WebP reads and returned attachments
21
+ require matching formats, canonical base64 and decodable pixels, including all
22
+ GIF/WebP frames. PNG preflight checks chunk boundaries and CRCs too. Failures
23
+ occur before shell boundaries or final commit/delivery, with no image attached.
24
+ - **Isolated image work:** Sharp 0.35.4 decodes at most 32 million pixels across
25
+ all frames, one image at a time, in a Node/Bun subprocess with a 5-second kill
26
+ deadline. Text-only work never loads the decoder. A bounded 16-entry digest cache
27
+ avoids decoding unchanged bytes again; neither image data nor file paths are cached.
28
+ Encoded limits remain 16 attachments / 20 MiB. Sharp's platform-specific optional
29
+ dependencies must be installed; decoder failure never falls back to unchecked data.
30
+ Local decoding does not guarantee acceptance under every provider's image policy.
31
+
32
+ - **Data is not a display preview:** ordinary text reads return complete data up to
33
+ 64 MiB; JSON selections remain actual values and directories remain arrays.
34
+ The former 160-line / 8192-character and 31,744-character restrictions no longer
35
+ constrain computation inside a program. Only returned/logged text is displayed.
36
+ - **Large batches stay bounded:** small reads share one reply; larger items are
37
+ delivered with acknowledgements within eight I/O slots, not retained as one
38
+ giant host-side batch. Explicit arrays and coalesced reads use the same path.
39
+ - **Output work stays in the worker:** bounded formatting avoids expanding large
40
+ values before clipping. Model-visible source previews retain exact ranges and
41
+ continuation; a clipped preview cannot be passed back as a complete edit view.
42
+
43
+ - **Cancellation no longer crashes the host:** bounded reads and CAS signing use
44
+ abort-checked file handles instead of aborting streams. A failed read can cancel
45
+ sibling reads without an uncaught `AbortError` terminating OMP.
46
+ - **Memory is charged to the guest:** worker-local heap and external buffers
47
+ replace process-wide RSS accounting. Bun enforcement remains best-effort.
48
+ - **Focused internals:** read adapters, file I/O, transactions, worker lifecycle,
49
+ tool ownership, source ranking and rendering have separate modules. All read
50
+ modes, batching, checkpoints and rollback behavior remain supported.
51
+
52
+ **Verified release candidate:** 315/315 package tests pass on both Node and Bun;
53
+ actual Pi/OMP checks and clean tarball installation checks also pass. See
54
+ [verification results and coverage limits](#verification) below.
55
+
56
+ ### Concurrent file operations
57
+
58
+ Batching and explicit parallel programs remain supported. Within one program,
59
+ `Promise.all` now overlaps native edits and writes to different files, up to eight
60
+ operations at once:
61
+
62
+ ```js
63
+ await Promise.all([
64
+ edit("src/a.js", "oldA", "newA"),
65
+ edit("src/b.js", "oldB", "newB"),
66
+ ]);
67
+ return await bash("npm test");
68
+ ```
69
+
70
+ Same-file operations retain submission order. Reads before/after mutations,
71
+ `bash`, edit checkpoints, and overridden mutating tools remain ordering barriers.
72
+ Shell calls inside one program stay sequential; use `programs` with
73
+ `parallel:true` for explicitly independent shell workflows or separate JS workers.
74
+ Edits still stage until program success (or a shell boundary); transactional disk
75
+ commits retain their conflict checks. `await edit(...)` one after another is still
76
+ sequential, and multiple replacements in one file remain one edit operation.
77
+
78
+ ## What is new in 0.8.2
79
+
80
+ This patch release fixes shell failure handling, cancellation and parallel-batch
81
+ limits, and makes one-call batching guidance explicit.
82
+
83
+ - **Shell quoting stays intact:** quoted executable paths are no longer unwrapped.
84
+ Shell syntax errors suggest literal `bash({command,args})` with `data` for
85
+ embedded scripts, or a quoted heredoc. Commands are not rewritten or retried.
86
+ - **Validation before commit:** invalid timeouts and null-byte
87
+ arguments are rejected before the shell boundary flushes staged files.
88
+ - **Useful failure output:** long command labels are bounded so the original
89
+ stderr is not crowded out by a repeated script.
90
+ - **Timeouts retain diagnostics:** the outer program deadline stops the worker
91
+ and gives pending host calls a bounded drain to retain shell output. Explicit
92
+ cancellation is reported separately from timeout. The outer `timeoutMs` covers
93
+ every wait and command, including `sleep`.
94
+ - **Parallel budgets fail honestly:** exceeding the shared log or image
95
+ allowance marks the batch failed and stops queued entries. Already-running
96
+ entries settle; their results and completed commits remain. Aggregate logs stay
97
+ capped rather than multiplying the allowance per guest. In 0.8.2 this also
98
+ applied to output text; 0.9.0 makes display-text clipping nonfatal.
99
+ - **Batch known work in one call:** combine independent reads/checks with
100
+ `Promise.all`, then sequence edits and verification in the same program. Use
101
+ another invocation when returned evidence is needed for the next decision.
102
+
103
+ Verified on **macOS / Node 26.7**: 267 package tests (384 repository tests),
104
+ 2,328 stress invocations, actual Pi/OMP host checks, lint and both token-budget
105
+ checks. This is not a claim of exhaustive platform or formal mutation testing.
106
+
107
+ ## 0.8.0 features and measurements
16
108
 
17
109
  - **Shared program source:** top-level `code` or `file` supplies a batch default;
18
110
  entries may override it. A shared program is sent once instead of in every entry,
@@ -27,7 +119,7 @@ transactional file operations, batching, bounded results and the grouped nova UI
27
119
  original cause and `committed`/`rolledBack` totals, marks writes whose
28
120
  persistence cannot be attributed as attempted, and labels pure JavaScript runs
29
121
  instead of "complete".
30
- - **Bounded, explicit reads:** errors state both limits (`160 lines / 8192
122
+ - **Historical read limits (superseded in 0.9.0):** errors stated both limits (`160 lines / 8192
31
123
  characters`) with copyable recovery (`offset`, `about`, `complete:true`, and
32
124
  `Promise.allSettled` for optional siblings). Markdown edits skip code-reference
33
125
  searches; exact-symbol evidence excludes generic matches.
@@ -81,14 +173,24 @@ Local checkout installs are for development, not distribution:
81
173
  pi install /path/to/pi-stack/packages/pi-supernova
82
174
  ```
83
175
 
84
- Git pushes do not update npm installations. Publish the new npm version first;
85
- then reinstall it in the host. Reinstall explicitly when an existing version
86
- range excludes the new minor version (`^0.6.0` excludes `0.7.0`). After 0.7.0 is
87
- published, pin that release with:
176
+ 0.9.0 adds Sharp for image validation. Keep its platform-specific optional
177
+ dependencies enabled. For a local checkout, refresh dependencies before starting
178
+ the host:
179
+
180
+ ```bash
181
+ npm install --prefix /path/to/pi-stack/packages/pi-supernova --include=optional
182
+ ```
183
+
184
+ Install dependencies on each target machine rather than copying `node_modules`
185
+ between operating systems or CPU architectures. Published-package installation
186
+ resolves these dependencies through the host's package manager.
187
+
188
+ Git pushes do not update npm installations. Publish the new npm version first,
189
+ then reinstall it in your host. To pin **0.9.0** once it is published:
88
190
 
89
191
  ```bash
90
- pi install npm:pi-supernova@0.7.0
91
- omp install npm:pi-supernova@0.7.0
192
+ pi install npm:pi-supernova@0.9.0
193
+ omp install npm:pi-supernova@0.9.0
92
194
  ```
93
195
 
94
196
  In Pi, `pi list` shows the configured package sources. A local path uses that
@@ -135,6 +237,21 @@ payloads are not repeated in owned direct-execution errors;
135
237
  stdout/stderr, exit status and source context remain. Session environment variables are taken
136
238
  from the current execution context, not inherited from a different parent session.
137
239
 
240
+ Shell strings are executed unchanged, including quoted executable paths. For inline
241
+ Python/Node scripts, prefer literal argv with `data` instead of nested shell quotes:
242
+
243
+ ```json
244
+ {
245
+ "code": "return await bash({command:\"python3\",args:[\"-c\",data.script]});",
246
+ "data": {"script": "q = {'name': 'example'}\nprint(f\"{q['name']}\")\n"}
247
+ }
248
+ ```
249
+
250
+ Shell syntax errors keep the original diagnostic and suggest argv or a quoted
251
+ heredoc; commands are never automatically rewritten or retried. Invalid timeouts
252
+ and null-byte arguments fail before flushing staged changes. Failure labels are
253
+ bounded so a large script cannot crowd out its stderr.
254
+
138
255
  Source questions locate a declaration in one command. An exact
139
256
  declaration match uses one bounded direct ripgrep search, without a prerequisite
140
257
  file listing, persistent index, embeddings or summarization. A transient filename
@@ -143,7 +260,7 @@ questions reuse lexical stemming. Source questions and focused `about` reads
143
260
  accept at most 16 keywords. Ripgrep must be available on PATH.
144
261
 
145
262
  `read(path)` stays raw text. `read("symbol")` is the same view as
146
- `read({query, resolve:true})` — not the file, not a path/range header:
263
+ `read({query, resolve:true})` -- not the file, not a path/range header:
147
264
 
148
265
  ```javascript
149
266
  const v = await read("validateRefreshToken");
@@ -152,7 +269,8 @@ await edit(v, v.text.replace("token.length > 3", "token.length > 5"));
152
269
  ```
153
270
 
154
271
  The view contains `status`, `path`, the matching `line`, span `lines`, unchanged
155
- `text`, `complete`, and `nextOffset` when a budget clip continues. A declaration
272
+ `text`, `complete`, and `nextOffset` when a model-facing preview continues.
273
+ The internal view is not shortened to fit the display. A declaration
156
274
  snap is that span (`complete` is false unless the span is the whole file). Uncertain
157
275
  results report `ambiguous`, `not_found` or `incomplete` with no selected path.
158
276
  Use `{path: directory, about: question}` to narrow the scope. Scoping a query
@@ -184,17 +302,18 @@ lines. Structural warnings and source windows are not substitutes for tests.
184
302
 
185
303
  ### Safe read-modify-write
186
304
 
187
- Path-only `read(path)` requires at most **160 lines and 8192 UTF-16 characters**.
188
- A short document can exceed the character limit. For larger files use
189
- `read(path,{offset:1,limit:80})` (one-based lines), `read(path,{about:"keywords"})`,
190
- or `read(path,{complete:true})`. The default raw-text read budget is **31,744
191
- characters**, derived from the configured call/return budgets, not an unlimited
192
- full-file buffer. Large JSONL needs a bounded parser through `bash({command,args})`.
193
-
194
- Plain reads are bounded views, not guaranteed full-file buffers. Use
195
- `read({path:"file.txt",complete:true})` when code needs the complete file; it
196
- throws rather than handing back partial text. Prefer `edit` for large-file
197
- replacements, or reconstruct exact `resolve:true` windows before writing.
305
+ A plain file read returns its complete text up to the **64 MiB UTF-8 I/O limit**,
306
+ independently of model-facing character budgets. Explicit `offset`/`limit` reads
307
+ return exact line windows, including long lines and LF/CRLF endings, or fail at
308
+ the same byte ceiling. Staged and on-disk data obey the same ceiling.
309
+ `complete:true` additionally rejects a window that omits part of the file.
310
+ For larger files/JSONL, use a bounded parser through `bash({command,args})`.
311
+
312
+ Compute on the full value and return only what the model needs. A direct large
313
+ return is an explicitly truncated display, not a complete artifact to parse or
314
+ write back. `resolve:true` source previews retain path/range/continuation metadata;
315
+ clipped previews are not editable. Prefer `edit` for replacements.
316
+ A write after reading that path still requires `edit` or explicit `replace:true`.
198
317
  Writes reject Supernova truncation markers, including legacy host-result markers.
199
318
  For intentionally writing literal marker documentation only, opt in with
200
319
  `write({path,content,allowReadArtifacts:true})`. This is a data-loss guard, not
@@ -208,6 +327,10 @@ These checks do not provide a cross-process lock or make shell/import mutations
208
327
  transactional. Extensionless filenames also support `complete:true`, for example
209
328
  `read({path:"LICENSE",complete:true})`.
210
329
 
330
+ Directory reads return complete string-entry arrays up to **10,000 unique entries**.
331
+ Larger listings fail with a path and bounded-parser guidance rather than silently
332
+ returning an incomplete array. Metadata lookups overlap eight at a time.
333
+
211
334
  Explicit read arrays reject missing/failed paths. For typed partial outcomes use
212
335
  `Promise.allSettled(paths.map(path => read(path)))`. Successful arrays remain arrays.
213
336
  For literal file content or scripts, prefer the optional tool-level `data` parameter:
@@ -337,7 +460,8 @@ programs that depend on whole-input replacement keep that behavior unless the
337
460
  caller explicitly requests `mergeData:true`.
338
461
 
339
462
  The batch stops on the first failed entry, cancellation/deadline, or exhausted
340
- output/log/image budget. Earlier successful commits remain; only the active
463
+ log/image budget. Display-text clipping does not stop execution or mark a
464
+ successful batch failed. Earlier successful commits remain; only the active
341
465
  program's uncommitted writes roll back. Admission errors throw before any program.
342
466
  Execution failures return a **typed stop report**, rather than throwing away prior
343
467
  results/images: isError and details.ok identify failure, details.programs contains
@@ -349,12 +473,16 @@ Set `parallel: true` with `programs` to run independent entries concurrently
349
473
  in submission order. A failed entry does not stop siblings. Two entries writing
350
474
  the same file race: the losing commit reports a conflict. Sequential remains the
351
475
  default. `parallel` and `mergeData` are invalid on a lone `code` or `file` call.
476
+ Log/image budget overflow marks the batch failed and stops queued entries;
477
+ already-running entries settle and their completed commits remain. Text overflow
478
+ only clips the displayed result and sets `details.returnTruncated`; queued entries
479
+ still run. Parallel execution does not multiply the aggregate allowances.
352
480
 
353
481
  The outer deadline, host-call budget, log allowance, text budget and image limits
354
482
  are shared across the batch. Individual read budgets are not reduced. Every
355
- attempted program's original text is returned in length-delimited blocks; ordinary
356
- limits still disclose clipping. Images retain program/image labels. Split a plan
357
- that would exceed the aggregate output budget.
483
+ attempted program's text is assembled in length-delimited blocks, then the combined
484
+ display is clipped if necessary. Images retain program/image labels. Return
485
+ summaries or use focused windows when you need every result to fit on display.
358
486
 
359
487
  Batch only continuations already chosen by the agent, such as edit then known
360
488
  verification, or create then run known audits. Keep a separate call whenever new
@@ -380,10 +508,13 @@ For long archive scans, use resumable chunks or a host background-job tool and w
380
508
  progress records under `.work`. Shell commands inherit the current program
381
509
  `timeoutMs` unless they specify their own; increasing the outer deadline no longer
382
510
  leaves a hidden 60-second shell cap. Set the inner `bash` timeout shorter than the
383
- outer program timeout (for example 10 seconds inside a 20-second program) to retain
384
- bounded shell diagnostics. A hard guest deadline cannot guarantee pending shell
385
- output delivery; progress files survive shell execution but staged VFS writes may
386
- roll back.
511
+ outer program timeout (for example 10 seconds inside a 20-second program). The outer
512
+ deadline covers **all** waits and commands, including `sleep`; a shell's own `timeout`
513
+ command does not extend it. On a deadline or cancellation, the worker stops and
514
+ pending host calls get a bounded 250ms drain to retain owned-shell diagnostics and
515
+ finalize process termination. Non-cooperating host executors may still outlive that
516
+ drain. Cancellation is reported separately from timeout; neither triggers a retry.
517
+ Progress files survive shell execution but staged VFS writes may roll back.
387
518
 
388
519
  Large returned objects are bounded previews, not retained artifacts. Select fields
389
520
  and array windows before returning, rather than parsing a truncated preview.
@@ -406,14 +537,14 @@ array length. Only own JSON properties are traversed; nothing is evaluated.
406
537
  Inputs are capped at 16 MiB, including staged files. JSON reads require regular
407
538
  files and reject named pipes without waiting for a writer. The entire input must
408
539
  be valid JSON before any selection. Each selector is budgeted before allocating
409
- the next slice; sparse selector/path/edit arrays are rejected. Selected JSON must
410
- fit the ordinary read budget. Oversized selections return a routing object
411
- `{status:"too_large",path,keys}` (or `length` for an array), not the requested
412
- array/object: check `status` before calling `.map` or `.filter`, then select
413
- narrower fields or slices. The input-size cap still throws before projection;
414
- JSON is never returned malformed or silently truncated. Oversized unwindowed
415
- plain .json reads also fail with a projection hint. Explicit offset/limit or
416
- resolve:true still allow raw inspection, but line windows are not JSON documents.
540
+ the next slice; sparse selector/path/edit arrays are rejected. Selections have a
541
+ separate **64 MiB estimated storage limit per read**, including aggregate
542
+ multi-selector expansion. Within it, arrays/objects/scalars retain their actual
543
+ values, even when larger than the display. No routing object is substituted:
544
+ `.map` and `.filter` work on the selected array. Multi-selector values remain
545
+ independently mutable. The input/storage safety limits throw with guidance.
546
+ Plain .json reads are raw text, including malformed JSON; parsing is requested
547
+ only by `json`. Explicit line windows are not necessarily JSON documents.
417
548
  Do not combine json with complete, line windows, or source views. External read
418
549
  overrides reject JSON projection rather than silently ignoring the option.
419
550
  Uncaught read errors abort the program, including `return {a:await read(...),
@@ -425,27 +556,44 @@ rollback for uncaught failures.
425
556
  Other read options, even false-valued flags, do not bypass a captured external
426
557
  read executor; its policy, transforms and failures remain authoritative.
427
558
 
428
- For large Markdown/log path audits, use read(path,{about:"document path"}) or
429
- explicit offset/limit, not complete:true. Larger JSON needs a streaming parser via
430
- bash. Arbitrary returned objects still have bounded previews, not implicit
559
+ For focused Markdown/log audits, use read(path,{about:"document path"}) or
560
+ explicit offset/limit. Use complete reads for computation within the 64 MiB
561
+ ceiling, and return a summary. JSON over 16 MiB needs a streaming parser via bash. Arbitrary returned objects still have bounded previews, not implicit
431
562
  continuation handles.
432
563
 
433
564
  ## Execution and automatic batching
434
565
 
566
+ Put already-known independent reads and checks in **one** Supernova program using
567
+ `Promise.all` (or `Promise.allSettled` when failures should remain independent).
568
+ Sequence edits and their known verification in that same program. Start another
569
+ invocation only when the returned evidence is needed to decide what to do next;
570
+ use focused read windows to keep the combined result within its output budget.
571
+
435
572
  Compatible independently started reads coalesce at the worker/host boundary.
436
573
  No additional batching command is required. Individual promises preserve their
437
- values, errors and per-read budgets. File reads have bounded parallelism; writes,
438
- edits, shell calls and checkpoint transitions form ordering barriers.
574
+ values, errors and per-read safety limits. Reads and known native mutations to
575
+ disjoint files overlap up to eight operations; same-file mutations stay ordered.
576
+ Read/mutation transitions, shells, checkpoints and overrides remain barriers.
439
577
 
440
578
  This does **not** reorder sequential `await`s or predict future model decisions.
441
- An explicit path-array read uses an aggregate text budget; automatic coalescing
442
- retains each independent read's budget instead of silently shrinking its result.
579
+ Explicit path arrays and automatic coalescing share the same typed delivery.
580
+ Small batches retain the single-reply fast path; beyond 64 KiB estimated storage,
581
+ items stream to the guest with acknowledgements. Delivery holds its I/O slot
582
+ until acknowledged, and the final read waits for its host barrier to settle.
443
583
 
444
584
  Every program runs in a fresh worker. One pristine worker is prepared for the next
445
585
  invocation, then disposed on session shutdown. Executed workers are never reused,
446
586
  so guest globals cannot leak into a later program. Worker preparation still costs
447
587
  CPU and memory; it is moved off the next invocation's critical path, not eliminated.
448
588
 
589
+ `maxHeapMb` sets Node's native worker heap cap. A worker-local check also limits
590
+ heap plus external buffers to 1.5 times that value, sampled every 50 ms and before
591
+ host calls and final results. Process-wide RSS is never charged to an individual
592
+ guest. These samples are best-effort: Bun does not enforce Node's native heap cap,
593
+ and non-yielding code can prevent sampling until it reaches a command or returns.
594
+ The outer deadline still terminates non-yielding workers. This is not a hard
595
+ process-memory or security boundary.
596
+
449
597
  File changes are staged until program success. A throw before an external-mutation
450
598
  barrier rolls them back. Shell execution flushes preceding changes; external shell
451
599
  side effects cannot be rolled back. Stale commits fail explicitly rather than
@@ -468,8 +616,9 @@ the active callback are rejected. Await the checkpoint before proceeding.
468
616
 
469
617
  - Plain reads are not replaced with earlier-context references. A local cache hit
470
618
  is not proof the model still retains an earlier result after compaction.
471
- - Oversized text reads provide an exact next-line offset. A single line too large
472
- for the budget fails explicitly instead of pretending it was read completely.
619
+ - Text and JSON computation is independent of display limits. Source previews
620
+ provide exact continuation; raw displayed text can be clipped and must not be
621
+ parsed as a complete file. I/O/storage limits still fail explicitly.
473
622
  - Model attachments support PNG, JPEG, GIF and WebP. BMP and other unsupported
474
623
  MIME types fail before attachment or commit, rather than causing a provider
475
624
  HTTP 400 on the next request. Convert those sources to PNG first; Supernova
@@ -552,18 +701,59 @@ not a claim that every third-party permission extension has been validated.
552
701
  ## Development and evidence
553
702
 
554
703
  Implementation is grouped under `src/`; all replacement tests are under `tests/`.
555
- The original 12 red acceptance tests were left unchanged. Additional strict tests
556
- cover batching fidelity, image/context retention, checkpoints, mutation ordering,
557
- external symlinks, deadlines, worker isolation and execution-context environment.
558
- The former deleted suite has not been silently reinstated.
704
+ Read-budget assertions now test the deliberate 0.9.0 contract: complete internal
705
+ values and bounded model-facing output. Frozen token snapshots are unchanged.
706
+ Strict regressions cover batching fidelity, image/context retention, checkpoints,
707
+ mutation ordering, external symlinks, deadlines, worker isolation, bounded read
708
+ delivery, and execution-context environment.
709
+
710
+ ### Module boundaries
711
+
712
+ | Responsibility | Modules |
713
+ |---|---|
714
+ | Registration and session lifecycle | `index.js` |
715
+ | Program admission and batching | `runtime/program.js`, `runtime/batch-input.js`, `runtime/program-batch.js` |
716
+ | Worker ownership and guest RPC | `runtime/runtime.js`, `runtime/worker-pool.js`, `runtime/guest-worker.js`, `runtime/guest-api.js` |
717
+ | Host permissions, ordering and trace | `bridge/host-bridge.js`, `bridge/tool-registry.js`, `bridge/trace.js` |
718
+ | Read routing and typed readers | `adapters/read.js`, `adapters/read-{text,json,image,focus}.js` |
719
+ | Image validation and isolated decoding | `shared/png.js`, `shared/image.js`, `shared/image-worker.js` |
720
+ | Bounded I/O and atomic transactions | `fs/file-io.js`, `fs/read-window.js`, `fs/vfs.js`, `fs/commit.js` |
721
+ | Source search and ranking | `context/query.js`, `context/snap-search.js`, `context/source-entry.js`, `context/evidence-{graph,rank}.js` |
722
+ | Model output and host rendering | `output/final.js`, `output/outcome.js`, `ui/host-render.js`, `ui/trace.js`, `ui/render.js` |
723
+
724
+ Paths above are relative to `src/`, except `index.js`. Layer tests require an
725
+ acyclic import graph and prohibit context modules from importing runtime code.
726
+
727
+ ### Verification
728
+
729
+ The final 0.9.0 release candidate was verified on **macOS**:
730
+
731
+ | Check | Result |
732
+ |---|---|
733
+ | Node 26.7 package suite | 315 passed; zero failures or skips |
734
+ | Bun 1.4 package suite | 315 passed; zero failures or skips |
735
+ | Pi 0.86.1 / OMP 18.2.6 | Actual host execution checks passed; Pi TUI checks passed |
736
+ | Clean production-only tarball installation | Node/Bun and actual Pi/OMP smoke checks passed |
737
+ | Lint, frozen token gates, repository release check and publish preflight | Passed |
738
+
739
+ Failure-first regressions cover corrupt image data, malformed base64, MIME
740
+ mismatches, decoded-pixel limits and nonfatal batch-text clipping. Additional
741
+ checks cover animated images, content-based validation reuse, cancellation,
742
+ decoder-watchdog recovery, and real failures after clipped output. The compiled
743
+ OMP native-module issue is covered by the actual-host checks, not only unit tests.
744
+
745
+ **Coverage limits:** a live Codex round-trip and Linux/Spark smoke checks were not
746
+ rerun after the final image-validation changes. These results are not a claim of
747
+ exhaustive platform coverage or guaranteed acceptance by every model provider.
559
748
 
560
749
  Test user-visible contracts through registered programs: exact source, on-disk
561
750
  results, failure/rollback, isolation, bounded output, and usable host rendering.
562
751
  Inject filesystem faults only to exercise real failure paths; do not prescribe
563
752
  private helper layouts, staging filenames, or syscall counts. New regressions must
564
753
  fail before the fix; for existing behavior, verify that a named deliberate defect
565
- makes the intended test fail before accepting it. Keep the original 12 acceptance
566
- tests unchanged. Cost gates cover avoidable search processes, per-read budgets and
754
+ makes the intended test fail before accepting it. Preserve existing assertions unless an explicitly requested contract changes;
755
+ then test both the new behavior and the retained safety boundary. Cost gates
756
+ cover avoidable search processes, per-read safety limits and
567
757
  progress flooding; latency claims belong in the explicit measurement lane, not
568
758
  arbitrary wall-clock assertions.
569
759
 
@@ -579,8 +769,8 @@ npm run test:hosts --prefix packages/pi-supernova
579
769
  ```
580
770
 
581
771
  The explicit host runner requires macOS network sandboxing and fails, rather than
582
- skips, when prerequisites are absent. Verified locally against Pi 0.85.1 and OMP
583
- 18.1.11: CodeMode execution, four primitives, automatic read coalescing, checkpoints,
772
+ skips, when prerequisites are absent. Verified locally against Pi 0.86.1 and OMP
773
+ 18.2.6: CodeMode execution, four primitives, automatic read coalescing, checkpoints,
584
774
  images and failed execution. Pi's actual loader/runner and TUI are exercised; OMP
585
775
  runs in a disposable process through its actual session registry, with networking
586
776
  denied. The Pi runner supplies a minimal tool registry, not a full provider session.
package/docs/CHANGELOG.md CHANGED
@@ -1,6 +1,116 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## [0.9.0] - 2026-09-20
4
+
5
+ ### Changed
6
+
7
+ - Split read routing, filesystem I/O and commits, guest commands and worker
8
+ lifecycle, host tool ownership and tracing, evidence selection, and rendering
9
+ into focused modules. Public entrypoints and guest command modes remain supported.
10
+ - Reuse bounded file reads, query analysis, overlay lookup, line and JSON
11
+ helpers, diff assembly, and error formatting instead of parallel implementations.
12
+
13
+ - `Promise.all` overlaps native edits, patches and writes to distinct files, up
14
+ to eight operations at once. Same-file operations remain ordered using canonical
15
+ commit destinations; existing alias-conflict protections remain in place.
16
+ - Removed the duplicate guest operation queue. The host owns read/mutation,
17
+ shell, override and checkpoint barriers, and waits for in-flight siblings before
18
+ crossing them. File identities are resolved only after external mutations finish.
19
+ - Batching and explicit `programs` / `parallel:true` execution remain supported;
20
+ standing guidance distinguishes these from per-file concurrency.
21
+
22
+ ### Fixed
23
+
24
+ - Aggregate display-text clipping no longer fails sequential/parallel program
25
+ batches or prevents later entries from running. The combined display remains
26
+ bounded and marks truncation; execution, deadline, log and image failures retain
27
+ their stop behavior.
28
+ - PNG/JPEG/GIF/WebP reads and returned attachments validate canonical base64,
29
+ matching signatures/MIME, and fully decoded pixels before shell boundaries or
30
+ final commit/model delivery. PNG framing/CRC checks reject the exact corrupt
31
+ fixture that caused repeated Codex errors. Tests also cover CRC-correct invalid
32
+ pixels, truncated streams, format mismatches, animated inputs, and rollback.
33
+ - Sharp 0.35.4 decoding runs in an isolated Node/Bun runtime process: at most
34
+ 32 million pixels across frames, one raster at a time, with cancellation and a
35
+ 5-second watchdog. This also fixes native dependency resolution in compiled OMP.
36
+ Text-only calls do not load Sharp; a bounded cache retains only 16 successful
37
+ content digests. Decoder installation failures reject rather than attach blindly.
38
+
39
+ - Native reads carry typed values across RPC rather than serialized display text.
40
+ Full text reads and exact line windows use the 64 MiB byte ceiling, not the
41
+ former 160-line / 8192-character or 31,744-character presentation restrictions.
42
+ JSON selections retain their types under separate input/storage safety limits.
43
+ - Large coalesced and explicit read batches stream with acknowledgements inside
44
+ eight I/O slots; the small-batch path still uses one reply. Sibling cancellation
45
+ drains delivery as well as I/O, and final promises wait for the host barrier.
46
+ - Directory entries remain arrays, metadata stats overlap, and exceeding 10,000
47
+ unique entries fails explicitly instead of returning an apparently complete list.
48
+ - Final formatting runs in the worker. Large string arrays, objects and logs are
49
+ bounded before rendering expansion; sparse positions and Unicode display stay
50
+ valid. Hidden metadata cannot bypass the transfer budget. Source previews keep
51
+ exact continuation and edit guards without shortening internal source values.
52
+ - Removed unused native routing producers and obsolete display-sized read caps;
53
+ legacy external-tool decoding remains. Staged windows retain the disk byte cap.
54
+
55
+ - Cancelled bounded reads and CAS signing use abort-checked file-handle reads,
56
+ avoiding a second unhandled stream error that crashed Node and Bun even when
57
+ the read rejection was caught. Byte caps and file-version checks are retained.
58
+ - Memory enforcement uses worker-local heap and external-buffer usage, not
59
+ process-wide RSS growth from the host or sibling workers. Node's native heap
60
+ cap remains; Bun sampling remains best-effort for non-yielding code. Memory
61
+ failures cancel and drain pending host calls before returning.
62
+
63
+ - Guest stack locations are recognized in both V8 and Bun/JSC; asynchronous
64
+ failures identify the source await consistently without moving direct throws.
65
+ - Commit I/O uses the shared filesystem promises export, so fault injection
66
+ exercises real partial replacement and failed recovery on both Node and Bun.
67
+ - Permission failures during canonical-path resolution retain the affected path
68
+ and actionable guidance instead of leaking raw EACCES errors on Bun.
69
+ - JSON projection recovers missing parse locations for inputs up to 65,536
70
+ characters, with a bounded diagnostic scan and no second value tree. Native
71
+ JSON.parse remains authoritative; caret columns and BOM handling are aligned.
72
+
73
+ ### Verification
74
+
75
+ - Complete package suites: 315 passed on Node 26.7 and 315 passed on Bun 1.4
76
+ on macOS, with zero failures or skips, including failure-first image validation
77
+ and batch-clipping regressions, animated-image preservation, cache invalidation,
78
+ cancellation, and decoder-watchdog recovery. All five former Bun failures remain fixed. Frozen token
79
+ snapshots are unchanged; obsolete internal-display-cap assertions now verify
80
+ full data while preserving real memory, parsing, rollback and edit guards.
81
+ - Lint, frozen token gates, the repository release check, and actual
82
+ Pi 0.86.1 / OMP 18.2.6 host checks passed.
83
+ The fatal cancellation was reproduced against the old Spark installation and
84
+ the fixed package passed Node/Bun checks in an isolated copy; no installed
85
+ copy was patched.
86
+ - See TOKEN_COSTS.md for the refactor's measured gains and small-operation costs.
87
+ Full image decoding adds image-only work and a native dependency; it is not
88
+ presented as a general latency improvement or proof of provider acceptance.
89
+
90
+ ## [0.8.2] - 2026-09-19
91
+
92
+ ### Fixed
93
+
94
+ - Shell commands preserve quoted executable paths. Parser failures suggest
95
+ literal argv for embedded scripts or a quoted heredoc, without rewriting or
96
+ automatically retrying commands.
97
+ - Invalid timeouts and null-byte arguments fail before flushing staged files.
98
+ Bounded command labels keep long scripts from crowding out diagnostics.
99
+ - Program deadlines retain pending shell output during bounded termination;
100
+ explicit cancellation is no longer misreported as a timeout.
101
+ - Parallel batches enforce shared output, log and image budgets instead of
102
+ reporting success after overflow. Queued entries stop, in-flight results and
103
+ completed commits remain, and aggregate logs stay capped.
104
+
105
+ ### Changed
106
+
107
+ - Guidance explicitly batches known reads/checks and edits/verification in one
108
+ invocation, and states that the outer deadline includes all waits and commands.
109
+
110
+ ### Internals
111
+
112
+ - 267 package tests (384 repository tests), 2,328 stress invocations, actual
113
+ Pi + OMP host checks, lint and both frozen token gates passed on macOS/Node 26.7.
4
114
 
5
115
  ## [0.8.1] - 2026-09-19
6
116
 
@@ -21,6 +21,44 @@ The benchmark uses js-tiktoken 1.0.21, pinned as a development dependency. It ru
21
21
  real Supernova programs in temporary workspaces without provider calls or downloads.
22
22
  The token regression gate also runs in the normal test suite.
23
23
 
24
+ ## 0.9.0 data-path tuning (2026-09-20)
25
+
26
+ Compared with the preserved pre-tuning 0.9.0 package on Apple M5 Max / Node
27
+ 26.7.0. No provider calls, changed reasoning settings or regenerated token
28
+ snapshots. This improves working-data fidelity and bounded execution; it is not
29
+ an across-the-board latency reduction.
30
+
31
+ | Measurement | Before | After |
32
+ | --- | ---: | ---: |
33
+ | 800-entry directory, median / p95 (60 samples) | 13.179 / 23.356 ms | 8.966 / 12.795 ms |
34
+ | Eight coalesced warm reads, median / p95 (80 alternating pairs) | 1.679 / 2.616 ms | 1.788 / 2.596 ms |
35
+ | Eight unbatched cold reads, median / p95 (same pairs) | 12.719 / 15.057 ms | 13.136 / 15.224 ms |
36
+ | Eight coalesced cold reads, median / p95 (same pairs) | 13.292 / 20.052 ms | 13.818 / 18.546 ms |
37
+ | 200-row report formatting, median (10,000 iterations) | 0.1510 ms | 0.1595 ms |
38
+ | Nested source formatting, median (10,000 iterations) | 0.02523 ms | 0.02480 ms |
39
+
40
+ Directory results have identical full-listing hashes/counts: the median fell
41
+ 32%, p95 45%. Small-read medians instead increased about 3--7%; the new accounting
42
+ adds about 0.009 ms to this small report formatter. Earlier non-interleaved samples
43
+ suggested a warm-read gain, so the table uses alternating measurements rather than
44
+ claiming a noisy speedup. Prewarm and provider time are excluded. Output hashes
45
+ for both formatting fixtures match exactly; these are local samples, not latency
46
+ bounds. Directory acceptance required identical data and lower median time;
47
+ read-wave acceptance required identical complete values and unchanged 8-to-1
48
+ coalescing, with regressions reported rather than hidden.
49
+
50
+ The frozen six-call traffic is now 9,771 / 9,647 tokens (o200k_base / cl100k_base),
51
+ versus 9,813 / 9,689 at the pre-tuning checkpoint. The difference is shorter
52
+ standing guidance, not missing observations. Shared-source/object-input traffic
53
+ is 3,567 / 3,511; every output and all 32 files still match the frozen snapshot.
54
+
55
+ Focused regressions verify the formerly failing full-text/JSON/directory cases,
56
+ 64 two-MiB reads in a Node host capped at 128 MiB, blocked-delivery cancellation
57
+ and follow-up use, bounded billion-character string expansions, sparse returns,
58
+ and complete/partial source-view edit rules. Bun runs the same tests, but its
59
+ heap flags and worker sampling do not provide Node's hard heap enforcement.
60
+ Installed copies were not modified; publication and restart remain separate.
61
+
24
62
  ## Unreleased explicit batch reuse (2026-09-19)
25
63
 
26
64
  **79.82% / 79.92% less traffic on the shared-source/object-input workload, not a