@salsita-ai/sdk 0.50.0-develop.9feae4851f → 0.50.0-develop.a4dde5f252

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 (252) hide show
  1. package/README.md +2 -2
  2. package/dist/admin/create-admin-pages-from-spec.d.ts +1 -1
  3. package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +1 -1
  4. package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
  5. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-domain-block.js +36 -36
  6. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-invariants.d.ts +1 -1
  7. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-invariants.js +1 -1
  8. package/dist/application-spec/generate-application/code/templates/domain.js +1 -1
  9. package/dist/application-spec/generate-application/code/templates/index.d.ts +0 -6
  10. package/dist/application-spec/generate-application/code/templates/index.js +1 -1
  11. package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
  12. package/dist/application-spec/generate-application/code/templates/skills/phoenix-create-configurator-skill.js +66 -42
  13. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +10 -12
  14. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +6 -8
  15. package/dist/application-spec/parse-application-files/raw-spec/raw-assistant.js +1 -1
  16. package/dist/client/phoenix-api.d.ts +5 -3
  17. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +34 -1
  18. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  19. package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +6 -0
  20. package/dist/configurator/pages/DefaultConfiguratorLayout.js +1 -0
  21. package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
  22. package/dist/docs/index.json +1 -1
  23. package/dist/docs/integrations/woocommerce/local-development.mdx +1 -1
  24. package/dist/docs/phoenix/configurator-interface.mdx +33 -6
  25. package/dist/docs/phoenix/expression-context.mdx +11 -3
  26. package/dist/docs/phoenix/getting-started.mdx +1 -1
  27. package/dist/docs/phoenix/phoenix-cli.mdx +17 -26
  28. package/dist/docs/phoenix/project-structure.mdx +5 -3
  29. package/dist/docs/phoenix/quickstart.mdx +2 -2
  30. package/dist/docs/phoenix/sdk-builder-workflow.mdx +2 -2
  31. package/dist/docs/phoenix/webhooks.mdx +1 -1
  32. package/dist/docs/ux-guidelines/choosing-a-control.mdx +11 -0
  33. package/dist/domain/admin-domain/implementation/common-admin-expressions.d.ts +10 -10
  34. package/dist/domain/admin-domain/index.d.ts +7 -2
  35. package/dist/domain/application/GetApplicationWrapperHandler.d.ts +1 -1
  36. package/dist/domain/application/GetThemeHandler.d.ts +1 -1
  37. package/dist/domain/application/GetWebComponentOptions.d.ts +1 -1
  38. package/dist/domain/application/admin-page-factories.d.ts +1 -2
  39. package/dist/domain/application/application-config.d.ts +3 -24
  40. package/dist/domain/application/assistant-mutations.d.ts +2 -1
  41. package/dist/domain/application/assistant-recipe-groups.d.ts +1 -1
  42. package/dist/domain/application/configurator-builder.d.ts +1 -1
  43. package/dist/domain/application/create-initial-published-data.d.ts +1 -2
  44. package/dist/domain/application/index.d.ts +1 -4
  45. package/dist/domain/application/index.js +1 -1
  46. package/dist/domain/application/published-data/DataRowValidatorHandler.d.ts +1 -1
  47. package/dist/domain/application/published-data/FilterPublishedChunksHandler.d.ts +1 -1
  48. package/dist/domain/application/published-data/MapPublishedChunkedDataHandler.d.ts +1 -1
  49. package/dist/domain/application/published-data/MapPublishedRevisionDataHandler.d.ts +1 -1
  50. package/dist/domain/application/published-data/SheetValidatorHandler.d.ts +1 -1
  51. package/dist/domain/application/published-data/build-legend-data.d.ts +1 -1
  52. package/dist/domain/application/published-data/format-field-type.d.ts +1 -1
  53. package/dist/domain/application/published-data/map-data-to-sheet.d.ts +1 -1
  54. package/dist/domain/application/published-data/map-published-chunked-data.d.ts +2 -2
  55. package/dist/domain/application/published-data/validate-sheet-data.d.ts +1 -1
  56. package/dist/domain/core/action/action-factory.d.ts +2 -2
  57. package/dist/domain/core/action/action.d.ts +19 -14
  58. package/dist/domain/core/component/domain-component-optic.d.ts +30 -40
  59. package/dist/domain/core/component/domain-component-optic.js +2 -2
  60. package/dist/domain/core/component/legacy-filter.d.ts +2 -17
  61. package/dist/domain/core/component/system-component-filter.d.ts +23 -18
  62. package/dist/domain/core/data-schema/data-cell-value.d.ts +4 -0
  63. package/dist/domain/core/data-schema/data-cell-value.js +1 -0
  64. package/dist/domain/core/data-schema/data-schema-array-field.d.ts +5 -0
  65. package/dist/domain/core/data-schema/data-schema-array-field.js +1 -0
  66. package/dist/domain/core/data-schema/data-schema-field-object.d.ts +4 -0
  67. package/dist/domain/core/data-schema/data-schema-field-object.js +1 -0
  68. package/dist/domain/core/data-schema/data-schema-field.d.ts +2 -0
  69. package/dist/domain/core/data-schema/data-schema-field.js +1 -0
  70. package/dist/domain/core/data-schema/data-schema-localized-field.d.ts +4 -0
  71. package/dist/domain/core/data-schema/data-schema-localized-field.js +1 -0
  72. package/dist/domain/core/data-schema/data-schema-primitive-field.d.ts +5 -0
  73. package/dist/domain/core/data-schema/data-schema-primitive-field.js +1 -0
  74. package/dist/domain/core/data-schema/data-schema.d.ts +2 -0
  75. package/dist/domain/core/data-schema/data-schema.js +1 -0
  76. package/dist/domain/core/data-schema/index.d.ts +7 -0
  77. package/dist/domain/core/data-schema/index.js +1 -0
  78. package/dist/domain/core/domain.d.ts +2 -2
  79. package/dist/domain/core/emission/index.d.ts +8 -0
  80. package/dist/domain/core/emission/index.js +1 -0
  81. package/dist/domain/core/emission/reset-state-emission.d.ts +12 -0
  82. package/dist/domain/core/emission/reset-state-emission.js +1 -0
  83. package/dist/domain/core/emission/state-emission.d.ts +4 -0
  84. package/dist/domain/core/emission/state-emission.js +1 -0
  85. package/dist/domain/core/emission/state-update-emission.d.ts +14 -0
  86. package/dist/domain/core/emission/state-update-emission.js +1 -0
  87. package/dist/domain/core/emission/state-validation-result.d.ts +18 -0
  88. package/dist/domain/core/emission/state-validation-result.js +1 -0
  89. package/dist/domain/core/emission/transformation-log.d.ts +2 -0
  90. package/dist/domain/core/emission/transformation-log.js +1 -0
  91. package/dist/domain/core/emission/transformer-log-entry.d.ts +6 -0
  92. package/dist/domain/core/emission/transformer-log-entry.js +1 -0
  93. package/dist/domain/core/emission/transformer-log.d.ts +11 -0
  94. package/dist/domain/core/emission/transformer-log.js +1 -0
  95. package/dist/domain/core/emission/transformer-phase.d.ts +1 -0
  96. package/dist/domain/core/emission/transformer-phase.js +1 -0
  97. package/dist/domain/core/expression/aliased-expressions.d.ts +2 -2
  98. package/dist/domain/core/expression/constant-expressions.d.ts +2 -2
  99. package/dist/domain/core/expression/constant-expressions.js +1 -1
  100. package/dist/domain/core/expression/custom-expression.d.ts +6 -6
  101. package/dist/domain/core/expression/custom-expression.js +1 -1
  102. package/dist/domain/core/expression/expression.d.ts +15 -17
  103. package/dist/domain/core/index.d.ts +2 -0
  104. package/dist/domain/core/invariant/custom-invariants.d.ts +5 -5
  105. package/dist/domain/core/invariant/index.d.ts +1 -1
  106. package/dist/domain/core/invariant/index.js +1 -1
  107. package/dist/domain/core/invariant/invariants.d.ts +4 -67
  108. package/dist/domain/core/invariant/invariants.js +1 -1
  109. package/dist/domain/core/invariant/violation.d.ts +1 -1
  110. package/dist/domain/core/relation/reference-component.d.ts +2 -2
  111. package/dist/domain/core/state/migrations.d.ts +14 -45
  112. package/dist/domain/core/state/migrations.js +1 -1
  113. package/dist/domain/domain-builder.d.ts +1 -1
  114. package/dist/domain/domain-builder.js +1 -1
  115. package/dist/domain/domain-context/action-system/action-system.d.ts +2 -2
  116. package/dist/domain/domain-context/action-system/action-system.js +1 -1
  117. package/dist/domain/domain-context/action-system/index.d.ts +1 -0
  118. package/dist/domain/domain-context/action-system/index.js +1 -0
  119. package/dist/domain/domain-context/analytics-system/index.d.ts +2 -0
  120. package/dist/domain/domain-context/analytics-system/index.js +1 -0
  121. package/dist/domain/domain-context/create-transformer.d.ts +1 -1
  122. package/dist/domain/domain-context/dimension-system/dimension-system.d.ts +2 -2
  123. package/dist/domain/domain-context/dimension-system/dimension-system.js +1 -1
  124. package/dist/domain/domain-context/dimension-system/index.d.ts +1 -0
  125. package/dist/domain/domain-context/dimension-system/index.js +1 -0
  126. package/dist/domain/domain-context/domain-context-systems.d.ts +7 -7
  127. package/dist/domain/domain-context/index.d.ts +8 -17
  128. package/dist/domain/domain-context/index.js +1 -1
  129. package/dist/domain/domain-context/navigation-system/index.d.ts +3 -0
  130. package/dist/domain/domain-context/navigation-system/index.js +1 -0
  131. package/dist/domain/domain-context/navigation-system/navigation-system.d.ts +2 -3
  132. package/dist/domain/domain-context/navigation-system/navigation-system.js +1 -1
  133. package/dist/domain/domain-context/navigation-system/selection-transformers.d.ts +1 -1
  134. package/dist/domain/domain-context/recipe-system/index.d.ts +1 -0
  135. package/dist/domain/domain-context/recipe-system/index.js +1 -0
  136. package/dist/domain/domain-context/recipe-system/recipe-cooker-system.d.ts +1 -1
  137. package/dist/domain/domain-context/recipe-system/recipe-cooker-system.js +1 -1
  138. package/dist/domain/domain-context/relation-transformers/cascade-deletes.d.ts +2 -2
  139. package/dist/domain/domain-context/relation-transformers/cascade-ref-pruning.d.ts +2 -2
  140. package/dist/domain/domain-context/relation-transformers/create-entity-refs.d.ts +2 -2
  141. package/dist/domain/domain-context/relation-transformers/index.d.ts +4 -0
  142. package/dist/domain/domain-context/relation-transformers/index.js +1 -0
  143. package/dist/domain/domain-context/relation-transformers/replace-refs.d.ts +2 -2
  144. package/dist/domain/domain-context/store-system/index.d.ts +4 -0
  145. package/dist/domain/domain-context/store-system/index.js +1 -0
  146. package/dist/domain/domain-context/store-system/reconcile-projected-entities.js +1 -1
  147. package/dist/domain/domain-context/store-system/store-system.d.ts +2 -35
  148. package/dist/domain/domain-context/store-system/store-system.js +2 -2
  149. package/dist/domain/domain-context/store-system/system-state.d.ts +1 -1
  150. package/dist/domain/domain-context/transformers/actions-builder.js +1 -1
  151. package/dist/domain/domain-context/transformers/auto-snap-transformer.d.ts +5 -7
  152. package/dist/domain/domain-context/transformers/auto-snap-transformer.js +1 -1
  153. package/dist/domain/domain-context/transformers/chain-builder.d.ts +1 -1
  154. package/dist/domain/domain-context/transformers/context.d.ts +2 -3
  155. package/dist/domain/domain-context/transformers/context.js +1 -1
  156. package/dist/domain/domain-context/transformers/entity-builder.js +1 -1
  157. package/dist/domain/domain-context/transformers/index.d.ts +1 -1
  158. package/dist/domain/domain-context/transformers/index.js +1 -1
  159. package/dist/domain/domain-context/transformers/when-builder.d.ts +2 -3
  160. package/dist/domain/domain-context/transformers/when-builder.js +1 -1
  161. package/dist/domain/domain-context/undo-system.d.ts +2 -3
  162. package/dist/domain/domain-runtime/domain-context/action-context.d.ts +11 -0
  163. package/dist/domain/domain-runtime/domain-context/action-context.js +1 -0
  164. package/dist/domain/domain-runtime/domain-context/domain-context.js +1 -1
  165. package/dist/domain/domain-runtime/domain-context/expression-context.d.ts +8 -0
  166. package/dist/domain/domain-runtime/domain-context/expression-context.js +1 -0
  167. package/dist/domain/domain-runtime/domain-context/index.d.ts +3 -0
  168. package/dist/domain/domain-runtime/domain-context/runtime-expression-context.d.ts +18 -0
  169. package/dist/domain/domain-runtime/domain-context/runtime-expression-context.js +1 -0
  170. package/dist/domain/domain-runtime/domain-context/selectors.d.ts +5 -10
  171. package/dist/domain/domain-runtime/domain-context/selectors.js +1 -1
  172. package/dist/domain/domain-runtime/domain-runtime.d.ts +52 -52
  173. package/dist/domain/domain-runtime/spec/index.d.ts +2 -0
  174. package/dist/domain/domain-runtime/spec/index.js +1 -1
  175. package/dist/domain/domain-runtime/spec/initialize.js +1 -1
  176. package/dist/domain/domain-runtime/spec/invariant-builder.d.ts +26 -0
  177. package/dist/domain/domain-runtime/spec/invariant-builder.js +1 -0
  178. package/dist/domain/{application → domain-runtime/spec/module-checks}/element-registration.d.ts +2 -2
  179. package/dist/domain/domain-runtime/spec/module-checks/element-registration.js +1 -0
  180. package/dist/domain/{application → domain-runtime/spec/module-checks}/handler-registration.d.ts +1 -1
  181. package/dist/domain/domain-runtime/spec/module-checks/handler-registration.js +1 -0
  182. package/dist/domain/domain-runtime/spec/module-checks/index.d.ts +8 -0
  183. package/dist/domain/domain-runtime/spec/module-checks/index.js +1 -0
  184. package/dist/domain/{project-modules → domain-runtime/spec/module-checks}/project-modules.d.ts +0 -16
  185. package/dist/domain/domain-runtime/spec/module-checks/project-modules.js +1 -0
  186. package/dist/domain/domain-runtime/spec/module-checks/resolve-action-modules.d.ts +4 -0
  187. package/dist/domain/domain-runtime/spec/module-checks/resolve-action-modules.js +1 -0
  188. package/dist/domain/domain-runtime/spec/module-checks/resolve-component-optic-modules.d.ts +4 -0
  189. package/dist/domain/domain-runtime/spec/module-checks/resolve-component-optic-modules.js +1 -0
  190. package/dist/domain/domain-runtime/spec/module-checks/resolve-expression-modules.d.ts +15 -0
  191. package/dist/domain/domain-runtime/spec/module-checks/resolve-expression-modules.js +1 -0
  192. package/dist/domain/{application → domain-runtime/spec/module-checks}/resolve-imported-transformers.d.ts +4 -5
  193. package/dist/domain/domain-runtime/spec/module-checks/resolve-imported-transformers.js +1 -0
  194. package/dist/domain/domain-runtime/spec/module-checks/resolve-invariant-modules.d.ts +6 -0
  195. package/dist/domain/domain-runtime/spec/module-checks/resolve-invariant-modules.js +1 -0
  196. package/dist/domain/domain-runtime/spec/selectors.d.ts +5 -6
  197. package/dist/domain/domain-runtime/spec/selectors.js +1 -1
  198. package/dist/domain/domain-runtime/spec/types.d.ts +3 -2
  199. package/dist/domain/index.d.ts +0 -1
  200. package/dist/domain/index.js +1 -1
  201. package/dist/domain/mocks/create-mock-domain-runtime-services.d.ts +1 -1
  202. package/dist/domain/mocks/create-mock-domain-runtime.d.ts +10 -10
  203. package/dist/domain/projections/blender-projections/blender-projections.d.ts +1 -2
  204. package/dist/domain/projections/blender-projections/camera.d.ts +1 -1
  205. package/dist/domain/projections/collision-projections.d.ts +1 -1
  206. package/dist/domain/projections/composition-projections.d.ts +1 -1
  207. package/dist/domain/projections/constraint-projections.d.ts +1 -1
  208. package/dist/domain/projections/index.d.ts +1 -1
  209. package/dist/domain/projections/position-projections.d.ts +1 -1
  210. package/dist/domain/projections/projected-entities-projections.d.ts +1 -1
  211. package/dist/domain/projections/snapping-projections.d.ts +1 -1
  212. package/dist/domain/projections/validation-projections.d.ts +3 -19
  213. package/dist/domain/sketching/sketching-projections.d.ts +1 -1
  214. package/dist/domain/system-components/phoenix-entity-elements/admin-data-table-sidebar.d.ts +1 -1
  215. package/dist/domain/system-components/phoenix-layout-elements/admin-connected-resource-page.d.ts +1 -1
  216. package/dist/domain/system-components/phoenix-layout-elements/admin-data-table-actions.d.ts +1 -1
  217. package/dist/domain/system-components/phoenix-layout-elements/admin-data-table-page.d.ts +1 -1
  218. package/dist/domain/utils/memo-eval.d.ts +2 -2
  219. package/dist/legacy/domain-cli/gen/constant-expressions.js +1 -3
  220. package/dist/legacy/domain-cli/gen/implementation.js +7 -11
  221. package/dist/legacy/domain-cli/gen/invariants.js +5 -3
  222. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  223. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  224. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
  225. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
  226. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
  227. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +1 -0
  228. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/domain-index.js +4 -4
  229. package/dist/phoenix/commands/init.d.ts +4 -4
  230. package/dist/phoenix/commands/init.js +1 -1
  231. package/dist/phoenix/commands/prettier.js +1 -1
  232. package/dist/react-sdk/application-runtime/runtime/create-application-runtime.d.ts +20 -20
  233. package/dist/react-sdk/domain-context/common-hooks/use-domain-context.d.ts +5 -5
  234. package/package.json +3 -3
  235. package/dist/application-spec/generate-application/code/templates/env-ci.d.ts +0 -1
  236. package/dist/application-spec/generate-application/code/templates/env-ci.js +0 -25
  237. package/dist/application-spec/generate-application/code/templates/env-example.d.ts +0 -1
  238. package/dist/application-spec/generate-application/code/templates/env-example.js +0 -94
  239. package/dist/application-spec/generate-application/code/templates/private-assets-readme.d.ts +0 -1
  240. package/dist/application-spec/generate-application/code/templates/private-assets-readme.js +0 -24
  241. package/dist/application-spec/generate-application/code/templates/public-assets-readme.d.ts +0 -1
  242. package/dist/application-spec/generate-application/code/templates/public-assets-readme.js +0 -24
  243. package/dist/application-spec/generate-application/code/templates/readme.d.ts +0 -1
  244. package/dist/application-spec/generate-application/code/templates/readme.js +0 -23
  245. package/dist/application-spec/generate-application/code/templates/skills/agents-md.d.ts +0 -1
  246. package/dist/application-spec/generate-application/code/templates/skills/agents-md.js +0 -2
  247. package/dist/domain/application/element-registration.js +0 -1
  248. package/dist/domain/application/handler-registration.js +0 -1
  249. package/dist/domain/application/resolve-imported-transformers.js +0 -1
  250. package/dist/domain/project-modules/index.d.ts +0 -1
  251. package/dist/domain/project-modules/index.js +0 -1
  252. package/dist/domain/project-modules/project-modules.js +0 -1
@@ -1,2 +1,2 @@
1
1
  export declare const mergeCursorRulesContent: (existingContent: string | undefined) => string;
2
- export declare const cursorRulesFile = "---\ndescription: Phoenix SDK project rules\nglobs:\nalwaysApply: true\n---\n\n[PHOENIX-SDK-START]\n## Phoenix Configurator Project\n\nDeclarative 3D product configurator built with Phoenix SDK. Domain model defined in YAML, custom logic in TypeScript.\n\n## Build Commands\n- `pnpm phoenix build` \u2014 Full production build\n- `pnpm phoenix dev` \u2014 Development mode with hot reload\n- `pnpm phoenix sync` \u2014 Sync generated files without full build\n\n## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)\n\n## Project Structure\n- `spec/` \u2014 Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` \u2014 Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/invariants/` \u2014 Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` \u2014 Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` \u2014 ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` \u2014 Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n- `src/handlers/` \u2014 Event & lifecycle handlers\n- `src/webhooks/` \u2014 Server-side webhook handlers (`phx.webhooks.*Builder`)\n- `src/migrations/` \u2014 Schema version migrations (v*.ts)\n- `src/locales/` \u2014 Locale catalogs (authored .po sources; compiled .ts, do not edit)\n- `src/admin/` \u2014 Admin interface (mirrors main src/ structure)\n- `src/_shared/` \u2014 Shared utilities (NOT auto-imported, requires explicit imports)\n- `.phoenix/` \u2014 Auto-generated files (DO NOT EDIT)\n- `public/` \u2014 Static assets (3D models, textures, images, HDRI maps, fonts)\n- `assets/` \u2014 Uploadable resources (PDF templates, email assets)\n\n## Architecture Principles\n- YAML-first: 99% of configuration in spec/*.yaml, custom code is last resort\n- ECS pattern: entities (domain objects) + components (behavior/UI) + systems (SDK runtime)\n- Reactive state: immutable domain state flows through RxJS pipelines\n- Data binding: `$read` (read-only), `$write` (write-only), `$bind` (bidirectional) connect components to domain\n- memoEval: all component implementations must use memoEval for stable object references\n\n## Key Patterns\n- Expressions = computed properties on entities (prefix: `$`), implemented per-entity in src/expressions/\n- Invariants = validation rules returning violations, static or dynamic\n- Transformers = auto-fixers maintaining consistency after state changes\n- Components defined in YAML with `$read`/`$bind` bindings, or custom in src/components/ using attachComponent builder\n- Webhooks = server-side finalization tasks (PDF, email, CSV, image rendering)\n- Filters = contextual component activation via navigationStates, viewStates, modes, selectedEntityIds\n\n## File Conventions\n- Components: PascalCase (.tsx)\n- Utilities: kebab-case (.ts)\n- Expressions: entity-name.ts\n- Migrations: v*.ts (sequential)\n- Specs: kebab-case.yaml\n- Underscore folders (_shared/, _utils/) are NOT auto-imported\n\n## Export Rules\nAll files in src/expressions/, src/invariants/, src/transformers/, src/components/, src/handlers/, src/webhooks/ MUST use default exports. Can be a single item or an array. Named exports are ignored by the SDK auto-import system.\n\n## Webhook Membership\n- User-authored components, admin components, and handlers are frontend-only by default.\n- A handler that registers `createMapPublishedRevisionDataHandler`, `createMapPublishedChunkedDataHandler`, `createDataRowValidatorHandler`, or `createSheetValidatorHandler` is included in the webhook automatically.\n- To include another component or handler in the webhook, put `'use webhook'` as its first statement (leading comments are allowed).\n- A webhook-included file and its runtime local-import closure must not import browser SDK entrypoints (`application`, `admin`, `configurator`, `editor`, `react`, `ui`) or style/font/image assets. Spec parsing reports the unsafe import and inclusion reason as a diagnostic.\n- Keep browser rendering in an unpinned file. Move shared server-safe logic into a separate module when both frontend and webhook code need it.\n\n## Do Not Edit\n- `.phoenix/` directory \u2014 completely regenerated on each build\n- `tsconfig.json`, `eslint.config.js`, `prettier.config.js`, `.prettierignore`, `.linguirc`, `.nvmrc`\n- `src/locales/` .ts files \u2014 compiled from .po files\n\n## Code Review\nUse `/review` command to review code changes before committing.\n\n## SDK Documentation\n\nAlways search SDK docs for relevant examples before implementing Phoenix features.\n\n### Commands\n- `pnpm phoenix docs` \u2014 Full documentation index with descriptions\n- `pnpm phoenix docs -s <term>` \u2014 Search all doc content and metadata (case-insensitive)\n- `pnpm phoenix docs --dir` \u2014 Print the absolute docs directory for grep or ripgrep\n- `pnpm phoenix docs -r <path>` \u2014 Read specific doc (raw text to stdout)\n- `pnpm phoenix docs -c <category>` \u2014 List docs in a category\n- `pnpm phoenix docs -l` \u2014 List all doc paths with titles\n\n### 3D Asset Inspection\n\nRun `pnpm phoenix inspect:assets` to discover all glTF/GLB files in `public/` and get a summary table. Use `--file <path>` for detailed single-file inspection.\n\n**When to use:** before writing YAML/code that references objectName, materialsToOverride, morphTargetInfluences, or object positioning.\n\n**What it shows per node:**\n- Name, type (Mesh/Light/Camera/Empty), children\n- Transform: `pos=`, `rot=`, `scale=` (only non-default values shown)\n- Per-node morph targets: `morphs=Width,Height`\n- Bounding box: `bounds=WxHxD` (width x height x depth in meters)\n- Origin placement: `origin=center`, `bottom-center`, `top-center`, `bottom-corner`, etc. with numerical offset\n\n**Use cases:**\n- Find exact node names for `objectName` in scene entity components\n- Find material names for `materialsToOverride`\n- Find morph target names for `morphTargetInfluences`\n- Check model dimensions (bounds) for positioning, dimension indicators, or invariants\n- Check origin placement to understand how models anchor (center vs bottom-center)\n- Use `--json` for programmatic access to all data\n\n**Flags:** `--objects`, `--materials`, `--morphs`, `--animations`, `--json`\n\n### Screenshot CLI\n\nCapture 3D canvas screenshots from a running dev server via `pnpm phoenix screenshot`.\n\n**Prerequisites:**\n1. `phoenix dev` must be running (starts the WebSocket server on port 3020)\n2. Configurator must be open in a browser (the browser does the actual rendering)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (default: `./screenshot.png`)\n- `--width, -w` \u2014 Width in pixels (default: 1920)\n- `--height` \u2014 Height in pixels (default: 1080)\n- `--format, -f` \u2014 Image format: PNG or JPEG (default: PNG)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example workflow:**\n1. Start dev server: `pnpm phoenix dev`\n2. Open configurator in browser (or via Playwright MCP)\n3. Take screenshot: `pnpm phoenix screenshot -o ./render.png -w 2560 --height 1440`\n\n**Use cases:** visual regression testing, generating product images, debugging 3D renders\n\n### Inspect: State\n\nGet the current editor runtime state as JSON via `pnpm phoenix inspect:state`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--sections, -s` \u2014 Comma-separated: entities, navigation, validation (default: all)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example:** `pnpm phoenix inspect:state -o ./state.json -s entities,navigation`\n\n**Lifecycle status:** Always included in response. Shows which systems are ready:\n- `domainLoaded` \u2014 domain data loaded\n- `domainContextReady` \u2014 domain context initialized (entities available)\n- `configuratorReady` \u2014 3D configurator initialized\n- `sessionAuthenticated` \u2014 session service active\n- `editorMode` \u2014 editor mode enabled\n\n**Tips:** Use `--sections` to limit payload size. Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:state | head -50`).\n\n**Use cases:** AI agent context, debugging entity state, inspecting navigation/validation\n\n### Inspect: Data\n\nGet the current editor context data as JSON via `pnpm phoenix inspect:data`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** publishedData, frontendData, backendData, sessionData, accessData, webComponentProperties\n\n**Example:** `pnpm phoenix inspect:data -o ./data.json`\n\n**Tips:** Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:data | head -30`).\n\n**Use cases:** AI agent context, debugging published/session/access data\n\n### Inspect: Scene\n\nGet the current Three.js scene graph as JSON via `pnpm phoenix inspect:scene`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** Recursive scene tree with per-node: name, type, visible, position, rotation, scale, userData (entityId), and for meshes: geometry name, bounding box, material properties (color, metalness, roughness, opacity, textures), morph target influences. Lights include color, intensity, and type-specific properties.\n\n**Example:** `pnpm phoenix inspect:scene -o ./scene.json`\n\n**Tips:** Scene graphs can be large. Pipe through `head`/`tail` for partial output.\n\n**Use cases:** AI agent context, debugging 3D scene layout, inspecting materials and lighting\n\n### Key Docs\n- `docs/phoenix/getting-started.mdx` \u2014 Setup, prerequisites, first project\n- `docs/phoenix/quickstart.mdx` \u2014 End-to-end tutorial building a configurator\n- `docs/phoenix/domain-model.mdx` \u2014 Entities, attributes, relations, specs\n- `docs/phoenix/components.mdx` \u2014 ECS pattern, YAML components, custom components\n- `docs/phoenix/project-structure.mdx` \u2014 Files, folders, conventions\n- `docs/phoenix/best-practices.mdx` \u2014 YAML-first, code patterns, common pitfalls\n- `docs/phoenix/state-management.mdx` \u2014 Reactive state, RxJS pipelines, data flow\n- `docs/phoenix/expression-context.mdx` \u2014 Expression API, context object, helpers\n- `docs/phoenix/webhooks.mdx` \u2014 Server-side finalization workflows\n- `docs/phoenix/finalization.mdx` \u2014 Finalization system, PDF/email/CSV generation\n- `docs/phoenix/migrations.mdx` \u2014 Schema versioning, migration files\n\n### Agent Workflow\n1. Find relevant docs by content: `pnpm phoenix docs -s \"camera\"`\n2. Read matching doc: `pnpm phoenix docs -r docs/3d-scene/cameras/transitions.mdx`\n3. Search within a doc: `pnpm phoenix docs -r <path> | grep \"example\"`\n4. Search titles only as a fallback: `pnpm phoenix docs -l | grep \"camera\"`\n5. Search generated files directly when needed: `grep -rn \"camera\" \"$(pnpm phoenix docs --dir)\"`\n6. Browse a topic area: `pnpm phoenix docs -c \"Layouts\"`\n\n### Playwright MCP Setup (for AI agents)\n\nTo interact with the 3D configurator in a browser, Playwright MCP needs GPU-enabled flags for WebGL rendering. Add to `~/.claude/.mcp.json`:\n\n```json\n{\n \"mcpServers\": {\n \"playwright\": {\n \"command\": \"npx\",\n \"args\": [\n \"@playwright/mcp@latest\",\n \"--headed\",\n \"--launch-options\",\n \"{\\\"args\\\":[\\\"--use-gl=swiftshader\\\",\\\"--enable-webgl\\\",\\\"--ignore-gpu-blocklist\\\"]}\"\n ]\n }\n }\n}\n```\n\nKey flags:\n- `--headed` \u2014 visible browser (required for GPU rendering)\n- `--use-gl=swiftshader` \u2014 software GPU fallback for environments without a physical GPU\n- `--enable-webgl` + `--ignore-gpu-blocklist` \u2014 ensure WebGL is available\n[PHOENIX-SDK-END]\n";
2
+ export declare const cursorRulesFile = "---\ndescription: Phoenix SDK project rules\nglobs:\nalwaysApply: true\n---\n\n[PHOENIX-SDK-START]\n## Phoenix Configurator Project\n\nDeclarative 3D product configurator built with Phoenix SDK. Domain model defined in YAML, custom logic in TypeScript.\n\n## Build Commands\n- `pnpm phoenix build` \u2014 Full production build\n- `pnpm phoenix dev` \u2014 Development mode with hot reload\n- `pnpm phoenix sync` \u2014 Sync generated files without full build\n\n## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)\n\n## Project Structure\n- `spec/` \u2014 Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` \u2014 Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/invariants/` \u2014 Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` \u2014 Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` \u2014 ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` \u2014 Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n - A layout element named `ConfiguratorLayout` replaces everything the built-in layout renders for a loaded configuration, the finalize page included, so prefer arranging the layout in the spec; when you register it, mount `LayoutSlots.SharedCanvas` (from `@salsita-ai/sdk/configurator`) in it, or the app loader stays on screen\n- `src/handlers/` \u2014 Event & lifecycle handlers\n- `src/webhooks/` \u2014 Server-side webhook handlers (`phx.webhooks.*Builder`)\n- `src/migrations/` \u2014 Schema version migrations (v*.ts)\n- `src/locales/` \u2014 Locale catalogs (authored .po sources; compiled .ts, do not edit)\n- `src/admin/` \u2014 Admin interface (mirrors main src/ structure)\n- `src/_shared/` \u2014 Shared utilities (NOT auto-imported, requires explicit imports)\n- `.phoenix/` \u2014 Auto-generated files (DO NOT EDIT)\n- `public/` \u2014 Static assets (3D models, textures, images, HDRI maps, fonts)\n- `assets/` \u2014 Uploadable resources (PDF templates, email assets)\n\n## Architecture Principles\n- YAML-first: 99% of configuration in spec/*.yaml, custom code is last resort\n- ECS pattern: entities (domain objects) + components (behavior/UI) + systems (SDK runtime)\n- Reactive state: immutable domain state flows through RxJS pipelines\n- Data binding: `$read` (read-only), `$write` (write-only), `$bind` (bidirectional) connect components to domain\n- memoEval: all component implementations must use memoEval for stable object references\n\n## Key Patterns\n- Expressions = computed properties on entities (prefix: `$`), implemented per-entity in src/expressions/\n- Invariants = validation rules returning violations, static or dynamic\n- Transformers = auto-fixers maintaining consistency after state changes\n- Components defined in YAML with `$read`/`$bind` bindings, or custom in src/components/ using attachComponent builder\n- Webhooks = server-side finalization tasks (PDF, email, CSV, image rendering)\n- Filters = contextual component activation via navigationStates, viewStates, modes, selectedEntityIds\n\n## File Conventions\n- Components: PascalCase (.tsx)\n- Utilities: kebab-case (.ts)\n- Expressions: entity-name.ts\n- Migrations: v*.ts (sequential)\n- Specs: kebab-case.yaml\n- Underscore folders (_shared/, _utils/) are NOT auto-imported\n\n## Export Rules\nAll files in src/expressions/, src/invariants/, src/transformers/, src/components/, src/handlers/, src/webhooks/ MUST use default exports. Can be a single item or an array. Named exports are ignored by the SDK auto-import system.\n\n## Webhook Membership\n- User-authored components, admin components, and handlers are frontend-only by default.\n- A handler that registers `createMapPublishedRevisionDataHandler`, `createMapPublishedChunkedDataHandler`, `createDataRowValidatorHandler`, or `createSheetValidatorHandler` is included in the webhook automatically.\n- To include another component or handler in the webhook, put `'use webhook'` as its first statement (leading comments are allowed).\n- A webhook-included file and its runtime local-import closure must not import browser SDK entrypoints (`application`, `admin`, `configurator`, `editor`, `react`, `ui`) or style/font/image assets. Spec parsing reports the unsafe import and inclusion reason as a diagnostic.\n- Keep browser rendering in an unpinned file. Move shared server-safe logic into a separate module when both frontend and webhook code need it.\n\n## Do Not Edit\n- `.phoenix/` directory \u2014 completely regenerated on each build\n- `tsconfig.json`, `eslint.config.js`, `prettier.config.js`, `.prettierignore`, `.linguirc`, `.nvmrc`\n- `src/locales/` .ts files \u2014 compiled from .po files\n\n## Code Review\nUse `/review` command to review code changes before committing.\n\n## SDK Documentation\n\nAlways search SDK docs for relevant examples before implementing Phoenix features.\n\n### Commands\n- `pnpm phoenix docs` \u2014 Full documentation index with descriptions\n- `pnpm phoenix docs -s <term>` \u2014 Search all doc content and metadata (case-insensitive)\n- `pnpm phoenix docs --dir` \u2014 Print the absolute docs directory for grep or ripgrep\n- `pnpm phoenix docs -r <path>` \u2014 Read specific doc (raw text to stdout)\n- `pnpm phoenix docs -c <category>` \u2014 List docs in a category\n- `pnpm phoenix docs -l` \u2014 List all doc paths with titles\n\n### 3D Asset Inspection\n\nRun `pnpm phoenix inspect:assets` to discover all glTF/GLB files in `public/` and get a summary table. Use `--file <path>` for detailed single-file inspection.\n\n**When to use:** before writing YAML/code that references objectName, materialsToOverride, morphTargetInfluences, or object positioning.\n\n**What it shows per node:**\n- Name, type (Mesh/Light/Camera/Empty), children\n- Transform: `pos=`, `rot=`, `scale=` (only non-default values shown)\n- Per-node morph targets: `morphs=Width,Height`\n- Bounding box: `bounds=WxHxD` (width x height x depth in meters)\n- Origin placement: `origin=center`, `bottom-center`, `top-center`, `bottom-corner`, etc. with numerical offset\n\n**Use cases:**\n- Find exact node names for `objectName` in scene entity components\n- Find material names for `materialsToOverride`\n- Find morph target names for `morphTargetInfluences`\n- Check model dimensions (bounds) for positioning, dimension indicators, or invariants\n- Check origin placement to understand how models anchor (center vs bottom-center)\n- Use `--json` for programmatic access to all data\n\n**Flags:** `--objects`, `--materials`, `--morphs`, `--animations`, `--json`\n\n### Screenshot CLI\n\nCapture 3D canvas screenshots from a running dev server via `pnpm phoenix screenshot`.\n\n**Prerequisites:**\n1. `phoenix dev` must be running (starts the WebSocket server on port 3020)\n2. Configurator must be open in a browser (the browser does the actual rendering)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (default: `./screenshot.png`)\n- `--width, -w` \u2014 Width in pixels (default: 1920)\n- `--height` \u2014 Height in pixels (default: 1080)\n- `--format, -f` \u2014 Image format: PNG or JPEG (default: PNG)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example workflow:**\n1. Start dev server: `pnpm phoenix dev`\n2. Open configurator in browser (or via Playwright MCP)\n3. Take screenshot: `pnpm phoenix screenshot -o ./render.png -w 2560 --height 1440`\n\n**Use cases:** visual regression testing, generating product images, debugging 3D renders\n\n### Inspect: State\n\nGet the current editor runtime state as JSON via `pnpm phoenix inspect:state`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--sections, -s` \u2014 Comma-separated: entities, navigation, validation (default: all)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example:** `pnpm phoenix inspect:state -o ./state.json -s entities,navigation`\n\n**Lifecycle status:** Always included in response. Shows which systems are ready:\n- `domainLoaded` \u2014 domain data loaded\n- `domainContextReady` \u2014 domain context initialized (entities available)\n- `configuratorReady` \u2014 3D configurator initialized\n- `sessionAuthenticated` \u2014 session service active\n- `editorMode` \u2014 editor mode enabled\n\n**Tips:** Use `--sections` to limit payload size. Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:state | head -50`).\n\n**Use cases:** AI agent context, debugging entity state, inspecting navigation/validation\n\n### Inspect: Data\n\nGet the current editor context data as JSON via `pnpm phoenix inspect:data`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** publishedData, frontendData, backendData, sessionData, accessData, webComponentProperties\n\n**Example:** `pnpm phoenix inspect:data -o ./data.json`\n\n**Tips:** Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:data | head -30`).\n\n**Use cases:** AI agent context, debugging published/session/access data\n\n### Inspect: Scene\n\nGet the current Three.js scene graph as JSON via `pnpm phoenix inspect:scene`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** Recursive scene tree with per-node: name, type, visible, position, rotation, scale, userData (entityId), and for meshes: geometry name, bounding box, material properties (color, metalness, roughness, opacity, textures), morph target influences. Lights include color, intensity, and type-specific properties.\n\n**Example:** `pnpm phoenix inspect:scene -o ./scene.json`\n\n**Tips:** Scene graphs can be large. Pipe through `head`/`tail` for partial output.\n\n**Use cases:** AI agent context, debugging 3D scene layout, inspecting materials and lighting\n\n### Key Docs\n- `docs/phoenix/getting-started.mdx` \u2014 Setup, prerequisites, first project\n- `docs/phoenix/quickstart.mdx` \u2014 End-to-end tutorial building a configurator\n- `docs/phoenix/domain-model.mdx` \u2014 Entities, attributes, relations, specs\n- `docs/phoenix/components.mdx` \u2014 ECS pattern, YAML components, custom components\n- `docs/phoenix/project-structure.mdx` \u2014 Files, folders, conventions\n- `docs/phoenix/best-practices.mdx` \u2014 YAML-first, code patterns, common pitfalls\n- `docs/phoenix/state-management.mdx` \u2014 Reactive state, RxJS pipelines, data flow\n- `docs/phoenix/expression-context.mdx` \u2014 Expression API, context object, helpers\n- `docs/phoenix/webhooks.mdx` \u2014 Server-side finalization workflows\n- `docs/phoenix/finalization.mdx` \u2014 Finalization system, PDF/email/CSV generation\n- `docs/phoenix/migrations.mdx` \u2014 Schema versioning, migration files\n\n### Agent Workflow\n1. Find relevant docs by content: `pnpm phoenix docs -s \"camera\"`\n2. Read matching doc: `pnpm phoenix docs -r docs/3d-scene/cameras/transitions.mdx`\n3. Search within a doc: `pnpm phoenix docs -r <path> | grep \"example\"`\n4. Search titles only as a fallback: `pnpm phoenix docs -l | grep \"camera\"`\n5. Search generated files directly when needed: `grep -rn \"camera\" \"$(pnpm phoenix docs --dir)\"`\n6. Browse a topic area: `pnpm phoenix docs -c \"Layouts\"`\n\n### Playwright MCP Setup (for AI agents)\n\nTo interact with the 3D configurator in a browser, Playwright MCP needs GPU-enabled flags for WebGL rendering. Add to `~/.claude/.mcp.json`:\n\n```json\n{\n \"mcpServers\": {\n \"playwright\": {\n \"command\": \"npx\",\n \"args\": [\n \"@playwright/mcp@latest\",\n \"--headed\",\n \"--launch-options\",\n \"{\\\"args\\\":[\\\"--use-gl=swiftshader\\\",\\\"--enable-webgl\\\",\\\"--ignore-gpu-blocklist\\\"]}\"\n ]\n }\n }\n}\n```\n\nKey flags:\n- `--headed` \u2014 visible browser (required for GPU rendering)\n- `--use-gl=swiftshader` \u2014 software GPU fallback for environments without a physical GPU\n- `--enable-webgl` + `--ignore-gpu-blocklist` \u2014 ensure WebGL is available\n[PHOENIX-SDK-END]\n";
@@ -1 +1 @@
1
- export declare const sdkContent = "[PHOENIX-SDK-START]\n## Phoenix Configurator Project\n\nDeclarative 3D product configurator built with Phoenix SDK. Domain model defined in YAML, custom logic in TypeScript.\n\n## Build Commands\n- `pnpm phoenix build` \u2014 Full production build\n- `pnpm phoenix dev` \u2014 Development mode with hot reload\n- `pnpm phoenix sync` \u2014 Sync generated files without full build\n\n## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)\n\n## Project Structure\n- `spec/` \u2014 Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` \u2014 Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/invariants/` \u2014 Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` \u2014 Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` \u2014 ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` \u2014 Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n- `src/handlers/` \u2014 Event & lifecycle handlers\n- `src/webhooks/` \u2014 Server-side webhook handlers (`phx.webhooks.*Builder`)\n- `src/migrations/` \u2014 Schema version migrations (v*.ts)\n- `src/locales/` \u2014 Locale catalogs (authored .po sources; compiled .ts, do not edit)\n- `src/admin/` \u2014 Admin interface (mirrors main src/ structure)\n- `src/_shared/` \u2014 Shared utilities (NOT auto-imported, requires explicit imports)\n- `.phoenix/` \u2014 Auto-generated files (DO NOT EDIT)\n- `public/` \u2014 Static assets (3D models, textures, images, HDRI maps, fonts)\n- `assets/` \u2014 Uploadable resources (PDF templates, email assets)\n\n## Architecture Principles\n- YAML-first: 99% of configuration in spec/*.yaml, custom code is last resort\n- ECS pattern: entities (domain objects) + components (behavior/UI) + systems (SDK runtime)\n- Reactive state: immutable domain state flows through RxJS pipelines\n- Data binding: `$read` (read-only), `$write` (write-only), `$bind` (bidirectional) connect components to domain\n- memoEval: all component implementations must use memoEval for stable object references\n\n## Key Patterns\n- Expressions = computed properties on entities (prefix: `$`), implemented per-entity in src/expressions/\n- Invariants = validation rules returning violations, static or dynamic\n- Transformers = auto-fixers maintaining consistency after state changes\n- Components defined in YAML with `$read`/`$bind` bindings, or custom in src/components/ using attachComponent builder\n- Webhooks = server-side finalization tasks (PDF, email, CSV, image rendering)\n- Filters = contextual component activation via navigationStates, viewStates, modes, selectedEntityIds\n\n## File Conventions\n- Components: PascalCase (.tsx)\n- Utilities: kebab-case (.ts)\n- Expressions: entity-name.ts\n- Migrations: v*.ts (sequential)\n- Specs: kebab-case.yaml\n- Underscore folders (_shared/, _utils/) are NOT auto-imported\n\n## Export Rules\nAll files in src/expressions/, src/invariants/, src/transformers/, src/components/, src/handlers/, src/webhooks/ MUST use default exports. Can be a single item or an array. Named exports are ignored by the SDK auto-import system.\n\n## Webhook Membership\n- User-authored components, admin components, and handlers are frontend-only by default.\n- A handler that registers `createMapPublishedRevisionDataHandler`, `createMapPublishedChunkedDataHandler`, `createDataRowValidatorHandler`, or `createSheetValidatorHandler` is included in the webhook automatically.\n- To include another component or handler in the webhook, put `'use webhook'` as its first statement (leading comments are allowed).\n- A webhook-included file and its runtime local-import closure must not import browser SDK entrypoints (`application`, `admin`, `configurator`, `editor`, `react`, `ui`) or style/font/image assets. Spec parsing reports the unsafe import and inclusion reason as a diagnostic.\n- Keep browser rendering in an unpinned file. Move shared server-safe logic into a separate module when both frontend and webhook code need it.\n\n## Do Not Edit\n- `.phoenix/` directory \u2014 completely regenerated on each build\n- `tsconfig.json`, `eslint.config.js`, `prettier.config.js`, `.prettierignore`, `.linguirc`, `.nvmrc`\n- `src/locales/` .ts files \u2014 compiled from .po files\n\n## Code Review\nUse `/review` command to review code changes before committing.\n\n## SDK Documentation\n\nAlways search SDK docs for relevant examples before implementing Phoenix features.\n\n### Commands\n- `pnpm phoenix docs` \u2014 Full documentation index with descriptions\n- `pnpm phoenix docs -s <term>` \u2014 Search all doc content and metadata (case-insensitive)\n- `pnpm phoenix docs --dir` \u2014 Print the absolute docs directory for grep or ripgrep\n- `pnpm phoenix docs -r <path>` \u2014 Read specific doc (raw text to stdout)\n- `pnpm phoenix docs -c <category>` \u2014 List docs in a category\n- `pnpm phoenix docs -l` \u2014 List all doc paths with titles\n\n### 3D Asset Inspection\n\nRun `pnpm phoenix inspect:assets` to discover all glTF/GLB files in `public/` and get a summary table. Use `--file <path>` for detailed single-file inspection.\n\n**When to use:** before writing YAML/code that references objectName, materialsToOverride, morphTargetInfluences, or object positioning.\n\n**What it shows per node:**\n- Name, type (Mesh/Light/Camera/Empty), children\n- Transform: `pos=`, `rot=`, `scale=` (only non-default values shown)\n- Per-node morph targets: `morphs=Width,Height`\n- Bounding box: `bounds=WxHxD` (width x height x depth in meters)\n- Origin placement: `origin=center`, `bottom-center`, `top-center`, `bottom-corner`, etc. with numerical offset\n\n**Use cases:**\n- Find exact node names for `objectName` in scene entity components\n- Find material names for `materialsToOverride`\n- Find morph target names for `morphTargetInfluences`\n- Check model dimensions (bounds) for positioning, dimension indicators, or invariants\n- Check origin placement to understand how models anchor (center vs bottom-center)\n- Use `--json` for programmatic access to all data\n\n**Flags:** `--objects`, `--materials`, `--morphs`, `--animations`, `--json`\n\n### Screenshot CLI\n\nCapture 3D canvas screenshots from a running dev server via `pnpm phoenix screenshot`.\n\n**Prerequisites:**\n1. `phoenix dev` must be running (starts the WebSocket server on port 3020)\n2. Configurator must be open in a browser (the browser does the actual rendering)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (default: `./screenshot.png`)\n- `--width, -w` \u2014 Width in pixels (default: 1920)\n- `--height` \u2014 Height in pixels (default: 1080)\n- `--format, -f` \u2014 Image format: PNG or JPEG (default: PNG)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example workflow:**\n1. Start dev server: `pnpm phoenix dev`\n2. Open configurator in browser (or via Playwright MCP)\n3. Take screenshot: `pnpm phoenix screenshot -o ./render.png -w 2560 --height 1440`\n\n**Use cases:** visual regression testing, generating product images, debugging 3D renders\n\n### Inspect: State\n\nGet the current editor runtime state as JSON via `pnpm phoenix inspect:state`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--sections, -s` \u2014 Comma-separated: entities, navigation, validation (default: all)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example:** `pnpm phoenix inspect:state -o ./state.json -s entities,navigation`\n\n**Lifecycle status:** Always included in response. Shows which systems are ready:\n- `domainLoaded` \u2014 domain data loaded\n- `domainContextReady` \u2014 domain context initialized (entities available)\n- `configuratorReady` \u2014 3D configurator initialized\n- `sessionAuthenticated` \u2014 session service active\n- `editorMode` \u2014 editor mode enabled\n\n**Tips:** Use `--sections` to limit payload size. Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:state | head -50`).\n\n**Use cases:** AI agent context, debugging entity state, inspecting navigation/validation\n\n### Inspect: Data\n\nGet the current editor context data as JSON via `pnpm phoenix inspect:data`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** publishedData, frontendData, backendData, sessionData, accessData, webComponentProperties\n\n**Example:** `pnpm phoenix inspect:data -o ./data.json`\n\n**Tips:** Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:data | head -30`).\n\n**Use cases:** AI agent context, debugging published/session/access data\n\n### Inspect: Scene\n\nGet the current Three.js scene graph as JSON via `pnpm phoenix inspect:scene`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** Recursive scene tree with per-node: name, type, visible, position, rotation, scale, userData (entityId), and for meshes: geometry name, bounding box, material properties (color, metalness, roughness, opacity, textures), morph target influences. Lights include color, intensity, and type-specific properties.\n\n**Example:** `pnpm phoenix inspect:scene -o ./scene.json`\n\n**Tips:** Scene graphs can be large. Pipe through `head`/`tail` for partial output.\n\n**Use cases:** AI agent context, debugging 3D scene layout, inspecting materials and lighting\n\n### Key Docs\n- `docs/phoenix/getting-started.mdx` \u2014 Setup, prerequisites, first project\n- `docs/phoenix/quickstart.mdx` \u2014 End-to-end tutorial building a configurator\n- `docs/phoenix/domain-model.mdx` \u2014 Entities, attributes, relations, specs\n- `docs/phoenix/components.mdx` \u2014 ECS pattern, YAML components, custom components\n- `docs/phoenix/project-structure.mdx` \u2014 Files, folders, conventions\n- `docs/phoenix/best-practices.mdx` \u2014 YAML-first, code patterns, common pitfalls\n- `docs/phoenix/state-management.mdx` \u2014 Reactive state, RxJS pipelines, data flow\n- `docs/phoenix/expression-context.mdx` \u2014 Expression API, context object, helpers\n- `docs/phoenix/webhooks.mdx` \u2014 Server-side finalization workflows\n- `docs/phoenix/finalization.mdx` \u2014 Finalization system, PDF/email/CSV generation\n- `docs/phoenix/migrations.mdx` \u2014 Schema versioning, migration files\n\n### Agent Workflow\n1. Find relevant docs by content: `pnpm phoenix docs -s \"camera\"`\n2. Read matching doc: `pnpm phoenix docs -r docs/3d-scene/cameras/transitions.mdx`\n3. Search within a doc: `pnpm phoenix docs -r <path> | grep \"example\"`\n4. Search titles only as a fallback: `pnpm phoenix docs -l | grep \"camera\"`\n5. Search generated files directly when needed: `grep -rn \"camera\" \"$(pnpm phoenix docs --dir)\"`\n6. Browse a topic area: `pnpm phoenix docs -c \"Layouts\"`\n\n### Playwright MCP Setup (for AI agents)\n\nTo interact with the 3D configurator in a browser, Playwright MCP needs GPU-enabled flags for WebGL rendering. Add to `~/.claude/.mcp.json`:\n\n```json\n{\n \"mcpServers\": {\n \"playwright\": {\n \"command\": \"npx\",\n \"args\": [\n \"@playwright/mcp@latest\",\n \"--headed\",\n \"--launch-options\",\n \"{\\\"args\\\":[\\\"--use-gl=swiftshader\\\",\\\"--enable-webgl\\\",\\\"--ignore-gpu-blocklist\\\"]}\"\n ]\n }\n }\n}\n```\n\nKey flags:\n- `--headed` \u2014 visible browser (required for GPU rendering)\n- `--use-gl=swiftshader` \u2014 software GPU fallback for environments without a physical GPU\n- `--enable-webgl` + `--ignore-gpu-blocklist` \u2014 ensure WebGL is available\n[PHOENIX-SDK-END]";
1
+ export declare const sdkContent = "[PHOENIX-SDK-START]\n## Phoenix Configurator Project\n\nDeclarative 3D product configurator built with Phoenix SDK. Domain model defined in YAML, custom logic in TypeScript.\n\n## Build Commands\n- `pnpm phoenix build` \u2014 Full production build\n- `pnpm phoenix dev` \u2014 Development mode with hot reload\n- `pnpm phoenix sync` \u2014 Sync generated files without full build\n\n## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)\n\n## Project Structure\n- `spec/` \u2014 Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` \u2014 Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/invariants/` \u2014 Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` \u2014 Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` \u2014 ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` \u2014 Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n - A layout element named `ConfiguratorLayout` replaces everything the built-in layout renders for a loaded configuration, the finalize page included, so prefer arranging the layout in the spec; when you register it, mount `LayoutSlots.SharedCanvas` (from `@salsita-ai/sdk/configurator`) in it, or the app loader stays on screen\n- `src/handlers/` \u2014 Event & lifecycle handlers\n- `src/webhooks/` \u2014 Server-side webhook handlers (`phx.webhooks.*Builder`)\n- `src/migrations/` \u2014 Schema version migrations (v*.ts)\n- `src/locales/` \u2014 Locale catalogs (authored .po sources; compiled .ts, do not edit)\n- `src/admin/` \u2014 Admin interface (mirrors main src/ structure)\n- `src/_shared/` \u2014 Shared utilities (NOT auto-imported, requires explicit imports)\n- `.phoenix/` \u2014 Auto-generated files (DO NOT EDIT)\n- `public/` \u2014 Static assets (3D models, textures, images, HDRI maps, fonts)\n- `assets/` \u2014 Uploadable resources (PDF templates, email assets)\n\n## Architecture Principles\n- YAML-first: 99% of configuration in spec/*.yaml, custom code is last resort\n- ECS pattern: entities (domain objects) + components (behavior/UI) + systems (SDK runtime)\n- Reactive state: immutable domain state flows through RxJS pipelines\n- Data binding: `$read` (read-only), `$write` (write-only), `$bind` (bidirectional) connect components to domain\n- memoEval: all component implementations must use memoEval for stable object references\n\n## Key Patterns\n- Expressions = computed properties on entities (prefix: `$`), implemented per-entity in src/expressions/\n- Invariants = validation rules returning violations, static or dynamic\n- Transformers = auto-fixers maintaining consistency after state changes\n- Components defined in YAML with `$read`/`$bind` bindings, or custom in src/components/ using attachComponent builder\n- Webhooks = server-side finalization tasks (PDF, email, CSV, image rendering)\n- Filters = contextual component activation via navigationStates, viewStates, modes, selectedEntityIds\n\n## File Conventions\n- Components: PascalCase (.tsx)\n- Utilities: kebab-case (.ts)\n- Expressions: entity-name.ts\n- Migrations: v*.ts (sequential)\n- Specs: kebab-case.yaml\n- Underscore folders (_shared/, _utils/) are NOT auto-imported\n\n## Export Rules\nAll files in src/expressions/, src/invariants/, src/transformers/, src/components/, src/handlers/, src/webhooks/ MUST use default exports. Can be a single item or an array. Named exports are ignored by the SDK auto-import system.\n\n## Webhook Membership\n- User-authored components, admin components, and handlers are frontend-only by default.\n- A handler that registers `createMapPublishedRevisionDataHandler`, `createMapPublishedChunkedDataHandler`, `createDataRowValidatorHandler`, or `createSheetValidatorHandler` is included in the webhook automatically.\n- To include another component or handler in the webhook, put `'use webhook'` as its first statement (leading comments are allowed).\n- A webhook-included file and its runtime local-import closure must not import browser SDK entrypoints (`application`, `admin`, `configurator`, `editor`, `react`, `ui`) or style/font/image assets. Spec parsing reports the unsafe import and inclusion reason as a diagnostic.\n- Keep browser rendering in an unpinned file. Move shared server-safe logic into a separate module when both frontend and webhook code need it.\n\n## Do Not Edit\n- `.phoenix/` directory \u2014 completely regenerated on each build\n- `tsconfig.json`, `eslint.config.js`, `prettier.config.js`, `.prettierignore`, `.linguirc`, `.nvmrc`\n- `src/locales/` .ts files \u2014 compiled from .po files\n\n## Code Review\nUse `/review` command to review code changes before committing.\n\n## SDK Documentation\n\nAlways search SDK docs for relevant examples before implementing Phoenix features.\n\n### Commands\n- `pnpm phoenix docs` \u2014 Full documentation index with descriptions\n- `pnpm phoenix docs -s <term>` \u2014 Search all doc content and metadata (case-insensitive)\n- `pnpm phoenix docs --dir` \u2014 Print the absolute docs directory for grep or ripgrep\n- `pnpm phoenix docs -r <path>` \u2014 Read specific doc (raw text to stdout)\n- `pnpm phoenix docs -c <category>` \u2014 List docs in a category\n- `pnpm phoenix docs -l` \u2014 List all doc paths with titles\n\n### 3D Asset Inspection\n\nRun `pnpm phoenix inspect:assets` to discover all glTF/GLB files in `public/` and get a summary table. Use `--file <path>` for detailed single-file inspection.\n\n**When to use:** before writing YAML/code that references objectName, materialsToOverride, morphTargetInfluences, or object positioning.\n\n**What it shows per node:**\n- Name, type (Mesh/Light/Camera/Empty), children\n- Transform: `pos=`, `rot=`, `scale=` (only non-default values shown)\n- Per-node morph targets: `morphs=Width,Height`\n- Bounding box: `bounds=WxHxD` (width x height x depth in meters)\n- Origin placement: `origin=center`, `bottom-center`, `top-center`, `bottom-corner`, etc. with numerical offset\n\n**Use cases:**\n- Find exact node names for `objectName` in scene entity components\n- Find material names for `materialsToOverride`\n- Find morph target names for `morphTargetInfluences`\n- Check model dimensions (bounds) for positioning, dimension indicators, or invariants\n- Check origin placement to understand how models anchor (center vs bottom-center)\n- Use `--json` for programmatic access to all data\n\n**Flags:** `--objects`, `--materials`, `--morphs`, `--animations`, `--json`\n\n### Screenshot CLI\n\nCapture 3D canvas screenshots from a running dev server via `pnpm phoenix screenshot`.\n\n**Prerequisites:**\n1. `phoenix dev` must be running (starts the WebSocket server on port 3020)\n2. Configurator must be open in a browser (the browser does the actual rendering)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (default: `./screenshot.png`)\n- `--width, -w` \u2014 Width in pixels (default: 1920)\n- `--height` \u2014 Height in pixels (default: 1080)\n- `--format, -f` \u2014 Image format: PNG or JPEG (default: PNG)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example workflow:**\n1. Start dev server: `pnpm phoenix dev`\n2. Open configurator in browser (or via Playwright MCP)\n3. Take screenshot: `pnpm phoenix screenshot -o ./render.png -w 2560 --height 1440`\n\n**Use cases:** visual regression testing, generating product images, debugging 3D renders\n\n### Inspect: State\n\nGet the current editor runtime state as JSON via `pnpm phoenix inspect:state`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--sections, -s` \u2014 Comma-separated: entities, navigation, validation (default: all)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Example:** `pnpm phoenix inspect:state -o ./state.json -s entities,navigation`\n\n**Lifecycle status:** Always included in response. Shows which systems are ready:\n- `domainLoaded` \u2014 domain data loaded\n- `domainContextReady` \u2014 domain context initialized (entities available)\n- `configuratorReady` \u2014 3D configurator initialized\n- `sessionAuthenticated` \u2014 session service active\n- `editorMode` \u2014 editor mode enabled\n\n**Tips:** Use `--sections` to limit payload size. Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:state | head -50`).\n\n**Use cases:** AI agent context, debugging entity state, inspecting navigation/validation\n\n### Inspect: Data\n\nGet the current editor context data as JSON via `pnpm phoenix inspect:data`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** publishedData, frontendData, backendData, sessionData, accessData, webComponentProperties\n\n**Example:** `pnpm phoenix inspect:data -o ./data.json`\n\n**Tips:** Pipe through `head`/`tail` for partial output (e.g., `pnpm phoenix inspect:data | head -30`).\n\n**Use cases:** AI agent context, debugging published/session/access data\n\n### Inspect: Scene\n\nGet the current Three.js scene graph as JSON via `pnpm phoenix inspect:scene`.\n\n**Prerequisites:** same as screenshot (dev server running + browser open)\n\n**Options:**\n- `--output, -o` \u2014 Output file path (prints to stdout if omitted)\n- `--pretty` \u2014 Pretty-print JSON (default: true)\n- `--port` \u2014 WebSocket server port (default: 3020)\n\n**Returns:** Recursive scene tree with per-node: name, type, visible, position, rotation, scale, userData (entityId), and for meshes: geometry name, bounding box, material properties (color, metalness, roughness, opacity, textures), morph target influences. Lights include color, intensity, and type-specific properties.\n\n**Example:** `pnpm phoenix inspect:scene -o ./scene.json`\n\n**Tips:** Scene graphs can be large. Pipe through `head`/`tail` for partial output.\n\n**Use cases:** AI agent context, debugging 3D scene layout, inspecting materials and lighting\n\n### Key Docs\n- `docs/phoenix/getting-started.mdx` \u2014 Setup, prerequisites, first project\n- `docs/phoenix/quickstart.mdx` \u2014 End-to-end tutorial building a configurator\n- `docs/phoenix/domain-model.mdx` \u2014 Entities, attributes, relations, specs\n- `docs/phoenix/components.mdx` \u2014 ECS pattern, YAML components, custom components\n- `docs/phoenix/project-structure.mdx` \u2014 Files, folders, conventions\n- `docs/phoenix/best-practices.mdx` \u2014 YAML-first, code patterns, common pitfalls\n- `docs/phoenix/state-management.mdx` \u2014 Reactive state, RxJS pipelines, data flow\n- `docs/phoenix/expression-context.mdx` \u2014 Expression API, context object, helpers\n- `docs/phoenix/webhooks.mdx` \u2014 Server-side finalization workflows\n- `docs/phoenix/finalization.mdx` \u2014 Finalization system, PDF/email/CSV generation\n- `docs/phoenix/migrations.mdx` \u2014 Schema versioning, migration files\n\n### Agent Workflow\n1. Find relevant docs by content: `pnpm phoenix docs -s \"camera\"`\n2. Read matching doc: `pnpm phoenix docs -r docs/3d-scene/cameras/transitions.mdx`\n3. Search within a doc: `pnpm phoenix docs -r <path> | grep \"example\"`\n4. Search titles only as a fallback: `pnpm phoenix docs -l | grep \"camera\"`\n5. Search generated files directly when needed: `grep -rn \"camera\" \"$(pnpm phoenix docs --dir)\"`\n6. Browse a topic area: `pnpm phoenix docs -c \"Layouts\"`\n\n### Playwright MCP Setup (for AI agents)\n\nTo interact with the 3D configurator in a browser, Playwright MCP needs GPU-enabled flags for WebGL rendering. Add to `~/.claude/.mcp.json`:\n\n```json\n{\n \"mcpServers\": {\n \"playwright\": {\n \"command\": \"npx\",\n \"args\": [\n \"@playwright/mcp@latest\",\n \"--headed\",\n \"--launch-options\",\n \"{\\\"args\\\":[\\\"--use-gl=swiftshader\\\",\\\"--enable-webgl\\\",\\\"--ignore-gpu-blocklist\\\"]}\"\n ]\n }\n }\n}\n```\n\nKey flags:\n- `--headed` \u2014 visible browser (required for GPU rendering)\n- `--use-gl=swiftshader` \u2014 software GPU fallback for environments without a physical GPU\n- `--enable-webgl` + `--ignore-gpu-blocklist` \u2014 ensure WebGL is available\n[PHOENIX-SDK-END]";
@@ -21,6 +21,7 @@ Declarative 3D product configurator built with Phoenix SDK. Domain model defined
21
21
  - \`src/transformers/\` — Automatic state fixers (\`phx.frontend.transformerBuilder\`)
22
22
  - \`src/components/\` — ECS system components (\`phx.domain.attachComponent.withEntity()\`)
23
23
  - \`src/elements/\` — Page-level React components (\`phx.frontend.createCustomPhoenixLayoutElement()\`)
24
+ - A layout element named \`ConfiguratorLayout\` replaces everything the built-in layout renders for a loaded configuration, the finalize page included, so prefer arranging the layout in the spec; when you register it, mount \`LayoutSlots.SharedCanvas\` (from \`@salsita-ai/sdk/configurator\`) in it, or the app loader stays on screen
24
25
  - \`src/handlers/\` — Event & lifecycle handlers
25
26
  - \`src/webhooks/\` — Server-side webhook handlers (\`phx.webhooks.*Builder\`)
26
27
  - \`src/migrations/\` — Schema version migrations (v*.ts)
@@ -2,15 +2,15 @@ import{fileHeader as n}from"./file-header.js";import{generateImports as i,getImp
2
2
  ${n.join(",\n ")}
3
3
  )`,a=(n,i)=>{if(0===n.length)return"{}";let o=n.map((n,o)=>{let t=e(n);return null===t?null:` ${t}: ${i[o]}`}).filter(n=>null!==n);return 0===o.length?"{}":`{
4
4
  ${o.join(",\n")}
5
- }`};export const generateIndexDomainFile=(s={})=>{let{includeMigrations:r=!0,includeI18n:m=!0,expressionsFiles:d=[],invariantsFiles:l=[],adminExpressionsFiles:p=[],adminInvariantsFiles:c=[],migrationsFiles:u=[],adminMigrationsFiles:g=[]}=s,x=(n,i)=>`${i?"adminMigrateToV":"migrateToV"}${e(n)}`,$=u.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} } from '${t}'`}).join("\n"),f=g.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} as adminMigrateToV${i} } from '${t}'`}).join("\n"),h=u.map(n=>x(n,!1)),A=g.map(n=>x(n,!0)),E=u.length>0,j=g.length>0,y=i(d,"expressions"),D=i(l,"invariants"),V=i(p,"adminExpressions"),v=i(c,"adminInvariants"),M=o(d,"expressions"),B=o(l,"invariants"),I=o(p,"adminExpressions"),F=o(c,"adminInvariants"),w=t(B),b=t(M),R=t(F),T=t(I),C=[y,D,V,v].filter(Boolean).join("\n"),P=[$,f].filter(Boolean).join("\n"),S=d.length>1||l.length>1||p.length>1||c.length>1,k=a(u,h),q=a(g,A),z=E?`
5
+ }`};export const generateIndexDomainFile=(s={})=>{let{includeMigrations:r=!0,includeI18n:m=!0,expressionsFiles:d=[],invariantsFiles:l=[],adminExpressionsFiles:p=[],adminInvariantsFiles:c=[],migrationsFiles:u=[],adminMigrationsFiles:x=[]}=s,g=(n,i)=>`${i?"adminMigrateToV":"migrateToV"}${e(n)}`,$=u.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} } from '${t}'`}).join("\n"),h=x.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} as adminMigrateToV${i} } from '${t}'`}).join("\n"),f=u.map(n=>g(n,!1)),A=x.map(n=>g(n,!0)),E=u.length>0,j=x.length>0,y=i(d,"expressions"),D=i(l,"invariants"),V=i(p,"adminExpressions"),v=i(c,"adminInvariants"),M=o(d,"expressions"),I=o(l,"invariants"),F=o(p,"adminExpressions"),B=o(c,"adminInvariants"),w=t(I),b=t(M),R=t(B),T=t(F),C=[y,D,V,v].filter(Boolean).join("\n"),P=[$,h].filter(Boolean).join("\n"),S=d.length>1||l.length>1||p.length>1||c.length>1,k=a(u,f),q=a(x,A),z=E?`
6
6
  const migrations = ${k}
7
7
 
8
- const migrate = MigrateFunctionBuilder.fromVersions(modelVersions).to(modelVersion).using(migrations).build()`:"",G=j?`
8
+ const migrate = createMigrateFunction(modelVersions, modelVersion, migrations)`:"",G=j?`
9
9
  const adminMigrations = ${q}
10
10
 
11
- const migrateAdmin = MigrateFunctionBuilder.fromVersions(adminModelVersions).to(adminModelVersion).using(adminMigrations).build()`:"";return`${n}
11
+ const migrateAdmin = createMigrateFunction(adminModelVersions, adminModelVersion, adminMigrations)`:"";return`${n}
12
12
  ${S?"import merge from 'lodash-es/merge.js'\n":""}
13
- import { type AliasedExpressions${r&&(E||j)?", MigrateFunctionBuilder":""} } from '@salsita-ai/sdk/domain'
13
+ import { type AliasedExpressions${r&&(E||j)?", createMigrateFunction":""} } from '@salsita-ai/sdk/domain'
14
14
 
15
15
  ${m?"import { createI18n } from './i18n.js'":""}
16
16
  import { adminDomainBuilder, adminInvariantBuilder } from './domain/admin-implementation.js'
@@ -6,10 +6,10 @@ export interface InitCommandProps {
6
6
  }
7
7
  /**
8
8
  * Starts a Phoenix project: writes a `package.json` that depends on this CLI's SDK version when the folder has none,
9
- * the starter spec and the pnpm settings the first install needs, and switches the project to the application-spec
10
- * pipeline. It touches no server and asks
11
- * nothing: the starter spec names the default project of whichever workspace the developer signs in to, and
12
- * everything else is generated by sync or the build.
9
+ * the starter spec and the pnpm settings the first install needs, adds the `dev`, `build`, `deploy`, `check` and `fix`
10
+ * scripts the project does not have yet, and switches the project to the application-spec pipeline. It touches no
11
+ * server and asks nothing: the starter spec names the default project of whichever workspace the developer signs in
12
+ * to, and everything else is generated by sync or the build.
13
13
  *
14
14
  * Refuses when a `spec/` folder exists, and when an existing `package.json` does not depend on the SDK.
15
15
  */
@@ -1 +1 @@
1
- import{existsSync as e}from"fs";import{mkdir as n,readFile as t,writeFile as i}from"fs/promises";import{basename as o,dirname as r,join as p}from"path";import{ensureWorkspaceInstallSettings as a}from"../utils/index.js";import{starterSpecFiles as s}from"./init-starter-spec.js";let c="@salsita-ai/sdk",l=async e=>{let n=`Install the SDK first (\`pnpm add ${c}\`), then rerun \`pnpm phoenix init\`.`,i=JSON.parse(await t(e,"utf-8"));if("object"!=typeof i||null===i||Array.isArray(i))throw Error(`phoenix init could not read package.json because it is not a JSON object. ${n}`);if(!["dependencies","devDependencies"].some(e=>{let n=Reflect.get(i,e);return"object"==typeof n&&null!==n&&c in n}))throw Error(`phoenix init found no ${c} dependency in package.json. ${n}`);return{...i}},d=async e=>{for(let t of s){let o=p(e,t.path);await n(r(o),{recursive:!0}),await i(o,t.content)}},m=async(e,n)=>{let t=n.phoenix;await i(e,JSON.stringify({...n,phoenix:{..."object"==typeof t&&null!==t?t:{},applicationFlow:!0}},null,2)+"\n")};export const runInitCommand=async(t,{logger:i})=>{var r,s;let f,u=t.projectRoot??process.cwd(),h=p(u,"package.json");if(e(p(u,"spec")))throw Error("phoenix init found an existing spec/ folder. init only starts new projects, and writing a starter spec would overwrite or mix with the existing one. To update an existing project, run `pnpm phoenix sync`; to start over, run init in an empty project folder.");let w=e(h)?await l(h):(r=u,s=t.sdkVersion,{name:(f=o(r).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[._-]+|[-]+$/g,"")).length>0?f:"phoenix-configurator",private:!0,type:"module",dependencies:{[c]:s},devDependencies:{"@lingui/cli":"5.9.5","@lingui/swc-plugin":"5.11.0"}});i.step(`Writing the starter project to ${u}`),await n(u,{recursive:!0}),await d(u),await m(h,w),a(u),i.success(`Phoenix project created in ${u}.`),i.info("\nNext steps, in the project folder:\n pnpm install\n pnpm phoenix sync\n pnpm phoenix login <workspace>\n pnpm phoenix dev\n pnpm phoenix deploy\n\nDeveloping against a Studio development environment instead? Paste its .env block into .env before phoenix dev.")};
1
+ import{existsSync as e}from"fs";import{mkdir as n,readFile as t,writeFile as i}from"fs/promises";import{basename as o,dirname as r,join as p}from"path";import{ensureWorkspaceInstallSettings as s}from"../utils/index.js";import{starterSpecFiles as a}from"./init-starter-spec.js";let c="@salsita-ai/sdk",l={dev:"phoenix dev",build:"phoenix build",deploy:"phoenix deploy",check:"phoenix check",fix:"phoenix fix"},d=async e=>{let n=`Install the SDK first (\`pnpm add ${c}\`), then rerun \`pnpm phoenix init\`.`,i=JSON.parse(await t(e,"utf-8"));if("object"!=typeof i||null===i||Array.isArray(i))throw Error(`phoenix init could not read package.json because it is not a JSON object. ${n}`);if(!["dependencies","devDependencies"].some(e=>{let n=Reflect.get(i,e);return"object"==typeof n&&null!==n&&c in n}))throw Error(`phoenix init found no ${c} dependency in package.json. ${n}`);return{...i}},h=async e=>{for(let t of a){let o=p(e,t.path);await n(r(o),{recursive:!0}),await i(o,t.content)}},f=async(e,n)=>{let t=n.phoenix,o=n.scripts,r="object"==typeof o&&null!==o?o:{},p=Object.fromEntries(Object.entries(l).filter(([e])=>!(e in r)));await i(e,JSON.stringify({...n,scripts:{...r,...p},phoenix:{..."object"==typeof t&&null!==t?t:{},applicationFlow:!0}},null,2)+"\n")};export const runInitCommand=async(t,{logger:i})=>{var r,a;let u,m=t.projectRoot??process.cwd(),x=p(m,"package.json");if(e(p(m,"spec")))throw Error("phoenix init found an existing spec/ folder. init only starts new projects, and writing a starter spec would overwrite or mix with the existing one. To update an existing project, run `pnpm phoenix sync`; to start over, run init in an empty project folder.");let w=e(x)?await d(x):(r=m,a=t.sdkVersion,{name:(u=o(r).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[._-]+|[-]+$/g,"")).length>0?u:"phoenix-configurator",private:!0,type:"module",scripts:l,dependencies:{[c]:a},devDependencies:{"@lingui/cli":"5.9.5","@lingui/swc-plugin":"5.11.0"}});i.step(`Writing the starter project to ${m}`),await n(m,{recursive:!0}),await h(m),await f(x,w),s(m),i.success(`Phoenix project created in ${m}.`),i.info("\nNext steps, in the project folder:\n pnpm install\n pnpm phoenix sync\n pnpm phoenix login <workspace>\n pnpm phoenix dev\n pnpm phoenix deploy\n\nDeveloping against a Studio development environment instead? Paste its .env block into .env before phoenix dev.")};
@@ -1 +1 @@
1
- import{readFile as t,writeFile as e}from"fs/promises";import{globby as o}from"globby";import{resolve as r}from"path";import*as i from"prettier";let a=["**/node_modules/**","**/dist/**","**/.git/**","**/webhooks/index.ts`","**/frontend-configurator.ts`","**/frontend-admin.ts`","**/frontend-embedded-admin.ts`","pnpm-lock.yaml",".linguirc"];export const formatFiles=async(n,f)=>{let{logger:l}=f,s=await o("."===n?"**/*":n,{gitignore:!0,ignore:a}),c=0;for(let o of s)try{let a=r(o),n=await t(a,"utf-8"),f=await i.resolveConfig(a);if((await i.getFileInfo(a)).ignored)continue;let l=await i.format(n,{...f,filepath:a});l!==n&&(await e(a,l,"utf-8"),c++)}catch(t){}c>0&&l.info(`Formatted ${c} file${1!==c?"s":""}`)};export const checkFiles=async(e,n)=>{let{logger:f}=n,l=await o("."===e?"**/*":e,{gitignore:!0,ignore:a}),s=[];for(let e of l)try{let o=r(e),a=await t(o,"utf-8"),n=await i.resolveConfig(o);if((await i.getFileInfo(o)).ignored)continue;await i.check(a,{...n,filepath:o})||s.push(e)}catch(t){}return!(s.length>0)||(f.error(`Found ${s.length} unformatted file${1!==s.length?"s":""}:`),s.forEach(t=>{console.error(` - ${t}`)}),!1)};
1
+ import{readFile as t,writeFile as e}from"fs/promises";import{globby as o}from"globby";import{resolve as i}from"path";import*as r from"prettier";let a=["**/node_modules/**","**/dist/**","**/.git/**","**/.phoenix/**","**/locales/*/*.ts","pnpm-lock.yaml",".linguirc"];export const formatFiles=async(n,l)=>{let{logger:f}=l,s=await o("."===n?"**/*":n,{gitignore:!0,ignore:a}),c=0;for(let o of s)try{let a=i(o),n=await t(a,"utf-8"),l=await r.resolveConfig(a);if((await r.getFileInfo(a)).ignored)continue;let f=await r.format(n,{...l,filepath:a});f!==n&&(await e(a,f,"utf-8"),c++)}catch(t){}c>0&&f.info(`Formatted ${c} file${1!==c?"s":""}`)};export const checkFiles=async(e,n)=>{let{logger:l}=n,f=await o("."===e?"**/*":e,{gitignore:!0,ignore:a}),s=[];for(let e of f)try{let o=i(e),a=await t(o,"utf-8"),n=await r.resolveConfig(o);if((await r.getFileInfo(o)).ignored)continue;await r.check(a,{...n,filepath:o})||s.push(e)}catch(t){}return!(s.length>0)||(l.error(`Found ${s.length} unformatted file${1!==s.length?"s":""}:`),s.forEach(t=>{console.error(` - ${t}`)}),!1)};
@@ -381,7 +381,7 @@ export declare function createApplicationRuntimeSlices<State extends Application
381
381
  selectViewStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
382
382
  selectToolStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
383
383
  selectExportStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
384
- selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory>;
384
+ selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").AnyCreateTransformersFactory>;
385
385
  selectLatestLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData | null>;
386
386
  selectLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData>;
387
387
  selectInitialDomainState: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").DomainState<any>>;
@@ -423,7 +423,7 @@ export declare function createApplicationRuntimeSlices<State extends Application
423
423
  getViewStates: () => readonly string[];
424
424
  getToolStates: () => readonly string[];
425
425
  getExportStates: () => readonly string[];
426
- getCreateTransformers: () => import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory | undefined;
426
+ getCreateTransformers: () => import("#package/domain").AnyCreateTransformersFactory | undefined;
427
427
  getLoadedData: () => import("#package/domain").ConfiguratorLoadedData;
428
428
  getInitialDomainState: () => import("#package/domain").DomainState<any>;
429
429
  getFrontendData: () => Record<string, unknown>;
@@ -442,9 +442,9 @@ export declare function createApplicationRuntimeSlices<State extends Application
442
442
  getSnappingProjections: () => import("#package/domain").AnySnappingProjections;
443
443
  getConstraintProjections: () => import("#package/domain").AnyConstraintProjections;
444
444
  getProjectedEntitiesProjections: () => import("#package/domain").AnyProjectedEntitiesProjections;
445
- getStoreSystem: () => import("../../../domain/domain-context/store-system/store-system.js").AnyStoreSystem;
446
- getNavigationSystem: () => import("../../../domain/domain-context/navigation-system/navigation-system.js").AnyNavigationSystem;
447
- getUndoSystem: () => import("../../../domain/domain-context/undo-system.js").AnyUndoSystem;
445
+ getStoreSystem: () => import("#package/domain").AnyStoreSystem;
446
+ getNavigationSystem: () => import("#package/domain").AnyNavigationSystem;
447
+ getUndoSystem: () => import("#package/domain").AnyUndoSystem;
448
448
  getRecipeCookerSystem: () => import("#package/domain").AnyRecipeCookerSystem;
449
449
  getActionSystem: () => import("#package/domain").AnyActionSystem;
450
450
  getBlenderProjections: () => import("#package/domain").AnyBlenderProjections;
@@ -490,7 +490,7 @@ export declare function createApplicationRuntimeSlices<State extends Application
490
490
  selectViewStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
491
491
  selectToolStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
492
492
  selectExportStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
493
- selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory>;
493
+ selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").AnyCreateTransformersFactory>;
494
494
  selectLatestLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData | null>;
495
495
  selectLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData>;
496
496
  selectInitialDomainState: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").DomainState<any>>;
@@ -532,7 +532,7 @@ export declare function createApplicationRuntimeSlices<State extends Application
532
532
  getViewStates: () => readonly string[];
533
533
  getToolStates: () => readonly string[];
534
534
  getExportStates: () => readonly string[];
535
- getCreateTransformers: () => import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory | undefined;
535
+ getCreateTransformers: () => import("#package/domain").AnyCreateTransformersFactory | undefined;
536
536
  getLoadedData: () => import("#package/domain").ConfiguratorLoadedData;
537
537
  getInitialDomainState: () => import("#package/domain").DomainState<any>;
538
538
  getFrontendData: () => Record<string, unknown>;
@@ -551,9 +551,9 @@ export declare function createApplicationRuntimeSlices<State extends Application
551
551
  getSnappingProjections: () => import("#package/domain").AnySnappingProjections;
552
552
  getConstraintProjections: () => import("#package/domain").AnyConstraintProjections;
553
553
  getProjectedEntitiesProjections: () => import("#package/domain").AnyProjectedEntitiesProjections;
554
- getStoreSystem: () => import("../../../domain/domain-context/store-system/store-system.js").AnyStoreSystem;
555
- getNavigationSystem: () => import("../../../domain/domain-context/navigation-system/navigation-system.js").AnyNavigationSystem;
556
- getUndoSystem: () => import("../../../domain/domain-context/undo-system.js").AnyUndoSystem;
554
+ getStoreSystem: () => import("#package/domain").AnyStoreSystem;
555
+ getNavigationSystem: () => import("#package/domain").AnyNavigationSystem;
556
+ getUndoSystem: () => import("#package/domain").AnyUndoSystem;
557
557
  getRecipeCookerSystem: () => import("#package/domain").AnyRecipeCookerSystem;
558
558
  getActionSystem: () => import("#package/domain").AnyActionSystem;
559
559
  getBlenderProjections: () => import("#package/domain").AnyBlenderProjections;
@@ -1041,7 +1041,7 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1041
1041
  selectViewStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1042
1042
  selectToolStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1043
1043
  selectExportStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1044
- selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory>;
1044
+ selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").AnyCreateTransformersFactory>;
1045
1045
  selectLatestLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData | null>;
1046
1046
  selectLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData>;
1047
1047
  selectInitialDomainState: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").DomainState<any>>;
@@ -1083,7 +1083,7 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1083
1083
  getViewStates: () => readonly string[];
1084
1084
  getToolStates: () => readonly string[];
1085
1085
  getExportStates: () => readonly string[];
1086
- getCreateTransformers: () => import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory | undefined;
1086
+ getCreateTransformers: () => import("#package/domain").AnyCreateTransformersFactory | undefined;
1087
1087
  getLoadedData: () => import("#package/domain").ConfiguratorLoadedData;
1088
1088
  getInitialDomainState: () => import("#package/domain").DomainState<any>;
1089
1089
  getFrontendData: () => Record<string, unknown>;
@@ -1102,9 +1102,9 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1102
1102
  getSnappingProjections: () => import("#package/domain").AnySnappingProjections;
1103
1103
  getConstraintProjections: () => import("#package/domain").AnyConstraintProjections;
1104
1104
  getProjectedEntitiesProjections: () => import("#package/domain").AnyProjectedEntitiesProjections;
1105
- getStoreSystem: () => import("../../../domain/domain-context/store-system/store-system.js").AnyStoreSystem;
1106
- getNavigationSystem: () => import("../../../domain/domain-context/navigation-system/navigation-system.js").AnyNavigationSystem;
1107
- getUndoSystem: () => import("../../../domain/domain-context/undo-system.js").AnyUndoSystem;
1105
+ getStoreSystem: () => import("#package/domain").AnyStoreSystem;
1106
+ getNavigationSystem: () => import("#package/domain").AnyNavigationSystem;
1107
+ getUndoSystem: () => import("#package/domain").AnyUndoSystem;
1108
1108
  getRecipeCookerSystem: () => import("#package/domain").AnyRecipeCookerSystem;
1109
1109
  getActionSystem: () => import("#package/domain").AnyActionSystem;
1110
1110
  getBlenderProjections: () => import("#package/domain").AnyBlenderProjections;
@@ -1150,7 +1150,7 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1150
1150
  selectViewStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1151
1151
  selectToolStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1152
1152
  selectExportStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
1153
- selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory>;
1153
+ selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").AnyCreateTransformersFactory>;
1154
1154
  selectLatestLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData | null>;
1155
1155
  selectLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData>;
1156
1156
  selectInitialDomainState: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").DomainState<any>>;
@@ -1192,7 +1192,7 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1192
1192
  getViewStates: () => readonly string[];
1193
1193
  getToolStates: () => readonly string[];
1194
1194
  getExportStates: () => readonly string[];
1195
- getCreateTransformers: () => import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory | undefined;
1195
+ getCreateTransformers: () => import("#package/domain").AnyCreateTransformersFactory | undefined;
1196
1196
  getLoadedData: () => import("#package/domain").ConfiguratorLoadedData;
1197
1197
  getInitialDomainState: () => import("#package/domain").DomainState<any>;
1198
1198
  getFrontendData: () => Record<string, unknown>;
@@ -1211,9 +1211,9 @@ declare const createApplicationRuntimeImpl: <EXTENSIONS extends readonly AnyAppl
1211
1211
  getSnappingProjections: () => import("#package/domain").AnySnappingProjections;
1212
1212
  getConstraintProjections: () => import("#package/domain").AnyConstraintProjections;
1213
1213
  getProjectedEntitiesProjections: () => import("#package/domain").AnyProjectedEntitiesProjections;
1214
- getStoreSystem: () => import("../../../domain/domain-context/store-system/store-system.js").AnyStoreSystem;
1215
- getNavigationSystem: () => import("../../../domain/domain-context/navigation-system/navigation-system.js").AnyNavigationSystem;
1216
- getUndoSystem: () => import("../../../domain/domain-context/undo-system.js").AnyUndoSystem;
1214
+ getStoreSystem: () => import("#package/domain").AnyStoreSystem;
1215
+ getNavigationSystem: () => import("#package/domain").AnyNavigationSystem;
1216
+ getUndoSystem: () => import("#package/domain").AnyUndoSystem;
1217
1217
  getRecipeCookerSystem: () => import("#package/domain").AnyRecipeCookerSystem;
1218
1218
  getActionSystem: () => import("#package/domain").AnyActionSystem;
1219
1219
  getBlenderProjections: () => import("#package/domain").AnyBlenderProjections;
@@ -37,7 +37,7 @@ export declare const useDomainContextSelectors: () => {
37
37
  selectViewStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
38
38
  selectToolStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
39
39
  selectExportStates: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, readonly string[]>;
40
- selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory>;
40
+ selectCreateTransformers: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, undefined> | import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").AnyCreateTransformersFactory>;
41
41
  selectLatestLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData | null>;
42
42
  selectLoadedData: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").ConfiguratorLoadedData>;
43
43
  selectInitialDomainState: import("@salsita-ai/common/utils").Selector<import("#package/domain").DomainContextSelectorState, import("#package/domain").DomainState<any>>;
@@ -79,7 +79,7 @@ export declare const useDomainContextSelectors: () => {
79
79
  getViewStates: () => readonly string[];
80
80
  getToolStates: () => readonly string[];
81
81
  getExportStates: () => readonly string[];
82
- getCreateTransformers: () => import("../../../domain/domain-context/store-system/store-system.js").AnyCreateTransformersFactory | undefined;
82
+ getCreateTransformers: () => import("#package/domain").AnyCreateTransformersFactory | undefined;
83
83
  getLoadedData: () => import("#package/domain").ConfiguratorLoadedData;
84
84
  getInitialDomainState: () => import("#package/domain").DomainState<any>;
85
85
  getFrontendData: () => Record<string, unknown>;
@@ -98,9 +98,9 @@ export declare const useDomainContextSelectors: () => {
98
98
  getSnappingProjections: () => import("#package/domain").AnySnappingProjections;
99
99
  getConstraintProjections: () => import("#package/domain").AnyConstraintProjections;
100
100
  getProjectedEntitiesProjections: () => import("#package/domain").AnyProjectedEntitiesProjections;
101
- getStoreSystem: () => import("../../../domain/domain-context/store-system/store-system.js").AnyStoreSystem;
102
- getNavigationSystem: () => import("../../../domain/domain-context/navigation-system/navigation-system.js").AnyNavigationSystem;
103
- getUndoSystem: () => import("../../../domain/domain-context/undo-system.js").AnyUndoSystem;
101
+ getStoreSystem: () => import("#package/domain").AnyStoreSystem;
102
+ getNavigationSystem: () => import("#package/domain").AnyNavigationSystem;
103
+ getUndoSystem: () => import("#package/domain").AnyUndoSystem;
104
104
  getRecipeCookerSystem: () => import("#package/domain").AnyRecipeCookerSystem;
105
105
  getActionSystem: () => import("#package/domain").AnyActionSystem;
106
106
  getBlenderProjections: () => import("#package/domain").AnyBlenderProjections;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salsita-ai/sdk",
3
- "version": "0.50.0-develop.9feae4851f",
3
+ "version": "0.50.0-develop.a4dde5f252",
4
4
  "description": "TypeScript SDK and CLI for building, running, and deploying Phoenix configurator applications.",
5
5
  "keywords": [
6
6
  "salsita",
@@ -292,8 +292,8 @@
292
292
  "yaml": "2.9.0",
293
293
  "yargs": "17.7.2",
294
294
  "zod": "3.25.76",
295
- "@salsita-ai/common": "0.50.0-develop.9feae4851f",
296
- "@salsita-ai/contracts": "0.50.0-develop.9feae4851f"
295
+ "@salsita-ai/contracts": "0.50.0-develop.a4dde5f252",
296
+ "@salsita-ai/common": "0.50.0-develop.a4dde5f252"
297
297
  },
298
298
  "devDependencies": {
299
299
  "@clerk/clerk-react": "5.61.8",
@@ -1 +0,0 @@
1
- export declare const generateApplicationSpecEnvCi: () => string;
@@ -1,25 +0,0 @@
1
- export const generateApplicationSpecEnvCi=()=>`# CI Environment Configuration
2
- #
3
- # This file is used to initialize environment variables in CI pipelines with mock data.
4
- # It allows the frontend and webhooks to be built without requiring actual credentials.
5
- # These values are sufficient for builds. DEPLOYMENT_ID also supports local-storage runtime;
6
- # server-backed runtime operations still require real deployment credentials.
7
- #
8
- # To use: run 'pnpm run prepare:ci' to copy this file to .env
9
-
10
- # Frontend
11
- DEPLOYMENT_ID=will-not-work-but-will-initialize
12
- SERVER_URL=http://not.valid
13
- FRONTEND_URL=http://not.valid
14
- RESOURCES_URL=http://not.valid
15
- CLERK_PUBLISHABLE_KEY=will-not-work-but-will-initialize
16
- GTM_ID=GTM-XXXXXX
17
- DATADOG_CLIENT_TOKEN=XXXXXX
18
- DATADOG_SITE=XXX
19
- SERVICE_NAME=project-template
20
-
21
- # Webhook
22
- AWS_S3_PUBLIC_RESOURCES_BUCKET=private
23
- AWS_S3_PRIVATE_RESOURCES_BUCKET=public
24
- AWS_S3_RESOURCES_REGION=eu-central-1
25
- `;
@@ -1 +0,0 @@
1
- export declare const generateApplicationSpecEnvExample: () => string;
@@ -1,94 +0,0 @@
1
- export const generateApplicationSpecEnvExample=()=>`# This file documents developer-supplied Phoenix variables. Copy the values you
2
- # need into an untracked .env; never commit .env.
3
- # phoenix dev, deployment:prepare-dev, and deployment:prepare-local write
4
- # server-generated values to .env.generated; do not maintain them here.
5
-
6
- # ============================================================================
7
- # Development environment (phoenix dev and deployment:prepare-dev)
8
- # ============================================================================
9
- # Not needed when you are signed in with phoenix login. Otherwise create a
10
- # development environment in PHX Studio and paste its block here.
11
- #
12
- # SERVER_URL=http://localhost:3000
13
- # PROJECT_SLUG=<project-slug>
14
- # ENVIRONMENT_SLUG=<development-environment-slug>
15
- # DEVELOPMENT_KEY=<development-key>
16
-
17
- # ============================================================================
18
- # Shared-server access (deployment:prepare-local and CI commands only)
19
- # ============================================================================
20
- # Ask DevOps for these values when using the legacy prepare-local or CI flows.
21
- # SERVER_URL=https://phoenix.example.com
22
- # ENVIRONMENT_API_KEY=<shared-server-api-key>
23
- # PROJECT_KEY=<shared-server-project-key>
24
- # PROJECT_SLUG=<project-slug>
25
- # ENVIRONMENT_SLUG=<environment-slug>
26
- # LAMBDA_URL=http://localhost:8080
27
-
28
- # ============================================================================
29
- # Dev Configuration (phoenix dev)
30
- # ============================================================================
31
- # Override these to run multiple projects simultaneously.
32
- # Ports auto-increment if occupied, but setting explicit values avoids surprises.
33
- #
34
- # EDITOR_WS_PORT=3020
35
- # ENABLE_EDITOR=true
36
- # Enable Lingui extraction and compilation during dev. Phoenix warns when this is disabled.
37
- # WITH_LINGUI=false
38
- # DEBUG=false
39
- # FORCE_REBUILD=false
40
- # USE_APPLICATION_SPEC=true
41
- # IS_DEV=true
42
- # A development environment keeps the assistant thread when the assistant setup
43
- # (manifest, instructions, AI settings) changes. Set to true to lock the thread
44
- # on a setup change, as every other environment does.
45
- # ASSISTANT_STRICT_THREADS=false
46
- #
47
- # Persistence mode controls how configurator state is stored.
48
- # Options: 'server' (default), 'local-storage', 'memory'
49
- # PERSISTENCE_MODE=server
50
-
51
- # deployment:prepare-dev and deployment:prepare-local output and behavior overrides:
52
- # OUT_FILE=.env.generated
53
- # SKIP_UPLOAD also applies to the deployment phoenix dev prepares at startup.
54
- # SKIP_UPLOAD=false
55
- # OVERRIDE_SCHEMA=true
56
-
57
- # ============================================================================
58
- # Project-Specific Environment Variables
59
- # ============================================================================
60
- # Additional environment variables can be defined in spec/application.yaml
61
- # under the 'env.frontend' and 'env.webhook' sections.
62
- #
63
- # These are useful for project-specific needs such as:
64
- # - Third-party API keys (e.g., salesforce)
65
- # - External service URLs
66
- # - Feature flags
67
- # - Custom configuration values
68
- #
69
- # Example in spec/application.yaml:
70
- # env:
71
- # frontend:
72
- # SALESFORCE_CLIENT_ID:
73
- # type: str
74
- # devDefault: pk_test_xxx
75
- # webhook:
76
- # SALESFORCE_CLIENT_SECRET:
77
- # type: str
78
- # SALESFORCE_REDIRECT_URI:
79
- # type: str
80
- #
81
- # These will be automatically validated and available in your code via
82
- # the generated frontend.config.ts and webhooks.config.ts files.
83
- #
84
- # IMPORTANT: If you add required custom environment variables (without defaults),
85
- # remember to also add them to .env.ci with mock values so CI builds can succeed.
86
-
87
- # ============================================================================
88
- # Generated environment
89
- # ============================================================================
90
- # Deployment variables (DEPLOYMENT_ID, RESOURCES_URL, and related values)
91
- # are auto-generated by the PHX server and written to .env.generated when you run
92
- # phoenix dev, deployment:prepare-dev, or deployment:prepare-local. Development
93
- # environment settings can be managed via PHX Studio.
94
- `;
@@ -1 +0,0 @@
1
- export declare const generateApplicationSpecPrivateAssetsReadme: () => string;
@@ -1,24 +0,0 @@
1
- export const generateApplicationSpecPrivateAssetsReadme=()=>`# Private Assets
2
-
3
- This folder contains private environment resources that will be uploaded to S3 and made available only to your webhooks with authentication.
4
-
5
- ## Usage
6
-
7
- 1. Place any private assets in this folder
8
- 2. Files uploaded here will require authentication to access
9
- 3. These assets are typically used in webhook implementations for server-side operations
10
-
11
- ## Examples
12
-
13
- - Private configuration files
14
- - Server-side resources
15
- - Blender scripts
16
-
17
- ## Deployment
18
-
19
- When you run \`pnpm run deployment:prepare-local\`, all files in this folder will be:
20
-
21
- - Uploaded to S3 with private access control
22
- - Only accessible by authenticated webhook requests
23
- - Available via signed URLs
24
- `;
@@ -1 +0,0 @@
1
- export declare const generateApplicationSpecPublicAssetsReadme: () => string;
@@ -1,24 +0,0 @@
1
- export const generateApplicationSpecPublicAssetsReadme=()=>`# Public Assets
2
-
3
- This folder contains public environment resources that will be uploaded to S3 and made available to your configurator and webhooks.
4
-
5
- ## Usage
6
-
7
- 1. Place any public assets (images, 3D models, textures, etc.) in this folder
8
- 2. Files uploaded here will be publicly accessible via S3 URLs
9
- 3. These assets can be referenced in your configurator frontend and webhook implementations
10
-
11
- ## Examples
12
-
13
- - Product images
14
- - Icons and logos
15
- - Public configuration files
16
-
17
- ## Deployment
18
-
19
- When you run \`pnpm run deployment:prepare-local\`, all files in this folder will be:
20
-
21
- - Uploaded to S3
22
- - Made publicly accessible
23
- - Available via the configured CDN/S3 URL
24
- `;
@@ -1 +0,0 @@
1
- export declare const generateApplicationSpecReadme: (projectName?: string) => string;