1. Module Scope Violations
Check that these are NOT inside the pattern body:
| Violation | Fix |
|-----------|-----|
| handler() defined inside pattern | Move to module scope, or use action() instead |
| lift() immediately invoked (lift(...)(args)) | Use computed() or define lift at module scope |
| Helper functions defined inside pattern | Move to module scope |
Allowed inside patterns: computed(), action(), .map() callbacks, JSX event handlers.
2. Reactivity Violations
| Violation | Fix |
|-----------|-----|
| [NAME]: someProp (reactive value) | [NAME]: computed(() => someProp) |
| [NAME]: \text ${someProp}\` | [NAME]: computed(() => \text ${someProp}\)` |
| Writable.of(reactiveValue) | Initialize empty, set in handler/action |
| .get() on computed/lift result | Access directly (only Writable has .get()) |
| items.filter(...) inline in JSX | Wrap in computed() outside JSX |
| items.sort(...) inline in JSX | Wrap in computed() outside JSX |
| Nested computed with outer scope vars | Pre-compute with lift or outer computed |
| lift() closing over reactive deps | Pass deps as explicit params |
| Cells from composed patterns in ifElse | Wrap in local computed() |
3. Conditional Rendering
| Violation | Fix |
|-----------|-----|
| onClick inside computed() | Move button outside, use disabled attr |
Note: Ternaries work fine in JSX - the transformer auto-converts them to ifElse(). Both {show ? : null} and {ifElse(show, ...)} are valid.
4. Type System
| Violation | Fix |
|-----------|-----|
| Array without Default | Add default to prevent undefined |
| Missing Writable<> for .set()/.push() | Add Writable to input type |
| Map or Set in cell data | Use plain objects/arrays (serialization) |
| Custom id property for identity | Use equals() function instead |
5. Binding
| Violation | Fix |
|-----------|-----|
| checked={item.done} | $checked={item.done} (add $ prefix) |
| value={title} | $value={title} (add $ prefix) |
| $checked={item} (whole item) | $checked={item.done} (bind property) |
| Wrong event name | Use onct-send, onct-input, onct-change |
6. Style Syntax
| Element Type | Required Syntax |
|--------------|-----------------|
| HTML (div, span) | Object: style={{ backgroundColor: "#fff" }} |
| Custom (ct-*) | String: style="background-color: #fff;" |
| Violation | Fix |
|-----------|-----|
| String style on HTML | Convert to object syntax |
| Object style on ct-* | Convert to string syntax |
| kebab-case props on ct-* | Use camelCase: allowCustom not allow-custom |
7. Handler Binding
| Violation | Fix |
|-----------|-----|
| onClick={addItem({ title: "x", items })} | Event data comes at runtime, bind state only |
| Creating handlers inside .map() | Create handler once at module/pattern scope |
8. Stream/Async
| Violation | Fix |
|-----------|-----|
| Stream.of() | Doesn't exist. Bound handler IS the stream |
| .subscribe() on stream | Doesn't exist. Return stream from pattern |
| async/await in handlers | Use fetchData() (blocks UI otherwise) |
| await generateText(...) | Reactive, not a promise. Use .result |
| await generateObject(...) | Reactive, not a promise. Use .result |
9. LLM Integration
| Violation | Fix |
|-----------|-----|
| Array as root schema for generateObject | Wrap in object: { items: T[] } |
| Missing /// directive | Add at top of file |
| Prompt derived from agent-written cells | Causes infinite loop. Use separate cells |
| Invalid model name format | Use vendor:model (e.g., anthropic:claude-sonnet-4-5) |
10. Performance
| Violation | Fix |
|-----------|-----|
| Handler created per-item in .map() | Create handler once, bind with item |
| Expensive computation inside loop | Pre-compute outside, reference result |
11. Design Review
Check the domain model quality:
| Check | What to look for |
|-------|------------------|
| Clear entity boundaries | Each pattern represents one concept (Card, Column, Board) |
| Actions match user intent | Handler names reflect what user wants (addCard, moveCard, removeCard) |
| Unidirectional data flow | Parent owns state, children receive props |
| Normalized state | No duplicate data, single source of truth |
| Self-documenting types | Type names and fields are clear without comments |
| Appropriate granularity | Not too fine (trivial patterns) or too coarse (god patterns) |
12. Regression Check (for updates only)
When reviewing changes to existing code:
| Check | What to verify |
|-------|----------------|
| Tests still pass | Run existing tests after changes |
| Type signatures preserved | Or intentionally changed with migration path |
| Handlers still work | Existing functionality not broken |
| No unintended side effects | Changes scoped to intended area |