Skip to content

Add CompletionDirection (forward/backward) to completion pipeline#2020

Merged
curtisman merged 6 commits intomicrosoft:mainfrom
curtisman:curtism/completion-direction
Mar 18, 2026
Merged

Add CompletionDirection (forward/backward) to completion pipeline#2020
curtisman merged 6 commits intomicrosoft:mainfrom
curtisman:curtism/completion-direction

Conversation

@curtisman
Copy link
Member

@curtisman curtisman commented Mar 18, 2026

Summary

Replace CommitMode ("eager"/"explicit") with a host-provided CompletionDirection ("forward"/"backward") signal threaded through the entire completion pipeline. This lets the shell tell the backend whether the user is moving ahead (typing, selecting) or reconsidering (backspacing), eliminating the grammar-side heuristic that tried to guess user intent.

Changes by layer

Grammar matcher (actionGrammar/grammarMatcher.ts)

  • Support backward completion for literal string parts and varNumber parts via emitBackwardCompletion()
  • Track lastMatchedPartInfo (string or number) on MatchState for backing up to the most recently matched item
  • Refactor duplicate emit logic into three helpers: emitPropertyCompletion, emitStringCompletion, emitBackwardCompletion
  • Compute directionSensitive from couldBackUp (matched parts without trailing separator) in tryPartialStringMatch
  • Add consumeTrailingSeparators() so trailing whitespace is included in matchedPrefixLength
  • New required field directionSensitive on GrammarCompletionResult

Construction cache (cache/constructionCache.ts)

  • Thread direction through completion() and related methods
  • Use matchedStarts for backward to locate previous part position
  • Track noTrailingSeparator × partialPartCount ≥ 1 for directionSensitive

SDK & RPC

  • Add CompletionDirection = "forward" | "backward" type to agentSdk
  • Thread direction through agentRpc client/server and dispatcher RPC types

Dispatcher (dispatcher/completion.ts)

  • Replace CommitMode with directionSensitive: boolean on CommandCompletionResult
  • Replace tokenBoundary() (whitespace rewind) with hasWhitespaceBefore() — trailing whitespace is now consumed as a commit signal rather than stripped
  • Rename uncommittedCommandreconsideringCommand — direction-gated instead of trailing-space-gated
  • Thread separatorMode through CompletionTarget; agent only overrides when it advances startIndex via matchedPrefixLength
  • OR-merge directionSensitive across target + agent results

Shell (partialCompletionSession.ts)

  • Auto-detect direction: backward only when new input is a strict prefix of previous input (genuine backspace)
  • Store directionSensitive and lastDirection from backend result
  • New re-fetch trigger A7: direction changed AND directionSensitive AND input === anchor
  • Once the user types past the anchor, loaded completions are reused regardless of direction change

Documentation

  • Update docs/architecture/completion.md with direction model, category table showing backward behavior, and directionSensitive field
  • Add breadcrumb comments (Architecture: docs/architecture/completion.md — §N) in all source files

Tests

Grammar (actionGrammar)

  • 40 directionSensitive flag tests: single string, multi-part, wildcard, Category 3b, varNumber, optional ()?, repeat ()+/()*, spacing=none backward, minPrefixLength + backward, forward/backward agreement
  • Prefix length tests for optional backward completions

Construction cache (cache)

  • 8 backward direction tests
  • 5 conflicting directionSensitive tests: sensitive-wins, any-sensitive, longer-match-resets, trailing-space-commits

Dispatcher

  • 7 directionSensitive flag tests (exact subcommand, trailing space, pending flag, boolean flag, empty input)
  • 8 backward direction tests (subcommand reconsideration, nested commands, flag backtrack, empty input)
  • 3 flat agent backward tests (no subcommand table, boolean flag, trailing space)
  • 1 graceful fallback test (unknown agent with backward)
  • 2 catch-block tests with a throwing agent (throwtest) that exercises the error recovery path

Shell

  • 5 direction detection pattern tests (backspace, different text, forward typing)
  • 3 direction-change-while-PENDING tests (re-fetch trigger A7)
  • 2 spacePunctuation + direction interaction tests
  • All existing tests updated for parameter threading

Thread a CompletionDirection type through the entire completion
pipeline so completions can look ahead (forward) or reconsider
the previous part (backward) depending on user intent.

SDK & RPC:
- Add CompletionDirection = 'forward' | 'backward' to agentSdk
- Thread direction through agentRpc client/server and dispatcher
  RPC types

Grammar matcher:
- Support backward completion for literal parts (not just wildcards)
- Add lastStringPartInfo to MatchState for tracking the last matched
  literal position
- Fix lastWildcard bug: clear stale wildcard info when new wildcards
  are encountered so backward returns the correct startIndex
- Pass direction into tryPartialStringMatch for all categories

Construction cache:
- Thread direction through completion() and related cache methods
- Use matchedStarts for backward to locate the previous part position

Dispatcher:
- Update completion command and request handlers to accept and
  forward direction

Shell:
- Auto-detect direction in PartialCompletion.update(): backward only
  when the new input is a strict prefix of the previous input (genuine
  backspace), forward otherwise
- Remove explicit direction parameter from update(); reset
  previousInput before post-selection update instead
- Pass direction from PartialCompletionSession to dispatcher

Tests:
- Add backward completion tests for grammar matcher (7 sub-describes)
- Add backward completion tests for construction cache
- Add 8 backward tests for dispatcher completion
- Rename commitMode.spec.ts to direction.spec.ts; update shell tests
  for direction parameter threading
- Update all shell test files for parameter reordering
Grammar matcher:
- Fix empty input backward returning no completions: emitBackwardCompletion
  now returns false when there's nothing to back up to, allowing the caller
  to fall through to forward behavior
- Generalize lastStringPartInfo → lastMatchedPartInfo to track both string
  and varNumber parts, enabling backward completion to back up to number
  slots with property completions
- Refactor duplicate code across Categories 1-3 into three helpers:
  emitPropertyCompletion, emitStringCompletion, emitBackwardCompletion
- Add tests for empty input backward, varNumber backward, and forward

Dispatcher completion:
- Fix separatorMode incorrectly set to 'optional' when suffix exists
  (e.g. '@config agent --off'): the space between command and first
  parameter is structural, not trailing
- Agent separatorMode now only overrides when the agent advances
  startIndex via matchedPrefixLength (authoritative position),
  preserving the target-level separatorMode otherwise
Thread a directionSensitive boolean through the entire completion
pipeline so the shell can avoid wasteful re-fetches when the user
switches direction (forward ↔ backward) and the completions would
be identical.

Grammar matcher: compute directionSensitive from canBackward
(matched parts exist without trailing separator) and couldBackUp
(tryPartialStringMatch). Required field on GrammarCompletionResult.

Construction cache: track noTrailingSeparator × partialPartCount ≥ 1
to determine when forward and backward would pick different parts.

grammarStore: OR-merge directionSensitive across grammar entries.

Dispatcher: set directionSensitive on CompletionTarget (5 return
paths), merge with agent result via OR, propagate through
completeDescriptor and getCommandCompletion. Required field on
CommandCompletionResult.

Shell (PartialCompletionSession): store directionSensitive and
lastDirection from backend result. Re-fetch trigger A7: when
direction changed AND directionSensitive AND input === anchor
(at the direction-sensitive boundary). Once the user types past
the anchor, the loaded completions are reused regardless of
direction change.

Tests: 22 grammar, 8 construction cache, 7 dispatcher, 5 shell
direction tests added (all passing).
…stem

- Fix stale CompletionDirection comment (described 'current'/'next' but
  values are 'forward'/'backward')
- Fix garbled escape sequences in partialCompletionSession update() comment
- Remove dead default parameter from reuseSession() private method
- Unify 'trailing separator' / 'commit signal' terminology in dispatcher
- Fix stray comma in directionSensitive comment
- Add directionSensitive to CommandCompletionResult type block in docs
- Rename uncommittedCommand to reconsideringCommand for direction model
- Add inline comment at isEditingFreeFormValue call site
- Update grammar category table to show backward direction behavior
- Rename canBackward to couldBackUp for consistency with tryPartialStringMatch
- Move A7 (direction changed) from section C to section A in reuseSession
  comment and add it to completion.md table
…ce files

Add 'Architecture: docs/architecture/completion.md' comments pointing to
the relevant section in each source file that implements the completion
system:

- §1 Grammar Matcher: actionGrammar/grammarMatcher.ts
- §2 Cache Layer: cache constructionCache, cache.ts, grammarStore, constructionStore
- §3 Agent SDK: command.ts types, commandHelpers.ts
- §4 Dispatcher: dispatcher completion.ts
- §5 Shell Completion Session: partialCompletionSession.ts
- §6 Shell DOM Adapter: partial.ts
- §7 Shell Search Menu: searchMenuBase.ts, search.ts
- CLI integration: cli interactive.ts
- Data flow / Key types: dispatcher types dispatcher.ts
- Grammar: optional ()?, repeat ()+/()*, spacing=none, minPrefixLength backward
- Cache: conflicting directionSensitive across constructions
- Dispatcher: graceful fallback, catch block with throwing agent, flat agent backward
- Shell: direction change while PENDING, direction detection patterns, spacePunctuation + direction
@curtisman curtisman enabled auto-merge March 18, 2026 04:22
@curtisman curtisman added this pull request to the merge queue Mar 18, 2026
Merged via the queue into microsoft:main with commit eaa5329 Mar 18, 2026
13 of 15 checks passed
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.

1 participant