@rettangoli/check
v0.1.2
Published
Static contract checker for Rettangoli projects
Readme
Rettangoli Check (Brainstorm)
Working name:
rettangoli-check(possible package:@rettangoli/check)
This package is intended to be a dedicated static analyzer for Rettangoli projects. It should validate that component contracts are respected across files before runtime/build errors happen.
Execution plan: see packages/rettangoli-check/ROADMAP.md.
Loop retrospective: see packages/rettangoli-check/LOOP_LEARNINGS.md.
Current Implementation Status
Implemented now:
- package + CLI entrypoint (
@rettangoli/check,rtgl check) - discovery and component grouping
- model building for YAML/JS contracts
- FE parity checks (schema required, forbidden view keys, legacy
.prop=binding) - schema/constants checks
- listener config checks
- strict handler naming checks (
handle*only) - cross-file symbol checks (handler/action/method existence)
- YAHTML attr/prop validation for template selector bindings
- semantic scope graph (YAHTML + Jempl + FE binding context)
- schema-aware expression checks (unresolved roots, invalid schema paths, boolean type mismatch)
- lifecycle signature checks (
handleBeforeMount,handleOnUpdate) - inter-component compatibility checks (required props, events, boolean prop binding type)
- UI primitive/component registry generation from
rettangoli-ui - reporters:
text,json,sarif - watch mode with incremental component model cache
- robustness harnesses: export differential + template pipeline fuzzing
- CI integration in
.github/workflows/ci-ui.yamlviabun run check:contracts
Template parser architecture:
docs/template-analysis.md(YAML -> Jempl -> YAHTML pipeline)
Checklist progress is tracked with [x]/[ ] in packages/rettangoli-check/ROADMAP.md.
CLI Usage
# default (uses rettangoli.config.yaml fe.dirs when available)
rtgl check
# explicit directory
rtgl check --dir src/components
# JSON output
rtgl check --dir src/components --format json
# SARIF output
rtgl check --dir src/components --format sarif
# enable expression scope/type checks
rtgl check --dir src/components --expr
# watch mode (incremental)
rtgl check --watch --watch-interval-ms 500
# treat warnings as errors
rtgl check --warn-as-error
# run without YAHTML attr checks (contract-only mode)
rtgl check --dir src/components --no-yahtml
# preview safe autofixes
rtgl check --dir src/components --autofix-dry-run --format json
# preview safe autofixes with patch output
rtgl check --dir src/components --autofix-dry-run --autofix-patch --format json
# apply safe autofixes
rtgl check --dir src/components --autofix --autofix-min-confidence 0.95rtgl-check command surface:
# check contracts
rtgl-check --dir src/components --format jsonCLI contract references:
packages/rettangoli-check/docs/cli-contract.mdpackages/rettangoli-check/docs/semantic-compatibility-guarantees.mdpackages/rettangoli-check/docs/diagnostics-reporting-contract.mdpackages/rettangoli-check/docs/diagnostics-reference.mdpackages/rettangoli-check/docs/diagnostics-sarif-contract.mdpackages/rettangoli-check/docs/security-parser-attack-surface.md
JS Export Parser Backend
rettangoli-check now uses Oxc as the single runtime JS export extractor.
Legacy regex extraction is retained only in test parity harnesses:
bun run --cwd packages/rettangoli-check test:diff-js-exportsKnown Strict Findings (Current UI Baseline)
Current baseline is clean in strict mode:
packages/rettangoli-uicontract checks pass with YAHTML enabled- CI runs strict contract checks (no
--no-yahtmlbypass)
Why this package
@rettangoli/fe already has a contract checker (rtgl fe check), but today it focuses on a small set of structural rules:
- required
.schema.yamlper component - forbidden metadata keys inside
.view.yaml - legacy
.prop=syntax detection
That baseline is good, but many contract violations are still caught late (during build, runtime, or manually).
What we learned from current codebase
FE contract sources
Canonical docs are in packages/rettangoli-fe/docs/:
overview.mdview.mdschema.mdstore.mdhandlers.mdmethods.mdconstants.md
Existing FE check implementation
Main check path today:
packages/rettangoli-fe/src/cli/check.jspackages/rettangoli-fe/src/cli/contracts.jspackages/rettangoli-fe/src/core/contracts/componentFiles.js
Runtime/build validations that are currently not fully static
Important checks currently happen at build/runtime, not as deep static analysis:
- schema contract and methods mapping:
packages/rettangoli-fe/src/core/schema/validateSchemaContract.js - listener config validation (handler/action exclusivity, modifiers, debounce/throttle):
packages/rettangoli-fe/src/core/view/refs.js - action dispatch to store action name validation:
packages/rettangoli-fe/src/core/runtime/lifecycle.js - build-time parse/compose of component files:
packages/rettangoli-fe/src/cli/build.js
UI package shape
packages/rettangoli-ui/src/components/* consistently uses the FE multi-file model (.view.yaml, .schema.yaml, optional .handlers.js/.store.js/.methods.js).
That makes it a strong first target for static checks.
Proposed goals for rettangoli-check
- Catch contract violations earlier than runtime.
- Give precise file-level diagnostics (and line-level when possible).
- Separate rule engine from FE runtime, so checkers can run in CI/editor/pre-commit.
- Support both human and machine output (
text,json, latersarif).
Rule ideas
V1 (high value, low ambiguity)
- File-set rules
.schema.yamlrequired per component- no unsupported FE file suffixes in component folders (optional strict mode)
- Schema rules
componentNamerequired, non-empty, valid custom element format- reject
attrsSchema methodsmust be object schema withproperties
- Cross-file symbol rules
schema.methods.properties.*must exist in.methods.jsexports- exported methods in
.methods.jsshould be documented inschema.methods(warn-level first) refs.*.eventListeners.*.handlermust exist in.handlers.jsrefs.*.eventListeners.*.actionmust exist in.store.js
- Listener config static validation
- exactly one of
handleroraction debounceandthrottleare mutually exclusive- modifier types (
boolean, non-negative number)
- Component identity rules
- detect duplicate
componentNameacross project - optional: enforce expected mapping between folder/file base name and schema component name
- Constants rules
.constants.yamlroot must be an object
V2 (medium complexity)
- Refs and ID contracts
- if ID refs are used, matched element IDs should satisfy camelCase constraints used by runtime
- Store/handlers shape checks
handleBeforeMountshould not be async (or return Promise)- basic export-order/lint checks for
.store.js(if still desired as strict rule)
- API consistency checks for UI libraries
- event naming conventions (
kebab-case, suffix consistency) - payload contract hints from schema vs emitted event docs (warn-level)
V3 (advanced / optional)
- Template expression linting and unresolved symbol checks.
- Inter-component prop compatibility checks (requires component registry graph).
- Autofix mode for mechanical issues.
Architecture proposal
1. Core flow
- Discover component files from configured dirs.
- Parse YAML files (
js-yaml) and JS files (AST-based, likely@babel/parser). - Build a component model:
- metadata (
category,component, paths) - schema model
- view refs/listeners model
- JS export indexes for store/handlers/methods
- Run rule engine over model.
- Format diagnostics.
2. Module boundaries
src/discovery/file walking and groupingsrc/parsers/yaml/js/template helperssrc/model/normalized IR for rulessrc/rules/one file per rule with code + testssrc/reporters/text/json/sarif formatterssrc/cli/command wiring
3. Integration points
Short-term:
- keep
rtgl fe checkas-is - add optional command path that can call new checker
Long-term:
- make
rtgl fe checkdelegate to@rettangoli/checkfor FE rules - allow package-specific presets (
fe,ui, custom)
Suggested CLI surface (draft)
# full project scan from rettangoli.config.yaml
rtgl check
# explicit directories
rtgl check --dirs src/components --dirs src/pages
# output modes
rtgl check --format text
rtgl check --format json
rtgl check --format sarif
# rule controls
rtgl check --preset fe
rtgl check --preset ui
rtgl check --warn-as-errorMinimal milestone plan
- Bootstrap package with CLI + discovery + current FE parity rules.
- Add cross-file symbol rules (handler/action/method existence).
- Add duplicate component name and method-doc coverage diagnostics.
- Wire into CI in
rettangoli-uiand one example app.
Open design questions
- Naming:
rettangoli-checkvsrettangoli-contractsvsrettangoli-lint. - Should
rtgl fe checkremain FE-specific wrapper, or fully replaced by genericrtgl check? - Error code strategy:
- keep existing
RTGL-CONTRACT-xxx - or introduce package-specific namespaces (example:
RTGL-CHECK-FE-xxx)
- Strictness defaults:
- what is error vs warning in CI by default?
Immediate next step (implementation)
Create @rettangoli/check with:
- package scaffolding
- parser/model foundation
- parity checks from existing
@rettangoli/fecheck - at least one new high-value cross-file rule (
action->.store.jsexport exists)
