Skip to content

[issues/592] Prevent extension-managed pty terminals from being offered as bindable destinations#595

Merged
couimet merged 16 commits into
mainfrom
issues/592
May 20, 2026
Merged

[issues/592] Prevent extension-managed pty terminals from being offered as bindable destinations#595
couimet merged 16 commits into
mainfrom
issues/592

Conversation

@couimet
Copy link
Copy Markdown
Owner

@couimet couimet commented May 20, 2026

Summary

The R-D bind picker, the terminal context menus, and the "Bind to Terminal" command all used to treat Jest watchers, task runners, and other extension-managed pty terminals as valid bind destinations. Sending text to them is meaningless because they only accept structured Pseudoterminal output, not arbitrary shell input. This branch hardens every entry point: pty terminals are filtered out of the picker, the context-menu "Bind Here" entries are hidden via a new context key, and the command handler rejects direct invocations with a clear error message.

Late iteration replaced the original "not bindable" badge with VS Code-native filtering (matching how the file picker omits non-text files), and harmonized the error messages around the "bindable" vocabulary that the codebase already uses for context keys and helpers.

Changes

  • Classification helperclassifyTerminalForBinding(terminal) returns a tagged union ({ visible: false } | { visible: true, nonBindableReason? }). Drives both the picker filter and the menu-visibility context key from one place.
  • Picker filteringgetEligibleTerminals excludes any terminal where the classification carries nonBindableReason. Downstream code paths (R-D unified picker, "Bind to Terminal" command, R-D secondary picker) see only bindable terminals, so the terminal section is omitted entirely when no shell terminals are open.
  • Menu visibility — new context key rangelink.isActiveTerminalBindable maintained by wireActiveTerminalBindabilityContext, subscribed to onDidOpenTerminal / onDidCloseTerminal / onDidChangeActiveTerminal. The terminal/title/context and terminal/context bind entries gain a when clause that reads this key.
  • Command guardsBindToTerminalCommand rejects non-bindable terminals on the context-menu (preferredTerminal) path with BIND_TO_TERMINAL_NOT_BINDABLE_REJECT. The picker-side single-non-bindable branch is unreachable after filtering and was deleted.
  • Error message vocabulary — added ERROR_NO_BINDABLE_TERMINAL ("No bindable terminal. Open a new terminal and try again.") used by BindToTerminalCommand when no bindable terminals remain. Renamed ERROR_NO_ACTIVE_TEXT_EDITORERROR_NO_BINDABLE_TEXT_EDITOR ("No bindable text editor. Open a file and try again.") so the toast is accurate when an image viewer or webview is focused. ERROR_NO_ACTIVE_TERMINAL is preserved for TerminalSelectionService, which is genuinely about focus, not eligibility.
  • Integration teststerminal-picker-014 (filtered out of R-D), terminal-picker-015 (context-menu reject), terminal-picker-016 (R-D terminal section absent when only a pty is open). Four assisted TCs context-menus-terminal-006009 cover the menu-visibility when clause: 006/007 verify "Bind Here" is absent on pty tab and content menus (verdict-based); 008 verifies the when clause is not overly broad by having the human bind via the shell's tab and checking log-side that the shell — not the pty — was bound (action-based, mirroring 005's pattern); 009 verifies the pty content menu shows "Unbind" but not "Bind Here" when something else is bound, proving Unbind rides on rangelink.isBound and not on bindability.
  • Documentation: CHANGELOG bullet added to the Terminal Picker feature description (this filtering is part of that new feature's scope, not a fix against pre-existing behavior — the Terminal Picker itself is new in [Unreleased]). README: not needed — context menus and bind commands are documented at the user-action level, no new commands or settings.

Key discoveries

  • VS Code exposes no isReadOnly / acceptsInput property on Terminal. The only structurally stable signal for "extension-managed" is the presence of creationOptions.pty (i.e., the terminal was created via ExtensionTerminalOptions). isTransient is not reliably set by task runners; shellIntegration is positive but incomplete.
  • VS Code when clauses cannot read creationOptions.pty directly, so menu visibility required a custom context key wired through terminal lifecycle events.
  • Mid-implementation realization: the "not bindable" badge was a learning surface VS Code does not impose elsewhere (file picker filters PNG, command palette filters unavailable commands). Switching to filtering removed the badge concept, simplified the picker pipeline, and brought UX in line with platform conventions.
  • The original ERROR_NO_ACTIVE_TEXT_EDITOR was misleading for image viewers: a PNG IS an active editor, just not a text editor. The "bindable" framing matches the existing isActiveTerminalBindable context key and the classifyTerminalForBinding helper, making vocabulary coherent end-to-end.

Test plan

  • All 110 unit suites pass (1947 tests)
  • QA coverage validation passes (150 automated, 117 assisted)
  • Targeted integration run for terminal-picker-014, terminal-picker-015, terminal-picker-016, bind-to-destination-010, bind-to-destination-013 — all green
  • Full automated integration suite: pnpm test:release:automated
  • Assisted run for the four new context-menu TCs: pnpm test:release:grep "context-menus-terminal-006|context-menus-terminal-007|context-menus-terminal-008|context-menus-terminal-009" --assisted

Related

Summary by CodeRabbit

  • Bug Fixes

    • Terminal picker now excludes extension-managed pseudo-terminals so only shell terminals can be targeted.
    • “RangeLink: Bind Here” appears only when the active terminal is bindable.
    • Error/toast messages clarified when attempting to bind non-bindable terminals or when no bindable files/terminals exist.
  • New Features

    • Active-terminal bindability is tracked so picker and menu visibility stay accurate.

Review Change Stack

couimet added 14 commits May 19, 2026 16:22
…bility bug

Locks the post-fix contract for the issue #592 bug as a red integration test before any production code changes. The pty terminal is spawned via an inline minimal Pseudoterminal alongside a shell terminal that takes active focus, so the assertion covers both the pty case AND a negative-control regression on the shell case (catches a future over-filter blocking legitimate shells).

Today the test fails on `description: undefined` and `nonBindableReason: undefined` for the pty entry. The shell entry validates as expected. Subsequent steps (S1 classification + S2 badge) flip the pty fields to `'not bindable'` and `'extension-managed'` and turn the test green.
…nd arg typed as `Omit<...TerminalOptions, 'name'> | Omit<...ExtensionTerminalOptions, 'name'>`, spread into the call. All existing one-arg call sites compile unchanged and the existing automated `terminal-picker-*` tests pass. The pty terminal now flows through the standard tracking + teardown path, eliminating the try/finally + manual dispose the test would otherwise need.
…rned during this spike: the `:grep` script does not accept `--` before the pattern, and it does not filter assisted tests on its own. The targeted-command guidance now spells out `pnpm test:release:grep "<pattern>" --exclude-assisted` and explains why the flag is required.
`ss.createCapturingTerminal` already enrolls the underlying terminal in the suite-level `tmpTerminals` array, which `SsContextImpl` disposes on `teardown` after each test. The `try { ... } finally { capturing.terminal.dispose(); }` wrapper around 16 dirty-buffer-warning tests was therefore double-cleanup. Removing the wrapper flattens each test body and eliminates a misleading hint that the dispose was load-bearing.

One try/finally is preserved because it restores the `files.trimTrailingWhitespace` workspace config — that is real cleanup that cannot be deferred to teardown without leaking state into the next test.

Verified: the four automated dirty-buffer-warning TCs (004, 006, 007, 019) still pass under `--exclude-assisted`. The 13 assisted TCs in the same file weren't run as part of this verification but the change is mechanical (no logic touched).
Introduces `classifyTerminalForBinding(terminal)` returning `{ visible: false }` (exited, hideFromUser, null/undefined) or `{ visible: true, nonBindableReason? }`. Extension-managed pty terminals (Jest task runner, debug consoles, etc.) now get `nonBindableReason: 'extension-managed'` instead of being silently treated as bindable. The single boolean `isTerminalEligible` is removed in favour of the richer classification — only one caller existed, so no compatibility shim is kept.

`EligibleTerminal` and `TerminalBindableQuickPickItem` both grow an optional `nonBindableReason: NonBindableReason` field that flows from `getEligibleTerminals` through `DestinationAvailabilityService.buildTerminalItem` and `buildTerminalPickerItems` to the final QuickPick item. `VscodeAdapter.showQuickPick`'s log projection is extended to surface the field so integration tests can assert on it.

The structural signal for "extension-managed" is the presence of `creationOptions.pty` (i.e. the terminal was created via `ExtensionTerminalOptions`). VS Code exposes no `isReadOnly` / `acceptsInput` property, and `isTransient` is not reliably set by every task runner, so `pty` is the most stable distinction available. Capturing pty terminals used in integration tests are also caught by this rule — S4 will neutralize that by marking them `hideFromUser: true`.

`nonBindableReason` is also surfaced at the top level of `TerminalBindableQuickPickItem`, mirroring the existing pattern for `isActive` and `boundState`. This is duplication that `VscodeAdapter.showQuickPick`'s log projection currently depends on. Two TODO comments (at the type definition and at the log projection) point at #594, which tracks dropping the duplication holistically across both terminal and file picker items.

Effect on the S0 spike (`terminal-picker-014`): the assertion mismatch on `nonBindableReason` is now satisfied. The remaining red — `description: 'not bindable'` — is S2's responsibility (badge in description).
…cker

Adds a `not bindable` badge to the terminal QuickPick description whenever the upstream `EligibleTerminal.nonBindableReason` is set. The badge composes with the existing `bound` / `active` badges via the same ` · ` separator and shows last in the sequence. `bound` and `not bindable` cannot co-occur in practice because the bind path will reject non-bindable terminals once S3 lands — `active` and `not bindable` can co-occur and are emitted in that order.

A single new `MessageCode.TERMINAL_PICKER_NOT_BINDABLE_DESCRIPTION` is added with the catalog string `"not bindable"`. VS Code's QuickPick API has no per-item disabled state and no hover tooltip, so a description badge is the closest match to the A002 design decision ("minimal tooltip we'll tightly control"). The selection-rejection guard that completes the disabled-style UX is S3 (`showTerminalPicker`).

Turns the S0 spike `terminal-picker-014` fully green: the pty entry now reports `description: 'not bindable'` alongside the `nonBindableReason: 'extension-managed'` that S1 already supplies, and the shell entry continues to validate as `description: 'active'`. The negative-control assertion catches any future over-filter that would block legitimate shell terminals.
…ckers

VS Code's QuickPick has no per-item disabled state, so clicking the "not bindable" entry from S2 still resolves the picker with that item. Without a guard, the bind path would happily call `vscode.window.activeTerminal.sendText` on an extension-managed pty terminal, which is exactly the Jest-terminal bug that #592 exists to fix.

`showTerminalPicker` and `DestinationPicker.handleQuickPickSelection` now check `terminalInfo.nonBindableReason` (and the equivalent top-level `nonBindableReason` for the destination picker, which sees a wider `DestinationQuickPickItem` union) before invoking the success path. When set: log the rejection, route through `handlers.onDismissed` if provided, otherwise return undefined / `{ outcome: 'cancelled' }`. The badge from S2 explains to the user why nothing happened.

No notification is shown at this layer — the picker badge is the user-visible signal. S3.5 will add a notification for the parallel `CMD_BIND_TO_TERMINAL_HERE` palette / keybinding entry points where there is no equivalent visual cue.

Tests: showTerminalPicker gets two new cases (default-dismiss returns undefined and skips onSelected; explicit onDismissed routes through). DestinationPicker gets one new case (clicking a pty entry returns `{ outcome: 'cancelled' }` and logs the reason). The `createMockTerminalQuickPickItem` helper now accepts an optional `nonBindableReason` argument so tests can construct disabled entries.
…ty terminals

Context menus, command palette, and keybindings for "Bind Here" / "Bind to
Terminal" now all reject extension-managed terminals (pty). A new context key
`rangelink.isActiveTerminalBindable` hides the terminal bind menu entries when
the active terminal is non-bindable, catching the paths the command handler
can't (context menus render before the command runs). The
`wireActiveTerminalBindabilityContext` helper maintains this key by subscribing
to terminal lifecycle events.
…message vocabulary

The "not bindable" badge approach was leaking an implementation detail (extension-managed pty) into the UI. VS Code's own pickers (file open, command palette) filter out non-applicable items rather than rendering them disabled; aligning with that convention removes a learning surface and makes the picker faster to scan. Extension-managed pty terminals are now excluded at `getEligibleTerminals`, so the entire picker pipeline downstream sees only bindable terminals. The R-D unified picker already skipped empty sections, so a pty-only setup now silently omits the terminals section.

Error messages now use "bindable" instead of "active" for eligibility failures. `ERROR_NO_ACTIVE_TEXT_EDITOR` previously fired for image viewers, webviews, and settings tabs — the message was misleading because those ARE active editors, just not text editors. The "bindable" framing matches the `isActiveTerminalBindable` context key and the `classifyTerminalForBinding` helper already in use, keeping vocabulary coherent end-to-end. `ERROR_NO_ACTIVE_TERMINAL` is preserved for `TerminalSelectionService` since that path is genuinely about focus, not eligibility.

A new integration test `terminal-picker-016` asserts the absence invariant directly: a single pty terminal yields a picker with no terminal section and no overflow item. This catches the failure mode where filtering breaks and non-bindable items leak back into the UI without anything else regressing.

Benefits:
- Picker UX matches VS Code conventions (filter, not disable)
- Smaller surface area: badge rendering, selection short-circuits, and the unreachable single-non-bindable branch all removed
- Error toasts now correctly describe the PNG-viewer / pty-only failure modes
- `terminal-picker-016` locks in the filtering invariant against future regressions
The `when: rangelink.isActiveTerminalBindable` clauses on `terminal/title/context` and `terminal/context` shipped in commit `6bac5adf` without any TC verifying the menu items actually hide on pty terminals in a real VS Code host. VS Code exposes no API to query rendered context-menu items, so coverage requires assisted TCs with `waitForHumanVerdict`. These four TCs close that gap: 006 and 007 prove "Bind Here" is absent on the pty tab and content-area menus respectively; 008 proves the `when` clause is not overly broad by checking that a bindable shell tab still shows the entry when a pty is also open; 009 proves "Unbind" rides on `rangelink.isBound` (not bindability) by verifying it remains reachable from the pty content-area menu when a different terminal is bound.

Benefits:
- Closes the safety-net gap left by the original pty-hardening commit
- Catches both over-hiding (008) and under-hiding (006/007) regressions
- 009 documents that Unbind reachability is independent of bindability
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 20, 2026

⚠️ QA Coverage Gap Detected

The PR introduces a new filtering behavior for extension-managed pty terminals in the terminal picker, which is a user-visible change that requires additional test coverage.

Suggested test cases:

  • Terminal Picker: Extension-managed pty terminal (Jest task runner, etc.) is filtered out of the R-D picker (automatable)

Generated by QA Gap Check (GPT-4o-mini via GitHub Models)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d3992318-c392-425d-bfbd-f5933a88d907

📥 Commits

Reviewing files that changed from the base of the PR and between c1bf7a6 and 21782a7.

📒 Files selected for processing (2)
  • packages/rangelink-vscode-extension/src/__integration-tests__/helpers/capturingPtyHelpers.ts
  • packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts

Walkthrough

This PR classifies terminals to identify extension-managed PTY terminals as non-bindable, wires a VS Code context key that reflects active-terminal bindability, gates terminal-bind menu visibility, rejects direct-bind attempts to non-bindable terminals, refactors eligibility, updates messages, and adds integration/unit tests and test-fixture helpers.

Changes

Extension-Managed PTY Terminal Filtering and Bindability Context

Layer / File(s) Summary
Terminal classification contract & implementation
src/destinations/utils/classifyTerminalForBinding.ts, src/__tests__/destinations/utils/classifyTerminalForBinding.test.ts
Defines TerminalBindingClassification and classifyTerminalForBinding to mark terminals hidden, bindable, or visible-but-non-bindable (e.g., 'extension-managed' PTYs).
getEligibleTerminals: classification-driven filtering
src/destinations/utils/getEligibleTerminals.ts, src/destinations/utils/index.ts
Replaces isTerminalEligible with classification-driven filtering that excludes non-bindable terminals; removes old predicate re-export.
Active-terminal bindability context wiring
src/destinations/wireActiveTerminalBindabilityContext.ts, src/constants/contextKeys.ts, src/destinations/index.ts
Adds wireActiveTerminalBindabilityContext to compute and publish rangelink.isActiveTerminalBindable, subscribe to terminal lifecycle events, and export the wiring helper.
Menu visibility & command checks
package.json, src/commands/BindToTerminalCommand.ts, src/commands/BindToTextEditorCommand.ts
Gates rangelink.terminal.bind menu entries on the new context key; BindToTerminalCommand classifies preferredTerminal and cancels non-bindable direct binds; error codes/messages updated to "no bindable ...".
VscodeAdapter terminal events & mocks
src/ide/vscode/VscodeAdapter.ts, src/__tests__/helpers/createMockWindow.ts, src/__tests__/extension.test.ts
Adds adapter wrappers for onDidOpenTerminal and onDidChangeActiveTerminal; test mocks updated and lifecycle subscription count adjusted.
Subscription wiring
src/wireSubscriptions.ts, src/__tests__/wireSubscriptions.test.ts
Registers the bindability context wiring as a disposable during extension subscription setup; tests spy/assert the extra disposable.
Test infra: terminal creation & fixture registry
src/__integration-tests__/helpers/ssContext.ts, src/__integration-tests__/helpers/capturingPtyHelpers.ts, src/destinations/utils/testFixtureRegistry.ts, .vscode-test.base.mjs
SsContext.createTerminal accepts options; capturing helpers mark PTY terminals as test fixtures; introduces testFixtureRegistry and enables fixtures in test base env.
Terminal picker integration tests
src/__integration-tests__/suite/terminalPicker.test.ts
Adds tests verifying PTY terminals are excluded from the destination picker, direct bind to PTY is rejected with toast, and picker omits terminal section when only PTY exists.
Context-menu integration tests
src/__integration-tests__/suite/contextMenuTerminal.test.ts
Adds assisted tests ensuring PTY tab/content menus do not show "Bind Here", and shell-binding scenarios remain valid when PTY terminals are present.
Classification & eligibility unit tests
src/__tests__/destinations/utils/classifyTerminalForBinding.test.ts, src/__tests__/destinations/utils/getEligibleTerminals.test.ts
Unit tests cover null/exited/hidden/pty/fixture classification and getEligibleTerminals PTY-filtering behavior.
Wire context unit tests
src/__tests__/destinations/wireActiveTerminalBindabilityContext.test.ts
Tests verify context initialization, updates on active-terminal changes, subscription registration, and disposal cleanup.
Command & package.json contract tests
src/__tests__/commands/*, src/__tests__/constants/packageJsonContracts.test.ts, src/__tests__/statusBar/RangeLinkStatusBar.test.ts
Tests updated to expect new "No bindable ..." messages; BindToTerminalCommand direct-bind tests ensure non-bindable/exited terminals are rejected; package.json contract tests require the new when condition.
Dirty Buffer Warning integration tests refactor
src/__integration-tests__/suite/dirtyBufferWarning.test.ts
Refactors many assisted and automated dirty-buffer tests to remove try/finally terminal disposal while preserving assertions for each flow.
Test helpers & quick-pick logging
src/__tests__/helpers/*, src/__tests__/ide/vscode/VscodeAdapter.test.ts, src/types/QuickPickTypes.ts
Mocks and helpers updated; quick-pick logging test adds an extra terminal item; TODO added about duplicated quick-pick semantic fields.
QA, changelog & release docs
qa/qa-test-cases-v1.1.0.yaml, packages/rangelink-vscode-extension/CHANGELOG.md, CLAUDE.md
QA YAML adds PTY-focused test cases; changelog mentions PTY filtering; CLAUDE.md release-test guidance refined.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #592: Implements PTY-based exclusion and disabled-entry behavior described by the issue (structural PTY detection, test-fixture handling, QA coverage).

Possibly related PRs

Poem

🐰 A rabbit hums, with nimble paws so spry,

PTY terminals now politely pass by;
Only true shells the binder will embrace,
Menus and keys align with gentle grace.
Hooray — the picker’s tidy, neat, and sly!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: preventing extension-managed pty terminals from being offered as bindable destinations, directly addressing issue #592.
Linked Issues check ✅ Passed The PR fulfills all key requirements from issue #592: filters extension-managed pty terminals using structural signals (creationOptions.pty), implements context-key-based visibility control, excludes non-bindable terminals from the picker, and preserves test infrastructure via test-fixture registry.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing issue #592: terminal classification, eligibility filtering, context-key wiring, menu visibility, command guards, error messages, test infrastructure exemptions, and supporting test cases. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/592

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts (1)

733-762: ⚡ Quick win

Add log assertions for these assisted dirty-buffer send flows.

These tests validate behavior but don’t assert the expected handleDirtyBufferWarning log path. This weakens failure diagnostics (and in Line 740 / Line 775 / Line 847, logCapture.mark(...) is currently not validated).

Proposed patch pattern (apply similarly to 013/014/016/017)
   const logCapture = getLogCapture();
   logCapture.mark('before-rf-save');
   capturing.clearCaptured();
@@
   await ss.settle();
+  const lines = logCapture.getLinesSince('before-rf-save');
+  const showingWarningLog = lines.find(
+    (l) =>
+      l.includes('handleDirtyBufferWarning') &&
+      l.includes('Document has unsaved changes, showing warning'),
+  );
+  assert.ok(
+    showingWarningLog,
+    'Expected handleDirtyBufferWarning to log "showing warning" — dialog must actually fire',
+  );

As per coding guidelines, "Include logger assertions in tests that verify method behavior — logging provides critical visibility for debugging; never create separate tests just for logging, consolidate with behavior tests".

Also applies to: 768-797, 836-870, 876-907

🤖 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/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts`
around lines 733 - 762, The test currently marks logs with
logCapture.mark('before-rf-save') but never asserts the expected
handleDirtyBufferWarning logging path; update this test (and the sibling tests
for 013/014/016/017) to capture and assert the logger output after the R-F Save
& Send flow: use getLogCapture()/logCapture to retrieve logs after the save,
verify a log entry indicating the handleDirtyBufferWarning code path (e.g., a
message or tag produced by handleDirtyBufferWarning), and assert that the mark
'before-rf-save' was advanced/recorded as expected so the log marker is
validated alongside the existing behavior assertions.
packages/rangelink-vscode-extension/src/__tests__/commands/BindToTerminalCommand.test.ts (1)

419-439: ⚡ Quick win

Add a logger assertion for the exited-terminal rejection path.

This test verifies behavior but currently skips the debug-log contract asserted in the PTY variant.

Suggested addition
         expect(mockDestinationManager.bind).not.toHaveBeenCalled();
         expect(mockAdapter.__getVscodeInstance().window.showErrorMessage).toHaveBeenCalledWith(
           'Cannot bind to "dead-shell": it is managed by an extension and does not accept input.',
         );
+        expect(mockLogger.debug).toHaveBeenCalledWith(
+          {
+            fn: 'BindToTerminalCommand.execute',
+            terminalName: 'dead-shell',
+            source: 'context-menu',
+            nonBindableReason: 'not-visible',
+          },
+          'Rejected bind to non-bindable terminal from context menu',
+        );

As per coding guidelines **/*.test.ts: Include logger assertions in tests that verify method behavior — logging provides critical visibility for debugging; never create separate tests just for logging, consolidate with behavior tests.

🤖 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/rangelink-vscode-extension/src/__tests__/commands/BindToTerminalCommand.test.ts`
around lines 419 - 439, Add a logger assertion to the existing exited-terminal
test: after calling command.execute(exitedTerminal) assert that mockLogger.debug
(or the logger method used by BindToTerminalCommand) was called with a message
indicating the bind was rejected for the exited terminal and includes the
terminal name "dead-shell"; this should be added alongside the existing
expectations so the test verifies both behavior and the debug log contract of
BindToTerminalCommand.execute when given an exited terminal created via
createMockTerminal.
packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts (1)

152-157: ⚡ Quick win

Strengthen the 4th disposable assertion.

The test title says active-terminal bindability context is pushed, but the body only checks call count. Please also assert the 4th pushed value is a disposable from that wiring path (not just “some 4th item”).

Suggested assertion tightening
   it('pushes disposables: delimiterCache, statusBar, destinationManager, and active terminal bindability context', () => {
     expect(registrar.pushDisposable).toHaveBeenNthCalledWith(1, services.delimiterCache);
     expect(registrar.pushDisposable).toHaveBeenNthCalledWith(2, services.statusBar);
     expect(registrar.pushDisposable).toHaveBeenNthCalledWith(3, services.destinationManager);
     expect(registrar.pushDisposable).toHaveBeenCalledTimes(4);
+    const fourthDisposable = registrar.pushDisposable.mock.calls[3][0] as {
+      dispose: () => void;
+    };
+    expect(typeof fourthDisposable.dispose).toBe('function');
   });

As per coding guidelines, “When testing that a list contains items, assert on specific item labels/fields, not just array.length.”

🤖 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/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts`
around lines 152 - 157, The fourth disposable assertion is weak — instead of
only checking call count, assert the exact fourth pushed value; update the test
that currently checks registrar.pushDisposable calls so the 4th expectation
verifies the active-terminal bindability disposable (e.g., add an assertion like
expect(registrar.pushDisposable).toHaveBeenNthCalledWith(4,
services.activeTerminalBindabilityContext) or equivalent using
registrar.pushDisposable.mock.calls[3][0] to match the specific disposable from
the wiring path) while keeping the existing first three assertions for
services.delimiterCache, services.statusBar, and services.destinationManager.
🤖 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/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml`:
- Around line 270-274: Update the expected_result for test id
terminal-picker-015 to use the new "bindable" terminology (or make the assertion
less string-literal brittle) instead of the old sentence that ends with "does
not accept input"; specifically edit the expected_result value for
terminal-picker-015 so it expects an error notification referencing "bindable"
(e.g., 'Cannot bind to "<name>": it is not bindable' or change to a
pattern/contains check) so the QA spec matches the new standardized messaging.

In `@packages/rangelink-vscode-extension/src/i18n/messages.en.ts`:
- Around line 14-16: The rejection message keyed by
MessageCode.BIND_TO_TERMINAL_NOT_BINDABLE_REJECT uses wording that mentions
"managed by an extension" which can be incorrect for exited or non-visible
terminals; update the string value for
MessageCode.BIND_TO_TERMINAL_NOT_BINDABLE_REJECT to a generic rejection copy
(e.g., "Cannot bind to \"{name}\": terminal does not accept input.") so it
applies to all non-bindable cases without implying extension management.

---

Nitpick comments:
In
`@packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts`:
- Around line 733-762: The test currently marks logs with
logCapture.mark('before-rf-save') but never asserts the expected
handleDirtyBufferWarning logging path; update this test (and the sibling tests
for 013/014/016/017) to capture and assert the logger output after the R-F Save
& Send flow: use getLogCapture()/logCapture to retrieve logs after the save,
verify a log entry indicating the handleDirtyBufferWarning code path (e.g., a
message or tag produced by handleDirtyBufferWarning), and assert that the mark
'before-rf-save' was advanced/recorded as expected so the log marker is
validated alongside the existing behavior assertions.

In
`@packages/rangelink-vscode-extension/src/__tests__/commands/BindToTerminalCommand.test.ts`:
- Around line 419-439: Add a logger assertion to the existing exited-terminal
test: after calling command.execute(exitedTerminal) assert that mockLogger.debug
(or the logger method used by BindToTerminalCommand) was called with a message
indicating the bind was rejected for the exited terminal and includes the
terminal name "dead-shell"; this should be added alongside the existing
expectations so the test verifies both behavior and the debug log contract of
BindToTerminalCommand.execute when given an exited terminal created via
createMockTerminal.

In `@packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts`:
- Around line 152-157: The fourth disposable assertion is weak — instead of only
checking call count, assert the exact fourth pushed value; update the test that
currently checks registrar.pushDisposable calls so the 4th expectation verifies
the active-terminal bindability disposable (e.g., add an assertion like
expect(registrar.pushDisposable).toHaveBeenNthCalledWith(4,
services.activeTerminalBindabilityContext) or equivalent using
registrar.pushDisposable.mock.calls[3][0] to match the specific disposable from
the wiring path) while keeping the existing first three assertions for
services.delimiterCache, services.statusBar, and services.destinationManager.
🪄 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: CHILL

Plan: Pro

Run ID: ea1fd1ca-84b3-4841-8b6e-3250922fe389

📥 Commits

Reviewing files that changed from the base of the PR and between 26d99a7 and 9957879.

📒 Files selected for processing (40)
  • CLAUDE.md
  • packages/rangelink-vscode-extension/CHANGELOG.md
  • packages/rangelink-vscode-extension/package.json
  • packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
  • packages/rangelink-vscode-extension/src/__integration-tests__/helpers/ssContext.ts
  • packages/rangelink-vscode-extension/src/__integration-tests__/suite/contextMenuTerminal.test.ts
  • packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts
  • packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/commands/BindToTerminalCommand.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/commands/BindToTextEditorCommand.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/constants/packageJsonContracts.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/utils/classifyTerminalForBinding.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/utils/getEligibleTerminals.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/utils/isTerminalEligible.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/wireActiveTerminalBindabilityContext.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/extension.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/helpers/createMockBindableQuickPickItem.ts
  • packages/rangelink-vscode-extension/src/__tests__/helpers/createMockWindow.ts
  • packages/rangelink-vscode-extension/src/__tests__/ide/vscode/VscodeAdapter.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/statusBar/RangeLinkStatusBar.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts
  • packages/rangelink-vscode-extension/src/commands/BindToTerminalCommand.ts
  • packages/rangelink-vscode-extension/src/commands/BindToTextEditorCommand.ts
  • packages/rangelink-vscode-extension/src/constants/contextKeys.ts
  • packages/rangelink-vscode-extension/src/destinations/DestinationPicker.ts
  • packages/rangelink-vscode-extension/src/destinations/index.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/classifyTerminalForBinding.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/getEligibleTerminals.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/index.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/isTerminalEligible.ts
  • packages/rangelink-vscode-extension/src/destinations/wireActiveTerminalBindabilityContext.ts
  • packages/rangelink-vscode-extension/src/i18n/messages.en.ts
  • packages/rangelink-vscode-extension/src/ide/vscode/VscodeAdapter.ts
  • packages/rangelink-vscode-extension/src/statusBar/RangeLinkStatusBar.ts
  • packages/rangelink-vscode-extension/src/types/EligibleTerminal.ts
  • packages/rangelink-vscode-extension/src/types/MessageCode.ts
  • packages/rangelink-vscode-extension/src/types/NonBindableReason.ts
  • packages/rangelink-vscode-extension/src/types/QuickPickTypes.ts
  • packages/rangelink-vscode-extension/src/types/index.ts
  • packages/rangelink-vscode-extension/src/wireSubscriptions.ts
💤 Files with no reviewable changes (2)
  • packages/rangelink-vscode-extension/src/tests/destinations/utils/isTerminalEligible.test.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/isTerminalEligible.ts

Comment thread packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
Comment thread packages/rangelink-vscode-extension/src/i18n/messages.en.ts
@github-actions
Copy link
Copy Markdown

❌ CI / Test & Validate — run summary

Duration 15m 52s
Unit tests passed 1947 / 1947
Integration tests passing 120
Integration tests failed 22
QA TC IDs exercised status-bar-menu-002, status-bar-menu-003, status-bar-menu-005, status-bar-menu-006, bind-to-destination-010, bind-to-destination-013, terminal-picker-001, terminal-picker-002, terminal-picker-003, terminal-picker-004, terminal-picker-005, terminal-picker-007, terminal-picker-008, terminal-picker-011, terminal-picker-012, terminal-picker-013, terminal-picker-014, terminal-picker-015, terminal-picker-016, file-picker-001, file-picker-002, file-picker-003, file-picker-004, file-picker-005, file-picker-009, file-picker-011, file-picker-012, clipboard-preservation-001, clipboard-preservation-002, clipboard-preservation-003, clipboard-preservation-005, clipboard-preservation-006, clipboard-preservation-007, clipboard-preservation-008, clipboard-preservation-009, clipboard-preservation-013, clipboard-preservation-014, clipboard-preservation-015, clipboard-preservation-016, send-file-path-001, send-file-path-002, send-file-path-004, send-file-path-005, send-file-path-006, send-file-path-007, send-file-path-008, send-file-path-010, send-file-path-011, send-file-path-012, dirty-buffer-warning-004, dirty-buffer-warning-006, dirty-buffer-warning-007, dirty-buffer-warning-019, send-terminal-selection-003, send-terminal-selection-006, send-terminal-selection-007, go-to-link-001, unbind-001, unbind-003, unbind-004, editor-binding-validation-004, full-line-navigation-001, full-line-navigation-002, char-navigation-001, char-navigation-002, full-line-link-generation-001, wrapped-link-navigation-001, wrapped-link-navigation-002, wrapped-link-navigation-003, wrapped-link-navigation-004, markdown-link-navigation-001, url-exclusion-001, stale-viewcolumn-001, hidden-tab-paste-001, hidden-tab-paste-002, full-line-selection-validation-001, core-send-commands-r-l-001, core-send-commands-r-l-002, core-send-commands-r-c-001, core-send-commands-r-l-004, core-send-commands-r-c-002, core-send-commands-r-l-005, core-send-commands-r-p-001, core-send-commands-r-v-001, clickable-file-paths-001, clickable-file-paths-002, clickable-file-paths-003, clickable-file-paths-004, clickable-file-paths-005, clickable-file-paths-006, clickable-file-paths-007, clickable-file-paths-008, clickable-file-paths-009, clickable-file-paths-010, clickable-file-paths-011, clickable-file-paths-012, smart-padding-001, smart-padding-003, smart-padding-005, smart-padding-006, smart-padding-007, smart-padding-008, smart-padding-011, duplicate-tab-group-001, duplicate-tab-group-002, duplicate-tab-group-003, duplicate-tab-group-004, langswitch-binding-001, langswitch-binding-002, navigation-clamping-001, navigation-clamping-002, navigation-clamping-003, navigation-clamping-004, untitled-navigation-001, untitled-navigation-002, untitled-navigation-003, untitled-navigation-004, untitled-navigation-005, untitled-navigation-006, navigation-toast-settings-001, navigation-toast-settings-002, navigation-toast-settings-003, filename-fallback-navigation-001, filename-fallback-navigation-002, filename-fallback-navigation-003, filename-fallback-navigation-004, custom-ai-assistant-001, custom-ai-assistant-002, custom-ai-assistant-004, custom-ai-assistant-005, custom-ai-assistant-006, custom-ai-assistant-007, custom-ai-assistant-008, custom-ai-assistant-009, custom-ai-assistant-015, custom-ai-assistant-016, github-copilot-chat-001, release-notifier-001, release-notifier-002, status-bar-appearance-001, status-bar-appearance-002
Report View run & artifacts

To re-run failed tests:

./scripts/run-integration-tests.sh --exclude-label "requires-extensions" --exclude-label "cursor" --automated --grep "clipboard-preservation-001|clipboard-preservation-003|clipboard-preservation-005|clipboard-preservation-006|core-send-commands-r-l-001|core-send-commands-r-l-004|dirty-buffer-warning-006|dirty-buffer-warning-007|full-line-selection-validation-001|send-file-path-001|send-file-path-002|send-file-path-004|send-file-path-005|send-file-path-007|send-file-path-010|send-file-path-011|smart-padding-001|smart-padding-005|smart-padding-006|smart-padding-007|smart-padding-008|smart-padding-011"
/home/runner/work/rangeLink/rangeLink/packages/rangelink-vscode-extension:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  rangelink-vscode-extension@1.0.0 test:release:automated: `./scripts/run-integration-tests.sh --automated --exclude-label requires-extensions --exclude-label cursor`
Exit status 1
 ELIFECYCLE  Command failed with exit code 1.

The pty terminal filtering introduced a bindability classifier that correctly excluded extension-managed terminals from the picker, but it also broke every integration test that uses a capturing pty fixture. Those tests call createAndBindCapturingTerminal which now failed because the pty terminal was classified as non-bindable, causing the bind step to show an error toast instead of binding, and subsequent paste commands to open a picker that no one was there to dismiss, timing out after 20s. The fix uses a property marker on the terminal object — not a WeakSet — because esbuild bundles the extension into dist/extension.js while integration test helpers load from out/, creating two separate module graphs that cannot share a WeakSet instance. A property on the vscode.Terminal object itself bridges that gap since both sides hold a reference to the same JS object.

Also addresses CodeRabbit feedback: generic wording for the non-bindable rejection message (covers extension-managed, exited, and hideFromUser cases equally), QA YAML sync for the same message, a missing logger assertion in the exited-terminal rejection test, and a count-only disposable assertion upgraded to a spy-based identity check on the wireActiveTerminalBindabilityContext return value. Backfills handleDirtyBufferWarning log assertions in four assisted dirty-buffer-warning tests that marked the log but never read it.

Benefits:
- 20 integration tests that were timing out now pass
- Non-bindable rejection message accurately describes all three rejection cases, not just extension-managed
- Disposable assertion catches regressions where wireActiveTerminalBindabilityContext returns the wrong object
- Logger assertions close a visibility gap for assisted dirty-buffer tests

Ref: #595 (review)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts (1)

164-169: ⚡ Quick win

Prefer call matchers over direct .mock.calls/.mock.results indexing.

Lines 164–169 are more brittle than necessary. Use a stable mocked disposable and assert with toHaveBeenNthCalledWith / toHaveReturnedWith.

Proposed refactor
   let services: ReturnType<typeof createMockWiringServices>;
   let wireActiveTerminalBindabilityContextSpy: jest.SpyInstance;
+  let activeTerminalBindabilityDisposable: { dispose: jest.Mock };

   beforeEach(() => {
     registrar = createMockSubscriptionRegistrar();
     services = createMockWiringServices();
+    activeTerminalBindabilityDisposable = { dispose: jest.fn() };
     wireActiveTerminalBindabilityContextSpy = jest.spyOn(
       wireActiveTerminalBindabilityContextModule,
       'wireActiveTerminalBindabilityContext',
-    );
+    ).mockReturnValue(activeTerminalBindabilityDisposable);
     wireSubscriptions(registrar, services);
   });
@@
-    const fourthDisposable = registrar.pushDisposable.mock.calls[3][0];
-    expect(fourthDisposable).toHaveProperty('dispose');
-    expect(typeof fourthDisposable.dispose).toBe('function');
+    expect(registrar.pushDisposable).toHaveBeenNthCalledWith(
+      4,
+      activeTerminalBindabilityDisposable,
+    );
     expect(wireActiveTerminalBindabilityContextSpy).toHaveBeenCalledTimes(1);
-    expect(wireActiveTerminalBindabilityContextSpy.mock.results[0].value).toBe(fourthDisposable);
+    expect(wireActiveTerminalBindabilityContextSpy).toHaveReturnedWith(
+      activeTerminalBindabilityDisposable,
+    );

As per coding guidelines: "Use toHaveBeenCalledWith for mock assertions - Use .toHaveBeenCalledWith(param1, param2, ...) instead of accessing .mock.calls[0]."

🤖 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/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts`
around lines 164 - 169, Replace brittle direct mock indexing with stable
call-match assertions: create a mocked disposable instance and assert
registrar.pushDisposable was called with it using toHaveBeenNthCalledWith(4,
mockedDisposable) (or toHaveBeenCalledWith if order not important), then assert
wireActiveTerminalBindabilityContextSpy returned that same disposable using
toHaveReturnedWith(mockedDisposable) or toHaveNthReturnedWith(1,
mockedDisposable); refer to the existing symbols registrar.pushDisposable,
wireActiveTerminalBindabilityContextSpy, and the current fourthDisposable
variable when implementing the stable mockedDisposable replacement.
🤖 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/rangelink-vscode-extension/src/__integration-tests__/helpers/capturingPtyHelpers.ts`:
- Around line 52-54: The terminal created by vscode.window.createTerminal is not
disposed if markRangeLinkTestFixture(terminal) throws; wrap the calls that use
the newly created terminal (markRangeLinkTestFixture(terminal) and
trackingArray?.push(terminal)) in a try/catch, and in the catch call
terminal.dispose() before rethrowing the error so the terminal is not leaked;
ensure trackingArray?.push(terminal) only runs after markRangeLinkTestFixture
succeeds.

---

Nitpick comments:
In `@packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts`:
- Around line 164-169: Replace brittle direct mock indexing with stable
call-match assertions: create a mocked disposable instance and assert
registrar.pushDisposable was called with it using toHaveBeenNthCalledWith(4,
mockedDisposable) (or toHaveBeenCalledWith if order not important), then assert
wireActiveTerminalBindabilityContextSpy returned that same disposable using
toHaveReturnedWith(mockedDisposable) or toHaveNthReturnedWith(1,
mockedDisposable); refer to the existing symbols registrar.pushDisposable,
wireActiveTerminalBindabilityContextSpy, and the current fourthDisposable
variable when implementing the stable mockedDisposable replacement.
🪄 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: CHILL

Plan: Pro

Run ID: 75c105c6-7a3c-4a23-be4c-039e734051bb

📥 Commits

Reviewing files that changed from the base of the PR and between 9957879 and c1bf7a6.

📒 Files selected for processing (14)
  • packages/rangelink-vscode-extension/.vscode-test.base.mjs
  • packages/rangelink-vscode-extension/qa/qa-test-cases-v1.1.0.yaml
  • packages/rangelink-vscode-extension/src/__integration-tests__/helpers/capturingPtyHelpers.ts
  • packages/rangelink-vscode-extension/src/__integration-tests__/suite/dirtyBufferWarning.test.ts
  • packages/rangelink-vscode-extension/src/__integration-tests__/suite/terminalPicker.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/commands/BindToTerminalCommand.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/utils/classifyTerminalForBinding.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/destinations/utils/testFixtureRegistry.test.ts
  • packages/rangelink-vscode-extension/src/__tests__/wireSubscriptions.test.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/classifyTerminalForBinding.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/index.ts
  • packages/rangelink-vscode-extension/src/destinations/utils/testFixtureRegistry.ts
  • packages/rangelink-vscode-extension/src/errors/RangeLinkExtensionErrorCodes.ts
  • packages/rangelink-vscode-extension/src/i18n/messages.en.ts

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

❌ CI / Integration Tests (with extensions) — run summary

Duration 228m 6s
Unit tests Ran in Test & Validate job
Integration tests passing 129
Integration tests failed 22
QA TC IDs exercised clipboard-preservation-011, clipboard-preservation-012, custom-ai-assistant-003, claude-code-001, claude-code-006, claude-code-007, gemini-code-assist-001, gemini-code-assist-005, gemini-code-assist-006
Report View run & artifacts

To re-run failed tests:

./scripts/run-integration-tests.sh --exclude-label "cursor" --exclude-assisted --with-extensions --grep "clipboard-preservation-001|clipboard-preservation-003|clipboard-preservation-005|clipboard-preservation-006|core-send-commands-r-l-001|core-send-commands-r-l-004|dirty-buffer-warning-006|dirty-buffer-warning-007|full-line-selection-validation-001|send-file-path-001|send-file-path-002|send-file-path-004|send-file-path-005|send-file-path-007|send-file-path-010|send-file-path-011|smart-padding-001|smart-padding-005|smart-padding-006|smart-padding-007|smart-padding-008|smart-padding-011"
/home/runner/work/rangeLink/rangeLink/packages/rangelink-vscode-extension:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  rangelink-vscode-extension@1.0.0 test:release:with-extensions: `./scripts/run-integration-tests.sh --with-extensions --exclude-assisted --exclude-label cursor`
Exit status 1
 ELIFECYCLE  Command failed with exit code 1.

If markRangeLinkTestFixture throws (env var not set), the capturing-pty terminal was never disposed. The wireSubscriptions disposable test accessed mock.calls and mock.results directly, violating T006.

Ref: #595 (review)
@github-actions
Copy link
Copy Markdown

✅ CI / Integration Tests (with extensions) — run summary

Duration 9m 14s
Unit tests Ran in Test & Validate job
Integration tests passing 151
QA TC IDs exercised clipboard-preservation-011, clipboard-preservation-012, custom-ai-assistant-003, claude-code-001, claude-code-006, claude-code-007, gemini-code-assist-001, gemini-code-assist-005, gemini-code-assist-006
Report View run & artifacts

@github-actions
Copy link
Copy Markdown

✅ CI / Test & Validate — run summary

Duration 9m 36s
Unit tests passed 1954 / 1954
Integration tests passing 142
QA TC IDs exercised status-bar-menu-002, status-bar-menu-003, status-bar-menu-005, status-bar-menu-006, bind-to-destination-010, bind-to-destination-013, terminal-picker-001, terminal-picker-002, terminal-picker-003, terminal-picker-004, terminal-picker-005, terminal-picker-007, terminal-picker-008, terminal-picker-011, terminal-picker-012, terminal-picker-013, terminal-picker-014, terminal-picker-015, terminal-picker-016, file-picker-001, file-picker-002, file-picker-003, file-picker-004, file-picker-005, file-picker-009, file-picker-011, file-picker-012, clipboard-preservation-001, clipboard-preservation-002, clipboard-preservation-003, clipboard-preservation-005, clipboard-preservation-006, clipboard-preservation-007, clipboard-preservation-008, clipboard-preservation-009, clipboard-preservation-013, clipboard-preservation-014, clipboard-preservation-015, clipboard-preservation-016, send-file-path-001, send-file-path-002, send-file-path-004, send-file-path-005, send-file-path-006, send-file-path-007, send-file-path-008, send-file-path-010, send-file-path-011, send-file-path-012, dirty-buffer-warning-004, dirty-buffer-warning-006, dirty-buffer-warning-007, dirty-buffer-warning-019, send-terminal-selection-003, send-terminal-selection-006, send-terminal-selection-007, go-to-link-001, unbind-001, unbind-003, unbind-004, editor-binding-validation-004, full-line-navigation-001, full-line-navigation-002, char-navigation-001, char-navigation-002, full-line-link-generation-001, wrapped-link-navigation-001, wrapped-link-navigation-002, wrapped-link-navigation-003, wrapped-link-navigation-004, markdown-link-navigation-001, url-exclusion-001, stale-viewcolumn-001, hidden-tab-paste-001, hidden-tab-paste-002, full-line-selection-validation-001, core-send-commands-r-l-001, core-send-commands-r-l-002, core-send-commands-r-c-001, core-send-commands-r-l-004, core-send-commands-r-c-002, core-send-commands-r-l-005, core-send-commands-r-p-001, core-send-commands-r-v-001, clickable-file-paths-001, clickable-file-paths-002, clickable-file-paths-003, clickable-file-paths-004, clickable-file-paths-005, clickable-file-paths-006, clickable-file-paths-007, clickable-file-paths-008, clickable-file-paths-009, clickable-file-paths-010, clickable-file-paths-011, clickable-file-paths-012, smart-padding-001, smart-padding-003, smart-padding-005, smart-padding-006, smart-padding-007, smart-padding-008, smart-padding-011, duplicate-tab-group-001, duplicate-tab-group-002, duplicate-tab-group-003, duplicate-tab-group-004, langswitch-binding-001, langswitch-binding-002, navigation-clamping-001, navigation-clamping-002, navigation-clamping-003, navigation-clamping-004, untitled-navigation-001, untitled-navigation-002, untitled-navigation-003, untitled-navigation-004, untitled-navigation-005, untitled-navigation-006, navigation-toast-settings-001, navigation-toast-settings-002, navigation-toast-settings-003, filename-fallback-navigation-001, filename-fallback-navigation-002, filename-fallback-navigation-003, filename-fallback-navigation-004, custom-ai-assistant-001, custom-ai-assistant-002, custom-ai-assistant-004, custom-ai-assistant-005, custom-ai-assistant-006, custom-ai-assistant-007, custom-ai-assistant-008, custom-ai-assistant-009, custom-ai-assistant-015, custom-ai-assistant-016, github-copilot-chat-001, release-notifier-001, release-notifier-002, status-bar-appearance-001, status-bar-appearance-002
Report View run & artifacts

@couimet couimet merged commit c61be81 into main May 20, 2026
5 checks passed
@couimet couimet deleted the issues/592 branch May 20, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jest task-runner terminal appears in the R-D bind picker

1 participant