microsoft / microsoft/vscode

NES: speculative-request trajectory cancellation is disabled, but `handleIgnored` still relies on it for the superseded case

Open
#327,620 0 comments 0 reactions 1 assignee Claimed by @ulugbekna View on GitHub
bug
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

- Copilot Chat Extension Version: 0.60.0 (in-tree, `extensions/copilot`)
- VS Code Version: 1.132.0 (built from source, `3ddd267c500`)
- OS Version: macOS 26.5.2
- Feature: NES / inline edits — speculative requests

## Problem

The speculative-request trajectory check is implemented, documented and tested, but its only call site is commented out:

```ts
// src/extension/inlineEdits/node/nextEditProvider.ts:263-268
store.add(runOnChange(doc.value, (value) => {
this._cancelPendingRequestDueToDocChange(doc.id, value);
// FIXME: don't invoke before fixing false positive cancellations
// this._specManager.onActiveDocumentChanged(doc.id, value.value);
}));
```

This isn't just dead code — **`handleIgnored` explicitly delegates the superseded case to it**:

```ts
// nextEditProvider.ts:1598-1603
// Note: the superseded case is intentionally NOT handled here. The trajectory
// check on `_specManager.onActiveDocumentChanged` already cancels the
// speculative iff the user's edit moved off the type-through trajectory; ...
```

Since the check never runs, when a shown suggestion is superseded and the user then types away from the predicted trajectory, **nothing cancels the in-flight speculative request**. It survives until some unrelated trigger fires (`Superseded` on the next fetch, `Rejected`, `IgnoredDismissed` when not superseded, document close, `clearCache`, or dispose) — i.e. exactly the wasted server slot `SpeculativeRequestManager` was built to avoid.

Knock-on effects:

- The four `DivergedFromTrajectory{Form,Prefix,Middle,Suffix}` reasons in `speculativeRequestManager.ts` are unreachable.
- The doc comment at `nextEditProvider.ts:292-294` still claims speculative requests "have their own divergence handling via `SpeculativeRequestManager.onActiveDocumentChanged` (trajectory check)", which is no longer true.
- `trajectoryPrefix` / `trajectorySuffix` / `trajectoryNewText` are computed on **every** speculative request (`nextEditProvider.ts:1292-1295` — two slices of the whole pre-edit document) and never read.

## Evidence

The only two tests covering the behaviour are skipped:

```
src/extension/inlineEdits/test/node/nextEditProviderSpeculative.spec.ts:433 it.skip('cancels speculative request when active document edit moves off the type-through trajectory')
src/extension/inlineEdits/test/node/nextEditProviderSpeculative.spec.ts:461 it.skip('keeps speculative alive while user types characters of the suggestion (type-through)')
```

- Un-skipping them: **both fail by timeout** waiting on `cancellationRequested` — the cancellation never happens.
- Restoring the commented-out line: **all 35 tests in that file pass**, and the full `src/extension/inlineEdits` + `src/platform/inlineEdits` suite (**1736 tests**) stays green.

So no existing test reproduces the "false positive cancellations" the FIXME refers to. Whatever the concern was, it is currently undocumented and unverifiable from the test suite — which makes it hard for anyone to safely re-enable the feature.

## Suggested next steps

1. Capture the false-positive scenario as a failing test (CRLF normalisation, formatter-on-type, multi-cursor and external/auto edits all look like plausible candidates for spurious divergence).
2. Then either re-enable the check, or delete the mechanism and handle the superseded case explicitly in `handleIgnored` — the current middle state has the cost of both and the benefit of neither.
3. Either way, fix the `nextEditProvider.ts:292-294` comment and stop computing the unused trajectory strings.

## Side observation

With `github.copilot.chat.advanced.inlineEdits.speculativeRequests: "on"`, every `_triggerSpeculativeRequest` in my session short-circuited with `already have cached edit for post-edit state`, because the xtab provider streams several edits per response and pre-populates the cache (one request logged "3 edits returned"). Worth checking how often speculative requests actually fire in practice.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.