The ReplayConfig.overrideFile JSDoc still described only whole-script
replacement; it now names both sidecar forms and links ReplayOverrideDoc
(config catalog regenerated: source line shifted).
The override sidecar now accepts { patches: [{ at, entry }] } alongside the
legacy whole-script ReplayEntry[] replacement: the JSONL-derived script is
kept and only the named call indexes are swapped (at == length appends, for
a retry attempt following an injected transient throw). Out-of-range or
non-integer indexes fail loud with the derived length in the diagnostic.
This is the mock-LLM error capability the web e2e scenarios drive: 'call N
throws AUTH/SERVER, everything else replays as recorded'.
Regenerate config-catalog for the llm-replay paceMs row; condense the
testing.md web-lane entry to pointer form and raise its ceiling 1020->1060
(the two-sentence tier entry for a genuinely new surface does not fit the
old ceiling after relocation-first trims); internalize two harness helpers
knip flagged (rawSessionLog/normalizeAria are module-internal).
BootHostOptions.llm: 'deepseek' | false — false mounts no adapter, boots
keyless, and leaves the llm capability seam open for the embedder to fill
on RunningHost.ctx (now the third sanctioned ctx use, JSDoc + README
amended); an unfilled seam fails loud with NO_ADAPTER at the first stream.
dsh-llm-replay grows two additive surfaces for the web browser e2e lane:
paceMs (validated per-chunk delay so a real transport shows incremental
delivery; abort during a pace wait cancels promptly) and a ReplayHandle
return — dispose() plus assertConsumed(), the teardown check that every
recorded script bound and drained, converting silent fixture underruns
into diagnostics. Existing callers updated; config catalog regenerated.
Master removed the stdio demo (#702c8cc30) — accept the deletion; this
branch's packChunks passthrough survives in acp-demo (auto-merged), and
cli-demo/tui-demo arrived from master without one (the follow-up snapshot
PR decides which demos expose the switch). Generated catalogs regenerated
over merged sources; the hand-written session.md durability paragraph
re-weaves this branch's lossless-encoding wording with master's invariant-
companion sentence.
Conflicts: the four generated catalog docs (regenerated over merged sources),
session index.ts exports (keep chunk-rows exports + master's SessionSurface
re-export), stdio/acp demo config schema and persistence wiring (thread
packChunks through master's DEFAULT_PERSISTENCE_ROOT/UI shape), stdio README
config table, and the jsonl spec import line. The packed-chunk fixture also
gains the provenance field master made required on assistant/message.
Providers stream token-sized deltas, so a session log stores hundreds of
near-identical assistant/chunk lines whose JSON envelopes dwarf their
payloads (~56x measured on a real DeepSeek session, 73% of file bytes).
Add a lossless storage codec to dsh-session: packChunkRuns() folds each
run of >=3 consecutive same-block delta chunks into one storage row --
text-chunks / reasoning-chunks / tool-call-chunks, bare slash-less tags
like the header line's 'session' so rows cannot be confused with session
events -- and decodeStorageRecord() expands rows back to the exact
original events (seq0/time0 + dt gap array reconstruct every member's
seq/time; tool-call rows carry the run-constant id/name). The encoder
whitelists exact shapes and stores anything unrecognized verbatim; the
decoder validates row-tagged values and fails loud on malformation.
The JSONL backend gains a packChunks config (default false). Writing
packs only when enabled -- default-off output stays byte-identical to
the previous layout, so snapshot goldens are untouched. Reading is
layout-blind: scanLog always decodes rows and now checks seq contiguity
with a cursor instead of the line index, so packed, unpacked, and mixed
files all load identically. Fixture readers (llm-replay parseSessionLog,
acp-snapshot normalizeSessionLog) share the codec; the normalizer zeroes
a row's time0/dt exactly like an event's time. The two demo bundles
plumb packChunks from cordis.yml to the backend.
Measured on a real coding session: 105 KB -> 42 KB (-60%), 475 lines ->
74, with reasoning/tool-call heavy sessions saving the most. Covered by
example + fast-check round-trip codec tests, backend packed/mixed/torn-
tail specs, and an end-to-end demo run loading a packed log through a
default-config backend.
Every packages/*/* README now carries a canonical '## Known Limitations and
Deferred Work' section: condensed, evidence-backed bullets for consumer-visible
gaps (unimplemented features, platform caveats, MVP cuts) and consciously
postponed work (TODO/FIXME/XXX markers, RFC deferrals still open). The ten
pre-existing ad-hoc variants ('What is NOT here (TODO)', 'Deferred',
'Limitations (MVP)', 'Known limitations (tracked TODOs)', ...) are normalized
into the canonical heading.
A new doc-sync gate, scripts/verify-readme-limitations.ts, enforces the shape:
exactly one limitations-like heading per package README, byte-equal to the
canonical h2, with at least one bullet; near-miss headings fail so variants
cannot creep back. Packages with genuinely nothing to declare (dsh-brand,
dsh-timeout, dsh-subagent-mock, dsh-app-boot) are whitelisted in the script and
must NOT carry the section; whitelist entries are validated against the scanned
package set so a rename fails loud.
Wired into the doc-sync chain (package.json) and the run-gates doc-sync leaf
set; the standing rule lands in packages/AGENTS.md and the adding-a-package
cookbook; decision record in
docs/rfc/implemented/process/2026-07-10-readme-known-limitations-gate.md
(RFC index regenerated).
Also fixes two stale '(deferred)' markers claiming dsh-compact-basic is
unimplemented (the dsh-compact seam README's package table and the seam's
module doc comment).