Been a couple of months since the last release, so a lot's packed in here. v0.11 is headlined by two major new subsystems - a static type checker and a much richer language server - plus a canonical formatter, built-in docs, and interactive argument entry.
✨ Highlights
Static type checker. Rad now catches whole classes of mistakes before your script runs: provable type mismatches, unknown typed-map keys, out-of-scope identifiers, and more - with type narrowing across if/while/for/switch/catch and closures. Uncertain cases stay non-blocking so it doesn't get in your way.
Our language server, radls, sees massive improvements. Hover, go-to-definition, find-references, rename, completion, semantic tokens, document symbols, and quick-fix code actions - backed by incremental parsing.
rad fmt - canonical formatter. One true formatting for Rad scripts, including args blocks and for with-clauses, driven by a documented rule catalog.
rad docs - docs in the binary. Look up any built-in straight from the CLI (rad docs <name>), no internet required.
Interactive argument entry (-i / --interactive). Fill in a script's arguments through a guided prompt, with a colorized transcript and the equivalent invocation echoed back. Interactive prompts (input, confirm, pick, multipick) are now powered by our own radish library.
Signal handling. New signal_trap and signal_ignore builtins, and defer blocks now run on SIGINT/SIGTERM for clean shutdown.
🧰 New builtins
- to_json() - serialize values to JSON
- get_pid() - current process ID
- parse_duration() now accepts a w (weeks) suffix
- Time maps now include a weekday field
And various bug fixes, see list of commits below.
Don't hesitate to ask questions or raise issues!
Changelog
- 176e3e9 chore(check): tighten resolve types and binder issue plumbing
- 7649595 docs(check): fix stale Hint note in typed_local snapshot
- 62581d9 docs(errors): sweep error_docs comments + add validation test
- e9409a0 docs(fmt): document full-convergence vision and roadmap
- 956b619 docs(type-system): document scoping and name resolution
- 613e2b8 feat!: reject inapplicable global flags on built-in commands
- d9a8608 feat(check): T? suggestion in every nullable type position
- 9c788fe feat(check): add Scope/Symbol/Resolved name-resolution layer
- 11b67a5 feat(check): add bidirectional type-checker skeleton
- af4d5e1 feat(check): add binder-emitted issues + duplicate-param diagnostic
- 3818769 feat(check): add narrowing primitives + null predicate
- aa0e16f feat(check): bind for / while / list-comp scopes
- d324dc9 feat(check): bind function and lambda parameter scopes
- b7ce7ae feat(check): bind switch / defer / cmd_block scopes
- d437dfe feat(check): catch block narrows target to error
- a7bcfc8 feat(check): catch indexed assignment of wrong element type
- f276968 feat(check): closure rule drops narrowing on reassigned captures
- 876ce87 feat(check): collapse uninhabited tuples in union joins
- a57904b feat(check): detect unreachable switch cases (RAD40012)
- de97305 feat(check): diagnose lambda return body vs declared mismatch
- 6a0fe53 feat(check): enforce args-block and cmd-block types statically
- e33fd26 feat(check): faithful typing for fallible calls and literals
- 45e2a21 feat(check): for/while loop narrowing
- e83aa78 feat(check): gate provable type mismatches as errors
- d3cb295 feat(check): infer hoisted fn return types with SCC ordering
- 997def0 feat(check): infer lambda return type for structural matching
- 451af1d feat(check): infer tuple return type for multi-value returns
- ebe5242 feat(check): not / and / or narrowing predicates
- 684a7e4 feat(check): operator overload table for static expression types
- 2f95f53 feat(check): per-arg type-check on builtin calls
- 3e2537d feat(check): plumb suggestions through static diagnostics
- 85b5d87 feat(check): pre-plant lambda signature for recursive references
- 070e917 feat(check): promote provable type diagnostics to Error
- 9de2d1c feat(check): reassignment widening for while-loop bodies
- b2b0d6e feat(check): refine catch/?? result types
- e04715e feat(check): reject typed re-declaration (RAD40011)
- 68a78e1 feat(check): snapshot harness runs full Check() pipeline
- 7f4231d feat(check): static arity-check builtin calls
- 78dc8c9 feat(check): static call typing for user-defined functions
- cddc15e feat(check): static synthesis for list and map literals
- ec36cf9 feat(check): static undefined-identifier diagnostic with did-you-mean
- f131715 feat(check): structural matching for fn-value arguments
- 0d71264 feat(check): suggest '?' when 'null' appears in a type union
- c5a3a70 feat(check): switch narrowing + exhaustiveness diagnostic
- ce1aca9 feat(check): tighten ErrorType cascade prevention
- 33067e6 feat(check): truthy null-strip and in-literal-list narrowing
- 068f1d0 feat(check): type for-loop vars from union iterables and map k/v pairs
- c1ee6e9 feat(check): type_of, string-enum, in/not-in predicates
- 41d317b feat(check): typed local declarations end-to-end
- af58a63 feat(check): walk lambda bodies under captured frame
- 53da9c0 feat(check): wire narrowing through if/elif/else
- 69b4a84 feat(check,radls): diagnose unknown typed-map keys + key completion
- e7af68c feat(errors): retire dead parser codes + invest in three high-value ones
- 4ade0bd feat(fmt): add 'rad fmt' canonical formatter
- a16e46a feat(fmt): turn formatting rules into a documented catalog
- 60fdaa5 feat(lsp): resolve command callback references
- bf1a416 feat(radls): UFCS-aware completion ranking
- 3153632 feat(radls): add textDocument/definition
- b410882 feat(radls): add textDocument/documentSymbol
- 6241558 feat(radls): add textDocument/hover
- df4e1c1 feat(radls): add textDocument/references
- b977872 feat(radls): add textDocument/semanticTokens/full
- 8cb11d1 feat(radls): code actions surface diagnostic quick fixes
- 29446ba feat(radls): debounce diagnostics publishing per URI
- 8aaaeb9 feat(radls): filter internal builtins + parameter token for args
- cd70d46 feat(radls): immutable DocumentVersion snapshots per document
- 492c0dd feat(radls): introduce FileID indirection for documents
- 65a230e feat(radls): negotiate LSP position encoding via LineIndex
- 2e0b232 feat(radls): plumb context.Context and wire $/cancelRequest
- e4b2022 feat(radls): real completion - scope-walk + type-aware
- f9ee5c2 feat(radls): semantic tokens for type annotations
- b2ce132 feat(radls): structured docs in builtin hover + funcs doc infrastructure
- 7396532 feat(radls): textDocument/rename
- 4363b5c feat(types): add Dynamic (implicit any) distinct from explicit Any
- 640f213 feat(types): add ErrorType poison for static-check cascade prevention
- 35208d9 feat(types): add IsAssignableFrom to TypingT interface
- 80cfc24 feat(types): add Never bottom type for narrowing exhaustiveness
- b3dba6b feat(types): parens type groups + inline-colon lambdas + drop list[T]
- d4ade01 feat(typing): introduce TypingNullT for sound null literal handling
- a446ae8 feat: add get_pid() builtin
- dc047f6 feat: add signal_trap and signal_ignore builtins
- 5f80b7a feat: add to_json() builtin
- 05a233e feat: add weekday field to time maps
- 1834da2 feat: back pick() with radish instead of huh
- a2b47a3 feat: clean and navigate the rad docs corpus
- 8be4d28 feat: colorize the -i transcript and equivalent invocation
- 4c74002 feat: docs/funcs/ as source-of-truth for builtins + diagnostic sweep
- 841d4e2 feat: format the args block in rad fmt
- f3055f8 feat: interactive arg-entry mode (--interactive / -i)
- 8b35833 feat: make signal force-exit testable and shutdown deterministic
- 3a54604 feat: parse_duration accepts 'w' (weeks) suffix
- 6c3040d feat: readable -i transcripts and grouped bool multi-pick
- ed21d6e feat: replace huh with radish for input/confirm/multipick
- b4ad6b0 feat: run defer blocks on SIGINT/SIGTERM exit
- 475af15 feat: serve documentation from the binary via rad docs
- dae8dfa fix(benchmark): migrate off removed $! shell syntax
- 126df53 fix(check): accept string literals matching a StrEnum param
- 4b29812 fix(check): bind scopes only at function boundaries
- 8eadc6d fix(check): consult builtin set for cmd-callback resolution
- a928822 fix(check): deep divergence scan for branch joins
- dc7bc20 fix(check): give dynamic union arms bare-dynamic leniency in operators
- 35d6990 fix(check): isolate nested function bodies from outer narrowing
- 95890d8 fix(check): keep uncertain type mismatches non-blocking
- 957271a fix(check): narrowByTypeOf preserves null arm of Optional
- fca8db5 fix(check): null soundness in unions + promote bare-null mismatch
- 9d986d8 fix(check): stop false positives on valid scripts (#129-131, #133)
- fa4872f fix(check): structural union subsumption in joinFrames
- 57eb321 fix(check): switchDiverges read ExprTypes, don't re-enter synth
- cb769ac fix(check): while loop carries body frame mutations forward
- 7e9ca52 fix(check): widen while-loop narrowing on nested reassignments
- 12a4c7b fix(check, radls): name-precision DeclSpans for params/loop vars
- 39c90b6 fix(check, radls): point fn DeclSpan + SelectionRange at name
- d85f630 fix(radls): Mux.Notify - drop dead branch, omit nil params
- d3233ff fix(radls): correct inverted nil check in newError
- b62b89d fix(radls): debouncer race - superseded callback no longer clobbers successor
- 5a0fac0 fix(radls): dispatch quick fixes on error code, not message text
- d90a3de fix(radls): emit semantic token at fn name definition site
- a003530 fix(radls): file-scope completion respects cursor position
- d174a1e fix(radls): find references / goto-def from fn / args decl sites
- 9c587ee fix(radls): hover - nil for unresolved, drop redundant builtin tag
- f7edd7e fix(radls): refcount DocumentVersion to free tree-sitter C memory
- be4c7da fix(radls): release per-request context cancel funcs
- 5d0f42b fix(radls): scope-proximity completion order via SortText
- 4747f1f fix(radls): sort document symbols in source order
- 3be5ad7 fix(radls): suppress info-only code actions from the lightbulb
- fb92f6f fix(shell): don't crash when a confirm prompt is aborted
- 990e926 fix(signatures): complete type_of return enum
- 991e30a fix(types): close silent runtime enforcement gaps
- a60a9b7 fix: catch handlers losing caller scope on nested error propagation
- f607b00 fix: drop empty Examples markers from generated function docs
- 200d43b fix: drop stray "=" artifact in multipick docs
- 226277f fix: expand leading ~ in path builtins
- 8416607 fix: explain under-indented multi-line string errors
- 5ae7343 fix: harden -i argv synthesis and align walk with ra semantics
- 2a83f61 fix: keep go:embed'd doc corpora LF on Windows checkouts
- 6f9e554 fix: make --shell reserve stdout for eval-able output on help
- bd6b192 fix: normalize docs/funcs source to LF to match its embedded copy
- d2393a0 fix: preserve for-loop with-clause in rad fmt
- 8b0f39c fix: report out-of-range int literals instead of panicking
- 686be9d fix: unify any[], dynamic[], and list into one type
- c7ba354 fix: write state and stash files atomically
- 72160d0 refactor(check): emit fn/arg shadowing from the binder
- 414f3e2 refactor(check): route cmd-callback hint through resolved view
- 6fe1639 refactor(radls): bind encoding into DocumentVersion
- d460e82 refactor(radls): consolidate AST walk + span helpers
- 32d7f37 refactor(radls): handlers grab snapshots at the request boundary
- 03dcc61 refactor(rts): RadTree holds language not parser - close cgo trap
- 8ae4efd refactor: adopt radish's cleaner pick result contract
- fe92034 style(check): fix shell-escape artifacts in comments
- 3319e1e style: reformat code
- c608290 test(check): comprehensive snapshot coverage for narrowing
- 677b79a test(check): snapshot harness for narrowing
- 535a564 test(radls): differential harness for incremental vs from-scratch
- 816efe5 test(radls): extend lstesting harness with 5 new action types
- 2952d3e test(radls): port documentSymbol cases to wire-level snapshot
- ae57e98 test(radls): port findReferences cases to wire-level snapshot
- ca0310e test(radls): port goto-definition cases to wire-level snapshot
- 27ad1b5 test(radls): port hover behavior cases to wire-level snapshot
- b3ee77c test(radls): port semanticTokens cases to wire-level snapshot
- e7b31a2 test(radls): trim completion + code-action Go tests
- 552f59d ux(radls, check): contextual rename errors + did-you-mean grammar + hover stutter