Kumiki Specification
This is the normative specification of the Kumiki language and runtime. When the implementation in packages/ and this text disagree, this text wins, and the PR records which side gets fixed.
You do not have to read it end to end. Language Core is the one document to read before writing Kumiki; the rest answer a question you already have. Tutorials and how-tos are not specification and live in the guide, and every feature has a runnable file in examples.
Documents
| Document | Contents |
|---|---|
| Language Core | the 7 layers (type / slot / effect / reducer / tile / fn / app) and expressions, statements, patterns |
| Standard Library | List / Map / Set / Option / Result / Time / domain types |
| Routing | patterns, parameters, route.enter / route.leave, redirects |
| Style | Style, layout, and themes |
| Forms | Forms, bind, validation |
| HTTP / Storage | HTTP / Storage effects and policies (latest / debounce / once …) |
| Lifecycle | Lifecycle, capabilities, error boundaries, suspense |
| Runtime | Runtime implementation guide (signal graph, mount, dispatch, dispose) |
| AI Editing | AI editing API, CRDT ops, referential integrity |
| Testing | Testing strategy |
| Error Codes | Error code catalog (E0000..E08xx) |
Indexes
Three cross-references into the documents above, each generated from the compiler and the examples rather than written by hand.
Layer × feature matrix — where each feature touches the 7 layers
A cell links to the section that specifies that intersection; — means the dimension has no layer-specific rules there.
AI-editing CRDT ops (add / replace / remove / rename, §9.3.1) apply uniformly to definitions of every layer; the matrix row lists only the layer-specific sections.
Diagnostic codes — every code in Error Codes, by layer and feature
| Code | Kind | Layer | Feature |
|---|---|---|---|
| E0000 | parse-error | all | core |
| E0001 | missing-404 | app | routing |
| E0002 | duplicate-timer-name | app | lifecycle |
| E0003 | missing-app | app | core |
| E0004 | duplicate-app | app | core |
| E0005 | tile-cycle | tile | core |
| E0006 | fn-cycle | fn | core |
| E0007 | duplicate-definition | all | core |
| E0008 | duplicate-clause / duplicate-key / duplicate-field / duplicate-param / duplicate-variant | all | core |
| E0009 | type-cycle | type | core |
| E0102 | undef-reducer | reducer | core |
| E0103 | undef-ref / undef-slot | slot | core |
| E0104 | undef-effect / init-not-effect-call | effect | core |
| E0106 | undef-timer | reducer | lifecycle |
| E0105 | undef-tile | tile | core |
| E0107 | undef-motion | tile | style |
| E0108 | undef-member | fn | stdlib |
| E0110 | unknown-token-group | tile | style |
| E0109 | test-wildcard-misuse | reducer | testing |
| E0111 | orphan-sub-routes | tile | routing |
| E0112 | duplicate-sub-route | tile | routing |
| E0113 | sub-routes-without-outlet | tile | routing |
| E0114 | sub-routes-without-wildcard-parent | tile | routing |
| E0115 | reserved-slot-name | slot | core |
| E0116 | undef-call | fn | core |
| E0117 | undef-type | type | core |
| E0118 | undef-theme | app | style |
| E0119 | route-bind-out-of-scope | reducer | routing |
| E0120 | route-in-app-init | app | routing |
| E0121 | reserved-bind-name | reducer | core |
| E0122 | duplicate-pattern-bind | reducer | core |
| E0123 | duplicate-effect-bind | reducer | core |
| E0124 | type-constructor-qualifier | type | core |
| E0127 | fn-as-value | all | core |
| E0128 | value-as-child | tile | core |
| E0129 | unrendered-arg | tile | core |
| E0201 | type-mismatch | type | core |
| E0202 | emit-arg-type-mismatch | reducer | core |
| E0204 | effect-id-misuse | effect | http |
| E0205 | bind-on-file-input | tile | forms |
| E0206 | file-only-prop | tile | forms |
| E0207 | pat-arity-mismatch | type | core |
| E0208 | pat-type-mismatch | type | core |
| E0209 | pat-unknown-variant | type | core |
| E0210 | type-arity-mismatch | type | core |
| E0211 | undef-tile-in-selector | reducer | core |
| E0212 | selector-id-mismatch | reducer | core |
| W0212 | ui-event-tile-mismatch | reducer | core |
| E0213 | call-arity-mismatch | fn | core |
| E0214 | missing-record-field | type | core |
| E0215 | unknown-record-field | type | core |
| E0216 | unknown-variant | type | core |
| E0217 | int-literal-precision | type | core |
| E0218 | for-over-non-list | type | core |
| E0219 | bind-strict-prop | tile | forms |
| E0220 | boundary-fallback-input | tile | lifecycle |
| E0225 | radio-bind-without-value | tile | forms |
| E0226 | input-bind-type | tile | forms |
| W0213 | handler-on-inert-tile | tile | core |
| W0214 | fmt-placeholder-argument-mismatch | all | stdlib |
| W0216 | selection-beside-bind | tile | forms |
| E0301 | missing-capability | effect | stdlib |
| E0302 | unknown-capability | app | stdlib |
| E0303 | invalid-cancel-target | effect | http |
| E0304 | derived-slot | slot | core |
| E0305 | fn-impurity | fn | core |
| E0306 | err-type-not-text | effect | http |
| E0401 | motion-unknown-property | tile | style |
| E0402 | motion-invalid-timing | tile | style |
| E0403 | motion-malformed | tile | style |
| E0601 | duplicate-write | reducer | core |
| E0602 | unassignable-member | reducer | core |
| E0701 | a11y-button | tile | lifecycle |
| E0702 | a11y-image | tile | lifecycle |
| E0703 | a11y-link | tile | lifecycle |
| E0704 | unknown-icon | tile | style |
| E0705 | a11y-label-for | tile | lifecycle |
| E0712 | episode-mock-invalid | effect | testing |
| E0713 | test-shape-invalid | effect | testing |
| E0714 | test-section-unknown | effect | testing |
| E0801 | unimplemented-method | fn | stdlib |
| E0802 | unimplemented-function | fn | stdlib |
| E0803 | unimplemented-refinement | type | core |
| E0804 | refinement-args-invalid | type | core |
Feature examples — one runnable file per matrix cell
Layers name the definitions the example centers on; Spec links the section it demonstrates.
| Example | Layers | Feature | Spec |
|---|---|---|---|
01-slot-and-reducer.kumiki | slot, reducer | core | §1.4 §1.6 |
02-nominal-type.kumiki | type | core | §1.3 |
03-union-and-match.kumiki | type | core | §1.3 |
04-record-and-copy.kumiki | type | core | §1.3 |
05-pure-fn.kumiki | fn | core | §1.8 |
06-if-expression.kumiki | fn | core | §1.9 |
07-list.kumiki | fn | stdlib | §2.2.3 |
08-map.kumiki | fn | stdlib | §2.2.1 |
09-set.kumiki | fn | stdlib | §2.2.2 |
10-option.kumiki | fn | stdlib | §2.2.4 |
11-time-and-duration.kumiki | fn | stdlib | §2.2.8 |
12-layout.kumiki | tile | style | §4.4 |
13-text-input-bind.kumiki | slot, tile | forms | §5.1 |
14-select.kumiki | tile | forms | §5.5.1 |
15-checkbox.kumiki | tile | forms | §5.3.1 |
16-conditional-ui.kumiki | tile | core | §1.7 |
17-theme.kumiki | app | style | §4.2 |
18-routing.kumiki | app, tile | routing | §3.1 |
19-effect-http.kumiki | effect | http | §6.2 |
20-effect-storage.kumiki | effect | http | §6.7 |
21-timer.kumiki | reducer | lifecycle | §7.1.5 |
22-result.kumiki | type | stdlib | §2.2.5 |
23-lifecycle-route-enter.kumiki | reducer | routing | §3.4 |
24-fold.kumiki | fn | stdlib | §2.2.3 |
25-stop-timer.kumiki | effect, reducer | lifecycle | §7.1.5 |
26-overlay.kumiki | tile | stdlib | §2.3.7 |
27-custom-capability.kumiki | app, effect | stdlib | §2.5 |
28-tests.kumiki | reducer | testing | §8.1 |
30-motion.kumiki | tile | style | §4.9 |
31-argless-methods.kumiki | fn | stdlib | §2.2 |
32-panic-boundary.kumiki | tile, app | lifecycle | §7.3 |
33-field-vs-method.kumiki | fn, type | stdlib | §2.2 |
34-builtin-tiles.kumiki | tile | stdlib | §2.3 |
35-match-and-args.kumiki | tile, type | core | §1.9 |
36-effect-indexed-db.kumiki | effect | http | §6.7.4 |
37-lifecycle-events.kumiki | reducer | lifecycle | §7.1 |
38-confirm-leave-guard.kumiki | reducer | routing | §3.5.2 |
39-effect-session.kumiki | effect | http | §6.7.4 |
40-nested-routes.kumiki | app, tile | routing | §3.6 |
40-token-refs.kumiki | tile | style | §4.3 |
41-link-prefetch.kumiki | tile | routing | §3.8 |
42-scroll-restoration.kumiki | app | routing | §3.9 |
43-file-upload-preview.kumiki | tile | forms | §5.10 |
44-episode-test.kumiki | effect | testing | §8.6 |
45-ui-key-hover-tuple.kumiki | reducer, tile | core | §1.6 |
46-stdlib-paren-methods.kumiki | fn | stdlib | §2.2 |
47-icon-set.kumiki | tile | style | §4.8 |
48-effect-cancel.kumiki | effect | http | §6.4 |
49-ui-focus-blur.kumiki | reducer, tile | core | §1.6 |
50-match-pattern-integrity.kumiki | type | core | §1.9 |
51-selector-id.kumiki | reducer | core | §1.6.2 |
52-selector-id-arg.kumiki | reducer | core | §1.6.2 |
53-keyed-list-identity.kumiki | tile | core | §10.3.10 |
54-select-preserves-state.kumiki | tile | core | §10.3.11 |
55-video-preserves-currenttime.kumiki | tile | core | §10.3.11 |
56-details-preserves-open.kumiki | tile | core | §10.3.11 |
57-editable-preserves-focus.kumiki | tile | core | §10.3.11 |
58-unkeyed-conditional-rebuild.kumiki | tile | core | §10.3.12 |
59-overlay-keyed-layers.kumiki | tile | core | §10.3.10 |
60-empty-state-keyed-list.kumiki | tile | core | §10.3.10 |
61-reserved-identifier-names.kumiki | fn, reducer | core | §1.2 |
62-conditional-inline-tile-handlers.kumiki | tile, reducer | core | §10.3.13 |
63-reducer-batch-atomicity.kumiki | slot, reducer | core | §10.3.3 |
64-init-slot-argument.kumiki | app, effect | core | §1.12 |
65-prefers-dark.kumiki | app, reducer | style | §4.6.1 |
66-value-types.kumiki | type, slot, fn | core | §1.9.4 |
67-self-reference.kumiki | type, slot, tile, fn | core | §1.3.6 |
68-name-uniqueness.kumiki | type, slot, fn | core | §1.3.1 |
69-builtin-effect-capabilities.kumiki | reducer, effect | stdlib | §2.6 |
70-spec-grammar.kumiki | type, slot, fn, reducer | core | §1.2 |
71-button-type.kumiki | slot, reducer, tile | forms | §5.2.2 |
72-time-format.kumiki | slot, fn, tile | stdlib | §2.2.8 |
73-effect-policy-queue.kumiki | slot, effect, reducer | lifecycle | §10.4.3 |
74-common-tile-props.kumiki | slot, reducer, tile | style | §2.3.10 |
75-paren-less-stdlib-constants.kumiki | slot, effect, reducer | http | §6.1.4 |
76-conditional-adds-a-universal-handler.kumiki | slot, reducer, tile | core | §10.3.11 |
77-int-float-math.kumiki | slot, reducer, tile | stdlib | §2.2.7 |
78-editable-input-selector.kumiki | slot, reducer, tile | core | §W0212 |
79-option-get-assignment.kumiki | slot, reducer, tile | core | §1.6.3 |
80-route-in-tests.kumiki | slot, effect, reducer, tile | testing | §8.2.5 |
81-http-config-from-slots.kumiki | slot, effect, reducer, tile | http | §6.3.1 |
82-handler-on-a-user-tile.kumiki | slot, reducer, tile | core | §1.7.3 |
83-let-shadowing.kumiki | slot, reducer, fn, tile | core | §1.6.7 |
84-off-origin-link.kumiki | app, tile | routing | §3.3.1 |
85-capitalised-reducer-handler.kumiki | slot, reducer, tile | core | §1.7.3 |
86-container-selector-through-reference.kumiki | slot, reducer, tile | core | §1.6.2 |
87-replayed-environment-read.kumiki | slot, reducer, tile | core | §10.5.1 |
88-string-formatting.kumiki | slot, reducer, tile | stdlib | §2.4.5 |
89-qualified-show.kumiki | type, slot, reducer, tile | stdlib | §2.4.3 |
90-refinement-validation.kumiki | type, slot, reducer | forms | §5.6 |
91-conjoined-refinements.kumiki | type, slot, reducer, tile | core | §1.3.1 |
92-outlet-error-boundary.kumiki | slot, reducer, tile, app | lifecycle | §7.3 |
93-panic-info.kumiki | slot, reducer, tile, app | lifecycle | §7.2.3 |
94-editable-key-focus-blur-selectors.kumiki | slot, reducer, tile | core | §W0212 |
95-disabled-controls-refuse-a-step.kumiki | slot, reducer, tile | testing | §8.10 |
96-shortcut-named-fields.kumiki | type, slot, reducer, tile | core | §1.6.3 |
97-get-or-two-readings.kumiki | slot, reducer, tile | core | §2.2.1 |
98-receiver-decided-results.kumiki | slot, reducer, tile | core | §2.2 |
99-route-into-a-slot.kumiki | slot, fn, reducer, tile | routing | §E0304 |
100-option-filter.kumiki | slot, reducer, tile | stdlib | §2.2.4 |
101-list-index-write.kumiki | type, slot, reducer, tile | core | §1.6.3 |
102-non-text-keys.kumiki | type, slot, reducer, tile | stdlib | §2.2.2 |
103-generic-alias-refinement.kumiki | type, slot, reducer, tile | core | §1.3.1 |
104-nested-refinements.kumiki | type, slot, reducer, tile | core | §1.3.3 |
105-refused-bind.kumiki | slot, reducer, tile | forms | §5.1.2 |
107-builtin-content-is-positional.kumiki | slot, reducer, tile | core | §1.7.1 |
108-call-site-handler-joins-lifted.kumiki | slot, reducer, tile | core | §1.7.3 |
109-control-key-focus-blur-selectors.kumiki | slot, reducer, tile | core | §W0212 |
110-parse-by-base.kumiki | type, slot, reducer, tile | stdlib | §2.4.3 |
111-applied-type-qualifier.kumiki | type, slot, reducer, tile | stdlib | §E0124 |
113-match-value-type.kumiki | type, slot, reducer, fn, tile | core | §1.9 |
114-unit-value.kumiki | slot, reducer, fn, tile | stdlib | §2.1 |
115-fn-name-fragment.kumiki | slot, reducer, fn, tile | core | §1.8.6 |
116-emit-id-after-key-write.kumiki | slot, effect, reducer, tile | http | §6.4 |
119-effect-payload-bind-types.kumiki | type, slot, effect, reducer, tile | core | §1.6.5 |
120-http-config-value-types.kumiki | slot, effect, reducer, tile, app | http | §6.3.1 |
121-boundary-fallback-input.kumiki | type, slot, reducer, tile | lifecycle | §7.3 |
122-value-equality.kumiki | type, slot, reducer, tile | core | §1.9.4 |
123-one-key-per-value.kumiki | type, slot, reducer, tile | stdlib | §2.2.1 |
124-set-literal.kumiki | type, slot, reducer, tile, fn | stdlib | §2.2.2 |
127-http-query-string.kumiki | type, slot, effect, reducer, tile | http | §6.1.2 |
128-http-body-variants.kumiki | slot, effect, reducer, tile | http | §6.1.3 |
129-http-decode-failure.kumiki | type, slot, effect, reducer, tile | http | §6.5 |
130-storage-remove-clear.kumiki | slot, effect, reducer, tile | http | §6.7.2 |
132-toggle-bind.kumiki | type, slot, reducer, tile | forms | §5.1.1 |
133-typed-input-bind.kumiki | type, slot, reducer, tile | forms | §5.1.1 |
134-record-field-bind.kumiki | type, slot, tile | forms | §5.6 |
135-form-submit-gate.kumiki | slot, reducer, tile | forms | §5.2.2 |
136-submit-button-click.kumiki | slot, reducer, tile | forms | §5.2.2 |
139-get-unwrap-with-parentheses.kumiki | slot, reducer, tile | stdlib | §2.2.4 |
140-is-empty-both-spellings.kumiki | slot, reducer, tile | stdlib | §2.2.1 |
141-el-kebab-prop.kumiki | type, slot, reducer, tile | core | §1.6.5 |
142-tile-body-own-scope.kumiki | type, slot, reducer, tile | core | §1.7.2 inv. 1 |
143-fn-positional-arguments.kumiki | slot, reducer, fn, tile | core | §1.6.5 |
144-builtin-effect-input.kumiki | slot, reducer, tile | stdlib | §2.6 |
145-receiver-members.kumiki | slot, reducer, tile | stdlib | §2.2.3 |
153-route-specificity.kumiki | slot, reducer, tile, app | routing | §3.1.2 |
154-ssr-redirect.kumiki | tile, app | routing | §3.10 |
155-leave-on-param-change.kumiki | slot, reducer, tile, app | routing | §3.4 |
156-heading-level.kumiki | slot, reducer, tile | stdlib | §2.3.2 |
157-theme-switch.kumiki | slot, reducer, tile, app | style | §4.6 |
158-responsive-breakpoints.kumiki | tile, app | style | §4.5 |
159-replayed-event-payload.kumiki | type, slot, effect, reducer, tile | core | §10.5.3 |
160-tile-test-content-fields.kumiki | slot, tile | testing | §8.4 |
161-reducer-reads-its-own-write.kumiki | type, slot, reducer, tile | core | §1.6.4 |
162-fragment-binds-by-type.kumiki | slot, reducer, tile | stdlib | §2.2.3 |
163-keyed-list-tile.kumiki | type, slot, reducer, tile | core | §10.3.10 |
164-decode-refused-value.kumiki | type, slot, effect, reducer, tile | http | §6.7.2 |
165-sort-by-text-key.kumiki | type, slot, reducer, tile | stdlib | §2.2.3 |
166-map-map.kumiki | slot, reducer, tile | stdlib | §2.2.1 |
167-time-parse-calendar.kumiki | slot, reducer, fn, tile | stdlib | §2.2.8 |
168-map-index-absent-key.kumiki | type, slot, reducer, tile | core | §1.6.3 |
169-for-repeated-values.kumiki | slot, reducer, tile | core | §10.3.10 |