# AGENTS.md Operational notes for maintainers and AI agents. Keep changes small and boring. ## Repo shape ``` lib/host.js Host plugin (ESM): stores, HTTP routes, agent/pre-step, log backfill lib/client.js Browser module loaded by window.__ModuleLoader__ (no build step) cordis.patch.yml Profile bundle patch (plugin id: quote-annotation) dsh.plugin.json Release manifest (metadata only; DSH loads package.json) test/host.test.js node:test smoke tests for the Host half ``` There is no bundler and no generated client source: `lib/client.js` is the artifact. Tests use the built-in `node:test` runner, so there is still no dependency to install. ## Runtime model 1. Client selection calls `POST /dsh-quote-annotation/add`. 2. Host keeps a per-session pending list. 3. On the next `agent/pre-step` that contains a direct user message, Host appends a **separate** `user/message` with `source.kind = "conversation-quote"` and `source.references = [{ quote, annotation?, source }]`. 4. Chat hides ordinary context nodes (`isVisibleChatNode`), so the raw context never renders. Do not prepend the prompt to the direct user message. 5. `GET /dsh-quote-annotation/sent` rebuilds sent records from `ctx.sessions.get(id).snapshotEvents()`; the client places pills above matching `[data-chat-flow-kind="user"][data-chat-turn]` flows. ## Inline notes - `sentAnnotations(sessionId)` flattens sent records into a stable `turn:index` key and a session-wide `注释 N` number. - A marker is inserted only into an `assistant-step` flow of the same turn, and only after that turn's `turn-tail` exists (i.e. the turn is complete). Skipping streaming avoids moving the marker as text arrives. - Appends the marker to the end of the paragraph/block containing the quote; no text-node splitting. Fallback is the last paragraph of the reply. - The marker is `