Semantic language features for CSS Modules in VS Code.
The extension is built for projects that use CSS Modules through
classnames/bind, classnames, clsx, or direct styles.* access.
Definition, hover, references, rename, diagnostics, and code actions all
resolve through the same semantic pipeline.
import classNames from "classnames/bind";
import styles from "./Button.module.scss";
const cx = classNames.bind(styles);
export function Button({ active, size }: { active: boolean; size: "sm" | "lg" }) {
return <button className={cx("button", { active }, size)}>Save</button>;
}- Source-side language features
- Go to Definition and Hover from
cx(...),styles.foo, andstyles["foo-bar"] - Completion inside
cx(,classnames(, andclsx(calls - Diagnostics for unknown classes and missing module imports
- Quick fixes to replace a misspelled class, add a missing selector, or create a missing module file
- Go to Definition and Hover from
- Style-side language features
- Hover, Find References, and CodeLens from
.module.css,.module.scss, and.module.less - Rename across style files and source call sites
- Unused selector diagnostics
composestoken definition/references/hover inside style modules- Diagnostics and quick fixes for unresolved composed modules
- Same-file
@keyframeshover/definition/references plus missing-target recovery - Local and imported
@valuedefinition/references/diagnostics plus missing-target recovery
- Hover, Find References, and CodeLens from
- Resolution behavior
classnames/bindbindings, multiple bindings per file, and function-local bindingsclassnames/clsxcalls that usestyles.fooorstyles["foo-bar"]- Template literals and symbol references with local flow analysis and TypeScript union fallback
css-loader-compatible class name transform modes- Multi-root workspaces with resource-scoped transform and path-alias settings
- The
Omena CSS Modulesstatus bar item shows the language server lifecycle and opens the leveledOmena CSS ModulesOutput panel for filtered runtime logs.
cx("button")cx("button", { active, disabled })cx(`button-${variant}`)cx(size)wheresizeresolves from local control flow or string-literal unionsclassnames(styles.button, flag && styles.active)clsx(styles.button, { [styles.active]: flag })styles.buttonstyles["button-primary"]
CSS, SCSS, and Less modules are supported. The extension activates for TypeScript, TSX, JavaScript, JSX, CSS, SCSS, and Less files.
Install from the VS Code Marketplace or build from source.
pnpm install
pnpm package
code --install-extension omena-css-*.vsixThe public benchmark surface is documented in docs/performance.md.
External Sass module migration and omena.lock compatibility behavior are
documented in docs/migration.md.
It covers Rust parser/semantic/abstract-value micro-benchmarks and an LSP
macro-benchmark for hover, definition, completion, references, and event-loop
latency.
5.0.0 marks the Rust stable core closure for the compiler-grade CSS Modules
semantic engine. The packaged extension defaults to the Rust omena-lsp-server,
the Rust selected-query runtime, and the bundled tsgo type-fact path; the VS
Code host remains a thin client responsible for process orchestration, UI
commands, and file watching.
Release notes should describe shipped editor/runtime behavior and the gates that prove it. Lower-level V0 contract substrates are kept internal unless a release gate maps them to user-visible behavior; they are not claims of final APIs, completed proofs, or external runtime support by themselves.
All settings live under the omena.* namespace.
| Setting | Default | Description |
|---|---|---|
omena.features.definition |
true |
Enable Go to Definition. |
omena.features.hover |
true |
Enable Hover. |
omena.features.completion |
true |
Enable Completion. |
omena.features.references |
true |
Enable Find References and CodeLens. |
omena.features.rename |
true |
Enable Rename. |
omena.diagnostics.severity |
"warning" |
Severity for unknown-class diagnostics. |
omena.diagnostics.unusedSelector |
true |
Show unused selector hints in style modules. |
omena.diagnostics.missingModule |
true |
Warn when a CSS Module import cannot be resolved. |
omena.hover.maxCandidates |
10 |
Maximum dynamic candidates shown in hover. |
omena.typeFactBackend |
"tsgo" |
Type-fact backend: bundled tsgo, workspace tsgo, or current TypeScript. |
omena.scss.classnameTransform |
"asIs" |
Mirror of css-loader modules.localsConvention. |
For a selector .btn-primary:
| Mode | Exposed keys | Notes |
|---|---|---|
asIs |
btn-primary |
Original selector only. |
camelCase |
btn-primary, btnPrimary |
Both forms resolve. |
camelCaseOnly |
btnPrimary |
Alias only. Rename is rejected. |
dashes |
btn-primary, btnPrimary |
Dashes become word boundaries. |
dashesOnly |
btnPrimary |
Alias only. Rename is rejected. |
Alias-only modes keep navigation and references, but rename is blocked because the reverse mapping back to the original selector is lossy.
The extension resolves non-relative CSS Module imports from:
compilerOptions.pathsin the workspacetsconfig.jsonorjsconfig.json- native
omena.pathAlias
This allows imports such as:
import styles from "@/components/Button.module.scss";
import theme from "@styles/theme.module.scss";Configure extension-specific aliases with omena.pathAlias:
The runtime follows one semantic pipeline:
source/style text
-> HIR documents
-> source binding
-> abstract class-value analysis
-> read models
-> LSP providers
Current structure:
server/
├── engine-core-ts/ # semantic core, contracts, checker core, abstract value
├── engine-host-node/ # workspace/runtime hosting, batch checker host, parity assembly
├── lsp-server/ # generic LSP transport, providers, handler wiring
└── checker-cli/ # batch checker CLI surface
At a high level:
- HIR preserves document facts from source and style files.
- Binder resolves source-side names such as
cx,styles, imports, locals, and shadowing. - The abstract-value layer models dynamic class expressions such as flow branches, unions, and template prefixes.
- Semantic storage keeps workspace references, dependency lookups, and style-to-style relationships such as
composes. engine-host-nodequery helpers turn low-level semantic state into stable summaries that providers consume.- Providers adapt those summaries to LSP features such as hover, definition, references, diagnostics, and rename.
The important constraint is that providers do not recompute semantic meaning on their own. They read the shared pipeline through the host query boundary rather than importing core query or rewrite internals directly.
Contract status:
V2is the canonical live contract surface.V1remains available only as a historical compatibility view derived fromV2.
For a fuller design explanation, see docs/architecture-v3.md.
Requirements:
- Node.js
>= 22 pnpm@10
Common commands:
pnpm install
pnpm check
pnpm check:semantic-smoke
pnpm check:lsp-server-smoke
pnpm check:rust-gate-evidence
pnpm check:rust-checker-style-recovery-canonical-candidate
pnpm check:plugin-consumer-example
pnpm check:plugin-consumers
pnpm check:eslint-plugin-smoke
pnpm check:stylelint-plugin-smoke
pnpm check:release-batch
pnpm check:contract-parity-v2-smoke
pnpm check:contract-parity-v2-golden
pnpm test
pnpm test:bench
pnpm build
pnpm packageBatch checker:
pnpm check:semantic-smoke
pnpm check:release-batch
pnpm check:workspace -- . --preset changed-style --changed-file src/Button.module.scss
pnpm check:workspace -- . --preset changed-source --changed-file src/App.tsx
pnpm check:workspace -- . --preset ci
pnpm check:workspace -- --list-bundles
pnpm check:workspace -- . --include-bundle source-missing --summary
pnpm check:workspace -- . --preset changed-style --changed-file src/Button.module.scss --compact
pnpm check:workspace -- . --format json --fail-on none
pnpm explain:expression -- src/App.tsx:12:24
pnpm explain:expression -- src/App.tsx:12:24 --jsonCurrent checker policy:
@keyframesvalidation is same-file only in the current first pass@valuevalidation covers local declarations and imported bindings between style modules- named bundles group common finding families such as
ci-default,source-missing,style-recovery, andstyle-unused - presets also apply default bundle policy unless explicit include flags are provided
ci=>ci-defaultchanged-style=>style-recovery,style-unusedchanged-source=>source-missing
changed-styleandchanged-sourcepresets use compact text output by defaultpnpm check:semantic-smokeis the canonical repo-local smoke commandpnpm check:lsp-server-smokespawns the builtlsp-serverover stdio and verifies hover/definition through a generic protocol clientpnpm check:selected-query-boundaryis the current3.9selected-query lock point- it runs the editor-facing protocol subset for
definition,hover,completion,references,rename, andcodeLens - these providers now route their main selected-query and source/style rewrite reads through
engine-host-nodehelpers instead of directly owning the core query/rewrite calls in the LSP layer
- it runs the editor-facing protocol subset for
pnpm check:rust-selected-query-consumersis the current local lock point for the first live Rust selected-query consumer slice- it runs the explicit unit/runtime coverage for the current opt-in Rust consumers: source
definition, sourcehover, sourcereferences, sourcerename, stylehoverusage-summary resolution, stylereferenceslocation resolution, stylereference-lenstitle/count summary and location resolution, style module usage / style diagnostics unused-selector resolution, stylerenamerewrite-safety and direct edit-site resolution,explain-expression, source diagnostics symbol-ref invalid-class analysis, and host-sideengine-query-v2query-result emission forsource-expression-resolution,expression-semantics, andselector-usage OMENA_SELECTED_QUERY_BACKEND=rust-selected-queryis the unified explicit backend for that slice; the narrowerrust-source-resolution,rust-expression-semantics, andrust-selector-usagevalues remain available for isolated debugging- in packaged VSIX runtime, an unset
OMENA_SELECTED_QUERY_BACKENDnow selectsrust-selected-querywhen the packaged/prebuiltengine-shadow-runneris available; source checkouts keep the unset default ontypescript-currentso localdist/artifacts do not change dev/test behavior OMENA_SELECTED_QUERY_BACKEND=autoexplicitly exercises the same Rust-if-packaged-runner-available selection in source checkouts
- it runs the explicit unit/runtime coverage for the current opt-in Rust consumers: source
pnpm check:rust-selected-query-default-candidateis the current default-candidate evidence lane forOMENA_SELECTED_QUERY_BACKEND=rust-selected-query- it first runs
pnpm check:rust-selected-query-release-default, which builds the packaged runner and runs the full protocol suite withOMENA_SELECTED_QUERY_BACKEND=auto - it then warms
engine-shadow-runner, runs the live Rust selected-query unit consumer slice, and repeats the full protocol suite with the unified Rust selected-query backend explicitly enabled andOMENA_ENGINE_SHADOW_RUNNER=prebuilt - prebuilt runner mode is explicit so ad-hoc local runs still use
cargo runand do not accidentally reuse a stalerust/targetbinary - prebuilt mode can resolve an explicit
OMENA_ENGINE_SHADOW_RUNNER_PATH, a packageddist/bin/<platform>-<arch>/engine-shadow-runner, or the warmedrust/target/debugrunner - it is regression evidence for keeping the packaged runner matrix safe while
rust-selected-queryis the packaged default - GitHub Actions runs the same lane in the
Rust Selected Query Default Candidateshadow workflow onmaster
- it first runs
pnpm check:rust-phase-2-swap-readinessremains the historical Phase 2 swap evidence gate- it runs
pnpm check:provider-host-routing-boundary,pnpm check:rust-omena-lsp-server-lane,pnpm check:rust-selected-query-default-candidate, andpnpm check:rust-checker-release-gate-shadow - the v5 release gate is
pnpm release:verify, which includes the broader Rust release bundle, tsgo release bundle, plugin consumers, tests, and VSIX packaging checks
- it runs
pnpm buildnow prepares the current-platform releaseengine-shadow-runnerand default-candidateomena-lsp-serverbinaries atdist/bin/<platform>-<arch>/pnpm check:packaged-engine-shadow-runner-matrixverifies packaged runner targets before VSIX packaging; CI and publish require Linux, macOS, and Windows runner artifactspnpm check:packaged-selected-query-defaultverifies the generated VSIX file set still makes packaged runtime chooserust-selected-queryandomena-lsp-serverby default, excludes checkout-only Rust/source markers, and preserves the required runner matrixpnpm check:editor-path-boundaryis the current editor-path runtime lock point- it runs
pnpm check:selected-query-boundaryplus the protocol subset fordiagnostics,scss-diagnostics,code-actions, watched-file invalidation, workspace-folder changes, and settings reload - those paths now route diagnostics/checker entry, code-action planning, session bootstrap, workspace-folder mutation, watched-file invalidation, and settings-reload orchestration through
engine-host-nodehelpers or aggregates instead of owning the runtime policy directly in the LSP layer
- it runs
pnpm check:provider-host-routing-boundarystatically prevents LSP providers from importing core query, semantic graph, indexing, or TypeScript resolver internals directlypnpm check:plugin-consumer-exampleruns the clean repo-local lint-consumer example workspace under both ESLint and Stylelintpnpm check:plugin-consumersruns the current ESLint and Stylelint consumer smokes togetherpnpm check:eslint-plugin-smokeruns the ESLint consumer against JSX fixtures and asserts that source-side semantic findings are reported as ESLint diagnostics- current config split: aggregate
recommended, granularfocused, optionaldynamicMoat
- current config split: aggregate
pnpm check:stylelint-plugin-smokeruns the first Stylelint consumer against a CSS Modules fixture and asserts that unused selectors are reported as Stylelint diagnosticspnpm check:rust-gate-evidencerecords wall-clock timings for the current second/third-consumer proof set so Rust gate discussions use measured repo-local workloads instead of guesses- current baseline variant:
typescript-current - future variants can be selected with
--variant <label> - repeated runs can be summarized with
--repeat <n> - current comparison slot:
tsgooncheck:backend-typecheck-smoke
- current baseline variant:
pnpm check:backend-typecheck-smokeruns a small multi-case corpus (template-literals,path-alias,flow-relations) for the selected typecheck backend- the unset
OMENA_TYPE_FACT_BACKENDdefault is nowtsgo, which activates a host-side tsgo probe before delegating symbol resolution to the current TS resolver - packaged extension runtime uses the bundled
dist/bin/<platform>-<arch>/tsgoprobe;omena.typeFactBackend=tsgo-workspacepreserves the old workspacepnpm exec tsgomode for power users omena.typeFactBackend=typescript-currentorOMENA_TYPE_FACT_BACKEND=typescript-currentremains available as the explicit current-TypeScript fallback
- the unset
OMENA_TYPE_FACT_BACKEND=tsgo pnpm check:release-batchandpnpm check:real-project-corpusnow exercise the checker path through the same host-side tsgo probepnpm check:type-fact-backend-paritycompares canonicalEngineInputV2.typeFactsacrosstypescript-currentandtsgoon the backend smoke corpuspnpm check:ts7-phase-a-readinessis the current aggregate Phase A gate for the TS 7 beta path- it runs backend typecheck smoke, type-fact backend parity, and
rust-gate-evidence -- --variant tsgo --repeat 1 --json
- it runs backend typecheck smoke, type-fact backend parity, and
pnpm check:release-batch-tsgois the current tsgo-backed variant of the release-batch operational pathpnpm check:real-project-corpus-tsgois the current tsgo-backed variant of the real-project operational pathpnpm check:lsp-server-smoke-tsgois the current tsgo-backed variant of the stdio LSP smoke pathpnpm check:ts7-phase-a-shadowis the current non-release shadow path for TS 7 beta Phase A- it runs the tsgo-backed release-batch, real-project-corpus, and LSP smoke commands together
pnpm check:ts7-phase-a-stabilitydirectly checks the two tsgo-specific risk points that the basic shadow path does not prove by itself- repeated
EngineInputV2.typeFactssnapshots fromtsgomust stay byte-stable across runs - concurrent
release-batchandreal-project-corpusinvocations underOMENA_TYPE_FACT_BACKEND=tsgomust keep identical outputs across rounds - tsgo probe calls run through the repo-pinned
@typescript/native-previewbinary in source checkouts and the packageddist/bin/<platform>-<arch>/tsgobinary in VSIX runtime; the stability matrix now also repeats backend smoke under fixed--checkersvalues (1,2,4) viaOMENA_TSGO_CHECKERS
- repeated
pnpm check:ts7-phase-a-tsgo-laneis the current limited non-release aggregate for TS 7 beta Phase A- it builds the repo, then runs readiness, shadow, and stability together
pnpm check:ts7-phase-a-shadow-reviewreviews recentTS7 Phase A Shadowworkflow history throughgh- today it reports whether the repo has accumulated the current minimum of
3successful shadow runs before any broader release-facing judgment
- today it reports whether the repo has accumulated the current minimum of
pnpm check:ts7-phase-a-decision-readyis the current lock point for Phase A- it requires both the local tsgo lane and the successful-shadow-run threshold
pnpm check:ts7-phase-b-protocol-tsgois the first bounded protocol-layer tsgo path for TS 7 beta Phase B- it runs
lifecycle,hover,definition,diagnostics, andcompletionprotocol tests underOMENA_TYPE_FACT_BACKEND=tsgo
- it runs
pnpm check:ts7-phase-b-editing-tsgois the second bounded protocol-layer tsgo path for TS 7 beta Phase B- it runs
references,rename, andcode-actionsprotocol tests underOMENA_TYPE_FACT_BACKEND=tsgo
- it runs
pnpm check:ts7-phase-b-build-tsgois the current bounded build-mode tsgo path for TS 7 beta Phase B- it runs
pnpm exec tsgo -b server/tsconfig.json --checkers 2 --builders 2
- it runs
pnpm check:ts7-phase-b-workspace-build-tsgois the current workspace-level project-reference tsgo path for TS 7 beta Phase B- it runs
pnpm exec tsgo -b tsconfig.json --checkers 2 --builders 2
- it runs
pnpm check:ts7-phase-b-readinessis the current entry check for Phase B- it requires
pnpm check:ts7-phase-a-decision-readyfirst, then the bounded protocol, editing, server-build, and workspace-build tsgo subsets
- it requires
pnpm check:tsgo-operational-laneis the current bounded non-release operational lane for the tsgo backend- it runs the local
ts7-phase-a-tsgo-laneplus the bounded Phase B protocol, editing, server-build, workspace-build, and Phase C edge-readiness tsgo subsets
- it runs the local
pnpm check:tsgo-release-bundleis the release-shaped tsgo variant and is part ofpnpm release:verifypnpm check:ts7-phase-c-readinessis the first TS 7 Phase C edge-readiness slice- it runs long-lived LSP session edits, multi-root workspace churn, watched-file invalidation, and source/style staleness checks under
OMENA_TYPE_FACT_BACKEND=tsgo
- it runs long-lived LSP session edits, multi-root workspace churn, watched-file invalidation, and source/style staleness checks under
pnpm check:operational-laneis the current limited non-release default lane- today it resolves to the tsgo-backed operational lane
pnpm check:operational-shadow-reviewis the current limited non-release default review command- today it resolves to
pnpm check:tsgo-operational-shadow-review
- today it resolves to
pnpm check:tsgo-operational-shadow-reviewreviews recentTSGO Operational Shadowworkflow history throughgh- today it reports whether the repo has accumulated the current minimum of
3successful shadow runs before any limited non-release default judgment
- today it reports whether the repo has accumulated the current minimum of
pnpm check:ts7-decision-readyis the current top-level judgment gate for the TS 7 track- it requires
Phase A decision-ready,Phase B readiness, andPhase C readiness
- it requires
.github/workflows/tsgo-operational-shadow.ymlis the observational workflow for that bounded operational lane- it builds the repo, runs the tsgo-backed release batch, real-project corpus, LSP smoke, and full operational lane, and records repeatable shadow history for the next default-candidate judgment
.github/workflows/ts7-phase-a-shadow.ymlbuilds the repo, then runs the Phase A readiness gate, non-release shadow path, and stability check on everymasterpush and on manual dispatchpnpm check:rust-parser-scaffoldexercises the current product parser scaffold crate,rust/crates/omena-parserpnpm check:rust-parser-git-consumerverifies that the split parser repo can be consumed as a remote git dependency by the repo-stored standalone fixture atrust/external-consumers/engine-style-parser-git-consumerpnpm check:rust-parser-split-boundaryverifies the full parser split boundary: parser public-product validation inside the monorepo plus remote git-consumer validation againstomena-engine-style-parserpnpm check:rust-input-producers-git-consumerverifies that the split input-producers repo can be consumed as a remote git dependency by the repo-stored standalone fixture atrust/external-consumers/engine-input-producers-git-consumerpnpm check:rust-input-producers-split-boundaryverifies the full input-producers split boundary: monorepo producer-boundary validation plus remote git-consumer validation againstomena-engine-input-producerspnpm check:rust-split-boundariesruns the current Rust split-boundary checks togetherpnpm check:rust-split-publish-readinessverifies the published split crate set against crates.io metadata, registry dependency contracts, andcargo publish --dry-runpnpm check:rust-split-consumer-pinsverifies that the repo-stored split consumer fixtures are pinned to the currentmaincommit of each split repopnpm update:rust-split-consumer-pinsrefreshes those fixture refs plus lockfiles when the split repos advance- The current external Rust split boundaries are:
omenien/omena-engine-input-producersomenien/omena-engine-style-parseromenien/omena-semanticomenien/omena-abstract-valueomenien/omena-resolveromenien/omena-bridgeomenien/omena-query- keep them pinned behind repeatable remote-consumer checks before any new rename or public packaging move
pnpm check:rust-parser-parity-litecompares theomena-parserscaffold against the current TS style parser on a bounded shared fixture setpnpm check:rust-parser-css-modules-intermediatecompares the Rust parser CSS Modules intermediate facts against the current TS style HIR on a bounded shared fixture setpnpm check:rust-parser-index-producerremains as a compatibility alias for the same intermediate producer checkpnpm check:rust-parser-canonical-candidatevalidates the versioned parser canonical-candidate bundle over the current parity-lite + CSS Modules intermediate artifactspnpm check:rust-parser-evaluator-candidatesvalidates the selector-level parser evaluator-candidate artifact against the current TS style HIRpnpm check:rust-parser-canonical-producervalidates the parser canonical-producer signal over that canonical-candidate bundle and current gate placementpnpm check:rust-parser-laneruns the current parser lane bundle: scaffold tests, parity-lite, CSS Modules intermediate producer, parser canonical-candidate, parser evaluator-candidates, and parser canonical-producerpnpm check:rust-parser-consumer-boundaryconsumes the parser canonical-producer output into a bounded downstream-style summary and compares that against the current TS style HIRpnpm check:rust-parser-public-productis the canonical parser/public-product gate and currently runs the parser lane bundle plus that consumer-boundary checkpnpm check:rust-checker-style-recovery-canonical-candidateis the current bounded checker-canonical entrance check; it compares thestyle-recoverychecker subset against a versioned Rust shadow canonical-candidate bundlepnpm check:rust-checker-style-recovery-canonical-producervalidates the matching checker canonical-producer signal for that same boundedstyle-recoverysubsetpnpm check:rust-checker-style-recovery-consumer-boundaryvalidates the opt-inchecker-cliRust consumer path for that same bounded subsetpnpm check:rust-checker-style-recovery-laneruns the full bounded checker entrance lane: canonical-candidate, canonical-producer, and opt-in consumer-boundary consistencypnpm check:rust-checker-source-missing-canonical-candidateis the matching bounded entrance check for thesource-missingchecker subsetpnpm check:rust-checker-source-missing-canonical-producervalidates the matching checker canonical-producer signal for that boundedsource-missingsubsetpnpm check:rust-checker-source-missing-consumer-boundaryvalidates the opt-inchecker-cliRust consumer path for that bounded source subsetpnpm check:rust-checker-source-missing-laneruns the full bounded source-side checker lane: canonical-candidate, canonical-producer, and opt-in consumer-boundary consistencypnpm check:rust-checker-style-unused-canonical-candidateis the matching bounded entrance check for thestyle-unusedsubsetpnpm check:rust-checker-style-unused-canonical-producervalidates the matching checker canonical-producer signal for that boundedstyle-unusedsubsetpnpm check:rust-checker-style-unused-consumer-boundaryvalidates the opt-inchecker-cliRust consumer path for that bounded unused-selector subsetpnpm check:rust-checker-style-unused-laneruns the full bounded unused-selector checker lane: canonical-candidate, canonical-producer, and opt-in consumer-boundary consistencypnpm check:rust-checker-bounded-lanesis the current aggregate entry for release-enforced checker-canonical lanes; today it runsstyle-recovery,source-missing, andstyle-unusedpnpm check:rust-checker-entranceis the official checker-canonical entrance gate; it currently aliasespnpm check:rust-checker-bounded-lanespnpm check:rust-checker-promotion-reviewvalidates the current promotion stance for bounded checker lanes; today it confirms all three checker lanes are inside the broader Rust lane and the release gatepnpm check:rust-checker-broader-lane-readinesslocks the current broader-lane promotion criteria for those bounded lanes; today it requires three bounded lanes, a promotion-review command, and a broader target ofpnpm check:rust-lane-bundle, with all three lanes promoted into the broader Rust lane and the release gatepnpm check:rust-checker-real-project-boundedvalidates all three bounded checker lanes against a small multi-file real-project-like corpus instead of smoke-only fixturespnpm check:rust-checker-promotion-evidenceruns the full bounded checker promotion evidence set: promotion review, broader-lane readiness, and real-project bounded corpus validationpnpm check:rust-checker-release-gate-readinesslocks the release-gate promotion criteria for the current checker lanes; today it requires the broader-lane promotion evidence to exist, a release target ofpnpm check:rust-release-bundle, a shadow soak target ofpnpm check:rust-checker-release-gate-shadow, and a minimum bounded-lane count of3, with all three lanes now enforced in the release gatepnpm check:rust-checker-release-gate-shadowis now a post-enforcement observation soak for checker entrance; it runs the release-facing Rust bundle, the checker entrance gate, and the checker promotion evidence togetherpnpm check:rust-checker-release-gate-shadow-reviewreviews the current GitHub Actions shadow history for that workflow; today it reports whether the repo has accumulated the3successful shadow runs that were required before the enforcement flip.github/workflows/checker-release-gate-shadow.ymlnow runs that same post-enforcement observation soak on everymasterpush, builds the repo artifacts plusserver/engine-core-tsandserver/engine-host-nodedist needed byrust-gate-evidence, and executes the release bundle components, checker entrance, and promotion evidence as separate steps so failures are attributable from the workflow UI- Rust shadow validation now covers:
- input summaries:
pnpm check:rust-type-fact-compare,pnpm check:rust-query-plan-compare,pnpm check:rust-expression-domain-compare - input-only candidates:
pnpm check:rust-expression-domain-candidates - expression-domain evaluator candidates:
pnpm check:rust-expression-domain-evaluator-candidates - query skeletons:
pnpm check:rust-*-query-fragments - match fragments:
pnpm check:rust-expression-semantics-match-fragments,pnpm check:rust-source-resolution-match-fragments - output-like candidates:
pnpm check:rust-expression-semantics-candidates,pnpm check:rust-source-resolution-candidates - evaluator candidates:
pnpm check:rust-expression-semantics-evaluator-candidates,pnpm check:rust-source-resolution-evaluator-candidates - canonical-candidate bundles:
pnpm check:rust-expression-domain-canonical-candidate,pnpm check:rust-expression-semantics-canonical-candidate,pnpm check:rust-source-resolution-canonical-candidate - canonical-producer signals:
pnpm check:rust-expression-domain-canonical-producer,pnpm check:rust-expression-semantics-canonical-producer,pnpm check:rust-source-resolution-canonical-producer - consolidated source-side lane:
pnpm check:rust-source-side-canonical-candidate,pnpm check:rust-source-side-evaluator-candidates,pnpm check:rust-source-side-canonical-producer - consolidated semantic lane:
pnpm check:rust-semantic-canonical-candidate,pnpm check:rust-semantic-evaluator-candidates,pnpm check:rust-semantic-canonical-producer - aggregated producer-boundary checks:
pnpm check:rust-source-side-lane,pnpm check:rust-semantic-lane,pnpm check:rust-producer-boundary - parser canonical boundary:
pnpm check:rust-parser-canonical-candidate,pnpm check:rust-parser-evaluator-candidates,pnpm check:rust-parser-canonical-producer - parser/public-product gate:
pnpm check:rust-parser-consumer-boundary,pnpm check:rust-parser-public-product - bounded checker entrance:
pnpm check:rust-checker-style-recovery-canonical-candidate - bounded checker producer signal:
pnpm check:rust-checker-style-recovery-canonical-producer - bounded checker consumer path:
pnpm check:rust-checker-style-recovery-consumer-boundary - bounded checker lane:
pnpm check:rust-checker-style-recovery-lane - bounded source-side checker entrance:
pnpm check:rust-checker-source-missing-canonical-candidate - bounded source-side checker producer signal:
pnpm check:rust-checker-source-missing-canonical-producer - bounded source-side checker consumer path:
pnpm check:rust-checker-source-missing-consumer-boundary - bounded source-side checker lane:
pnpm check:rust-checker-source-missing-lane - bounded style-unused checker entrance:
pnpm check:rust-checker-style-unused-canonical-candidate - bounded style-unused checker producer signal:
pnpm check:rust-checker-style-unused-canonical-producer - bounded style-unused checker consumer path:
pnpm check:rust-checker-style-unused-consumer-boundary - bounded style-unused checker lane:
pnpm check:rust-checker-style-unused-lane - bounded checker lane aggregate:
pnpm check:rust-checker-bounded-lanes - official checker entrance gate:
pnpm check:rust-checker-entrance - checker lane promotion review:
pnpm check:rust-checker-promotion-review - broader checker lane readiness:
pnpm check:rust-checker-broader-lane-readiness - real-project bounded checker evidence:
pnpm check:rust-checker-real-project-bounded - checker promotion evidence bundle:
pnpm check:rust-checker-promotion-evidence - checker release-gate readiness:
pnpm check:rust-checker-release-gate-readiness - checker release-gate shadow soak:
pnpm check:rust-checker-release-gate-shadow - checker release-gate shadow review:
pnpm check:rust-checker-release-gate-shadow-review - broader Rust lane bundle:
pnpm check:rust-lane-bundle - release-facing Rust bundle:
pnpm check:rust-release-bundle - full snapshot parity:
pnpm check:rust-shadow-compare
- input summaries:
- Current
5.0.0framing is the Rust stable core closure on top of the Rust-backed semantic core GA baseline:expression-semanticsandsource-resolutionstill carry family-level canonical-producer signals and a shared top-level source-side laneexpression-domaincarries input-only canonical artifacts plus type-fact-backed evaluator-candidate coverage on the Rust shadow path- a top-level
semanticlane now consolidatessource-side + expression-domaininto one canonical-candidate / evaluator-candidate / canonical-producer path omena-parsernow owns the canonical parser/public-product gate, parser canonical-candidate bundle, parser evaluator-candidates, parser canonical-producer signal, bounded CSS Modules intermediate producer surface, and downstream consumer-boundary check over that producer output; legacyengine-style-parseris confined to oracle, benchmark, and split-compatibility paths- the ESLint and Stylelint plugin consumers now form a first plugin-facing batch with focused rule surfaces, aggregate configs, a clean example workspace, and release-facing consumer gates
- the bounded checker entrance (
style-recovery+source-missing+style-unused) is now enforced inpnpm check:rust-release-bundle - packaged VSIX runtime now defaults to
rust-selected-querythrough a long-livedengine-shadow-runnerdaemon when the bundled runner is present, while source checkouts keep the unset default ontypescript-current - non-daemon async selected-query calls also use a true asynchronous one-shot runner path, so disabling the daemon does not reintroduce event-loop blocking
- LSP providers now consume
engine-host-nodequery helpers instead of importingcore/queryinternals directly, andpnpm check:provider-host-routing-boundaryguards that provider boundary omena.lspServerRuntime=autonow selects the bundled or built Rustomena-lsp-serverand fails fast when no binary is available; the legacy Node LSP server is only selected through explicitomena.lspServerRuntime=node. The Rust path carries provider parity coverage for style providers, source selector providers, source/style diagnostics, quick fixes, watched-file style index updates, and imported-module source reference scoping- style providers now consume Rust-backed semantic graph read models for selector identity, references, diagnostics, completions, rename safety, hover metadata, and style-module usage through host-side caches
pnpm check:rust-phase-2-swap-readinessremains the historical Phase 2 swap batch;pnpm release:verifyis the current v5 release gate- the Omena Rust split crates are published and externally consumable through crates.io; v5 treats them as the stable internal product baseline, not a separate semver-1.0 crate freeze
OMENA_TYPE_FACT_BACKENDnow defaults totsgo, packaged runtime carries its own tsgo binary, andtypescript-currentis retained as an explicit comparison fallbacktsgois wired into release-batch, real-project corpus, LSP smoke, protocol/editing, server build, workspace build, and Phase C edge-readiness checks- the current release-shaped TS 7 aggregate is
pnpm check:tsgo-release-bundle, andpnpm release:verifyincludes it - the current limited non-release default lane is
pnpm check:operational-lane - the current limited non-release default review command is
pnpm check:operational-shadow-review - the current top-level TS 7 judgment command is
pnpm check:ts7-decision-ready TS 7 Phase Cnow covers watch / incremental behavior, long-lived LSP session behavior beyond one-shot smoke, and multi-root / workspace-edge casesselector-usageremains a shadow validation family, not a release-gating canonical candidate- current
EngineInputV2does not preserve enough reference-level evidence to reproduceselector-usagesemantics as an input-only canonical producer - the current internal Rust producer boundary is
rust/crates/omena-engine-input-producers - the current internal Rust parser/public-product scaffold starts in
rust/crates/omena-parser
pnpm check:real-project-corpusruns a clean multi-file corpus that mimics common product patterns (variants,@value+@keyframes,composes,.module.less)- semantic smoke cases are versioned in
scripts/semantic-smoke-corpus.tsand should be updated when new semantic surfaces become release-relevant pnpm check:release-batchis the canonical release-facing batch checker pass- the release batch corpus is versioned in
scripts/release-batch-corpus.ts; it stays intentionally clean even ifexamples/contains negative recovery fixtures pnpm check:contract-parity-v2-smokeandpnpm check:contract-parity-v2-goldenare the canonical parity gates- frozen V1 baseline commands remain available as historical references:
pnpm check:contract-parity-v1-smokepnpm check:contract-parity-v1-goldenpnpm update:contract-parity-v1-golden
- V2 exposes constrained bundle metadata today for:
- Bundle 1:
suffix,prefixSuffix - Bundle 2:
charInclusion - Bundle 3:
composite TypeFactTableV2EngineOutputV2.queryResultspnpm explain:expression --json
- Bundle 1:
- explicit CLI flags override preset defaults
Test layout:
| Tier | Location | Purpose |
|---|---|---|
| Unit | test/unit/ |
Pure logic and provider tests with mock dependencies |
| Protocol | test/protocol/ |
Full LSP roundtrips through the in-process harness |
| Benchmark | test/benchmark/ |
Provider microbenchmarks |
The first ESLint consumer lives at packages/eslint-plugin.
Current scope:
- source-side rules only
missing-modulemissing-static-classmissing-template-prefixmissing-resolved-class-valuesmissing-resolved-class-domaininvalid-class-referenceno-unknown-dynamic-class- aggregate
source-check
Flat config example:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const omena = require("@omena/eslint-plugin");
export default [...omena.configs.recommended];Focused variant:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const omena = require("@omena/eslint-plugin");
export default [...omena.configs.focused];Optional dynamic moat:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const omena = require("@omena/eslint-plugin");
export default [...omena.configs.dynamicMoat];Repo-local clean example:
Supported rule options today:
workspaceRootclassnameTransformpathAliasincludeMissingModule(source-check/missing-module)
The first Stylelint consumer lives at packages/stylelint-plugin.
Current scope:
- style-side rules only
unused-selectormissing-composed-modulemissing-composed-selectormissing-value-modulemissing-imported-valuemissing-keyframes
See packages/stylelint-plugin/README.md for usage. See examples/plugin-consumers for a clean repo-local consumer workspace.
Minimal setup docs for the generic lsp-server:
examples/ contains scenario-based manual QA fixtures for the extension
development host. See examples/README.md.
Before opening a change:
- run
pnpm check - run
pnpm test - verify the affected scenario in
examples/when the change touches editor behavior
Keep commits scoped to a single concern when possible.
MIT. See LICENSE.