mythik 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +68 -44
  2. package/dist/actions/dispatcher.d.ts +2 -0
  3. package/dist/actions/dispatcher.d.ts.map +1 -1
  4. package/dist/actions/dispatcher.js +11 -2
  5. package/dist/actions/dispatcher.js.map +1 -1
  6. package/dist/contract/extractor.js +3 -0
  7. package/dist/contract/extractor.js.map +1 -1
  8. package/dist/data/data-sources.d.ts +4 -0
  9. package/dist/data/data-sources.d.ts.map +1 -1
  10. package/dist/data/data-sources.js +3 -1
  11. package/dist/data/data-sources.js.map +1 -1
  12. package/dist/editor-session/engine.d.ts +1 -0
  13. package/dist/editor-session/engine.d.ts.map +1 -1
  14. package/dist/editor-session/engine.js +5 -4
  15. package/dist/editor-session/engine.js.map +1 -1
  16. package/dist/fetch/framework-fetch.d.ts +1 -0
  17. package/dist/fetch/framework-fetch.d.ts.map +1 -1
  18. package/dist/fetch/framework-fetch.js +34 -4
  19. package/dist/fetch/framework-fetch.js.map +1 -1
  20. package/dist/fetch/interceptors/auth.d.ts +2 -0
  21. package/dist/fetch/interceptors/auth.d.ts.map +1 -1
  22. package/dist/fetch/interceptors/auth.js +31 -2
  23. package/dist/fetch/interceptors/auth.js.map +1 -1
  24. package/dist/fetch/types.d.ts +4 -0
  25. package/dist/fetch/types.d.ts.map +1 -1
  26. package/dist/renderer/engine.d.ts.map +1 -1
  27. package/dist/renderer/engine.js +29 -4
  28. package/dist/renderer/engine.js.map +1 -1
  29. package/dist/renderer/prop-schemas.d.ts +5 -0
  30. package/dist/renderer/prop-schemas.d.ts.map +1 -1
  31. package/dist/renderer/prop-schemas.js +11 -2
  32. package/dist/renderer/prop-schemas.js.map +1 -1
  33. package/dist/runtime/mount-spec-runtime.d.ts +2 -0
  34. package/dist/runtime/mount-spec-runtime.d.ts.map +1 -1
  35. package/dist/runtime/mount-spec-runtime.js +4 -1
  36. package/dist/runtime/mount-spec-runtime.js.map +1 -1
  37. package/dist/security/spec-validator.d.ts.map +1 -1
  38. package/dist/security/spec-validator.js +61 -0
  39. package/dist/security/spec-validator.js.map +1 -1
  40. package/dist/spec-stores/file.js +1 -1
  41. package/dist/spec-stores/file.js.map +1 -1
  42. package/dist/types.d.ts +8 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/docs/consumer/ai-context-patterns.md +42 -7
  45. package/docs/consumer/ai-context-primitives.md +25 -2
  46. package/docs/consumer/ai-context-runtime-semantics.md +36 -26
  47. package/docs/consumer/ai-context.md +57 -38
  48. package/docs/consumer/reference-doc.md +97 -59
  49. package/docs/wiki/compiled/concept-component-variants.md +39 -10
  50. package/docs/wiki/compiled/concept-templates-vs-variants.md +77 -13
  51. package/docs/wiki/compiled/pattern-reusable-components.md +42 -12
  52. package/package.json +1 -1
@@ -88,7 +88,7 @@ Every screen is a flat tree: `root` ID + `elements` map + optional `initialActio
88
88
  | `style` | object | CSS styles (can contain expressions) |
89
89
  | `visible` | expression | Show/hide condition |
90
90
  | `permission` | object | `{ visible, editable, readonly }` per role |
91
- | `repeat` | object | Iterate over array: `{ statePath, key }` or `{ source, key }` |
91
+ | `repeat` | object | Iterate over array: `{ statePath, key }` or `{ source, key }`; optional `layout` controls item row direction/gap/wrap |
92
92
  | `on` | object | Event handlers: `{ press, change, submit }` |
93
93
  | `hover` | object | Style overrides on pointer enter |
94
94
  | `active` | object | Style overrides on press |
@@ -108,17 +108,17 @@ mythik init-store --dialect postgres --dry-run # Print SQL store DDL f
108
108
  mythik init-store --dialect sqlserver --server localhost --database Mythik --user "$DB_USER" --password "$DB_PASSWORD" --encrypt false --trust-server-certificate
109
109
  mythik manifest <screen> # See structural tree
110
110
  mythik elements <screen> <id1,id2> # Get element details
111
- mythik patch <screen> --from-file patch.json --author <agent> # Apply versioned RFC 6902 patches
112
- mythik pull <screen> # Export full spec for backup/review
113
- mythik push <screen> --from-file spec.json --author <agent> # Create a new spec
114
- mythik push <screen> --from-file spec.json --replace --author <agent> # Intentional full replacement
115
- mythik validate <screen> # Validate spec
116
- mythik reveal start # Start local runtime context bridge
117
- mythik reveal apps --json # List connected running apps
118
- mythik reveal context --app <name> # Read live app contract/state/diagnostics
119
- mythik reveal element <id> --app <name> # Inspect one live element
120
- mythik agent init codex|claude|all # Install project-local AI operating protocol
121
- mythik agent context --app <app-id> --include-screens --out .mythik/agent/context.md
111
+ mythik patch <screen> --from-file patch.json --author <agent> # Apply versioned RFC 6902 patches
112
+ mythik pull <screen> # Export full spec for backup/review
113
+ mythik push <screen> --from-file spec.json --author <agent> # Create a new spec
114
+ mythik push <screen> --from-file spec.json --replace --author <agent> # Intentional full replacement
115
+ mythik validate <screen> # Validate spec
116
+ mythik reveal start # Start local runtime context bridge
117
+ mythik reveal apps --json # List connected running apps
118
+ mythik reveal context --app <name> # Read live app contract/state/diagnostics
119
+ mythik reveal element <id> --app <name> # Inspect one live element
120
+ mythik agent init codex|claude|all # Install project-local AI operating protocol
121
+ mythik agent context --app <app-id> --include-screens --out .mythik/agent/context.md
122
122
  ```
123
123
 
124
124
  ### Required edit loop for existing specs
@@ -128,15 +128,17 @@ When an AI agent modifies an existing Mythik spec, use this loop by default:
128
128
  1. `mythik manifest <screen>` - inspect the current structure and identify candidate element IDs.
129
129
  2. `mythik elements <screen> <id1,id2,...>` - inspect only the exact elements and nearby containers that will change.
130
130
  3. Write a small RFC 6902 patch file.
131
- 4. `mythik patch <screen> --from-file patch.json --author <agent>` - apply the surgical change through the validated, versioned CLI path.
132
- 5. Run `mythik validate <screen>`.
133
- 6. Re-run `mythik manifest <screen>` or `mythik elements <screen> <ids>` to verify the changed surface.
134
-
135
- Do not edit database rows directly, do not call `SpecStore.save()` from app code, and do not replace a whole screen with `push` when a targeted `patch` can express the change. `pull` is for backup, migration, review, or full-spec creation workflows; it is not the normal first step for a small edit.
131
+ 4. `mythik patch <screen> --from-file patch.json --author <agent>` - apply the surgical change through the validated, versioned CLI path.
132
+ 5. Run `mythik validate <screen>`.
133
+ 6. Re-run `mythik manifest <screen>` or `mythik elements <screen> <ids>` to verify the changed surface.
134
+
135
+ Do not edit database rows directly, do not call `SpecStore.save()` from app code, and do not replace a whole screen with `push` when a targeted `patch` can express the change. `pull` is for backup, migration, review, or full-spec creation workflows; it is not the normal first step for a small edit.
136
136
 
137
- **Patch rules:** `"op": "add"` with numeric index **inserts before** (not replace). Use `/-` to append. Use `"op": "replace"` to overwrite. Prefer `mythik patch <id> --from-file patch.json --author <agent>` for any patch containing `$state`, `$template`, `$auth`, or other shell-sensitive strings.
137
+ Mythik Sentinel is built into the CLI to help fresh agents stay on that loop. It prints advisory guidance on first project use and when it detects repeated full-replacement intent with little/no patch usage. Sentinel is best-effort: it does not change command exit codes, it does not store specs or credentials, and it preserves JSON/TOON machine-readable outputs. Disable only for exceptional automation with `MYTHIK_SENTINEL=off`.
138
138
 
139
- **Patch input precedence:** explicit sources win. `--from-file <path>` reads that file even if the host process has non-TTY stdin (common in PowerShell/agent runners). Stdin still works via `--from-file -` or by piping without `--from-file`: `cat patch.json | mythik patch <id> --author <agent>`.
139
+ **Patch rules:** `"op": "add"` with numeric index **inserts before** (not replace). Use `/-` to append. Use `"op": "replace"` to overwrite. Prefer `mythik patch <id> --from-file patch.json --author <agent>` for any patch containing `$state`, `$template`, `$auth`, or other shell-sensitive strings.
140
+
141
+ **Patch input precedence:** explicit sources win. `--from-file <path>` reads that file even if the host process has non-TTY stdin (common in PowerShell/agent runners). Stdin still works via `--from-file -` or by piping without `--from-file`: `cat patch.json | mythik patch <id> --author <agent>`.
140
142
 
141
143
  All commands accept `--json`, `--table <name>`, `--store`, `--url`, `--key`. Never pass API keys inline — use `.mythikrc` + env vars.
142
144
 
@@ -197,7 +199,7 @@ should ask Reveal before proposing a patch.
197
199
 
198
200
  ### CLI store configuration
199
201
 
200
- The CLI can read and write specs from `memory`, `file`, `supabase`, `sqlserver`, `postgres`, `mysql`, and `sqlite` stores. SQL stores share the same commands and the same required edit loop: `manifest -> elements -> patch --from-file --author -> validate -> verify`.
202
+ The CLI can read and write specs from `memory`, `file`, `supabase`, `sqlserver`, `postgres`, `mysql`, and `sqlite` stores. SQL stores share the same commands and the same required edit loop: `manifest -> elements -> patch --from-file --author -> validate -> verify`.
201
203
 
202
204
  ```bash
203
205
  # SQLite: local development, tests, demos, lightweight deployments
@@ -229,13 +231,13 @@ Environment equivalents: `MYTHIK_STORE`, `MYTHIK_DATABASE_URL`, `MYTHIK_SQLITE_F
229
231
 
230
232
  Per reference-doc rule 248: three approved forms.
231
233
 
232
- - **Shell**: `mythik push <id> --from-file spec.json --author <agent>` and `mythik patch <id> --from-file patch.json --author <agent>` (cross-shell ergonomic for any spec/patch containing `$state`, `$template`, `$auth`, or `$row`)
233
- - **Bulk**: `mythik push --from-dir <folder> --author <agent>` — sequential per-file push of every `*.json`. Continue-on-error: failures don't stop subsequent specs. No rollback. Partial state recovers by fixing failures and re-running.
234
- - **Programmatic**: `import { runPush, runPatch, parsePatchInput, type PushResult } from 'mythik-cli/api'` — same code path as the binary, no shell. Pass `json: true` in options to receive structured command output via `JSON.parse(result.output)`. `runPatch` success output includes `versioned: boolean` and `version?: number` when a versioned store + `author` creates history.
235
-
236
- `SpecStore.save()` is `@internal` — calling it from application code skips validation and produces runtime errors only at render time. The three forms above are the only validated paths.
237
-
238
- Existing persisted specs are protected by the Agent Protocol: full replacements require `--replace`, and persisted writes require `--author <name>` for versioned stores or explicit `--allow-unversioned` for intentionally unversioned stores.
234
+ - **Shell**: `mythik push <id> --from-file spec.json --author <agent>` and `mythik patch <id> --from-file patch.json --author <agent>` (cross-shell ergonomic for any spec/patch containing `$state`, `$template`, `$auth`, or `$row`)
235
+ - **Bulk**: `mythik push --from-dir <folder> --author <agent>` — sequential per-file push of every `*.json`. Continue-on-error: failures don't stop subsequent specs. No rollback. Partial state recovers by fixing failures and re-running.
236
+ - **Programmatic**: `import { runPush, runPatch, parsePatchInput, type PushResult } from 'mythik-cli/api'` — same code path as the binary, no shell. Pass `json: true` in options to receive structured command output via `JSON.parse(result.output)`. `runPatch` success output includes `versioned: boolean` and `version?: number` when a versioned store + `author` creates history.
237
+
238
+ `SpecStore.save()` is `@internal` — calling it from application code skips validation and produces runtime errors only at render time. The three forms above are the only validated paths.
239
+
240
+ Existing persisted specs are protected by the Agent Protocol: full replacements require `--replace`, and persisted writes require `--author <name>` for versioned stores or explicit `--allow-unversioned` for intentionally unversioned stores.
239
241
 
240
242
  ### Pre-push linting
241
243
 
@@ -515,7 +517,7 @@ Any action binding may include `params.skipIf`. Mythik resolves `skipIf` at disp
515
517
  - Sets `/ui/loading` while in flight
516
518
  - On error: sets `/ui/lastError` with status and message
517
519
  - Optional `errorTarget` writes the same structured error to a screen-owned path and clears that path on success. Use it for critical screen-load fetches instead of relying only on global `/ui/lastError`
518
- - Auth headers auto-injected for `authDomains` URLs
520
+ - Auth headers auto-injected for `apiBaseUrl` exact-origin framework URLs and explicit `authDomains` hosts
519
521
 
520
522
  ### Transactions (Optimistic Updates)
521
523
 
@@ -621,6 +623,18 @@ Chain: `$array: "filter"` → `$array: "search"` → `$array: "slice"` for filte
621
623
 
622
624
  Inside repeated elements: `$item`, `$index`, `$bindItem` access current item.
623
625
 
626
+ Repeated rows can opt into horizontal/wrapping layout without changing the child primitive:
627
+
628
+ ```json
629
+ "repeat": {
630
+ "source": { "$state": "/filters" },
631
+ "key": "id",
632
+ "layout": { "direction": "horizontal", "gap": 8, "wrap": true }
633
+ }
634
+ ```
635
+
636
+ For grouped repeats, group headers and footers remain vertical; `repeat.layout` applies only to each group's item row.
637
+
624
638
  ### Grouped Repeat
625
639
 
626
640
  **Client-side** (engine groups flat array): `groupBy: "category"`
@@ -920,7 +934,7 @@ Interceptors:
920
934
  "interceptors": { "logging": true, "timeout": { "ms": 15000 }, "retryOnError": { "maxRetries": 2, "statuses": [502, 503] } }
921
935
  ```
922
936
 
923
- Security: tokens NEVER in state (engine closure only). `$auth` blocks token/password fields. Auth headers only for `authDomains`. Credentials cleared after login. Rate limit: 5/min. Cross-tab sync automatic.
937
+ Security: tokens NEVER in state (engine closure only). `$auth` blocks token/password fields. Auth headers are injected only for the host `apiBaseUrl` exact origin or explicit `authDomains`. Credentials cleared after login. Rate limit: 5/min. Cross-tab sync automatic.
924
938
 
925
939
  Custom JWT provider response mapping: `tokenPath`, `refreshTokenPath`, and `userPath` are dot paths against the full login/refresh response. `rolePath` and `rolesPath` use a compat dual contract: plain keys like `"role"` / `"roles"` resolve inside the extracted `userPath` object; dotted paths like `"user.role"` or `"data.user.role"` resolve against the full response. If no role or roles are found, Mythik uses `defaultRole` (`"user"` by default) and warns in development.
926
940
 
@@ -1232,7 +1246,7 @@ Reference: `"hover": { "$token": "motion.presets.hoverLift" }`
1232
1246
 
1233
1247
  ## Component Variants
1234
1248
 
1235
- Token-driven styling. Define in `tokens.components.{type}.{variant}`:
1249
+ Token-driven styling. **Use this before copying the same style block into multiple elements.** Define in `tokens.components.{type}.{variant}` and reference it from `props.variant`:
1236
1250
 
1237
1251
  ```json
1238
1252
  "tokens": {
@@ -1249,7 +1263,9 @@ Token-driven styling. Define in `tokens.components.{type}.{variant}`:
1249
1263
  ```
1250
1264
  Usage: `{ "type": "button", "props": { "label": "Save", "variant": "primary" } }`
1251
1265
  `$path` references (`$colors.primary`) resolve against active tokens — dark mode works automatically.
1252
- Element-level style/hover overrides variant (variant is base, element is override). Supports: `style`, `hover`, `active`, `focus`, `transition`.
1266
+ Element-level style/hover overrides variant (variant is base, element is override). Supports: `style`, `hover`, `active`, `focus`, `transition`.
1267
+
1268
+ Important boundary: variants are for primitive visual slots. They do **not** carry arbitrary primitive props such as `table.headerStyle`, `table.rowStyle`, `columns`, or action bindings. For prop-bearing reusable patterns, define an AppSpec `templates` entry and use `$prop` to pass through data/columns/actions. Example: use `tokens.components.box.tableCard` for card styling, but use an `ops-table` template when several tables need the same `headerStyle` + `rowStyle` chrome. For composed filter chips (`touchable` + `text`), put static shared styling in variants and keep state/item-specific active colors on the element.
1253
1269
 
1254
1270
  ## Skeleton & Export
1255
1271
 
@@ -1466,8 +1482,8 @@ When the framework changes the schema in a future version, this section will gai
1466
1482
  28. loginScreen always accessible — prevents redirect loops
1467
1483
  29. Login renders fullscreen (no layout) — appears automatically when not authenticated
1468
1484
  30. Login paths: `/screens/login/...` not `/form/...` — clears on logout with statePolicy reset
1469
- 31. Auth headers auto-injected for `authDomains` — no manual headers in fetch
1470
- 32. Use `variant` prop for component styling — don't copy style objects
1485
+ 31. Auth headers auto-injected for `apiBaseUrl` exact-origin framework URLs and explicit `authDomains` hosts — no manual headers in fetch
1486
+ 32. Use `variant` prop for reusable primitive styling — don't copy style objects; put `variant` inside `props`
1471
1487
  33. `$path` references in variants resolve with dark mode automatically
1472
1488
  34. Use `mythik push` for spec creation — no seed scripts
1473
1489
  35. AppSpec patches use `/layout/elements/` not `/elements/`
@@ -1502,11 +1518,11 @@ When the framework changes the schema in a future version, this section will gai
1502
1518
  64. Custom element black-box boundary — consumer's instance-level `animations`, `hover`, `active`, `focus`, `motion`, `style`, `visible`, and `key` apply to the OUTER primitive only. Inner primitives are the author's domain and are not reachable from the consumer. Identity cascade (rule 63 / cascade level 1) still reaches inner primitives; consumer cannot override them directly
1503
1519
  65. `$prop` is nearest-enclosing-custom-element-scoped — inside a custom element's render tree, `$prop` resolves against THAT element's merged props. Nesting a custom element inside another pushes a new prop context; the outer's props are shadowed, not merged. Pass values explicitly via prop declarations when nested access is needed
1504
1520
  66. `$children` marker in custom element render trees — authors write `"$children"` as a string item in their render tree `children` array to mark where consumer children are inserted during expansion. Multiple markers each splice the full consumer children. Same slotting semantics as spec templates
1505
- 67. `variant` is a PROP — place it inside `props`, never as a top-level element field. Applies to built-in primitives and Layer 3 custom elements alike: `{ "type": "stat-card", "props": { "variant": "primary", ... } }`. Top-level `variant` is silently ignored (the renderer reads `props.variant` only). Consumer may drive it dynamically via an expression: `"variant": { "$switch": { "$state": "/filter/recordType" }, "cases": { "1": "active" }, "default": "inactive" }`
1521
+ 67. `variant` is a PROP — place it inside `props`, never as a top-level element field. Applies to built-in primitives and Layer 3 custom elements alike: `{ "type": "stat-card", "props": { "variant": "primary", ... } }`. Top-level `variant` is silently ignored (the renderer reads `props.variant` only). Consumer may drive it dynamically via an expression. Variants are style/interaction slots only; use templates/custom elements when the reusable pattern must carry props like table `headerStyle`/`rowStyle` or composed children.
1506
1522
  68. Custom elements may expose action-chain props — author declares a prop (e.g. `onSelect`, type `"array"`) and the render tree's `on:<event>` references it as `{ "$prop": "onSelect" }`. Consumers supply the full action array as the prop value; inner `$state` / `$template` / `$item` inside those actions resolve at press time with the current state (not at render time). Enables tabs, menu items, and similar patterns where the consumer owns the action chain
1507
1523
  69. Never use `$row` literal — there is no `$row` expression handler. Read row data via `$state: '/ui/selectedRow/<key>'` (framework writes clicked row before column action dispatch).
1508
1524
  70. Never combine `crud: {}` with `endpoint.path` ending in `/:id`. CRUD operations auto-append `/:id` to PUT/DELETE routes. Declaring `path: '/api/x/:id'` produces `/api/x/:id/:id`.
1509
- 71. Never include `:port` in `auth.authDomains[]` entries. The matcher uses `URL.hostname` for comparison ports are silently stripped, leading to apparent matches that don't actually match.
1525
+ 71. Prefer `MythikApp apiBaseUrl` for the app's own backend. Relative runtime URLs (`/api/...`) resolve against that base and inherit auth only for the exact base origin when `authDomains` is omitted or empty. Providing `authDomains` disables the automatic `apiBaseUrl` origin allowlist; list every trusted absolute host explicitly. Never include `:port` in `auth.authDomains[]` entries because that matcher uses hostnames.
1510
1526
  72. `spatial-map` is the generic SVG/data-first primitive for floor plans, seating maps, parking maps, warehouse layouts, hospital beds, and similar spatial workflows. JSON `onItemPress` actions write item context to `/ui/selectedSpatialItem` before lazy dispatch. Compose domain menus/drawers/modals externally; do not encode restaurant-specific behavior into the primitive. Use `{ "$state": "/path" }` expressions for dynamic `items`, `zones`, `mode`, and `statusStyles`; do not invent `*Path` prop aliases.
1511
1527
  73. For `spatial-map` editing, use `editPolicy` for movement rules and `onItemChange` for persistence. Do not use `interactionPolicy` for drag/keyboard movement. In JSON specs, persist moved items with `$array: "replace"` reading from `/ui/spatialItemChange` or the configured `itemChangePath`; use plain `setState` for non-undoable screens and wrap the same value in `editorCommit` for undoable editors.
1512
1528
  74. For JSON-created client-side item ids, use `$uniqueId` with an explicit `source`, `field`, `prefix`, and optional `padding`. It is deterministic and scoped to the source array; use it for local/editor objects, not as a substitute for database primary keys when a backend owns identity.
@@ -1521,12 +1537,12 @@ When the framework changes the schema in a future version, this section will gai
1521
1537
  82. Use `editorSessions.<id>.persistence` plus `editorSave` for generic editor document persistence. The AI should not hand-compose `transaction` + `editorMarkSaved` for normal editor saves. `editorSave` captures the tracked paths snapshot, persists it through the host fetcher with URL-guard checks, and marks only the sent snapshot as saved after success. Failed saves keep `dirty: true` and expose save metadata under `/ui/editorSessions/<id>`.
1522
1538
  83. Use `navigation.editorSessionGuard` for generic unsaved-changes protection in app specs instead of hand-rolled JSON dirty checks. Configure `sessions`, render your own JSON modal from `/ui/navigationGuard/pending`, call `navigationGuardCancel`, `navigationGuardSaveAndProceed`, `navigationGuardProceed`, or `navigationGuardDiscardAndProceed`, and keep `pendingPath` under a consumer-owned `/ui/<segment>` path that does not collide with reserved framework paths. `navigationGuardSaveAndProceed` is the normal save-first UX for persisted editor sessions; `navigationGuardProceed` is a low-level non-destructive retry that only resumes after the pending editor sessions are already clean; use `navigationGuardDiscardAndProceed` when the user explicitly chooses to abandon unsaved tracked-path changes.
1523
1539
  84. In React apps without auth framework fetch, pass `fetcher` to `MythikApp` when editor sessions use `editorSave` or `navigationGuardSaveAndProceed`. Auth-enabled apps continue to use the framework fetch produced by auth interceptors. Do not route save-and-continue through `/ui/lastError` or a hand-composed fetch action; the editor session engine owns save metadata under `/ui/editorSessions/<id>`.
1524
- 85. For existing spec edits, the required AI loop is `mythik manifest` -> `mythik elements` -> `mythik patch --from-file --author` -> `mythik validate` -> verify. Manifest tells you the structure; elements gives the exact JSON you are changing; patch is the validated write path. Do not skip directly to full-spec `pull`/rewrite/push for a local change, do not mutate DB rows manually, and do not call `SpecStore.save()` from app code. Use `push` for new specs or intentional full replacement only; existing specs require explicit `--replace`.
1540
+ 85. For existing spec edits, the required AI loop is `mythik manifest` -> `mythik elements` -> `mythik patch --from-file --author` -> `mythik validate` -> verify. Manifest tells you the structure; elements gives the exact JSON you are changing; patch is the validated write path. Do not skip directly to full-spec `pull`/rewrite/push for a local change, do not mutate DB rows manually, and do not call `SpecStore.save()` from app code. Use `push` for new specs or intentional full replacement only; existing specs require explicit `--replace`.
1525
1541
  86. Mythik's AI documentation ships with the `mythik` npm package. Before generating or modifying specs, locate it with `mythik docs path` and start from `docs/llms.txt`, `docs/consumer/ai-context.md`, and `docs/wiki/compiled/README.md`. Use `mythik docs copy ./mythik-docs` when a project-local copy is easier to hand to an AI agent.
1526
1542
  87. DNA numeric seeds (`roundness`, `density`, `depth`, `formality`) are canonical `0–1` values. Generate `0.7`, not `70`. The runtime tolerates legacy `0–100` values by normalizing any numeric seed greater than `1` with `/100` during DNA derivation, including initial AppSpec load and runtime `updateTokens`.
1527
1543
  88. API query endpoints can combine `pagination: "offset"` with `scopeFilter`. For generated counts, Mythik applies the scope filter to the source query before `COUNT(*)`, so paginated totals remain tenant-scoped. Prefer generated counts. If a custom `endpoint.count` is truly needed with `scopeFilter`, include `{{scopeWhere[:alias]}}` or `{{scopeAnd[:alias]}}`; Mythik expands the macro to the correct scope predicate and removes it for bypass roles. Other custom count SQL is left verbatim. Use `:alias` for JOIN/subquery counts, and do not reference internal scope params directly.
1528
1544
  89. Transaction `confirm` failures from `fetch` preserve backend error details for `onError`. Read `/tx/error/message` for the best available message; when the backend returns `{ error: { code, message } }`, Mythik keeps that message, `code`, HTTP `status`, and raw `data` after rollback. Do not parse `/ui/lastError` from transaction specs.
1529
- 90. For SQL-backed stores and servers, use the generic `mythik/server` SQL boundary. Initialize tables with `mythik init-store --dialect <sqlserver|postgres|mysql|sqlite>` or inspect DDL with `--dry-run`; configure the CLI with `--store`, `--url`/`--filename`/SQL Server flags, or `MYTHIK_*` environment variables; and keep spec edits on the required `manifest -> elements -> patch --from-file --author -> validate -> verify` loop. Write custom API SQL in the selected dialect with Mythik named params (`@name`); Mythik does not translate custom SQL between dialects.
1545
+ 90. For SQL-backed stores and servers, use the generic `mythik/server` SQL boundary. Initialize tables with `mythik init-store --dialect <sqlserver|postgres|mysql|sqlite>` or inspect DDL with `--dry-run`; configure the CLI with `--store`, `--url`/`--filename`/SQL Server flags, or `MYTHIK_*` environment variables; and keep spec edits on the required `manifest -> elements -> patch --from-file --author -> validate -> verify` loop. Write custom API SQL in the selected dialect with Mythik named params (`@name`); Mythik does not translate custom SQL between dialects.
1530
1546
  91. Event arrays may mix normal actions and transaction bindings. Mythik executes them sequentially and awaits each transaction before continuing. Use this when a flow needs a small action before or after an optimistic transaction; do not wrap a transaction inside another transaction phase.
1531
1547
  92. `$ref` and `$template` placeholders can read nested values from `$let` object bindings with dot notation, for example `{ "$ref": "user.name" }` or `${user.name}`. If a dotted `$ref` segment is missing, runtime throws an unknown `$ref` error rather than silently returning undefined.
1532
1548
  93. Use `params.skipIf` for a dispatch-time action guard when an action should be skipped but the surrounding action chain should continue. `skipIf` is resolved before other params and is removed before the action handler runs. Do not use `skipIf` as a substitute for form validation or transaction rollback.
@@ -1536,4 +1552,7 @@ When the framework changes the schema in a future version, this section will gai
1536
1552
  97. Missing SQL adapter errors are actionable. The thrown `SqlDriverError` includes `packageName`, `installCommand`, and a message with the exact `npm install ...` command for the selected dialect.
1537
1553
  98. For native Expo apps, install renderer peer packages with `npx expo install react-native-svg react-native-reanimated react-native-worklets ...` before installing `mythik mythik-react-native`, so Expo selects native module versions that match the app SDK. Keep `react-native-reanimated/plugin` last in the app Babel config. Keep `root` as a stable string element id; use `$platform` only inside localized props, style, children, or values. `$platform` matches exact platform keys first, then falls back from `ios`/`android` to `native`; it has no `default` key. Before using a primitive in native specs, check `REACT_NATIVE_PRIMITIVE_SUPPORT` or `getReactNativePrimitiveSupport` from `mythik-react-native`; native-milestone primitives should fail visibly instead of being treated as supported.
1538
1554
  99. Use Mythik Reveal before guessing about running-app behavior. Start `mythik reveal start`, wire the host `reveal` config in development, then inspect with `mythik reveal apps`, `context`, `current`, `screen`, or `element`. Reveal returns live renderer/environment/spec/state/diagnostics/events with redaction, so agents can diagnose runtime behavior from structured context instead of screenshots, stale pulled specs, or source-code assumptions. Never enable Reveal in production, never commit the token, and include/redact state paths deliberately.
1539
- 100. **Use Mythik Agent Context and Agent Protocol for fresh AI agents**. Run `mythik agent init codex`, `mythik agent init claude`, or `mythik agent init all` to install project-local agent instructions. `codex` creates/updates `AGENTS.md`, `claude` creates/updates `CLAUDE.md`, and `all` updates both; existing file content outside the Mythik-managed `<!-- mythik-agent-protocol:start -->` / `<!-- mythik-agent-protocol:end -->` block is preserved. Generate live project context with `mythik agent context --app <id> --include-screens --out .mythik/agent/context.md`. Existing stored specs stay on `manifest -> elements -> patch --from-file --author -> validate -> verify`. The active store is the source of truth; local spec files are drafts/snapshots/migrations/fixtures unless a file store is intentionally configured. Use TOON for large reads when supported, and use `mythik lint` for new local drafts, replacement files, bulk imports/migrations, and relevant consumer code changes.
1555
+ 100. **Use Mythik Agent Context, Agent Protocol, and Sentinel for fresh AI agents**. Run `mythik agent init codex`, `mythik agent init claude`, or `mythik agent init all` to install project-local agent instructions. `codex` creates/updates `AGENTS.md`, `claude` creates/updates `CLAUDE.md`, and `all` updates both; existing file content outside the Mythik-managed `<!-- mythik-agent-protocol:start -->` / `<!-- mythik-agent-protocol:end -->` block is preserved. Generate live project context with `mythik agent context --app <id> --include-screens --out .mythik/agent/context.md`. Existing stored specs stay on `manifest -> elements -> patch --from-file --author -> validate -> verify`. The active store is the source of truth; local spec files are drafts/snapshots/migrations/fixtures unless a file store is intentionally configured. Use TOON for large reads when supported, and use `mythik lint` for new local drafts, replacement files, bulk imports/migrations, and relevant consumer code changes. Mythik Sentinel runs from the CLI as advisory coaching: first project use reminds the agent to initialize instructions, repeated full replacement intent warns the agent back to patch-first edits, identical `push --replace` writes are skipped as `skipped: true`, and no spec contents or credentials are persisted in the Sentinel cache. Disable only with `MYTHIK_SENTINEL=off` for exceptional automation.
1556
+ 101. `repeat.layout` controls repeated item rows (`direction`, `gap`, `wrap`). In grouped repeats, headers/footers remain vertical and the layout applies only to the group item row.
1557
+ 102. `select` normalizes option identity for display: DB integer IDs and string option values match, `0` is a valid selected value, and null/undefined show the placeholder. Values emitted by existing `onChange` remain string-compatible.
1558
+ 103. `text.on.press` is supported for inline interactive text. Web receives button semantics plus keyboard activation; React Native receives `accessibilityRole="button"`. Use `button` or `touchable` for primary/larger actions.