Repository navigation
Decide selection and annotation placement #4
Description
Activity
- addedwayfinder:prototypeDecision explored through a prototype with the developerDecision explored through a prototype with the developer
on Sep 9, 2026 - added a parent issue
on Sep 9, 2026 Prototype checkpoint (decision remains open): a dev-only, in-memory annotation study now runs inside the existing T3 web shell in the active Delta worktree. It compares expanded comments, compact markers, and one-open-discussion layouts. Browser-checked passage selection, comment plus general-context submission, chronological context card with response below, and pending follow-up creation. No provider calls are made by prototype submission. Awaiting CasperEngl’s interaction feedback before recording a resolution or preserving the approved prototype on a throwaway branch. Current limitations: plain-text mock sources rather than production Markdown/diff renderers; no persistence, source-status management, or native mobile validation. Temporary local URLs and pairing credentials are intentionally not stored in this issue.
CasperEngl rejected the initial prototype as visually unlike the supplied Delta screenshot. New explicit requirements: selecting a passage and immediately typing starts its annotation; blurring an empty annotation removes it. Revised the mock to compact source-adjacent comment rows with author markers, highlight treatment, and no nested textarea frame or variant toolbar. Browser-verified that the first typed character is preserved and the editor gains focus, and clearing then blurring removes the empty draft and its highlight. Nonempty comments remain visible on blur. This supersedes the earlier variant comparison; the decision remains open pending visual feedback. Still a dev-only in-memory mock, not production selection/persistence support.
New approved placement requirement from CasperEngl: pending annotation summaries belong at the bottom of the scrollable timeline, not in the sticky submission footer. The user scrolls to the bottom to review them. Updated the prototype accordingly; removed the pending list’s independent height cap/scroll container. The sticky footer contains only general context and submit. Browser DOM inspection confirms pending annotations are outside the footer with no independent scrolling. Decision remains open.
Screenshot clarification from CasperEngl supersedes the previous footer interpretation: the entire submission area, including general-context textarea and submit action, belongs in normal timeline flow directly after pending annotations. No sticky composer/footer. Updated prototype accordingly with a borderless general-context textarea. Browser-verified no footer remains, composer starts below the viewport in the long sample timeline, and scrolling to the bottom reveals it. Decision remains open for feedback.
Keyboard decision from CasperEngl: Mod+Enter inside an annotation submits the complete pending conversation, not just that comment. Enter in the general chat composer submits normally; Shift+Enter adds a newline. Implemented in the mock through the same submission function as the button, including empty-submit and composition/repeat guards. Browser-verified Command+Enter annotation submission, Shift+Enter newline without submission, and Enter general-context submission.
Keyboard requirement refined by CasperEngl: inherit the existing Enter/Mod+Enter submission preference if available, rather than introducing annotation-specific bindings. Found composerSubmissionIntentForEnter in apps/web/src/composer-logic.ts; it currently encodes desktop Enter submission, Shift+Enter newline, and mobile Enter newline, with no preference parameter. Both mock textareas now share a handler using this existing helper. No new preference introduced. Browser-verified Shift+Enter newline and Enter submission from an annotation. The final implementation should honor any actual composer preference present at implementation time.
CasperEngl approved a continuous document-caret model: arrows navigate messages, code, comments and composer; Shift+arrows select read-only content; typing starts an annotation without editing the source. Implemented a first prototype pass using a protected browser editing host for the timeline and boundary navigation into/out of textareas. Browser-verified moving between source blocks, Shift-selection spanning two source messages followed by typing (both excerpts highlighted), source text surviving typing/deletion attempts, moving out of and back into the composer, keyboard submission, and empty annotation cleanup. Remaining prototype limitation: native textarea selection is separate from the read-only document selection; a single Shift-selection spanning source content and editable input is not yet supported. Vertical column preservation, IME and native mobile caret behavior also need further evaluation. These are interaction/architecture questions, not production-ready editor infrastructure. Ticket stays open.
Further decisions from CasperEngl: newly submitted user messages and agent replies must be annotatable; response cards reopen the original annotation for follow-ups; pending excerpt cards open it for add/edit; existing comments continue the same discussion, not nested annotations. Draft inputs, collapsed content and interface metadata remain excluded. Implemented a common message renderer for original and submitted content and verified annotation creation on both newly submitted user text and agent replies, plus reopening the original annotation from a response card. User/assistant labels replaced with user-initial and existing OpenAI icon avatars. Follow-up placement correction: top-level message avatars sit in the left gutter outside the content column, not in a flex column that indents message text. Browser geometry confirms avatar is outside and text stays aligned. Decision remains open.
Cleanup checkpoint: preserved the approved interaction flow while consolidating selection-to-target calculation, normalizing single/multi-message selection ranges, replacing the per-render document key listener with a timeline-scoped React handler, centralizing read-only mutation guards, and using stable IDs for submissions/comments. The prototype route now lazy-loads only in development. Recent approved details retained: open at bottom with context focused; no submitted-count label; bordered user avatars; Mod+Down focuses context; typing at a collapsed source caret annotates the whole message. Verification: targeted formatting/lint clean; 40 composer-logic tests pass; browser regressions cover initial focus/scroll, whole-message and cross-message annotations, empty blur, keyboard submission/newlines, Mod+Down, new-message/reply annotation, response-card follow-up, and independent output collapse/reopen. Web typecheck reports 11 errors only in the pre-existing unrelated providerRefreshFeedback files, not the changed files. No production editor framework or persistence introduced; mixed source-to-textarea Shift-selection and IME/native mobile behavior remain unresolved. Ticket stays open.
Consolidated decisions through the component-reuse handoff
This is the current decision record, combining the approved resolution in #3, the iterations above, and CasperEngl's latest direction. Later clarifications supersede the earlier mock variants and sticky-footer interpretation. This decision stays open. The prototype is not a production replacement.
Product boundary
- The Delta-inspired flow is an improved way to use T3, changing authoring and contextual discussion, not a separate reduced-capability chat app. Existing features, provider capabilities, settings, keyboard paths, and connection modes must remain available.
- Use actual existing components for every content example; fake data is fine. Keep only the experimental annotation/document-navigation layer and timeline layout custom. Reusing a component's shell or colors does not count as reusing its renderer or behavior.
- Reuse leaf renderers rather than substituting the entire production virtualized timeline into the interaction study. Do not duplicate the app's provider/orchestration/draft systems to make the mock appear integrated.
- This is planning and a throwaway, development-only prototype. Submissions are in memory and never call a provider. The inline terminal is the explicit exception: it uses real terminal APIs against the isolated test environment. No production rollout has been approved.
Sources and authoring
- Annotate whole messages or selected passages in user/assistant messages, fenced code, and expanded tool output/diffs within chat. New user messages and chronological agent replies are equally annotatable.
- Select then type to begin an annotation, preserving the first character. Typing with a collapsed caret in source content annotates the whole message. Whole-message annotation remains the fallback where passage selection is impractical.
- Show the highlight and the annotation editor/discussion immediately below the visual line where the selection ends, not beneath the entire message. For a multi-message selection, place it at the final selected source. Preserve the excerpts from all selected messages.
- Opening or typing into an annotation moves only later content. It must not shift earlier content or jump the viewport.
- Empty unsent annotations disappear on blur; nonempty drafts remain. Existing comment/response/pending cards reopen the same annotation for editing or follow-ups rather than creating annotations on annotations.
- Pending comments can be edited, removed, explicitly reselected, and navigated back to. Saving a comment does not send it. Pending cards and inline comments are two views of the same draft.
- Pending summaries followed by optional general context belong at the bottom of the scrollable timeline. No sticky footer, separate pending-list scroller, submit button, general-context placeholder, prototype page header, or submitted-count label. Open at the bottom with general context focused.
- User and provider avatars belong in the left gutter, outside the content column. The user avatar has a border. Reuse provider-aware icons rather than assuming every agent is Codex.
Keyboard and submission
- A continuous document caret navigates visible source, code, comments, context, and blurred terminal transcripts. Arrow keys navigate; Shift+arrows select source without mutating it. Mod+Down focuses general context.
- Interface chrome is not caret content: headers, tool statuses, instructions, button labels, avatars, and errors. Controls still retain native keyboard focus and activation. Collapsed content and draft inputs are not annotation sources.
- Both annotation and general-context inputs inherit the existing composer submission rules, including desktop Enter, Shift+Enter newline, mobile newline, modifier semantics, IME, and repeat protection. Submit the complete pending batch, not one annotation. Do not add annotation-specific settings or bypass current send/steer/queue behavior.
- All pending comments plus optional general context submit as one turn. Comments-only submission works. The response appears chronologically, with a compact excerpt/comment context card followed by the agent response outside it, never inserted back into old source messages.
- Submitted comments are fixed records of what was sent. Corrections are pending follow-ups on the same discussion.
Terminal interaction
!in general context opens a real independent terminal session in this worktree. Each terminal takes focus after startup and keeps its own shell state.- Escape returns to a read-only, caret-navigable transcript. Enter within that transcript re-enters the same live terminal. Terminal text is not an annotation source.
- Delete/Backspace within a blurred transcript closes and removes only that terminal. Sending a turn must preserve terminal identity, mount, position, and shell session.
- The existing terminal drawer and add-terminal-context feature must not be lost when adding this authoring shortcut. Literal punctuation and normal composer editing must remain possible.
Durable behavior approved in #3, not implemented by this prototype
- Pending annotations survive reloads and synchronize across devices.
- Already-visible streaming content may be annotated without stopping the active turn; preserve the selected excerpt. Sending while a turn runs follows T3's existing behavior.
- Preserve original excerpts. Show Source changed or Source unavailable instead of silently relocating the annotation or declaring it useless. Explicit pending reselection updates the excerpt and restores current-source status.
- Submitted annotations allow follow-up corrections, hiding at source, and new annotations on current content while retaining historical submissions and replies.
- Rewinds discard annotation submissions with discarded turns. Exact history/rewind edge cases remain for Decide history and rewind semantics #8.
- Eventual web, desktop, and mobile support uses shared behavior and separate client implementation tasks. Local, remote/relay, tunnel, multi-device, and multi-environment behavior are acceptance requirements.
- First version excludes automatic relocation, resolve/reopen workflows, and standalone file previews outside chat. Existing file-review and preview annotations are not removed or forcibly converted into this new discussion type.
Still open, not silently accepted as limitations
- Native selection across read-only sources and editable inputs, vertical caret-column preservation, IME, touch/mobile access, overlapping selections, streaming/reflow, and collapsed-source restoration require integrated proof.
- Rich Markdown source-to-rendered-text mapping, code-line insertion, and Pierre's shadow-DOM diff selection need renderer-specific integration. Slicing raw Markdown or mutating React-owned text nodes is not an acceptable shortcut.
- Draft identity/ownership, server persistence, submission transactions, provider delivery and reply association, source changes, rewind, and client delivery remain in Decide annotation identity and source changes #5–Decide client delivery boundaries and acceptance criteria #9. No storage schema or provider protocol has been approved.
- A real editor component alone does not bring the container's attachments, mentions/commands, approvals, tasks, drafts, controls, or send pipeline. Those must be audited and integrated before calling this an improved replacement for normal sessions.
Terminal deletion clarification
CasperEngl clarified that terminals behave like one document item for deletion, even when the caret is outside the terminal:
- Backspace immediately after a terminal removes it when there is no preceding text to delete in the current input. Delete immediately before it removes the next terminal.
- Existing text, selected draft text, and actual newlines are deleted first. A caret at the start of a nonempty following input may remove the terminal while preserving all text after the caret.
- Remove only the adjacent terminal and keep an outside caret where it was. A live viewport still counts as a terminal item when the caret is elsewhere.
- Backspace/Delete inside the live shell keep their normal shell behavior. Deleting from the blurred transcript remains supported.
Implemented in the development-only prototype with one timeline-level deletion handler and one shared terminal-close path. Arrow navigation and deletion share the same text-boundary check. Repeated requests for the same pending close are deduplicated; a failed close keeps the terminal visible.
Verification: reproduced the original failure from the empty context following a terminal, then verified native keyboard deletion in both directions, text/newline precedence, preserving text and caret after the deleted terminal, selected-text handling, two independent terminals, live-viewport adjacency, and unchanged live-shell/blurred-transcript behavior. Synthetic collapsed DOM ranges also exercise the bare block-boundary resolver. Every terminal created for this pass was closed through the app.
91 focused editor/composer/terminal tests passed; targeted lint, formatting and whitespace checks passed. Web typecheck still reports only the same 11 unrelated provider-refresh errors. This pass changes only the prototype; no normal chat, provider, contract, desktop-native or mobile implementation changed. #4 remains open, including the previously recorded mobile Send-action question.
Further interaction decisions approved with CasperEngl
This records CasperEngl's replies in the live planning discussion. It supplements the consolidated interaction record and the terminal deletion clarification. This ticket remains open; this is not a final resolution or rollout approval.
Approved
- Touch annotation entry: Preserve native long-press selection and offer Comment in its selection actions. Offer Comment on message in the message menu as the whole-message path. Both actions must be keyboard and screen-reader accessible. Select-and-type remains the desktop shortcut.
- Mobile submission: Retain an explicit Send action on mobile while keeping the button-free desktop layout. It submits all pending comments plus optional general context, not only the focused comment. The composer remains in normal timeline flow, not sticky. This resolves the previously recorded conflict between mobile Enter-as-newline and the absence of a touch-only submission action.
- Repeated and overlapping passages: Selecting the exact same passage reopens its discussion: edit an existing pending comment or add a pending follow-up to an already submitted discussion. A different, overlapping passage starts a separate discussion. Do not merge discussions automatically. Identical text at another source location is a different passage. Durable source identity remains for Decide annotation identity and source changes.
- Selection boundaries: Ordinary arrow navigation crosses between source and editable inputs, but selection extension stops at editable-input and terminal boundaries. Selection can span multiple source messages. A single typing/deletion gesture must not ambiguously annotate source and replace draft text. This is an explicitly approved interaction boundary, not an accidental prototype limitation.
- Streaming and reflow: Keep the comment attached to the original selected passage's ending visual line, not the end of a growing message. Preserve the active caret and reading position rather than snapping to new output. Selecting or writing pauses automatic following of new output; returning to the bottom resumes it.
Correction: annotations remain visible beside collapsed sources
CasperEngl explicitly corrected the proposed collapse behavior: the annotation should still be shown near the collapsed bit. Collapsing the source must not hide its annotation or replace the annotation with only an indicator. Pending drafts remain preserved and represented in the pending area.
The earlier proposal to hide inline discussions when their source collapses is rejected. The precise placement and whether opening a comment should expand its source still need confirmation; do not treat the rest of that proposal as approved.
Follow-on questions
- For a collapsed source, should annotation rows sit immediately below its collapsed header and remain editable there, with a separate Show source action to expand the source instead of expanding it on every comment interaction?
- When distinct discussions end on the same visual line, should they remain separate stacked rows, ordered by source endpoint and then creation order, while the highlight itself stays ordinary selectable source text rather than opening an ambiguity picker?
Evidence still owed
This update records decisions only; it does not implement or newly verify them. Production Markdown, code, tool-output and diff renderer reuse is unfinished. IME, vertical caret movement, touch access, collapsed-source behavior and streaming/reflow still need integrated proof. The existing-feature preservation audit remains applicable. No prototype gap is silently accepted as a production limitation.
Resolution: selection and annotation placement
Approved with CasperEngl through the prototype iterations and the live decision discussion. CasperEngl has now approved the last two follow-on choices: editing annotations beside collapsed sources without automatically expanding those sources, and stacking distinct discussions that end on the same visual line.
This is the final interaction contract for this ticket and supersedes conflicting earlier proposals here, particularly the sticky footer, hiding annotations when their source collapses, and the absence of a mobile Send action. It inherits the product boundaries in Confirm the first-version annotation experience.
Sources and starting a comment
- Support whole-message and passage annotations on user and agent messages, fenced code, and expanded tool output/diffs within chat. Newly submitted user messages and chronological agent replies are equally annotatable. Whole-message annotation is the fallback where passage selection is impractical.
- Selecting source and typing starts its annotation, preserves the first character, and focuses the comment editor. Typing with a collapsed source caret starts a whole-message annotation without editing the source.
- On touch devices, retain native long-press selection and offer Comment in its selection actions. Offer Comment on message in the message menu. These actions must also be keyboard and screen-reader accessible; select-and-type remains the desktop shortcut.
- Draft inputs, terminal text, collapsed content and interface metadata are not passage-annotation sources. Existing comment and response cards continue their original discussion instead of creating annotations on annotations.
Placement, repeated passages and overlap
- Highlight the selected passage and put its annotation immediately after the visual line where the selection ends, not beneath the whole message. A multi-source selection preserves all selected excerpts and places the annotation at the final selected source.
- Opening or typing in an annotation moves only later content, without shifting earlier content or jumping the viewport.
- Selecting the exact same passage reopens its discussion: edit its pending comment or add a pending follow-up if already submitted. A different, overlapping passage starts a separate discussion. Never merge discussions automatically. Identical wording elsewhere is a different passage.
- When distinct discussions end on the same visual line, stack separate annotation rows below it, ordered by passage endpoint and then creation order for ties. Highlights remain ordinary selectable source text, not click targets that open an ambiguity chooser. Annotation rows and pending cards open their respective discussions.
Collapsed sources
- Collapsing a source does not hide its annotations or replace them with only a badge. Keep annotation rows immediately below the collapsed header, with pending drafts preserved and still represented in the pending area.
- Opening or editing an annotation continues the discussion there without automatically expanding the source.
- A separate Show source action expands the source and reveals its highlighted passage. Unrelated collapsed content stays closed.
Drafts and the timeline
- Empty unsent annotations disappear on blur; nonempty drafts remain. Inline comments and pending cards are views of the same draft. Pending comments can be edited, removed, explicitly reselected, and navigated back to, as agreed in the first-version experience.
- Submitted comments remain fixed records of what was sent. Corrections are pending follow-ups on the same discussion.
- Pending summaries followed by optional general context belong at the bottom of normal timeline flow. No sticky composer, separate pending-list scroller, general-context placeholder, prototype page header or submitted-count label. Open at the bottom with general context focused.
- Desktop stays button-free. Mobile retains an explicit Send action. Neither surface restores a sticky submission area.
- User/provider avatars stay in the left gutter, outside the content column. The user avatar has a border. Reuse provider-aware icons.
- Submission sends the complete pending batch plus optional general context as one turn; comments-only submission works. The response appears chronologically, with a compact excerpt/comment context card followed by the agent response outside it, not inserted into old messages.
Keyboard and streaming
- A continuous document caret navigates visible source, code, comments, general context and blurred terminal transcripts. Ordinary arrows cross between source and editable inputs, but selection extension stops at editable-input and terminal boundaries. Source selection can span multiple source messages.
- Headers, statuses, instructions, button labels, avatars and errors are not caret content. Controls retain their native keyboard focus and activation.
- Mod+Down focuses general context. Annotation and general-context editors inherit the existing composer submission rules and any actual composer preference, including Shift+Enter, mobile Enter-as-newline, modifier behavior, IME and repeat protection. No annotation-specific submission setting or bypass of existing send/steer/queue behavior.
- Visible streaming content remains annotatable without stopping the turn. Preserve the selected excerpt. During streaming/reflow, keep the annotation attached to that passage's ending visual line, not the end of the growing message.
- Preserve the active caret and reading position instead of snapping to new output. Selecting or writing pauses automatic following of new output; returning to the bottom resumes it.
Terminals as document items
!in empty general context opens an independent real terminal in the worktree and focuses it after startup. Ordinary punctuation and composer editing remain possible. Preserve the existing terminal drawer and add-terminal-context feature.- Escape returns to a protected, caret-navigable transcript. Enter inside that transcript re-enters the same live shell. Terminal text is not annotatable.
- Backspace immediately after, or Delete immediately before, a terminal removes that adjacent terminal when no text/newline in the current input takes precedence. Selected draft text is deleted first. A caret at the start of a nonempty following input may remove the terminal while preserving text after the caret.
- Remove only the adjacent terminal and preserve an outside caret. A live viewport still counts as one terminal item when the caret is elsewhere. Deletion from inside the blurred transcript also removes that terminal; Backspace/Delete inside the live shell retain shell behavior.
- Sending a turn must preserve terminal identity, mount, order and shell session.
Reuse and preservation constraints
- This improves T3 authoring; it is not a reduced-capability replacement app. Existing features, settings, entry points, providers and connection modes must remain available.
- Use existing production content components for every prototype content example; fake data is acceptable. Only the experimental annotation/document-navigation layer and timeline layout stay custom. Reusing a shell or colors does not count as renderer reuse.
- Reuse leaf renderers rather than replacing the prototype with the entire virtualized timeline. Do not duplicate provider, orchestration or draft systems. Do not implement rich source selection by slicing raw Markdown or mutating React-owned source DOM.
Evidence and remaining work
This closes the interaction decision, not the implementation, feasibility investigation or rollout gate. No code changes or new verification runs were made while recording this resolution.
The existing study remains DEV-only and in-memory, with fake submissions and no provider calls. Its real terminals use the isolated test environment. Its code remains uncommitted in the active Delta workspace; no durable prototype branch has been published.
Existing evidence is recorded in the prototype/component-reuse checkpoint and the terminal deletion verification. The last approval round records the touch, mobile submission, selection-boundary and streaming choices. These are not evidence that every approved behavior already works.
- Decide annotation identity and source changes still owns durable targeting and mapping to the actual Markdown/code/tool/diff renderers. Rich-renderer and shadow-DOM selection feasibility is unproven, not waived by this resolution.
- Decide draft ownership and submission, Decide agent context and reply association, and Decide history and rewind semantics remain unresolved. No storage schema, transaction model or provider protocol is approved here.
- Decide client delivery boundaries and acceptance criteria retains the existing-feature preservation audit and the obligation to distinguish confirmed behavior from outstanding proof: actual renderer reuse, IME/vertical caret behavior, selection boundaries, touch/mobile access, overlap/collapse, streaming/reflow, accessibility, performance and multi-surface/connection-mode coverage.
If the remaining investigations expose a conflict with this interaction contract, bring it back for an explicit decision. Do not silently turn a prototype gap into a product limitation.
Question
How should selection, highlights, nearby comments, expandable discussions, and pending cards behave across prose, code, and expanded tool output/diffs?
Use the approved first-version experience as the constraint. Explore a cheap prototype with CasperEngl, including whole-message fallback, repeated/overlapping selections, collapsed content, streaming, keyboard access, and mobile selection. Do not implement production UI. Obtain permission before browser/computer use. Record approved interaction decisions and link any temporary prototype evidence.