| name | pattern-schema |
| description | Design schemas.tsx with Input/Output types for patterns |
| user-invocable | false |
Use the cf skill, or read skills/cf/SKILL.md, for CLI documentation when
running commands.
Schema Design Phase
Goal
Create schemas.tsx with all data types and Input/Output types BEFORE any
pattern code.
Read First
docs/common/concepts/types-and-schemas/default.md
docs/common/concepts/types-and-schemas/writable.md
docs/common/concepts/pattern.md (Input/Output section)
Rules
- ALWAYS use
pattern<Input, Output>() - Never use single-type
pattern<State>(). Single-type patterns cannot be tested via .send().
- Use
Writable<> in an Input type only for values the pattern receives and
intends to mutate.
- Output types never use
Writable<> - they reflect returned data shape
- Fields that could be undefined initially: use
Default<T, value>
- Actions in Output type:
Stream<T> (enables testing and linking)
- Sub-patterns need
[NAME]: string and [UI]: VNode in Output type
- Decide the sharing boundary now - choose
PerSpace<> / PerUser<> /
PerSession<> for every Input field at schema time; see the pattern-dev
skill for the new-tab test. Transient UI state (selected tab, filter text,
open modal) defaults to PerSession<>.
Top-Level vs Sub-Pattern Inputs
Pattern Factory create-mode deliverables are usually top-level patterns. A
top-level pattern should be usable by itself with sensible defaults and should
usually own its local state unless the brief explicitly describes caller-owned
cells, linking, or embedding.
Do not create required caller-provided Writable<> inputs solely because the UI
edits that field. If the top-level pattern owns the state, model that ownership
in the pattern implementation and expose the user-visible shape through the
Output type.
Use caller-provided writable inputs by default for nested sub-patterns that edit
state owned by a parent pattern. Those sub-patterns also need [NAME] and
[UI] when rendered by composition.
Template
import {
Default,
NAME,
type PerSession,
Stream,
UI,
VNode,
Writable,
} from "commonfabric";
export interface Item {
name: Default<string, "">;
done: Default<boolean, false>;
}
export interface ItemListInput {
items?: Writable<Item[] | Default<[]>>;
filterText?: PerSession<string | Default<"">>;
}
export interface ItemListOutput {
[NAME]: string;
[UI]: VNode;
items: Item[];
addItem: Stream<{ name: string }>;
}
export interface ItemInput {
item: Writable<Item>;
}
export interface ItemOutput {
[NAME]: string;
[UI]: VNode;
item: Item;
toggle: Stream<void>;
}
Done When
- All data types defined with correct Writable/Default wrapping
- All Input/Output types defined for each top-level pattern or sub-pattern
- No TypeScript errors:
deno task cf check schemas.tsx --no-run