Skip to content

feat(config): stdlib "did you mean?" suggestions#22

Merged
srnnkls merged 2 commits into
mainfrom
feat/stdlib-didyoumean-suggestions
Jun 27, 2026
Merged

feat(config): stdlib "did you mean?" suggestions#22
srnnkls merged 2 commits into
mainfrom
feat/stdlib-didyoumean-suggestions

Conversation

@srnnkls

@srnnkls srnnkls commented Jun 27, 2026

Copy link
Copy Markdown
Owner

What

Adds Levenshtein-based "did you mean?" hints for the fas stdlib. Previously the edit-distance suggester only fired for missing input keys (E0201); typo'd stdlib references produced a bare "undefined field" with no hint. Now a misspelled stdlib member gets a ranked suggestion rendered as a second caret under the error.

error[E0501]: ... undefined field: #Explor
  --> orient.cue:9:36
9 |     when: hook.#SubagentStart & agent.#Explor
  |                                       ^ undefined field: #Explor
9 |     when: hook.#SubagentStart & agent.#Explor
  |                                 ^^^^^^^^^^^^^ did you mean `agent.#Explore`?

How

  • internal/strdist — lifts the rune-scoped edit-distance DP out of internal/evaluator into a leaf package (Distance + Nearest); the two evaluator call sites (E0201 key-missing, disjunction arm ranking) now use it. Behavior identical; the comprehensive distance fixtures moved with it.
  • Dynamic stdlib index (StdlibIndex) — discovers sub-packages and their exported #Defs from the embedded FS. No hardcoded package list, so it tracks whatever stdlib the binary ships (a test pins index keys == discovered sub-package dirs).
  • suggest() — pure ranker/phraser. Qualified refs (pkg.#Member) rank their own package first, then fall back across the other packages (prefixing the package); bare idents rank AST-local names plus all stdlib members. Threshold max(2, len/3), top-3, comma phrasing without an Oxford comma.
  • Attachment on both error paths — qualified selector typos resolved at compile time via the file AST (agent.#Explor), bare unbound identifiers at lint time (E0501). Any locate miss → no note, never a wrong one.

No new error codes; suggestions reuse the existing Notes rendering.

Scope

Implements T1–T4 of the validate-cmd-and-suggestions design. The fas validate subcommand (T5–T7) is intentionally deferred to a follow-up — it's separable plumbing, and this PR is the part that directly answers "did you mean for the stdlib."

Testing

  • internal/strdist: Distance parity + Nearest threshold/top-N/tie-break/empty.
  • StdlibIndex: members discovered, typo absent, keys match embedded dirs, memoization.
  • suggest: qualified/cross-package/bare/no-match + phrasing.
  • End-to-end loader tests: qualified typo attaches agent.#Explore, far miss attaches nothing, bare typo attaches the local helper.
  • Full suite + go vet + golangci-lint green via the pre-commit gate.

srnnkls added 2 commits June 27, 2026 17:22
Post-merge fixes from the branch-diff review of the fas vet + FAS_LOG
payload-logging work.

debuglog:
- gc now removes only files matching the generated log-file name pattern
  (timestamp + 8 hex), so pointing FAS_LOG at a directory holding other
  *.json never deletes them (data-loss footgun).
- shortID rand-failure fallback widened to 8 chars so gc still matches it.
- unexport the test-only GC/LogFiles and drop the Dir() accessor; tests
  use the package-private forms.

cmd/fas:
- collectDiagErrors recurses into errors.Join children before the
  tree-descending errors.As, so `fas vet --format json|sarif` no longer
  duplicates the first diagnostic.
- record the preprocessed input envelope in the debug log (the advertised
  `input` field was never populated).
- vet rejects stray positional arguments instead of silently ignoring them.
- vet routes capability errors through the format-aware renderer and emits
  SARIF on success under --format sarif (was plain text).
- vet success summary writes to stdout instead of the errorf
  stderr-diagnostic helper; drop the inert --color flag from vet.
- extract registerCommonFlags shared by eval/explain/vet.
- document FAS_LOG payload sensitivity in the usage text.

Regression tests added for gc foreign-json preservation, the join
de-duplication, vet positional-arg rejection, and vet SARIF output.
Lift the rune-scoped edit-distance DP out of internal/evaluator into a
leaf package internal/strdist (Distance + Nearest); re-point the two
evaluator callers. Build a stdlib member index by discovering sub-packages
and their exported #Defs dynamically from the embedded FS — no hardcoded
package list, so it tracks whatever stdlib the binary ships.

A pure suggest() ranks candidates (qualified: own package then a
cross-package fallback; bare: AST-local names plus all stdlib members) and
phrases the hint. Attach it as a diagnostic Note on both error paths:
qualified selector typos (agent.#Explor) at compile time via the file AST,
and bare unbound identifiers at lint time (E0501). A locate miss yields no
note, never a wrong one.

Covers design tasks T1-T4 of validate-cmd-and-suggestions; the `fas
validate` subcommand (T5-T7) is deferred.
@srnnkls
srnnkls merged commit a57c00a into main Jun 27, 2026
5 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