Replace the hand-written inventory with scripts/gen-third-party-notices.ts,
verified fresh by a doc-sync leaf gate. Tier by declaring workspace area
rather than manifest section, so test-support runtime declarations stay
dev-only and every mountable plugin's dependencies are disclosed as
runtime; list the pnpm-patched packages; point the Python closure at
uv.lock. Re-record the translation-prompt snapshot the README link
invalidated.
Keep only groups with another path in the active round. This bounds skewed sampling by paths visited instead of rescanning every singleton for every late-group item.
The Note's pre-release-stance link used the wrong depth and target
(../../../CLAUDE.md); point it at ../../../../AGENTS.md with the section
anchor so verify-md-links passes. The presentResult decline test's meta
lacked the now-required offset, so it declined at meta narrowing instead of
exercising the content-shape decline (read.ts:181-183); add offset back.
- built-boot smoke asserts [data-variant=web][data-tool=web_search/fetch]
(the keyed WebRow) instead of [data-web] (which WebBlock draws even on the
GenericToolCard fallback, so a silent keyed-registration failure passed).
- WebBlock renders an explicit empty-state note when a search returns no
answer and no sources, instead of a blank <ol>; the chat row does not
surface the raw result content, so the backend's 'No results found.' was
otherwise invisible.
- README (ui-conversation, ui-primitives) and the frontend Agent Note record
the unknown-web-kind null arm, the details-panel flattened body, and the
empty-search copy; pairings re-recorded.
The coverage lane flagged transcript.ts line 63 (diffContentLines' empty-text
return) uncovered: the same-file diff test only fed newline-terminated sides.
Add a third hunk removing a line with an empty added side (a full deletion), so
the empty arm runs and the footer proves the empty side draws no `+ ` row
(+2 -1 · 1 file). Raise the test's line budget so every hunk row stays visible.
boot() asserts over ctx.loader after awaiting the Loader, but the TUI renders
as soon as its own fiber starts: an /exit typed before the last entry settles
runs disposeRootAndExit, which takes the Loader service with the tree. The
assertions then read undefined and crashed the process with a TypeError over
an app that exited exactly as asked. The keyless personal-overlay PTY smoke
lost this race in roughly two of three runs.
An empty read window (byte cap below the first selected line: `lines: []`
with `totalLines > 0`) dropped `offset` from the persisted presentation
meta, so a replayed read card could not report where the window starts or
where a continuation resumes. Carry `offset` on `FsReadMeta`,
`ReadResultView`, and the `presentationMeta` projection, and validate it in
`readMetaFromMeta` (1-based integer; the first line number may not fall
below it). Re-record the ACP fixtures and the cordis api catalog.
Also correct the Note's `parallel-file-reads` golden path
(examples/tui-agent -> apps/cli) and record the pre-card replay-degradation
tradeoff in the Decision section.
Address the review of the search render card:
- The search result view carries no `content`: it was a no-op for every
consumer and serialized the whole search text twice. A UI without a search
card falls back to the raw tool/result content; the TUI stays byte-identical
to the pre-search-card generic fallback.
- Bound the serialized presentationMeta with a configurable searchMetaMaxBytes
(default 64 KiB): the inline item cap does not bound bytes, and spill-policy
only shrinks content, never meta. capMetaBytes drops trailing groups/paths.
- Share one retention pass (retainGrepMatches/retainGlobPaths in search-core)
between the model-facing render and the meta projection; remove the second
cap/preview implementation and the presentation<->grep module cycle by
moving GrepMatch/previewLine to search-core.
- Rename the result-view discriminant kind -> shape so it no longer collides
with GenericCallView.kind (ToolCallKind, whose values include 'search').
- Narrow the entry export surface to consumed symbols.
- Sync the three bilingual ToolResultView doc pairs and the Agent Note pair;
document the deliberate empty-card acceptance vs diffsFromMeta.
- Regenerate config/tool/cordis catalogs for the new config field.
The web_search execute result and searchMetaFromValue each spread the
same {url, title?, snippet?, publishedAt?} projection over a seam source,
which the duplication gate flags as a clone. Extract projectSource, typed
on the seam's WebSearchSource, so both sites carry a byte-identical shape
from one definition.