Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/agent-guides/inbox-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
- The catalog: `GET /api/inbox/skills` (`packages/server/inbox-skills.ts`), plan review's `handleReferenceSkills`: the global skill folders only, read fresh. The window installs it as ui's `skillCatalogTransport`, so the comment composers on attached files list it too, and sets `skillInstructionsDestination: 'your reply'` (their human-only line says the instructions go with the reply).
- At Send the window composes ONE block at the end of the message (`packages/inbox/skills.ts`, Option B: the client composes the body, as plan review composes its feedback): references are read from the words and every comment on an attached file the Send carries (not a guided review's diff comments), once each; `renderSkillReferencesBlock` (ui) writes Plannotator's block in "the person … this reply / this message" wording (`@plannotator/core/skill-reference-block`): a model-invocable skill by name, a human-only skill's SKILL.md (read then from `GET /api/inbox/skills/content`, 20,000-character cap, truncation notice, marker lines neutralized) between BEGIN/END markers with `Skill directory:` naming its folder. At most 40,000 characters of instructions per message (`INBOX_SKILL_INSTRUCTIONS_BUDGET`); past it, or unreadable, a skill is named with "read SKILL.md in <dir>". A reply carries the block in its `feedback` (after the annotations' feedback, so it is the body's end; the server is unchanged); a New message appends it to `body`. The per-comment "Skills referenced" list is off in the Inbox (`configurePlannotatorUI({ skillReferenceExport: false })`), so a comment's `$name` stays plain text and the block covers it.
- Trust: only the person's Send composes a block; MCP has no skills field, and an agent's `$readback` is plain text. The window folds a block only under the person's own messages: `MessageBody` splits it off with `splitInboxSkillsBlock`, which takes the LAST Inbox heading (after a blank line) whose tail is exactly the shape the window composes: list lines, then nothing but blank lines and closed BEGIN/END sections for skills the list includes, to the end of the body. The real block is always last, so agent text a reply quotes (a guided-review comment's diff lines, an attached-file comment's `Feedback on:` quote) can never fold the person's feedback, not even with a fake unterminated BEGIN running on to the real END; fence parity is not read, since the agent controls it. Both code exporters (the review app's `exportFeedback.ts` and the Inbox's `guideCommentEntry`) also fence quoted code with more backticks than any run in it (`codeFenceFor`, `@plannotator/core/markdown-structure`; unchanged bytes for code without a backtick run). It draws `SkillsLine` (`components/SkillsLine.tsx`): "Skills: readback, write-better · readback's instructions went with this reply (0.4 KB) · Show", a `<details>` that opens on the block as the agent got it. The references in the sent words are painted as the composer painted them (`skillHighlight.ts`: the CSS Custom Highlight API, `::highlight(ib-skill-ref)` / `ib-skill-ref-human` with the dotted underline, matched against the skills the block names, never the live catalog, only in the person's own words (before the answers or feedback headings), at a priority below search's landing highlight; nothing painted where the API is missing). An agent's message is shown whole.
- Snippets and search read the person's words: `replyWords` and the folded line's snippet (`folding.ts`), and search's `inboxSearchReplyText`, drop the block (the `$name` stays in the words, so search still finds the reply by the skill's name; the SKILL.md text is not indexed for that reply). The stored body, `read_thread`, `wait_for_reply`, the wake and the phone carry the whole text (the accepted cost of Option B).
- Snippets and search read the person's words: `replyWords` and the folded line's snippet (`@plannotator/core/inbox-folding`), and search's `inboxSearchReplyText`, drop the block (the `$name` stays in the words, so search still finds the reply by the skill's name; the SKILL.md text is not indexed for that reply). The stored body, `read_thread`, `wait_for_reply`, the wake and the phone carry the whole text (the accepted cost of Option B).
- Phone (`PHONE_QUERY`): the picker opens full width directly above the reply box (no sheet, so the keyboard stays up and a tap inserts on pointerdown), 44 px rows with the description under the name, at most about 4½ rows.
- On the phone's device door (contract 7.46, 7.47). Tests: `packages/server/inbox-skills.test.ts`, `packages/inbox/skills.test.ts`, the DOM test `packages/inbox/skillReferences.test.tsx` (the whole window over a real Inbox; the DOM server pins the skill folders under the test's scratch HOME).

Expand Down
8 changes: 4 additions & 4 deletions docs/agent-guides/inbox-messages.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/agent-guides/inbox-window.md

Large diffs are not rendered by default.

Loading
Loading