RiX editor, language-server, execution, and AI tooling
This historical proposal specifies the intended RiX authoring toolchain. Use editor and coding-agent tooling for the current commands, integrations, and supported boundaries. Checked items in the implementation checklist already exist in the RiX repository. Unchecked items are proposed work and must not be presented as current behavior.
Objective
RiX should provide a responsive authoring experience in VS Code and other editors, a safe way to run and inspect programs, structured reporting for inline checks and tests, and deterministic feedback that coding agents can consume without scraping human-oriented terminal output.
The implementation should expose one portable language-service core rather than putting RiX semantics directly into each editor integration. A VS Code extension is the first full client, but the static analysis and execution protocols must remain host-neutral.
Goals
- Highlight and edit
.rixfiles, RiX documentation fences, and supported embedded notations accurately while a document is incomplete. - Report parser and lint diagnostics with stable codes and exact source ranges.
- Provide completion, hover, symbols, navigation, rename, code actions, formatting, and plugin/custom-operator awareness through an LSP server.
- Run files and selections without blocking the editor or language server.
- Surface
.Test,##@,##:, and##!results through structured events and appropriate native editor UI. - Render RiX’s portable rich outputs without making the editor a new evaluator or renderer authority.
- Give CI and coding agents stable JSON commands for the complete edit-check-run loop.
- Preserve RiX capability groups, plugin approval, and workspace trust at every execution boundary.
Non-goals
- The LSP server does not evaluate arbitrary source to answer completion, hover, navigation, or lint requests.
- The VS Code extension does not become the source of truth for parsing, plugin resolution, formatting, or runtime semantics.
- The first release does not implement a full step debugger. Structured diagnostics, traces, AST/IR inspection, and restartable execution come first.
- The first release does not require Tree-sitter, a Jupyter kernel, an MCP server, or separate implementations for every editor.
- Rich output does not permit unsanitized plugin HTML or workspace scripts to execute in the extension host or webview.
Resolved implementation decisions
The initial design review established these defaults:
- The extension begins in
rix/editors/vscode, not a separate repository. It retains its own package, version, build, tests, and release workflow. - Desktop is the first complete target. The portable language-service core and extension client should avoid unnecessary Node-only coupling so static web support can follow. A later web worker should reuse the evaluator subset already proven by RiX Web.
- Desktop execution uses the Node-compatible runtime supplied by VS Code and a version-matched worker bundled with the extension. The first release does not discover or require Bun.
- Inline checks participate in Check File and display source feedback by default. Discovery, source decorations, and Test Explorer publication are independently configurable.
- Formatting uses a Prettier-style document model with readable and compact profiles. It borrows the settled principles of JavaScript formatters without pretending RiX is JavaScript.
- Static plugin discovery may read and validate declarative headers and RiX operator declarations, but must not import or evaluate plugin modules.
- Portable output is the preferred preview boundary. Complete HTML renderer output is untrusted input to a webview and is never inserted directly.
rix.jsonfollows nearest-package configuration discovery. Parent configuration is inherited only through an explicitextendsfield.- The editor’s standard execution profile permits sandboxed RiX imports and approved permissionless plugins while denying network access, general file access, workspace JavaScript installers, and unrestricted background work.
Existing foundation
The first implementation should reuse these current components rather than replace them:
| Component | Current state | Intended reuse |
|---|---|---|
| Pratt parser and tokenizer | Implemented; semantic source of truth | Valid-document AST, static analysis, lowering, and execution |
| Lezer grammar and CodeMirror support | Implemented and tested | Error-tolerant editor structure, folding, indentation, highlighting classes, and embedded regions |
analyzeRix / lintRix |
Implemented | LSP diagnostics and code-action inputs |
explainRixScopes |
Implemented | Capture diagnostics, hover, local navigation, and rename safety |
complete |
Implemented for live contexts | Completion candidate model and runtime-session completion |
| CLI runner and REPL | Implemented | Execution behavior and initial worker adapter |
.Test and diagnostics registry |
Implemented | Structured test and diagnostic reporting foundation |
##@, ##:, and ##! |
Implemented | Inline checks and value-preserving diagnostic taps |
| Portable output and renderer registry | Implemented | Rich preview payloads and artifact rendering |
The important gaps are exact ranges on every relevant diagnostic, preservation of source locations through lowering, pass events for inline checks, a stable machine protocol, static symbol metadata independent of a live evaluator session, and editor packaging.
Architecture
flowchart TD
S["RiX source and workspace configuration"]
C["Portable language-service core"]
P["Tokenizer / Pratt parser"]
E["Lezer editor parser"]
A["Lint, scopes, symbols, docs, formatting"]
L["RiX language server"]
X["Structured CLI"]
W["Restartable execution worker"]
V["VS Code extension"]
O["Other LSP editors"]
I["CI and coding agents"]
U["Problems, Testing, Output, and rich preview"]
S --> C
C --> P
C --> E
C --> A
C --> L
C --> X
C --> W
L --> V
L --> O
X --> I
W --> V
V --> U
Proposed source layout
Keep portable logic inside the RiX package and editor packaging outside its runtime surface:
rix/
src/tools/language-service/ document model, symbols, diagnostics, docs
src/tools/lsp/ LSP request/response adapter
src/tools/execution/ worker protocol and event serialization
src/tools/codemirror/ existing CodeMirror integration
src/tools/lezer/ existing tolerant editor grammar
bin/rix-language-server.js stdio LSP entry point
bin/rix-worker.js isolated execution entry point
editors/vscode/ VS Code client, grammar, snippets, views
The VS Code extension may move to a separate repository when publishing and release cadence require it. Its client/server protocol must not depend on its physical repository location.
Process boundaries
The system has three distinct processes or logical workers:
- Extension client: owns VS Code registration and UI only.
- Language server: owns side-effect-free document and workspace analysis.
- Execution worker: owns mutable RiX contexts, plugin loading, evaluation, background tasks, and runtime diagnostics.
The language server must remain responsive if evaluation hangs or exhausts a work budget. Killing or restarting an execution worker must not discard LSP document state.
Parsing and grammar policy
The Pratt parser remains the semantic authority. The Lezer grammar remains the error-tolerant editor grammar and must accept useful partial source while the user types.
- A complete document is semantically parsed with the Pratt parser.
- Lezer supplies structure, folding, indentation, selection ranges, lexical highlighting, and fallback syntax errors for incomplete source.
- Semantic lint runs only over a trustworthy Pratt AST. A parse failure must not produce misleading downstream scope diagnostics.
- A small TextMate grammar provides immediate baseline VS Code highlighting. Semantic tokens refine it after analysis.
- Shared token/operator metadata and golden source fixtures should generate or test all three grammar surfaces to detect drift.
- Embedded backtick regions retain their explicit notation identity. Hosts may delegate to a registered embedded-language parser but must preserve the original RiX range mapping.
Language Server Protocol surface
The server communicates over stdio first. It should use standard LSP methods wherever they fit and custom requests only for RiX-specific inspection.
Required first-release methods
| LSP capability | RiX source |
|---|---|
| Diagnostics | Pratt parse plus analyzeRix |
| Completion | Static catalog, document scopes, plugin metadata, and adapted complete candidates |
| Hover | Symbol catalog, inferred ownership, operator and container help |
| Signature help | Callable catalog and current call argument |
| Document symbols | Assignments, functions, reactive cells, tests, and named containers |
| Definition | Current document declarations and resolved imported/operator definitions |
| References | Scope-aware identifier index |
| Rename | References with capture and system-name safety checks |
| Code actions | Machine-applicable lint fixes and safe syntax repairs |
| Folding ranges | Lezer container and comment structure |
| Selection ranges | Nested Lezer/AST structure |
| Semantic tokens | Declaration/reference roles, system names, captures, reactive names, methods |
| Formatting | Conservative token/AST formatter |
Later standard methods
- workspace symbols;
- call hierarchy;
- inlay hints for inferred capture direction, structural shape, or plugin origin where they remain low-noise;
- code lens for run, check, test, AST, and IR commands;
- linked editing and document links for imports, operator files, plugins, and documentation;
- pull diagnostics if client support justifies them.
RiX-specific requests
Custom requests should be few, versioned, and useful outside VS Code:
rix/explainScope
rix/inspectAst
rix/inspectIr
rix/runtimeCompletions
rix/catalog
Runtime completions require an explicit execution-session ID. Static requests must never silently start or mutate a session.
Completion behavior
Completion combines several side-effect-free providers:
- lexical and syntactic candidates appropriate to the cursor;
- current and enclosing document bindings;
- configured plugin and system-capability catalog entries;
- custom operators visible to the document;
- statically known members and map keys;
- snippets for brace containers, functions, tests, checks, and diagnostics;
- optional live-session values requested explicitly from the execution worker.
Every item should include a kind, insertion text, replacement range, signature or short detail, documentation, source/plugin identity, and a stable sort key. The server must not evaluate receiver expressions to discover members.
Formatting
Formatting should be conservative until RiX style is settled. The implementation should use a Prettier-style document algebra—groups, indentation, soft lines, and a print width—so the same syntax can choose a compact or expanded layout deterministically.
The initial profiles are:
| Profile | Purpose | Initial behavior |
|---|---|---|
readable |
Default source and documentation style | Candidate B: four-space indentation, printWidth: 100, spaces around infix operators and after separators, and balanced multiline blocks/containers when structure or comments benefit from it |
compact |
Dense formulas, examples, and small containers | Candidate A: retain or choose single-line groups more aggressively, while respecting the configured print width and mandatory sigil spacing |
Both profiles share the same semantics and only differ in line-breaking preferences. Candidate C is not a separate profile; its fully expanded layout is a last-resort fallback when width, comments, or deeply nested structure make the balanced layout impractical. The first stable formatter contract is intentionally narrow:
- preserve comments, tagged comments, documentation markers, and embedded notation contents;
- preserve the meaning and line-scoped behavior of
##@,##:, and##!; - keep a postfix check or diagnostic tap on the same logical line as its value;
- normalize unambiguous whitespace around operators, separators, assignments, arrows, and brace sigils;
- preserve statement separators in the first version rather than inserting or removing semicolons globally;
- be idempotent;
- avoid changing custom operator precedence through parenthesis removal;
- format only successfully parsed regions when a document contains errors;
- support whole-document, range, and format-on-type requests eventually;
- expose
rix format,rix format --check, and editor formatting through the same implementation.
Golden formatting fixtures must include every brace sigil, nested comments, custom operators, reactive syntax, async scopes, diagnostic taps, and embedded backtick forms.
Formatter candidate fixtures
“Short mathematical containers” means ordinary small arrays, maps, sets, tuples, and brace-sigil containers that hold formulas or exact values. It does not name a separate RiX feature. The selected formatter contract uses Candidate B for readable, Candidate A for compact, and Candidate C only as the last-resort expansion of groups that cannot remain clear in the balanced layout. All three examples parse today and represent the same program.
Candidate A, compact profile:
settings := {= bounds={: -3, 3 }, samples=[1/4, 1/2, 3/4], exact=1 };
total := settings[:samples]
|>? (x) -> x > 1/3
|>> (x) -> x^2 + 1
|>: (sum, x) -> sum + x;
## Keep the check attached to the expression it describes.
total ##@ > 0;
Candidate B, balanced readable (default):
settings := {=
bounds = {: -3, 3 },
samples = [1/4, 1/2, 3/4],
exact = 1
};
total := settings[:samples]
|>? (x) -> x > 1/3
|>> (x) -> x^2 + 1
|>: (sum, x) -> sum + x;
## Keep the check attached to the expression it describes.
total ##@ > 0;
Candidate C, fully expanded containers (last-resort fallback):
settings := {=
bounds = {:
-3,
3
},
samples = [
1/4,
1/2,
3/4
],
exact = 1
};
total := settings[:samples]
|>? (x) -> x > 1/3
|>> (x) -> x^2 + 1
|>: (sum, x) -> sum + x;
## Keep the check attached to the expression it describes.
total ##@ > 0;
The current common rules are independent of that selection:
- a broken pipeline places the pipe operator first on the continuation line;
- continuation pipes indent one level relative to the assignment/expression;
- comments are not automatically wrapped or moved;
- postfix checks/taps remain attached to the expression line even when that line exceeds
printWidth; - a user can select
compactexplicitly when dense formulas are preferred.
Workspace configuration
The toolchain should support a versioned rix.json at the workspace or package root. Source headers continue to provide per-file declarations. Command-line arguments override file and workspace configuration in the usual order.
Proposed initial shape:
{
"$schema": "https://rix.ratmath.com/schema/rix.schema.json",
"version": 1,
"plugins": ["standard"],
"operatorFiles": [],
"preamble": null,
"lint": {
"level": "standard",
"profiles": ["default"]
},
"format": {
"enabled": true,
"profile": "readable",
"printWidth": 100,
"indentWidth": 4
},
"execution": {
"mode": "isolated",
"timeoutMs": 10000,
"capabilityGroups": ["standard"],
"artifactDirectory": ".rix-output"
}
}The extension bundles the version-matched Node-compatible worker and does not perform runtime discovery in the first release. Protocol-major mismatches, unsupported configuration schema versions, and a worker missing a required advertised feature are hard failures. A newer compatible minor/patch component may produce a warning after successful capability negotiation, though the normal bundled installation should keep extension, server, and worker versions exactly aligned.
Configuration discovery starts at the document directory and selects the nearest rix.json, stopping at the active workspace-folder boundary. There is no implicit merge with more distant files. A configuration may declare extends, resolved relative to that file with cycle detection and the same workspace/trust boundaries. Source headers add file-local plugins and operator files but cannot widen execution permissions.
The remaining exact fields and capability group membership require a compatibility review against runtime configuration. The schema must reject unknown security-sensitive keys and provide descriptions/defaults to editors.
The language server watches resolved configuration, operator files, plugin metadata, and preambles. It invalidates only documents whose effective inputs changed.
VS Code extension
Declarative language support
The extension contributes:
- language ID
rixand.rixfile association; - TextMate grammar and Markdown/Quarto fence injection;
- language configuration for comments, brackets, autoclosing, surrounding, indentation, and folding;
- snippets for common RiX constructs;
- semantic-token scope mappings compatible with ordinary themes;
- configuration schema and settings;
- commands, menus, keybindings, view containers, and Testing integration.
The extension should use ordinary theme scopes and semantic token types before introducing RiX-specific types. System capabilities, outer captures, reactive cells, and embedded notations may use custom modifiers when standard token types are insufficient.
Native UI mapping
Use existing VS Code UI before adding custom webviews:
| Information | Primary surface |
|---|---|
| Parse, lint, and runtime errors | Problems and editor squiggles |
| Final scalar/text result | Output channel and optional inline decoration |
.Test groups and cases |
Test Explorer |
##@ and ##: checks |
Gutter decoration, CodeLens, and optional Test Explorer items |
##! Dump / Info |
Output channel or Diagnostics tree |
##! Trace / Debug |
Expandable tree with source navigation |
| AST and IR | Read-only virtual document |
| Graphics, plots, sheets, controls, HTML, and documents | Rich preview webview |
| Declared files | Artifact tree and normal file links |
Inline decorations are summaries, not the only record. Every result remains available through an accessible tree, Problems, Testing, or Output surface.
Commands
The initial command set is:
RiX: Run File
RiX: Run Selection
RiX: Check File
RiX: Run Tests
RiX: Restart Session
RiX: Show Output
RiX: Show AST
RiX: Show IR
RiX: Explain Scope at Cursor
RiX: Select Plugins and Capabilities
Run commands must make saved-versus-unsaved source behavior explicit. Running an unsaved editor buffer sends its exact versioned content to the worker and must not claim that generated artifacts came from the saved file.
Rich preview
The preview consumes portable RiX output or an approved renderer result. It does not call evaluator functions directly. Preview inputs fall into three classes:
| Input | Initial policy |
|---|---|
| Validated portable output such as Text, Fragment, Graphic, Table, Sheet, Figure, and Slides | Render through a VS Code-owned structural adapter |
| Validated assets such as bounded local raster images or renderer SVG | Serve through webview resource URIs after MIME, size, URL, and SVG policy checks |
| Complete HTML, Markdown-converted HTML, plugin CSS/JS, or unknown renderer markup | Never insert directly; sanitize through a dedicated adapter or expose as an artifact opened by an explicit user action |
The existing structured-output HTML traversal escapes text and filters URLs, so it is a useful implementation reference. It is not itself the webview trust boundary. In particular, the standalone HTML renderer accepts caller-provided CSS and returns a complete document; its output must be treated as untrusted markup.
The first release may keep preview deliberately small: text in Output plus portable Fragment/Table/Sheet/Graphic output already handled in-process by RiX Web. It does not run PDF, PNG rasterization, LaTeX, Quarto, video, or other external toolchains. Additional current renderer outputs can be enabled later only after their MIME and permission class joins the allowlist.
If untrusted HTML or SVG sanitization becomes necessary, use a pinned and promptly updated DOMPurify release with an explicit profile, together with the webview CSP. The initial SVG profile forbids scripts, event attributes, foreignObject, external URLs, <style>, and inline style attributes. The first release accepts no plugin-provided CSS; previews use extension-owned theme styles. Structural DOM construction remains preferable to sanitizing strings.
Requirements include:
- strict Content Security Policy and per-load nonces;
- no arbitrary network access;
- sanitization of renderer HTML and URLs;
- theme-token styling, keyboard access, ARIA labeling, and text fallbacks;
- bounded message and artifact sizes;
- explicit disposal of reactive subscriptions and workers;
- source/version/session labels so stale results are visible;
- static snapshot support when interactive controls are unavailable.
The existing HTML/output widget implementation can be adapted, but editor transport and security policy remain host-owned.
Web follow-up boundary
The first web follow-up should match the functionality already exercised by the RiX Web calculator rather than define a new browser runtime. Its worker bundle may include:
- tokenizer, Pratt parser, Lezer parser, lint, scopes, completion, and formatting;
Context, the default registry/system context, synchronous and asynchronous evaluation, exact values, reactive values, and session reset/disposal;- the generated browser-safe bundled plugin catalog and only its approved installers;
formatValue, portable output values, and the host-owned structured preview adapter.
It does not use the Node filesystem plugin scanner, execute uploaded/workspace JavaScript modules, spawn processes, or load external tool renderers. Workspace .rix imports require a VS Code workspace.fs adapter with the same contained, no-symlink path policy; they can follow after basic single-document execution. This makes web static support mostly a packaging/transport task, while web execution remains a separate worker and host-I/O integration milestone.
Execution model
Run modes
Support two explicit modes:
- Isolated: a fresh context for each file/check/test run. This is the default for reproducibility and CI.
- Session: a named restartable context used by selection evaluation and exploratory work. The UI always displays the active session and provides a restart command.
Selection execution in isolated mode evaluates only the selected source plus an explicitly configured preamble. It does not silently execute the rest of the file. Session mode may use prior successfully evaluated submissions but must identify that dependency in the run record.
Worker lifecycle
- One misbehaving run must be cancellable without restarting VS Code.
- Cancellation first uses cooperative abort; after a grace period the host terminates the worker.
- Timeouts, background-task draining, memory/output budgets, and maximum artifact sizes are explicit configuration.
- A crashed or terminated worker yields a structured
run-end, and a new run starts a clean worker unless the user deliberately restores a safe session. - The worker emits heartbeats or progress for operations expected to take long enough that the editor would otherwise appear stuck.
- Stdout/stderr from host tools are captured, bounded, and associated with the run rather than mixed with the LSP transport.
Plugins and capabilities
Static plugin metadata may be inspected without installing or executing plugin JavaScript. The current catalog’s deliberately small YAML header format is the allowed discovery surface. Static tooling may consume validated fields such as id, description, kind, mount, aliases, exports, groups, permissions, requires, optional, provides, schemas, targets, snapshot, deterministic, and operator-files.
For .plugin.rix, tooling may tokenize source to extract static custom-operator declarations without evaluation. For .plugin.rix.js, tooling reads only the leading manifest and must not import the module or infer behavior from its JavaScript body. Referenced operator files must be bounded text files resolved inside the plugin/workspace root unless they belong to the trusted bundled installation. A reference must be relative to its declaring file/configuration, must name that directory or a descendant, and may not contain or traverse a symbolic link. Static discovery rejects absolute paths, parent escapes, non-regular files, and any resolved path outside the active workspace folder. Use lstat on each existing path component and a final canonical-path containment check rather than relying on string-prefix comparison alone.
Initial defensive limits are 1 MiB per manifest/operator source, 10 MiB total per workspace analysis, 256 followed files, and 32 directory levels. These are RiX host limits, not universal Node conventions, and user/workspace settings may only lower them in an untrusted workspace. Dependency resolution may construct a proposed load graph from requires and provides, but it does not activate that graph.
Execution resolves plugins through the normal catalog and approval rules. Workspace-provided JavaScript installers require a trusted workspace and explicit host approval.
The worker receives a capability allowlist, not an unrestricted system context. A file cannot broaden that allowlist through a source header or workspace-owned setting. The initial standard profile is defined by policy, not merely by exposing every registered function:
- allow core arithmetic, logic, exact values, collections, strings, units, symbolic operations, portable output construction, and bounded internal async operations;
- allow
.riximports whose resolved paths remain inside the workspace or the bundled standard library; - allow host-preloaded first-party plugins and workspace
.plugin.rixplugins that request no denied permissions and stay inside the workspace; - deny
NET, generalFILES, unrestrictedBACKGROUND, and workspace.plugin.rix.jsinstallers by default; - do not grant source code an unrestricted
.Plugin.Load; the host resolves the configured plugin allowlist before the run; - allow
.Outonly as a host-mediated artifact declaration inside the selected output root, not as general file access; - omit renderers that invoke external tools from the first release.
Artifact writes retain the CLI’s path-escape checks. The exact function/group expansion of standard must be an explicit allowlist, not “all functions minus known-dangerous functions.” A generated, checked-in policy snapshot records every capability name and allowed first-party plugin ID plus its declared permissions. CI constructs a fresh default system context/catalog and fails if the generated snapshot differs. Adding or removing an entry therefore requires an intentional policy diff, review, tests, and a changelog note. Negative tests must prove that NET, FILES, unrestricted BACKGROUND, dynamic plugin loading, child processes, and unapproved JavaScript installers remain absent.
Checks, tests, and reports
Discovery
The static service discovers source locations and provisional identities for:
- postfix predicate checks (
##@); - structural checks (
##:); - diagnostic taps (
##!); .Test,.TestError, and.TestStopgroups when their labels are statically available;- documentation-only setup/output markers, which are identified but not treated as ordinary
.rixfile tests.
Dynamic test labels remain executable but may appear only after a run.
Inline check settings are independent:
rix.checks.inline.enabled = true
rix.checks.inline.decorations = true
rix.checks.inline.showInTestExplorer = true
Disabling Test Explorer publication does not disable Check File or source decorations. Disabling inline checks prevents their execution while leaving ordinary .Test discovery intact.
Result presentation
- Failed and errored checks create source diagnostics.
- Passed checks receive a subtle gutter state and optional CodeLens summary.
- Unresolved exact decisions are distinct from failures.
- Test Explorer represents
.Testgroups and cases; inline checks may appear under a per-file “Inline checks” group by default and can be hidden through configuration. - Selecting a result navigates to its precise source range.
- Re-running one discovered item is allowed only when the worker can preserve its setup and source semantics; otherwise the containing file/group runs.
Reporters
All reporters consume the same event/summary model:
| Reporter | Intended consumer |
|---|---|
| Human terminal | Local command line |
| JSON | Editors, scripts, and coding agents |
| JSON Lines | Streaming editor/worker protocol |
| JUnit XML | CI test dashboards |
| SARIF | Static parser/lint diagnostics and code-scanning systems |
| HTML | Shareable combined source/check/output report |
Runtime values need a safe canonical summary. JSON reporters must not serialize arbitrary cyclic runtime objects or rely on JavaScript class internals.
Security and trust
The extension supports limited functionality in untrusted workspaces:
| Feature | Untrusted workspace | Trusted workspace |
|---|---|---|
| TextMate/semantic highlighting | Yes | Yes |
| Parsing, linting, symbols, and local formatting | Yes | Yes |
| Reading workspace JavaScript plugin metadata | Only declarative bounded metadata | Yes |
| Running RiX source | No | Yes |
| Loading workspace plugin installers | No | With explicit approval |
| Running external renderer toolchains | No | Not included in the first release |
| Writing artifacts | No | Inside configured output root |
Security-sensitive settings must be declared as restricted workspace configuration. Hiding a command is insufficient; command handlers must also check trust and execution policy.
The execution worker is a containment boundary for reliability and accidental damage, not a complete operating-system sandbox. Documentation and UI must not claim stronger isolation than the host actually provides.
CLI and coding-agent support
The CLI is the primary portable interface for coding agents. It should expose:
rix parse --json file.rix
rix lint --json file.rix
rix symbols --json file.rix
rix explain-scope --json file.rix:line:column
rix format [--check] file.rix
rix check --json file.rix
rix test --json [filters...]
rix run --json --capabilities=standard file.rix
rix verify --json file.rix
rix verify is the preferred one-command feedback loop. It resolves the same configuration as the editor, parses, lints, and runs enabled checks/tests, then returns one versioned summary with deterministic exit codes.
Agent-facing support should also include:
- a concise canonical syntax and common-errors reference;
- generated callable/operator/plugin metadata;
- verified examples with source, AST/IR snapshots where useful, and expected results;
- stable diagnostics and machine-applicable edits;
- an
AGENTS.mdworkflow describingformat -> verify -> inspect diagnostic; - small fixtures that exercise one language feature at a time.
An MCP server may later wrap parse, lint, symbols, explainScope, runSandboxed, and documentation search. It must reuse the CLI/core contracts rather than establish a separate semantic implementation.
Testing and compatibility
Test layers
- Unit tests for offsets, UTF-16 position conversion, diagnostics, symbols, completion, formatting, serialization, and configuration merging.
- Golden parser/Lezer/TextMate fixtures covering complete and partial source.
- LSP protocol tests with version changes, cancellation, multi-root workspaces, watched configuration, and stale responses.
- Execution protocol tests for event order, cancellation, crashes, timeouts, output limits, plugin denial, and artifact path traversal.
- VS Code integration tests for Problems, completion, navigation, formatting, Testing, trusted/untrusted behavior, and worker restart.
- Webview tests for CSP, sanitization, accessibility, disposal, and stale results.
- End-to-end fixtures that produce scalar, trace, test, Graphic, Sheet, reactive, and artifact output.
Compatibility policy
- LSP uses standard capabilities and negotiates optional features.
- Custom LSP requests and execution events carry explicit protocol versions.
rix.jsoncarries a schema version.- Diagnostic codes and report field meanings are documented compatibility surface.
- The extension declares supported RiX and protocol version ranges and reports mismatches clearly.
- Golden fixtures run in the RiX test suite so syntax changes cannot silently break editor support.
Acceptance criteria for the first useful release
The first public extension release is complete when:
- A
.rixfile receives correct baseline highlighting, comments, brackets, indentation, and folding. - Unsaved edits receive debounced parse/lint diagnostics with accurate ranges and no stale results.
- Completion and hover cover local bindings, system capabilities, common methods, brace forms, and configured plugins without evaluating code.
- Go to definition and document symbols work within one file.
RX1001andRX1002offer tested capture-direction code actions.- Run File and Run Selection use a restartable worker and support cancellation.
##@,##:,##!, and.Testemit structured source-linked results.- Scalar and textual output use native VS Code UI. Rich Graphic/Sheet preview is an optional follow-up and does not block the basic extension release.
- Untrusted workspaces retain static language features but cannot execute RiX or workspace plugins.
rix verify --jsonreturns the same core diagnostics/check outcomes used by the extension.
Implementation checklist
The phases are ordered so each leaves a usable, testable layer. Work may be split into smaller pull requests, but later phases must not invent contracts that bypass earlier ones.
0. Confirm design and public contracts
1. Source spans and structured runtime events
2. Portable language-service core
3. Language server
4. VS Code extension baseline
5. Execution worker and CLI protocol
6. VS Code execution and reporting UI
7. Rich preview
8. Reports, CI, and coding-agent workflow
9. Broader editor and debugging support
Deferred review gate
The initial policy choices are resolved. One review remains after the relevant implementation exists: review the generated standard capability/plugin snapshot before release. The governing policy is an explicit allowlist plus deny-by-default CI, not a manually maintained prose list.
The formatter decisions should become golden fixtures, while preview and capability policy should become generated policy data and security tests rather than remain extension-specific conventions.