fix(terminal): preserve terminal selection#407
Conversation
📝 WalkthroughWalkthroughДобавлена подсистема для защиты терминального выделения при копировании через кэширование текста выделения перед перерисовками. Реализована подготовка нативного браузерного меню копирования позиционированием скрытого textarea в месте события. Контроллер ChangesSelection snapshot caching and protected contextmenu with native menu
Sequence Diagram(s)sequenceDiagram
participant User
participant Controller as TerminalCopyInteractionController
participant SnapCache as TerminalSelectionContextSnapshot
participant NativeMenu as Native Menu Preparation
participant Terminal as Terminal/xterm
rect rgba(200, 150, 255, 0.5)
Note over User,Terminal: Selection change subscription setup
Controller->>Terminal: subscribe to onSelectionChange
end
rect rgba(255, 200, 150, 0.5)
Note over User,Terminal: Terminal redraw clears live selection
Terminal->>Terminal: redraw occurs
Terminal->>SnapCache: onSelectionChange fires (empty)
SnapCache->>SnapCache: restore() called to fallback to cache
end
rect rgba(150, 255, 150, 0.5)
Note over User,Terminal: Right-click protected contextmenu flow
User->>Controller: mousedown (secondary button)
Controller->>NativeMenu: clearNativeBrowserCopyMenu()
Controller->>SnapCache: refresh() if needed
User->>Controller: contextmenu event
Controller->>Controller: hasProtectedSelectionContext()?
alt Protection required (tracking + selection)
Controller->>Terminal: force selection modifier
Controller->>SnapCache: refresh() if live selection
Controller->>NativeMenu: prepareNativeBrowserCopyMenu()
NativeMenu->>NativeMenu: position textarea at event,<br/>focus, select content
Controller->>Terminal: suppressTerminalMouseReport()
else No protection
Controller-->>User: return (allow native menu)
end
end
rect rgba(150, 200, 255, 0.5)
Note over User,Terminal: Copy via keyboard or native menu
User->>Controller: copy event
Controller->>NativeMenu: clearNativeBrowserCopyMenu()
Controller->>SnapCache: writeToClipboardData()
SnapCache-->>User: clipboard receives snapshot or live text
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related PRs
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error)
✅ Passed checks (6 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/terminal/tests/web/terminal-copy-interaction.test.ts`:
- Around line 241-261: Refactor both test cases to use property-based testing
with fast-check according to the project's testing policy for *.test.ts files.
In packages/terminal/tests/web/terminal-copy-interaction.test.ts (lines
241-261), convert the "suppresses protected context menus without blocking the
native menu" test to use fc.property with invariants that verify when
mouseTrackingMode is not "none" and selectedText length is greater than 0,
context menu suppression occurs without calling preventDefault. In
packages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts (lines
208-230), convert the snapshot-before-contextmenu test case to use fc.property
with invariants that verify for any selectedText value, after clearing
live-selection the snapshot is correctly copied. Both refactored tests should
use Effect test utilities without async/await rather than example-based testing
patterns.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6d9148d1-e796-4c59-bd19-64bc3df03d66
📒 Files selected for processing (3)
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: E2E (OpenCode)
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (Login context)
- GitHub Check: Lint
- GitHub Check: E2E (Clone cache)
- GitHub Check: Test
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: E2E (Browser command)
- GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never useanytype annotation in TypeScript; useunknownonly at SHELL boundaries for decoding, never exportunknownoutside boundary modules
Never useastype assertions in normal code; only permitasin a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through.exhaustive()orMatch.exhaustive()from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation:@pure,@effect,@invariant,@precondition,@postcondition,@complexity,@throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/{browser*,server*,app*,*.ts,*.js}
📄 CodeRabbit inference engine (README.md)
Web version must listen on 0.0.0.0 by default for accessibility across LAN devices
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/{cli*,command*,auto*,*.ts,*.tsx}
📄 CodeRabbit inference engine (README.md)
Implement auto-mode agent selection logic to choose Claude, Codex, Gemini, or Grok randomly from available authorized providers, or allow forced selection with --auto=
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**
⚙️ CodeRabbit configuration file
**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.
МОДЕЛЬ РАССУЖДЕНИЯ:
- Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
(архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).- Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:
- если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
- если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
- код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
- источники указывать только если реально использован внешний материал; иначе
SOURCE: n/a.ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):
- Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.- Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
затем сообщает, что было сделано и как повторить.- Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
Если проверить невозможно — явно фиксирует ограничение и перечисляе...
Files:
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts
🔇 Additional comments (1)
packages/terminal/src/web/terminal-copy-interaction.ts (1)
264-278: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/terminal/src/web/terminal-copy-native-menu.ts`:
- Around line 77-83: The exported function clearNativeBrowserCopyMenu is missing
required documentation according to coding guidelines. Add comprehensive TSDoc
comments above the function declaration that include the mandatory markers `@pure`
(or declare if impure), `@effect` (describing side effects), `@invariant`
(describing invariants), and `@complexity` (describing computational complexity).
Additionally, add functional comments within or before the function body
documenting CHANGE (what changes), WHY (reasoning), REF (references), SOURCE
(where this comes from), PURITY (whether it's pure), EFFECT (specific effects on
the textarea parameter), INVARIANT (any maintained invariants), and COMPLEXITY
(time/space complexity). Ensure the documentation provides clear context about
the function's behavior of clearing the textarea value and its side effects.
- Around line 3-26: The exported types TerminalCopyTextarea and
TerminalNativeCopyMenuHost lack required TSDoc documentation. Add comprehensive
TSDoc comments to both types describing: their purpose and role in the SHELL
layer, the contracts for the focus and select methods, invariants regarding
style mutations affecting DOM elements, and the relationship with native browser
copy menu. Include standard markers like `@pure`, `@invariant`, `@precondition`,
`@postcondition` as appropriate per the coding guidelines requiring comprehensive
TSDoc comments for all public API signatures.
- Around line 58-75: The exported function `prepareNativeBrowserCopyMenu` lacks
required TSDoc and functional documentation despite performing multiple DOM side
effects (style mutations, focus, and select operations). Add comprehensive TSDoc
comments above the function declaration that include `@effect` (to document the
DOM mutations), `@precondition` (validate selection.length > 0, textarea and
screenElement are defined), `@postcondition` (textarea positioned and selected),
and `@complexity` (O(1)). Additionally, add inline functional comments using
CHANGE/WHY/EFFECT/INVARIANT notation to explain each DOM operation sequence
(style assignments, focus, value setting, and select call) and document why each
step is necessary for the native browser copy menu functionality. Document that
this function is intentionally impure and performs coordinated side effects in a
specific order.
- Around line 58-75: The function `prepareNativeBrowserCopyMenu` performs
multiple DOM side effects (textarea style mutations, focus(), select(), and
value assignment) without using the Effect monad, violating the coding guideline
that all effects must use Effect from effect-ts. Refactor the function to return
Effect instead of boolean, wrapping all DOM operations (the textarea style
assignments, focus() call, select() call, and value assignment) using
Effect.sync for synchronous operations, and compose them together using pipe()
and Effect.flatMap() to enable typed error handling, composability, and
testability.
- Around line 35-51: The helper functions optionalNumber and
resolveContextMenuHostScreenElement are missing required TSDoc documentation and
functional comment markers. Add comprehensive TSDoc comments to each function
that include descriptions, parameter and return type documentation, and
mandatory markers including PURITY (specify either CORE or SHELL), mathematical
invariants where applicable, and any other relevant markers such as EFFECT or
COMPLEXITY. The optionalNumber function should document its nullish coalescing
behavior and the resolveContextMenuHostScreenElement function should document
its purpose in wrapping the host element and its null-safety checks.
In `@packages/terminal/tests/web/terminal-copy-interaction.test.ts`:
- Around line 275-276: Line 276 contains a duplicate check of
preventDefaultCalls which duplicates the check from line 275. Change the
expectation on line 276 to verify stopImmediatePropagationCalls instead, as
indicated by the test contract and the previous test at line 256. Replace the
duplicate preventDefaultCalls check with a check for
stopImmediatePropagationCalls.toBe(1) to properly validate that
stopImmediatePropagation was called once.
In `@packages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts`:
- Around line 62-153: Add a required "Proof of Fix" section to your PR
description that documents the bug fix according to coding guidelines. This
section must include three parts: (1) the root cause explaining why the bug
occurred (e.g., why xterm.onSelectionChange was not being called or how live
selection was being lost during redraw), (2) the solution describing what code
changes were made to fix it (e.g., adding subscription to onSelectionChange to
cache selection snapshot), and (3) proof referencing the specific test that
validates the fix, explaining what the test simulates and which assertions would
fail without your fix. Use the test in terminal-copy-redraw-interaction.test.ts
as evidence by referencing its specific line ranges and explaining how it
validates that the selection snapshot remains copyable after terminal redraw
clears the live selection.
- Around line 62-153: The test "keeps selection snapshot copyable after terminal
redraw clears live selection" violates the coding guidelines that require unit
tests to use Effect test utilities without async/await and to write
property-based tests using fast-check to verify mathematical invariants. Replace
the current it() call with it.effect() to use Effect test utilities for setup
and teardown, and add a separate property-based test using fc.assert() and
fc.property() that verifies the invariant: for all non-empty selections, when a
selection change is triggered followed by a redraw that clears the live
selection, the cached selection remains copyable via the clipboard. The property
test should generate arbitrary strings using fc.string() and verify that the
copied text matches the originally selected text, ensuring the snapshot
preservation invariant holds across different inputs rather than just testing
the hardcoded scenario.
- Around line 10-16: The keyboardCopyEvent constant lacks the as const
assertion, which prevents full immutability. Add as const to the end of the
keyboardCopyEvent object declaration to ensure the object is immutable and all
its properties are treated as readonly literals, following the functional
programming paradigm.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 274d8b80-f59f-4559-9d9f-08711dd61e52
📒 Files selected for processing (4)
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: Test
- GitHub Check: E2E (OpenCode)
- GitHub Check: E2E (Login context)
- GitHub Check: Lint
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (Clone cache)
- GitHub Check: E2E (Browser command)
- GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never useanytype annotation in TypeScript; useunknownonly at SHELL boundaries for decoding, never exportunknownoutside boundary modules
Never useastype assertions in normal code; only permitasin a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through.exhaustive()orMatch.exhaustive()from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation:@pure,@effect,@invariant,@precondition,@postcondition,@complexity,@throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts
**/{browser*,server*,app*,*.ts,*.js}
📄 CodeRabbit inference engine (README.md)
Web version must listen on 0.0.0.0 by default for accessibility across LAN devices
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/{cli*,command*,auto*,*.ts,*.tsx}
📄 CodeRabbit inference engine (README.md)
Implement auto-mode agent selection logic to choose Claude, Codex, Gemini, or Grok randomly from available authorized providers, or allow forced selection with --auto=
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
**
⚙️ CodeRabbit configuration file
**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.
МОДЕЛЬ РАССУЖДЕНИЯ:
- Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
(архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).- Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:
- если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
- если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
- код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
- источники указывать только если реально использован внешний материал; иначе
SOURCE: n/a.ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):
- Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.- Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
затем сообщает, что было сделано и как повторить.- Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
Если проверить невозможно — явно фиксирует ограничение и перечисляе...
Files:
packages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/src/web/terminal-copy-interaction.ts
🔇 Additional comments (10)
packages/terminal/src/web/terminal-copy-interaction.ts (8)
1-6: LGTM!Also applies to: 26-28, 45-46, 64-64
186-187: LGTM!
214-214: LGTM!Also applies to: 221-228
231-236: LGTM!
238-252: LGTM!
254-310: LGTM!
319-338: LGTM!
340-362: LGTM!packages/terminal/tests/web/terminal-copy-interaction.test.ts (1)
263-281: Новый тест также нарушает требование property-based testing.Тест добавлен как example-based, хотя coding guidelines требуют property-based тесты через
fc.propertyдля*.test.{ts,tsx}файлов. Также отсутствует использование Effect test utilities.Аналогично комментарию на строках 241-261, этот тест должен быть переписан как property-based инвариант. Например:
- Инвариант:
∀e ∈ ContextMenuEvents: hasProtectedContext(e) → (shiftKey(e) ∧ ¬preventDefault(e) ∧ stopPropagation(e))независимо от значенияbuttonSource: Coding guidelines
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts (1)
18-37: 💤 Low valueУлучшить типизацию test fixture.
Хотя мутабельность в test fixtures допустима, поля
styleи методы можно типизировать более строго для предотвращения ошибок.
| export const prepareNativeBrowserCopyMenu = ( | ||
| { event, host, selection, textarea }: PrepareNativeBrowserCopyMenuArgs | ||
| ): boolean => { | ||
| const screenElement = resolveContextMenuScreenElement(host) | ||
| if (selection.length === 0 || textarea === undefined || screenElement === null) { | ||
| return false | ||
| } | ||
| const screenPosition = screenElement.getBoundingClientRect() | ||
| textarea.style.width = `${terminalContextMenuTextareaSizePx}px` | ||
| textarea.style.height = `${terminalContextMenuTextareaSizePx}px` | ||
| textarea.style.left = `${optionalNumber(event.clientX) - screenPosition.left - terminalContextMenuTextareaOffsetPx}px` | ||
| textarea.style.top = `${optionalNumber(event.clientY) - screenPosition.top - terminalContextMenuTextareaOffsetPx}px` | ||
| textarea.style.zIndex = "1000" | ||
| textarea.focus() | ||
| textarea.value = selection | ||
| textarea.select() | ||
| return true | ||
| } |
There was a problem hiding this comment.
Критическое нарушение: отсутствует обязательная TSDoc и функциональные комментарии.
Экспортируемая функция prepareNativeBrowserCopyMenu выполняет множественные DOM-эффекты (мутации style, focus, select), но не содержит:
- TSDoc с маркерами
@pure,@effect,@invariant,@precondition,@postcondition,@complexity - Функциональных комментариев CHANGE/WHY/REF/SOURCE/FORMAT THEOREM/PURITY/EFFECT/INVARIANT/COMPLEXITY
Согласно coding guidelines, каждая функция с эффектами должна иметь исчерпывающую документацию математических гарантий.
📝 Пример требуемой документации
+/**
+ * Подготавливает нативное браузерное меню копирования через позиционирование и заполнение textarea.
+ *
+ * `@param` args - Аргументы: событие, host, selection текст, textarea
+ * `@returns` true если textarea подготовлен и готов к copy, false если preconditions не выполнены
+ *
+ * `@pure` false - мутирует textarea.style, вызывает focus/select, устанавливает value
+ * `@effect` Мутации DOM: textarea.style.{width,height,left,top,zIndex}, textarea.focus(), textarea.value, textarea.select()
+ * `@invariant` selection.length = 0 ∨ textarea = undefined ∨ screenElement = null → false
+ * `@invariant` selection.length > 0 ∧ textarea ≠ undefined ∧ screenElement ≠ null → textarea позиционирован и focused
+ * `@precondition` event.clientX и event.clientY могут быть undefined
+ * `@postcondition` result = true → textarea.value = selection ∧ focused(textarea) ∧ selected(textarea)
+ * `@complexity` O(1)/O(n) where n = selection.length
+ * `@throws` Never - guard clause возвращает false при нарушении preconditions
+ */
+// CHANGE: позиционирование textarea относительно координат contextmenu события
+// WHY: нативное браузерное меню копирования требует focused textarea с выделенным текстом в точке клика
+// QUOTE(ТЗ): "восстановить нативное меню копирования"
+// REF: issue-404
+// SOURCE: n/a
+// FORMAT THEOREM: ∀e,h,s,t: valid(s,t,screen(h)) → positioned(t,e) ∧ focused(t) ∧ t.value=s
+// PURITY: SHELL
+// EFFECT: DOM mutations on textarea (style, focus, value, select)
+// INVARIANT: empty selection or missing dependencies → early return false
+// COMPLEXITY: O(1)/O(n) where n = selection.length for value assignment
export const prepareNativeBrowserCopyMenu = (
{ event, host, selection, textarea }: PrepareNativeBrowserCopyMenuArgs
): boolean => {
// ...
}Как per coding guidelines: "Provide comprehensive TSDoc comments with mathematical notation: @pure, @effect, @invariant, @precondition, @postcondition, @complexity" и "ОБЯЗАТЕЛЬНЫЕ ТРЕБОВАНИЯ: ФУНКЦИОНАЛЬНЫЕ КОММЕНТАРИИ".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/terminal/src/web/terminal-copy-native-menu.ts` around lines 58 - 75,
The exported function `prepareNativeBrowserCopyMenu` lacks required TSDoc and
functional documentation despite performing multiple DOM side effects (style
mutations, focus, and select operations). Add comprehensive TSDoc comments above
the function declaration that include `@effect` (to document the DOM mutations),
`@precondition` (validate selection.length > 0, textarea and screenElement are
defined), `@postcondition` (textarea positioned and selected), and `@complexity`
(O(1)). Additionally, add inline functional comments using
CHANGE/WHY/EFFECT/INVARIANT notation to explain each DOM operation sequence
(style assignments, focus, value setting, and select call) and document why each
step is necessary for the native browser copy menu functionality. Document that
this function is intentionally impure and performs coordinated side effects in a
specific order.
Source: Coding guidelines
🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift
Существенное отклонение от архитектурных принципов: DOM-эффекты не обёрнуты в Effect monad.
Функция prepareNativeBrowserCopyMenu выполняет множественные побочные эффекты (мутации textarea.style, вызовы focus(), select(), присвоение value), но не использует Effect-TS монаду.
Согласно coding guidelines:
- "Use Effect<Success, Error, Requirements> monad from effect-ts for all effects"
- "Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping"
Несмотря на то, что это SHELL-слой, DOM-эффекты должны быть формализованы через Effect для:
- Типизированной обработки ошибок (focus/select могут выбросить исключение)
- Композируемости через pipe()
- Контролируемого выполнения эффектов
- Тестируемости через мок-зависимости
♻️ Пример рефакторинга с Effect monad
+import { Effect } from "effect"
+
+type PrepareNativeCopyMenuError =
+ | { readonly _tag: "EmptySelection" }
+ | { readonly _tag: "MissingTextarea" }
+ | { readonly _tag: "MissingScreenElement" }
+ | { readonly _tag: "FocusFailed"; readonly cause: unknown }
+
export const prepareNativeBrowserCopyMenu = (
{ event, host, selection, textarea }: PrepareNativeBrowserCopyMenuArgs
-): boolean => {
+): Effect.Effect<void, PrepareNativeCopyMenuError> => {
const screenElement = resolveContextMenuScreenElement(host)
- if (selection.length === 0 || textarea === undefined || screenElement === null) {
- return false
- }
- const screenPosition = screenElement.getBoundingClientRect()
- textarea.style.width = `${terminalContextMenuTextareaSizePx}px`
- textarea.style.height = `${terminalContextMenuTextareaSizePx}px`
- textarea.style.left = `${optionalNumber(event.clientX) - screenPosition.left - terminalContextMenuTextareaOffsetPx}px`
- textarea.style.top = `${optionalNumber(event.clientY) - screenPosition.top - terminalContextMenuTextareaOffsetPx}px`
- textarea.style.zIndex = "1000"
- textarea.focus()
- textarea.value = selection
- textarea.select()
- return true
+
+ return Effect.gen(function* (_) {
+ if (selection.length === 0) {
+ return yield* _(Effect.fail({ _tag: "EmptySelection" as const }))
+ }
+ if (textarea === undefined) {
+ return yield* _(Effect.fail({ _tag: "MissingTextarea" as const }))
+ }
+ if (screenElement === null) {
+ return yield* _(Effect.fail({ _tag: "MissingScreenElement" as const }))
+ }
+
+ const screenPosition = screenElement.getBoundingClientRect()
+ yield* _(Effect.sync(() => {
+ textarea.style.width = `${terminalContextMenuTextareaSizePx}px`
+ textarea.style.height = `${terminalContextMenuTextareaSizePx}px`
+ textarea.style.left = `${optionalNumber(event.clientX) - screenPosition.left - terminalContextMenuTextareaOffsetPx}px`
+ textarea.style.top = `${optionalNumber(event.clientY) - screenPosition.top - terminalContextMenuTextareaOffsetPx}px`
+ textarea.style.zIndex = "1000"
+ }))
+
+ yield* _(Effect.try({
+ try: () => {
+ textarea.focus()
+ textarea.value = selection
+ textarea.select()
+ },
+ catch: (cause) => ({ _tag: "FocusFailed" as const, cause })
+ }))
+ })
}Примечание: Текущая реализация согласована с остальной кодовой базой пакета terminal, которая не использует Effect для DOM-операций. Рефакторинг потребует изменений во всём пакете для единообразия.
Как per coding guidelines: "Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap()".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/terminal/src/web/terminal-copy-native-menu.ts` around lines 58 - 75,
The function `prepareNativeBrowserCopyMenu` performs multiple DOM side effects
(textarea style mutations, focus(), select(), and value assignment) without
using the Effect monad, violating the coding guideline that all effects must use
Effect from effect-ts. Refactor the function to return Effect instead of
boolean, wrapping all DOM operations (the textarea style assignments, focus()
call, select() call, and value assignment) using Effect.sync for synchronous
operations, and compose them together using pipe() and Effect.flatMap() to
enable typed error handling, composability, and testability.
Source: Coding guidelines
| describe("terminal copy redraw interaction", () => { | ||
| it("keeps selection snapshot copyable after terminal redraw clears live selection", () => { | ||
| let terminalSelection = "" | ||
| const keyHandlers: Array<(event: TerminalCopyKeyboardEvent) => boolean> = [] | ||
| const selectionChangeHandlers: Array<() => void> = [] | ||
| const clipboardWrites: Array<{ readonly data: string; readonly format: string }> = [] | ||
| const host = new FakeTerminalCopyScreenHost(100, 200) | ||
| const textarea = new FakeTerminalCopyTextarea() | ||
| const terminal: TerminalCopyInteractionTerminal = { | ||
| attachCustomKeyEventHandler: (handler) => { | ||
| keyHandlers.push(handler) | ||
| }, | ||
| getSelection: () => terminalSelection, | ||
| hasSelection: () => terminalSelection.length > 0, | ||
| modes: { mouseTrackingMode: "any" }, | ||
| onSelectionChange: (handler) => { | ||
| selectionChangeHandlers.push(handler) | ||
| return { | ||
| dispose: () => { | ||
| const handlerIndex = selectionChangeHandlers.indexOf(handler) | ||
| if (handlerIndex !== -1) { | ||
| selectionChangeHandlers.splice(handlerIndex, 1) | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| textarea | ||
| } | ||
| const disposable = attachTerminalCopyInteraction({ host, terminal }) | ||
|
|
||
| terminalSelection = "selected before redraw" | ||
| for (const handler of selectionChangeHandlers) { | ||
| handler() | ||
| } | ||
| terminalSelection = "" | ||
|
|
||
| expect(keyHandlers).toHaveLength(1) | ||
| const handleKey = keyHandlers[0] ?? expect.fail("Expected terminal copy key handler to be registered.") | ||
| expect(handleKey(keyboardCopyEvent)).toBe(false) | ||
|
|
||
| const rightClick = mouseEvent(2, "mousedown", { | ||
| clientX: 150, | ||
| clientY: 260 | ||
| }) | ||
| const contextMenu = mouseEvent(0, "contextmenu", { | ||
| clientX: 155, | ||
| clientY: 265 | ||
| }) | ||
| const copy = copyEvent({ | ||
| setData: (format: string, data: string) => { | ||
| clipboardWrites.push({ data, format }) | ||
| } | ||
| }) | ||
| host.dispatchMouse("mousedown", rightClick) | ||
|
|
||
| expect(rightClick.shiftKey).toBe(true) | ||
| expect(rightClick.preventDefaultCalls).toBe(0) | ||
| expect(rightClick.stopImmediatePropagationCalls).toBe(1) | ||
| expect(textarea.value).toBe("selected before redraw") | ||
| expect(textarea.focusCalls).toBe(1) | ||
| expect(textarea.selectCalls).toBe(1) | ||
|
|
||
| host.dispatchMouse("contextmenu", contextMenu) | ||
|
|
||
| expect(contextMenu.shiftKey).toBe(true) | ||
| expect(contextMenu.preventDefaultCalls).toBe(0) | ||
| expect(contextMenu.stopImmediatePropagationCalls).toBe(1) | ||
| expect(contextMenu.stopPropagationCalls).toBeGreaterThanOrEqual(1) | ||
| expect(textarea.value).toBe("selected before redraw") | ||
| expect(textarea.focusCalls).toBe(2) | ||
| expect(textarea.selectCalls).toBe(2) | ||
| expect(textarea.style).toEqual({ | ||
| height: "20px", | ||
| left: "45px", | ||
| top: "55px", | ||
| width: "20px", | ||
| zIndex: "1000" | ||
| }) | ||
|
|
||
| host.dispatchCopy(copy) | ||
|
|
||
| expect(clipboardWrites).toEqual([{ data: "selected before redraw", format: "text/plain" }]) | ||
| expect(copy.preventDefaultCalls).toBe(1) | ||
| expect(copy.stopPropagationCalls).toBe(1) | ||
| expect(textarea.value).toBe("") | ||
| expect(selectionChangeHandlers).toHaveLength(1) | ||
| expect(handleKey(keyboardCopyEvent)).toBe(true) | ||
|
|
||
| disposable.dispose() | ||
| expect(selectionChangeHandlers).toHaveLength(0) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
Отсутствует обязательная документация Proof of Fix.
Согласно coding guidelines: "Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution".
Хотя тест воспроизводит проблему, в PR description отсутствует обязательная секция Proof of Fix с:
- Причина: корневая причина bug (например, "xterm.onSelectionChange не вызывался перед redraw, live selection терялась без snapshot")
- Решение: что изменено для устранения (например, "добавлена подписка на onSelectionChange для кэширования snapshot перед redraw")
- Доказательство: конкретный тест/прогон, который падал до фикса и проходит после
📋 Пример обязательной документации
Добавьте в PR description:
## Proof of Fix
- **Причина**: При перерисовке TUI (Claude Code redraw) xterm очищает live selection buffer до того, как пользователь может выполнить copy. onSelectionChange не регистрировался, поэтому snapshot не кэшировался.
- **Решение**: Добавлена подписка `terminal.onSelectionChange(() => selectionContext.refresh())` для сохранения snapshot непустого выделения перед любым потенциальным redraw.
- **Доказательство**: Тест `terminal-copy-redraw-interaction.test.ts` → строки 92-96 симулируют selection + onChange + clear; строки 141-143 проверяют, что clipboard получает snapshot "selected before redraw". Тест падал бы без подписки onSelectionChange.As per coding guidelines: "Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts` around
lines 62 - 153, Add a required "Proof of Fix" section to your PR description
that documents the bug fix according to coding guidelines. This section must
include three parts: (1) the root cause explaining why the bug occurred (e.g.,
why xterm.onSelectionChange was not being called or how live selection was being
lost during redraw), (2) the solution describing what code changes were made to
fix it (e.g., adding subscription to onSelectionChange to cache selection
snapshot), and (3) proof referencing the specific test that validates the fix,
explaining what the test simulates and which assertions would fail without your
fix. Use the test in terminal-copy-redraw-interaction.test.ts as evidence by
referencing its specific line ranges and explaining how it validates that the
selection snapshot remains copyable after terminal redraw clears the live
selection.
Source: Coding guidelines
КРИТИЧНО: Тест нарушает обязательные guidelines для тестовых файлов.
Согласно coding guidelines для **/*.test.{ts,tsx}:
- "unit tests must use Effect test utilities without async/await" — тест должен использовать
it.effect()вместо обычногоit(). - "Write property-based tests using fast-check (fc.property) to verify mathematical invariants" — для проверки инвариантов
∀ selection: non_empty(selection) ∧ onChange(selection) ∧ redraw() => cached(selection)требуется property-based test.
Текущая реализация проверяет конкретный сценарий, но не доказывает математические свойства через property-based testing.
🔧 Рекомендуемая структура тестов
1. Property-based тест для инварианта snapshot preservation:
import fc from "fast-check"
describe("terminal copy redraw invariants", () => {
it(
"∀ selection: cached selection survives redraw and copy",
fc.assert(
fc.property(
fc.string({ minLength: 1, maxLength: 1000 }),
(selectedText) => {
// Setup
let terminalSelection = selectedText
const snapshot: string[] = []
const terminal = createMockTerminal(
() => terminalSelection,
(handler) => {
snapshot.push(terminalSelection)
handler()
}
)
const disposable = attachTerminalCopyInteraction({ host, terminal })
// Trigger snapshot
terminal.triggerSelectionChange()
// Simulate redraw clearing live selection
terminalSelection = ""
// Verify copy uses snapshot
const clipboardData = simulateCopy()
expect(clipboardData).toBe(selectedText)
disposable.dispose()
}
)
)
)
})2. Unit тест через Effect test utilities:
describe("terminal copy redraw interaction", () => {
it.effect("keeps selection snapshot copyable after terminal redraw", () =>
Effect.gen(function* (_) {
// Setup через Effect
const { terminal, host, getClipboard } = yield* _(createTestEnvironment)
// Trigger selection change
yield* _(terminal.setSelection("selected before redraw"))
yield* _(terminal.triggerSelectionChange())
// Clear live selection (simulate redraw)
yield* _(terminal.clearSelection())
// Copy should use snapshot
const clipboardData = yield* _(simulateCopyInteraction(host))
expect(clipboardData).toBe("selected before redraw")
})
)
})As per coding guidelines: "unit tests must use Effect test utilities without async/await" и "Write property-based tests using fast-check (fc.property) to verify mathematical invariants".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts` around
lines 62 - 153, The test "keeps selection snapshot copyable after terminal
redraw clears live selection" violates the coding guidelines that require unit
tests to use Effect test utilities without async/await and to write
property-based tests using fast-check to verify mathematical invariants. Replace
the current it() call with it.effect() to use Effect test utilities for setup
and teardown, and add a separate property-based test using fc.assert() and
fc.property() that verifies the invariant: for all non-empty selections, when a
selection change is triggered followed by a redraw that clears the live
selection, the cached selection remains copyable via the clipboard. The property
test should generate arbitrary strings using fc.string() and verify that the
copied text matches the originally selected text, ensuring the snapshot
preservation invariant holds across different inputs rather than just testing
the hardcoded scenario.
Source: Coding guidelines
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/terminal/tests/web/terminal-copy-selection-restore.test.ts`:
- Around line 158-257: Add property-based tests using fast-check to the
terminal-copy-selection-restore.test.ts file to validate invariants beyond the
fixed scenarios currently covered. Following the pattern from
packages/terminal/tests/core/output-buffer.test.ts, add 1-2 fc.property tests
that verify key invariants such as: selection coordinates remain correct after
terminal resize operations, selection length is calculated properly for variable
coordinate ranges, and skip-restore conditions are triggered only under target
conditions (buffer type changes, column count changes, etc.). Use fast-check
generators to vary inputs like row/column coordinates, selection text lengths,
buffer types, and terminal dimensions to ensure the selection restore logic
handles these variations correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1463ebe4-8c7a-4999-aaf3-5e6ae640f61a
📒 Files selected for processing (4)
packages/terminal/src/web/terminal-copy-interaction.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: E2E (Login context)
- GitHub Check: Test
- GitHub Check: E2E (Browser command)
- GitHub Check: E2E (OpenCode)
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: Lint
- GitHub Check: E2E (Clone cache)
- GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never useanytype annotation in TypeScript; useunknownonly at SHELL boundaries for decoding, never exportunknownoutside boundary modules
Never useastype assertions in normal code; only permitasin a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through.exhaustive()orMatch.exhaustive()from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation:@pure,@effect,@invariant,@precondition,@postcondition,@complexity,@throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.ts
**/{browser*,server*,app*,*.ts,*.js}
📄 CodeRabbit inference engine (README.md)
Web version must listen on 0.0.0.0 by default for accessibility across LAN devices
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/{cli*,command*,auto*,*.ts,*.tsx}
📄 CodeRabbit inference engine (README.md)
Implement auto-mode agent selection logic to choose Claude, Codex, Gemini, or Grok randomly from available authorized providers, or allow forced selection with --auto=
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
**
⚙️ CodeRabbit configuration file
**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.
МОДЕЛЬ РАССУЖДЕНИЯ:
- Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
(архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).- Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:
- если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
- если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
- код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
- источники указывать только если реально использован внешний материал; иначе
SOURCE: n/a.ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):
- Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.- Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
затем сообщает, что было сделано и как повторить.- Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
Если проверить невозможно — явно фиксирует ограничение и перечисляе...
Files:
packages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/src/web/terminal-copy-rules.tspackages/terminal/src/web/terminal-copy-selection-snapshot.tspackages/terminal/src/web/terminal-copy-interaction.ts
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/terminal/tests/web/terminal-copy-selection-restore.test.ts (1)
266-279:⚠️ Potential issue | 🟠 Major | ⚡ Quick winПереведите unit-тесты на
it.effect(...)для соблюдения тестового контракта.На Line 266 и Line 281 используются обычные
it(...), что расходится с обязательным правилом для**/*.test.ts. Здесь нужно использовать Effect test utilities (например,it.effect(..., () => Effect.sync(...))) безasync/await.As per coding guidelines, "
**/*.test.{ts,tsx}: ... unit tests must use Effect test utilities without async/await".Also applies to: 281-314
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/terminal/tests/web/terminal-copy-selection-restore.test.ts` around lines 266 - 279, The test functions use regular `it(...)` syntax instead of the required Effect test utilities. Per the coding guidelines for `**/*.test.ts` files, convert all unit tests to use `it.effect(...)` with `Effect.sync(...)` instead of regular `it(...)`. For the test at line 266 "does not restore xterm selection after intentional keyboard input clears the snapshot" and the other test(s) starting at line 281, replace the test callback function body with `Effect.sync(() => { /* test body here */ })` and use `it.effect(...)` instead of `it(...)`, removing any async/await if present.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/terminal/tests/web/terminal-copy-selection-restore.test.ts`:
- Around line 170-194: The test cleanup using harness.disposable.dispose() is
only executed in the happy path, which means if fc.assert or the expect
statement within the fc.property function throws an error, the disposal is
skipped and resources leak into subsequent test cases, causing instability. Wrap
the entire fc.assert call (including the fc.property logic) in a try-finally
block to guarantee that harness.disposable.dispose() is executed regardless of
whether the property-based test passes or fails. This same pattern needs to be
applied at all affected test locations: the main test case with
createSelectionRestoreHarness (starting at the described location), and the two
additional test cases at lines 196-229 and 231-264 that follow the same
structure.
---
Outside diff comments:
In `@packages/terminal/tests/web/terminal-copy-selection-restore.test.ts`:
- Around line 266-279: The test functions use regular `it(...)` syntax instead
of the required Effect test utilities. Per the coding guidelines for
`**/*.test.ts` files, convert all unit tests to use `it.effect(...)` with
`Effect.sync(...)` instead of regular `it(...)`. For the test at line 266 "does
not restore xterm selection after intentional keyboard input clears the
snapshot" and the other test(s) starting at line 281, replace the test callback
function body with `Effect.sync(() => { /* test body here */ })` and use
`it.effect(...)` instead of `it(...)`, removing any async/await if present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0b6cb8b5-8a5c-4830-b139-4f6e6a1a8301
📒 Files selected for processing (5)
packages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-interaction.test.tspackages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: E2E (Clone auto-open SSH)
- GitHub Check: E2E (OpenCode)
- GitHub Check: Lint
- GitHub Check: E2E (Browser command)
- GitHub Check: E2E (Runtime volumes + SSH)
- GitHub Check: E2E (Clone cache)
- GitHub Check: E2E (Login context)
- GitHub Check: Test
- GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files introduce path traversal or writes outside intended project/container state directories
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}
📄 CodeRabbit inference engine (Custom checks)
Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never useanytype annotation in TypeScript; useunknownonly at SHELL boundaries for decoding, never exportunknownoutside boundary modules
Never useastype assertions in normal code; only permitasin a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through.exhaustive()orMatch.exhaustive()from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation:@pure,@effect,@invariant,@precondition,@postcondition,@complexity,@throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/{browser*,server*,app*,*.ts,*.js}
📄 CodeRabbit inference engine (README.md)
Web version must listen on 0.0.0.0 by default for accessibility across LAN devices
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/{cli*,command*,auto*,*.ts,*.tsx}
📄 CodeRabbit inference engine (README.md)
Implement auto-mode agent selection logic to choose Claude, Codex, Gemini, or Grok randomly from available authorized providers, or allow forced selection with --auto=
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
**
⚙️ CodeRabbit configuration file
**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.
МОДЕЛЬ РАССУЖДЕНИЯ:
- Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
(архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).- Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:
- если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
- если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
- код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
- источники указывать только если реально использован внешний материал; иначе
SOURCE: n/a.ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):
- Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.- Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
затем сообщает, что было сделано и как повторить.- Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
Если проверить невозможно — явно фиксирует ограничение и перечисляе...
Files:
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.tspackages/terminal/tests/web/terminal-copy-right-click-interaction.test.tspackages/terminal/src/web/terminal-copy-native-menu.tspackages/terminal/tests/web/terminal-copy-selection-restore.test.tspackages/terminal/tests/web/terminal-copy-interaction.test.ts
🔇 Additional comments (4)
packages/terminal/src/web/terminal-copy-native-menu.ts (1)
3-230: LGTM!packages/terminal/tests/web/terminal-copy-interaction.test.ts (1)
2-3: LGTM!Also applies to: 34-35, 245-280
packages/terminal/tests/web/terminal-copy-right-click-interaction.test.ts (1)
2-2: LGTM!Also applies to: 128-155, 211-239
packages/terminal/tests/web/terminal-copy-redraw-interaction.test.ts (1)
2-2: LGTM!Also applies to: 17-17, 64-154
Source TZ / Issues
Summary
Copyitem available by preparing xterm's hidden textarea from the cached selection before right-click menus open.Requirements Alignment
tmux attach-sessionand covered bypackages/api/tests/terminal-sessions.test.tsassertions fortmux capture-pane,-S -10000, boundedtail -c 1048576, CR conversion, and command ordering before attach.fast-checkproperties interminal-copy-selection-restore.test.tsfor generated coordinates, terminal widths, selected text lengths, and active buffer types.Effect.acquireRelease/Effect.scoped, so harness disposal runs even when an invariant check fails.fast-checkproperties interminal-copy-interaction.test.tsandterminal-copy-right-click-interaction.test.ts.terminal-copy-native-menu.tswith TSDoc, functional markers, pre/postconditions, invariants, and complexity notes.Proof of fix
terminal.select(column, row, length)only if the current buffer shape still matches; otherwise keep the copy snapshot fallback.terminal-copy-selection-restore.test.tsnow includes property-based tests for coordinate restore, column mismatch fallback, and buffer-type mismatch fallback, with guaranteed harness cleanup; fixed examples still cover intentional keyboard clearing.Verification
rtk bun run --cwd packages/terminal lintrtk bun run --cwd packages/terminal typecheckrtk bun run --cwd packages/terminal test— 20 files, 150 testsrtk bun run --cwd packages/terminal buildrtk bun run --cwd packages/api test -- terminal-sessions.test.ts— 1 file, 12 testsRefs #404