TypeScript rules
112 rules across 23 categories, enforced by chisel-js.
agent · 1 rule
agent:tool-boundary
Section titled “agent:tool-boundary”An agent tool or protocol server constructed outside the declared tool adapters
Fix. Build tools through the adapter listed in agent.toolAdapters, which applies the shared approval and feedback policy.
Architecture
Section titled “Architecture”architecture · 12 rules
architecture:indirect-dependency
Section titled “architecture:indirect-dependency”Prohibited behaviour reached through an alias, barrel, namespace import, wrapper or injected function port; or an entry point calling a service, repository or store
Fix. Put the application operation in a controller and inject the narrow capability there. An entry point parses its input and calls controller operations.
architecture:public-service-helper
Section titled “architecture:public-service-helper”An exported service function or callable, or a public service member outside its implemented contract
Fix. Expose one cohesive class capability through its interface; keep helpers private. A test does not justify a public helper.
architecture:service-interface
Section titled “architecture:service-interface”A public service class without explicit interface contracts, including alias and default exports
Fix. Declare the capability callers need and implements it.
architecture:concrete-dependency
Section titled “architecture:concrete-dependency”A concrete implementation used as a dependency type, including through aliases, utility types and inferred factory results
Fix. Depend on the declared contract. Pick<ConcreteService, …> is still the concrete class, and a factory’s public results need interface annotations; satisfies keeps the inferred concrete type.
architecture:controller-orchestration
Section titled “architecture:controller-orchestration”A controller invoking another controller, through an interface, alias, getter or callback
Fix. Coordinate the underlying services in the owning controller. Shared data types belong in models.
architecture:controller-repository
Section titled “architecture:controller-repository”A controller calling a repository, directly or through an injected port typed as one
Fix. Put a service between them. The service owns the reads and writes and the rules around them.
architecture:controller-collaborator
Section titled “architecture:controller-collaborator”A controller result exposing a service, transport, repository or writable store
Fix. Return operation results or readonly state views, never the collaborators that produced them.
architecture:retained-service-state
Section titled “architecture:retained-service-state”Mutable service fields, module state or captured state that survive an operation
Fix. Keep values local to the operation. State that must outlive it is a database record on the server and a store in the browser.
architecture:store-workflow
Section titled “architecture:store-workflow”A store invoking a capability or network transport, directly or through a traced callback
Fix. A store applies controlled updates. Let a controller do the work and write the result.
architecture:factory-workflow
Section titled “architecture:factory-workflow”A factory executing a capability, including inside a callback it returns
Fix. Construct and connect dependencies only. Execution belongs to a controller, called by an entry point.
architecture:tool-operation
Section titled “architecture:tool-operation”An agent tool calling a service, repository or store instead of a controller operation
Fix. Wrap the one public controller operation the tool stands for. When none exists, give the controller an ordinary operation any entry point could call.
architecture:unresolved-source
Section titled “architecture:unresolved-source”Source or a local module the analyzer cannot inspect
Fix. Repair the syntax or the module path. An incomplete scan is not a passing one.
Bundle
Section titled “Bundle”bundle · 1 rule
bundle:oversized-app-chunk
Section titled “bundle:oversized-app-chunk”A client chunk containing application code exceeds the size budget
Fix. Split the route or import the heavy part dynamically. Vendor-only chunks are tolerated as a known cost; a chunk mixing application code is a regression. Requires a production build — run chisel-js bundle after building.
Checker
Section titled “Checker”checker · 1 rule
checker:unparseable-file
Section titled “checker:unparseable-file”A file that does not parse, so rules reading its syntax skipped it
Fix. Fix the syntax error the message names. Until then the file is checked by import and path rules only, and a violation inside it cannot be reported.
Coherence
Section titled “Coherence”coherence · 2 rules
coherence:empty-test-glob
Section titled “coherence:empty-test-glob”A test-runner include pattern matches no files
Fix. Fix the pattern or delete it. A glob matching nothing means part of the suite stopped running and CI stayed green — the one failure mode the test suite cannot report itself.
coherence:broken-doc-path
Section titled “coherence:broken-doc-path”Maintained documentation cites a path that does not exist
Fix. Update the reference or remove it. Checked in root and docs/ markdown; generated API references and build output are excluded. A path the repository gitignores is a file the project creates at run time, such as a cached login, so it is allowed to be absent.
Colour Enforcement
Section titled “Colour Enforcement”colour-enforcement · 4 rules
colour:arbitrary-value-banned
Section titled “colour:arbitrary-value-banned”Arbitrary Tailwind colour value syntax (bg-[…], text-[#…], border-[…], etc.)
Fix. Add the colour as a CSS custom property in app.css first, then reference it as a Tailwind token (e.g. bg-primary).
colour:palette-class-banned
Section titled “colour:palette-class-banned”Hardcoded Tailwind palette colour (text-red-500, bg-slate-800, from-blue-500)
Fix. Use a semantic token from app.css (bg-background, text-muted-foreground, text-destructive). A palette class pins one appearance and cannot follow the theme, so it looks wrong in whichever mode it was not written for.
colour:dynamic-class-banned
Section titled “colour:dynamic-class-banned”Dynamic class construction (class={bg-${variable}})
Fix. Use a lookup object of pre-approved token names instead: const colourMap = { primary: ‘bg-primary’ }.
colour:modifier-on-semantic
Section titled “colour:modifier-on-semantic”Experimental modifier class on semantic HTML
Fix. Modifier classes (.glass, .neumorphic) restricted to Hero components and Overlay widgets.
Component Enforcement
Section titled “Component Enforcement”component-enforcement · 24 rules
component-enforcement:html-button-banned
Section titled “component-enforcement:html-button-banned”Raw
Fix. Use <Button, Toggle> from shadcn.
component-enforcement:html-textarea-banned
Section titled “component-enforcement:html-textarea-banned”Raw
Fix. Use
component-enforcement:html-select-banned
Section titled “component-enforcement:html-select-banned”Raw
Fix. Use <Select, NativeSelect, Combobox> from shadcn.
component-enforcement:html-label-banned
Section titled “component-enforcement:html-label-banned”Raw
Fix. Use
component-enforcement:html-progress-banned
Section titled “component-enforcement:html-progress-banned”Raw
Fix. Use
component-enforcement:html-dialog-banned
Section titled “component-enforcement:html-dialog-banned”Raw
Fix. Use <Dialog, AlertDialog, Drawer, Sheet> from shadcn.
component-enforcement:html-nav-banned
Section titled “component-enforcement:html-nav-banned”Raw
Fix. Use <NavigationMenu, Breadcrumb, Menubar, Sidebar, Pagination> from shadcn.
component-enforcement:html-kbd-banned
Section titled “component-enforcement:html-kbd-banned”Raw element
Fix. Use from shadcn.
component-enforcement:html-hr-banned
Section titled “component-enforcement:html-hr-banned”Raw
element
Fix. Use
component-enforcement:html-form-banned
Section titled “component-enforcement:html-form-banned”Raw