Skip to content

Add openWildcard signal for sliding wildcard boundaries#2021

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

Add openWildcard signal for sliding wildcard boundaries#2021
curtisman merged 8 commits intomicrosoft:mainfrom
curtisman:curtism/completion-direction

Conversation

@curtisman
Copy link
Member

Add openWildcard boolean to the completion pipeline (grammar matcher →
cache → dispatcher → shell) to handle ambiguous wildcard boundaries.

When a grammar wildcard is finalized at end-of-input and the following
keyword is offered as a completion, the wildcard extent is uncertain.
Previously closedSet=true would permanently block re-fetching (CJK)
or cause wasteful per-keystroke re-fetches (Latin).

The shell now uses anchor sliding: instead of re-fetching or giving up,
it slides the anchor forward on further input. The trie stays intact so
the menu re-appears at each word boundary. Recovery is automatic via
trigger B4 when the user types the keyword.

Also fixes request/match/translate command handlers dropping openWildcard and
directionSensitive from requestCompletion() results.

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
Add openWildcard boolean to the completion pipeline (grammar matcher →
cache → dispatcher → shell) to handle ambiguous wildcard boundaries.

When a grammar wildcard is finalized at end-of-input and the following
keyword is offered as a completion, the wildcard extent is uncertain.
Previously closedSet=true would permanently block re-fetching (CJK)
or cause wasteful per-keystroke re-fetches (Latin).

The shell now uses anchor sliding: instead of re-fetching or giving up,
it slides the anchor forward on further input. The trie stays intact so
the menu re-appears at each word boundary. Recovery is automatic via
trigger B4 when the user types the keyword.

Fix request/match/translate command handlers dropping openWildcard and
directionSensitive from requestCompletion() results.
@curtisman curtisman enabled auto-merge March 18, 2026 15:11
@curtisman curtisman added this pull request to the merge queue Mar 18, 2026
Merged via the queue into microsoft:main with commit a4e8b06 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