From 0acbbf45ad7cb885e3a2c2f52670b84647c1aade Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 3 Nov 2026 13:15:21 +0000 Subject: [PATCH] Skip sorting flag aliases during completion --- completion_context.go | 4 ++-- docs/roadmap/remediation.md | 21 ++++++++++++++++----- flag_aliases.go | 16 +++++++++++++++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/completion_context.go b/completion_context.go index c90232a..f1fa314 100644 --- a/completion_context.go +++ b/completion_context.go @@ -32,12 +32,12 @@ func resolveCompletionContext(snapshot *routingSnapshot, completed []string, cur return context } context.tail = append([]string(nil), context.route.args[len(context.route.canonicalPath):]...) - context.aliases = snapshot.flagAliases[context.route.canonicalPath.Key()].neutralRecords() + context.aliases = snapshot.flagAliases[context.route.canonicalPath.Key()].lookupRecords() context.commandPosition = len(context.tail) == 0 case routeDiscovery: context.command = &commandmeta.Command{CoreFlags: commandmeta.ReportingFlags()} context.tail = append([]string(nil), context.route.args...) - context.aliases = snapshot.discoveryFlags[context.route.discoveryPath.Key()].neutralRecords() + context.aliases = snapshot.discoveryFlags[context.route.discoveryPath.Key()].lookupRecords() } return context } diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 152e4fd..753ddeb 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -1,7 +1,7 @@ # Shell completion audit remediation -Status: six fixes open; two efficiency findings for consideration. The completed invocation reporting audit is retained -below as historical evidence. +Status: all eight shell completion findings addressed. The completed +invocation reporting audit is retained below as historical evidence. ## Completion review scope @@ -133,7 +133,7 @@ even with `--quiet --debug` in the target words. The equivalent ordinary inspection with `--quiet` stayed silent. ConfigKit completion included `app` and `promptkit` for diff, and additionally `all` for validate, matching the installed capabilities. No new discrepancy was found in these paths. -The transport and public metadata findings above remain open. +The transport and public metadata findings were open at that review. ### 6. Supply the existing PromptKit smoke kinds as operand hints @@ -165,7 +165,7 @@ encoding are linear in the candidates and text they inspect or emit. Stage 4 expressly requires checking each suggested child against ordinary alias routing; this review does not propose removing or replacing that check. No additional correctness defect or newly introduced quadratic algorithm was identified within -the remaining scope. The six existing findings remain open. +the remaining scope. The six existing findings were open at that review. ### 7. Look up canonical completion metadata without scanning siblings @@ -190,7 +190,9 @@ refresh and the selected candidate insertion checks. ### 8. Avoid sorting resolved flag aliases on every completion query -Priority: P3. Status: for consideration. +Priority: P3. Status: complete. + +- [x] Completed: Completion builds its lookup records directly from unique resolved aliases in linear time. Existing help ordering is unchanged; scoped and discovery completion checks pass. [resolveCompletionContext](../../completion_context.go) calls [neutralRecords](../../flag_aliases.go) for the selected canonical or discovery @@ -207,6 +209,15 @@ display order matters and preserve scoped precedence and target availability. This is a source-level opportunity; no latency or allocation threshold is proposed. +## Shell completion remediation validation + +The root and both optional module suites passed in the local workspace, and +the root suite passed with `GOWORK=off`. Both opt-in interactive completion +suites passed with Bash 5.3.9, Zsh 5.9, and Fish 4.2.1. They cover literal +Tab-only input, actual edited arguments, attached and whole-word completion, +path hints, descriptions, and control-like literal choices. The ignored +workspace and module dependency versions were preserved. + --- ## Historical invocation reporting audit remediation diff --git a/flag_aliases.go b/flag_aliases.go index 560f7cd..f7d09f3 100644 --- a/flag_aliases.go +++ b/flag_aliases.go @@ -38,11 +38,25 @@ func (aliases resolvedFlagAliases) neutralRecords() []commandmeta.FlagAlias { records := make([]commandmeta.FlagAlias, 0, len(keys)) for _, key := range keys { alias := aliases.bySpelling[key] - records = append(records, commandmeta.FlagAlias{Source: alias.source.token(), Target: alias.target.token()}) + records = append(records, alias.neutralRecord()) } return records } +// lookupRecords skips sorting: resolved source spellings are unique and the +// parser's lookup does not depend on record order. +func (aliases resolvedFlagAliases) lookupRecords() []commandmeta.FlagAlias { + records := make([]commandmeta.FlagAlias, 0, len(aliases.bySpelling)) + for _, alias := range aliases.bySpelling { + records = append(records, alias.neutralRecord()) + } + return records +} + +func (alias resolvedFlagAlias) neutralRecord() commandmeta.FlagAlias { + return commandmeta.FlagAlias{Source: alias.source.token(), Target: alias.target.token()} +} + func (spelling capturedFlagSpelling) token() string { if spelling.short { return "-" + spelling.name