web_search now registers each result as a WEB_RESULT (locator {url}) and
renders a <web_results> block of <document view="excerpt"> [n] passages,
returning Command(update={messages, citation_registry}) like
search_knowledge_base. Collapse the duplicate research-subagent web_search
into the shared tool and teach the prompts to cite web hits with [n].
The main agent's search_knowledge_base tool runs the hybrid spine, renders
a <retrieved_context> of numbered [n] passages, and persists the registry.
KB subagent prompts teach citing [n] from <document view="full"> reads
(evidence.chunk_ids -> evidence.citations). Delete the now-unused
search->read highlighting hand-off: the kb_matched_chunk_ids state field,
its reducer default, the tool's _matched_chunk_ids writer, and the dead
KnowledgePriorityMiddleware writes.
Add the checkpointed CitationRegistry (load/merge helpers + state field)
and a lightweight CitationStateMiddleware so subagents can register into
the same conversation registry. Resolve [n] -> [citation:<payload>] at
stream finalize from the registry, polymorphically by source type.
Add a shared document_render package that renders sources as
<document view="excerpt|full"> blocks with server-assigned [n] passage
labels (KB locator {document_id, chunk_id}, web locator {url}). Wire the
KB read backend (kb_postgres) and read_file to the new renderer and drop
the legacy per-document XML renderer (document_xml, retrieved_context) and
the old chunk_index / matched="true" / <chunk id> read format.
Mermaid diagram rendering was wired up upstream but the package was never
declared, breaking the dev build ("Module not found: Can't resolve
'mermaid'"). Add it to package.json and lock it.
The composer cleared the live mention atom synchronously on send (via the
editor reset), which raced the async onNew handler that read it — dropping
every @-mention (docs, folders, connectors, and the new chat references)
from the request.
handleSubmit now snapshots the chips before clearing, and onNew consumes
that snapshot (falling back to the live atom for the send-button path),
derives the payload via deriveMentionedPayload, and sends mentioned_thread_ids.
Add a Chats tab to the mention picker (excluding the current chat), carry
the "thread" kind through the inline editor's chip nodes, and render thread
chips on user messages with navigation to the referenced conversation.
Add the "thread" mention kind (makeThreadMention + stable dedup key) so a
chat can be referenced like a document. Also introduce submittedMentionsAtom
and a pure deriveMentionedPayload() helper, the building blocks for capturing
chips at submit time and mapping them to backend payload buckets.
Mirror search_threads visibility in the referenced-chat resolver: a
search-space owner can now @-mention legacy threads that predate creator
tracking (null created_by_id), instead of those being silently dropped.
Add unit tests for role-specific turn extraction in the resolver and for
the transcript renderer: full rendering within budget, dropping oldest
turns with a marker, partial-tail fill of an overflowing turn, and
multi-chat tagging.