create-flowdular 0.2.3 → 0.2.5

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 (271) hide show
  1. package/README.md +11 -0
  2. package/agent-template/.agents/skills/agent-tool-design/SKILL.md +203 -0
  3. package/agent-template/.agents/skills/auth-security-review/SKILL.md +90 -0
  4. package/agent-template/.agents/skills/auto-review/SKILL.md +103 -0
  5. package/agent-template/.agents/skills/bug-hunt/SKILL.md +104 -0
  6. package/agent-template/.agents/skills/business-agent-design/SKILL.md +182 -0
  7. package/agent-template/.agents/skills/cli-extension/SKILL.md +108 -0
  8. package/agent-template/.agents/skills/core-extend/SKILL.md +99 -0
  9. package/agent-template/.agents/skills/database-adapter/SKILL.md +198 -0
  10. package/agent-template/.agents/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  11. package/agent-template/.agents/skills/migration-authoring/SKILL.md +161 -0
  12. package/agent-template/.agents/skills/module-new/SKILL.md +171 -0
  13. package/agent-template/.agents/skills/module-update/SKILL.md +91 -0
  14. package/agent-template/.agents/skills/perf-audit/SKILL.md +98 -0
  15. package/agent-template/.agents/skills/release-eject-pr/SKILL.md +107 -0
  16. package/agent-template/.agents/skills/spec-approval/SKILL.md +106 -0
  17. package/agent-template/.agents/skills/test-hardening/SKILL.md +79 -0
  18. package/agent-template/.agents/skills/translations-i18n/SKILL.md +78 -0
  19. package/agent-template/.agents/skills/ux-design/SKILL.md +92 -0
  20. package/agent-template/.agents/skills/variables/SKILL.md +156 -0
  21. package/agent-template/.agents/skills/workflow-development/SKILL.md +192 -0
  22. package/agent-template/.ai/README.md +62 -0
  23. package/agent-template/.ai/agents/README.md +27 -0
  24. package/agent-template/.ai/agents/module-executor.md +36 -0
  25. package/agent-template/.ai/agents/reviewer.md +23 -0
  26. package/agent-template/.ai/agents/sandbox/agentic-engineer.md +31 -0
  27. package/agent-template/.ai/agents/sandbox/backend-engineer.md +36 -0
  28. package/agent-template/.ai/agents/sandbox/business-manager.md +23 -0
  29. package/agent-template/.ai/agents/sandbox/frontend-engineer.md +27 -0
  30. package/agent-template/.ai/agents/sandbox/ux-designer.md +23 -0
  31. package/agent-template/.ai/agents/spec-author.md +29 -0
  32. package/agent-template/.ai/blueprints/add-migration/README.md +5 -0
  33. package/agent-template/.ai/blueprints/add-migration/allowed-paths.yaml +23 -0
  34. package/agent-template/.ai/blueprints/add-migration/blueprint.json +14 -0
  35. package/agent-template/.ai/blueprints/add-migration/examples/invalid/input-destructive.json +6 -0
  36. package/agent-template/.ai/blueprints/add-migration/examples/invalid/plan-unnumbered-file.json +9 -0
  37. package/agent-template/.ai/blueprints/add-migration/examples/valid/input.json +6 -0
  38. package/agent-template/.ai/blueprints/add-migration/examples/valid/plan.json +9 -0
  39. package/agent-template/.ai/blueprints/add-migration/gates.yaml +30 -0
  40. package/agent-template/.ai/blueprints/add-migration/input.schema.json +23 -0
  41. package/agent-template/.ai/blueprints/add-migration/plan.schema.json +54 -0
  42. package/agent-template/.ai/blueprints/add-migration/required-files.yaml +18 -0
  43. package/agent-template/.ai/blueprints/add-migration/spec-requirements.yaml +13 -0
  44. package/agent-template/.ai/blueprints/add-migration/steps.yaml +62 -0
  45. package/agent-template/.ai/blueprints/author-spec/README.md +5 -0
  46. package/agent-template/.ai/blueprints/author-spec/allowed-paths.yaml +7 -0
  47. package/agent-template/.ai/blueprints/author-spec/blueprint.json +14 -0
  48. package/agent-template/.ai/blueprints/author-spec/examples/invalid/input-missing-outcome.json +5 -0
  49. package/agent-template/.ai/blueprints/author-spec/examples/valid/input.json +6 -0
  50. package/agent-template/.ai/blueprints/author-spec/gates.yaml +13 -0
  51. package/agent-template/.ai/blueprints/author-spec/input.schema.json +20 -0
  52. package/agent-template/.ai/blueprints/author-spec/plan.schema.json +14 -0
  53. package/agent-template/.ai/blueprints/author-spec/required-files.yaml +6 -0
  54. package/agent-template/.ai/blueprints/author-spec/spec-requirements.yaml +35 -0
  55. package/agent-template/.ai/blueprints/author-spec/steps.yaml +28 -0
  56. package/agent-template/.ai/blueprints/author-spec/templates/module.yaml +45 -0
  57. package/agent-template/.ai/blueprints/bug-fix/README.md +5 -0
  58. package/agent-template/.ai/blueprints/bug-fix/allowed-paths.yaml +29 -0
  59. package/agent-template/.ai/blueprints/bug-fix/blueprint.json +14 -0
  60. package/agent-template/.ai/blueprints/bug-fix/examples/invalid/input-no-symptom.json +4 -0
  61. package/agent-template/.ai/blueprints/bug-fix/examples/invalid/plan-no-test.json +8 -0
  62. package/agent-template/.ai/blueprints/bug-fix/examples/valid/input.json +6 -0
  63. package/agent-template/.ai/blueprints/bug-fix/examples/valid/plan.json +8 -0
  64. package/agent-template/.ai/blueprints/bug-fix/gates.yaml +30 -0
  65. package/agent-template/.ai/blueprints/bug-fix/input.schema.json +25 -0
  66. package/agent-template/.ai/blueprints/bug-fix/plan.schema.json +53 -0
  67. package/agent-template/.ai/blueprints/bug-fix/required-files.yaml +7 -0
  68. package/agent-template/.ai/blueprints/bug-fix/spec-requirements.yaml +7 -0
  69. package/agent-template/.ai/blueprints/bug-fix/steps.yaml +51 -0
  70. package/agent-template/.ai/blueprints/core-extend/README.md +5 -0
  71. package/agent-template/.ai/blueprints/core-extend/allowed-paths.yaml +49 -0
  72. package/agent-template/.ai/blueprints/core-extend/blueprint.json +14 -0
  73. package/agent-template/.ai/blueprints/core-extend/examples/invalid/input-unknown-package.json +5 -0
  74. package/agent-template/.ai/blueprints/core-extend/examples/invalid/plan-missing-gates.json +7 -0
  75. package/agent-template/.ai/blueprints/core-extend/examples/valid/input.json +6 -0
  76. package/agent-template/.ai/blueprints/core-extend/examples/valid/plan.json +10 -0
  77. package/agent-template/.ai/blueprints/core-extend/gates.yaml +16 -0
  78. package/agent-template/.ai/blueprints/core-extend/input.schema.json +54 -0
  79. package/agent-template/.ai/blueprints/core-extend/plan.schema.json +39 -0
  80. package/agent-template/.ai/blueprints/core-extend/required-files.yaml +36 -0
  81. package/agent-template/.ai/blueprints/core-extend/spec-requirements.yaml +17 -0
  82. package/agent-template/.ai/blueprints/core-extend/steps.yaml +54 -0
  83. package/agent-template/.ai/blueprints/edit-module/README.md +9 -0
  84. package/agent-template/.ai/blueprints/edit-module/allowed-paths.yaml +27 -0
  85. package/agent-template/.ai/blueprints/edit-module/blueprint.json +20 -0
  86. package/agent-template/.ai/blueprints/edit-module/examples/invalid/input-unknown-change.json +5 -0
  87. package/agent-template/.ai/blueprints/edit-module/examples/invalid/plan-touches-platform.json +15 -0
  88. package/agent-template/.ai/blueprints/edit-module/examples/valid/input.json +5 -0
  89. package/agent-template/.ai/blueprints/edit-module/examples/valid/plan.json +25 -0
  90. package/agent-template/.ai/blueprints/edit-module/gates.yaml +30 -0
  91. package/agent-template/.ai/blueprints/edit-module/input.schema.json +31 -0
  92. package/agent-template/.ai/blueprints/edit-module/plan.schema.json +65 -0
  93. package/agent-template/.ai/blueprints/edit-module/required-files.yaml +80 -0
  94. package/agent-template/.ai/blueprints/edit-module/spec-requirements.yaml +15 -0
  95. package/agent-template/.ai/blueprints/edit-module/steps.yaml +115 -0
  96. package/agent-template/.ai/blueprints/new-module/README.md +7 -0
  97. package/agent-template/.ai/blueprints/new-module/allowed-paths.yaml +27 -0
  98. package/agent-template/.ai/blueprints/new-module/blueprint.json +20 -0
  99. package/agent-template/.ai/blueprints/new-module/examples/invalid/input-spec-outside-modules.json +4 -0
  100. package/agent-template/.ai/blueprints/new-module/examples/invalid/plan-unknown-gate.json +8 -0
  101. package/agent-template/.ai/blueprints/new-module/examples/valid/input.json +5 -0
  102. package/agent-template/.ai/blueprints/new-module/examples/valid/plan.json +22 -0
  103. package/agent-template/.ai/blueprints/new-module/gates.yaml +30 -0
  104. package/agent-template/.ai/blueprints/new-module/input.schema.json +21 -0
  105. package/agent-template/.ai/blueprints/new-module/plan.schema.json +58 -0
  106. package/agent-template/.ai/blueprints/new-module/required-files.yaml +73 -0
  107. package/agent-template/.ai/blueprints/new-module/spec-requirements.yaml +30 -0
  108. package/agent-template/.ai/blueprints/new-module/steps.yaml +138 -0
  109. package/agent-template/.ai/blueprints/release/README.md +5 -0
  110. package/agent-template/.ai/blueprints/release/allowed-paths.yaml +19 -0
  111. package/agent-template/.ai/blueprints/release/blueprint.json +14 -0
  112. package/agent-template/.ai/blueprints/release/examples/invalid/input-bad-version.json +4 -0
  113. package/agent-template/.ai/blueprints/release/examples/invalid/plan-bad-branch.json +7 -0
  114. package/agent-template/.ai/blueprints/release/examples/valid/input.json +5 -0
  115. package/agent-template/.ai/blueprints/release/examples/valid/plan.json +20 -0
  116. package/agent-template/.ai/blueprints/release/gates.yaml +20 -0
  117. package/agent-template/.ai/blueprints/release/input.schema.json +24 -0
  118. package/agent-template/.ai/blueprints/release/plan.schema.json +46 -0
  119. package/agent-template/.ai/blueprints/release/required-files.yaml +19 -0
  120. package/agent-template/.ai/blueprints/release/spec-requirements.yaml +8 -0
  121. package/agent-template/.ai/blueprints/release/steps.yaml +47 -0
  122. package/agent-template/.ai/blueprints/security-review/README.md +5 -0
  123. package/agent-template/.ai/blueprints/security-review/allowed-paths.yaml +6 -0
  124. package/agent-template/.ai/blueprints/security-review/blueprint.json +14 -0
  125. package/agent-template/.ai/blueprints/security-review/examples/invalid/input-unknown-kind.json +4 -0
  126. package/agent-template/.ai/blueprints/security-review/examples/invalid/plan-finding-without-scenario.json +14 -0
  127. package/agent-template/.ai/blueprints/security-review/examples/valid/input.json +4 -0
  128. package/agent-template/.ai/blueprints/security-review/examples/valid/plan.json +19 -0
  129. package/agent-template/.ai/blueprints/security-review/gates.yaml +22 -0
  130. package/agent-template/.ai/blueprints/security-review/input.schema.json +20 -0
  131. package/agent-template/.ai/blueprints/security-review/plan.schema.json +65 -0
  132. package/agent-template/.ai/blueprints/security-review/required-files.yaml +6 -0
  133. package/agent-template/.ai/blueprints/security-review/spec-requirements.yaml +9 -0
  134. package/agent-template/.ai/blueprints/security-review/steps.yaml +38 -0
  135. package/agent-template/.ai/examples/README.md +8 -0
  136. package/agent-template/.ai/examples/bad/client-imports-server/README.md +20 -0
  137. package/agent-template/.ai/examples/bad/client-imports-server/api.ts +12 -0
  138. package/agent-template/.ai/examples/bad/missing-acl/README.md +23 -0
  139. package/agent-template/.ai/examples/bad/missing-acl/endpoints.ts +12 -0
  140. package/agent-template/.ai/examples/bad/tenant-from-body/README.md +19 -0
  141. package/agent-template/.ai/examples/bad/tenant-from-body/endpoints.ts +33 -0
  142. package/agent-template/.ai/examples/client-contribution/CustomerListView.tsrx +34 -0
  143. package/agent-template/.ai/examples/client-contribution/README.md +11 -0
  144. package/agent-template/.ai/examples/client-contribution/contribution.tsrx +48 -0
  145. package/agent-template/.ai/examples/client-contribution/index.ts +20 -0
  146. package/agent-template/.ai/examples/client-contribution/permissions.ts +8 -0
  147. package/agent-template/.ai/examples/customer-cli-extension/README.md +14 -0
  148. package/agent-template/.ai/examples/customer-cli-extension/commands.json +17 -0
  149. package/agent-template/.ai/examples/customer-cli-extension/index.ts +36 -0
  150. package/agent-template/.ai/examples/module-create/task-packet.json +11 -0
  151. package/agent-template/.ai/guides/application-development.md +97 -0
  152. package/agent-template/.ai/policies/capabilities.yaml +164 -0
  153. package/agent-template/.ai/policies/model-routing.yaml +72 -0
  154. package/agent-template/.ai/policies/path-ownership.yaml +65 -0
  155. package/agent-template/.ai/policies/task-budgets.yaml +37 -0
  156. package/agent-template/.ai/references/catalog/LICENSE +21 -0
  157. package/agent-template/.ai/references/catalog/migrations/0001_catalog_core.down.sql +2 -0
  158. package/agent-template/.ai/references/catalog/migrations/0001_catalog_core.up.sql +21 -0
  159. package/agent-template/.ai/references/catalog/migrations/0002_catalog_history.down.sql +3 -0
  160. package/agent-template/.ai/references/catalog/migrations/0002_catalog_history.up.sql +20 -0
  161. package/agent-template/.ai/references/catalog/migrations/0003_catalog_history_service_actors.down.sql +3 -0
  162. package/agent-template/.ai/references/catalog/migrations/0003_catalog_history_service_actors.up.sql +36 -0
  163. package/agent-template/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.down.sql +3 -0
  164. package/agent-template/.ai/references/catalog/migrations/0004_catalog_idempotency_ledger.up.sql +19 -0
  165. package/agent-template/.ai/references/catalog/migrations/README.md +3 -0
  166. package/agent-template/.ai/references/catalog/module.json +27 -0
  167. package/agent-template/.ai/references/catalog/package.json +49 -0
  168. package/agent-template/.ai/references/catalog/spec/module.yaml +86 -0
  169. package/agent-template/.ai/references/catalog/src/acl/permissions.ts +6 -0
  170. package/agent-template/.ai/references/catalog/src/agent/tools.ts +164 -0
  171. package/agent-template/.ai/references/catalog/src/api/endpoints.ts +243 -0
  172. package/agent-template/.ai/references/catalog/src/client/CatalogHistoryDrawer.tsrx +123 -0
  173. package/agent-template/.ai/references/catalog/src/client/CatalogItemForm.tsrx +190 -0
  174. package/agent-template/.ai/references/catalog/src/client/CatalogView.tsrx +473 -0
  175. package/agent-template/.ai/references/catalog/src/client/api.ts +111 -0
  176. package/agent-template/.ai/references/catalog/src/client/contribution.tsrx +61 -0
  177. package/agent-template/.ai/references/catalog/src/client/index.ts +18 -0
  178. package/agent-template/.ai/references/catalog/src/client/navigation-copy.ts +9 -0
  179. package/agent-template/.ai/references/catalog/src/client/state.ts +24 -0
  180. package/agent-template/.ai/references/catalog/src/domain/types.ts +32 -0
  181. package/agent-template/.ai/references/catalog/src/domain/variables.ts +111 -0
  182. package/agent-template/.ai/references/catalog/src/index.ts +31 -0
  183. package/agent-template/.ai/references/catalog/src/platform.ts +35 -0
  184. package/agent-template/.ai/references/catalog/src/server/index.ts +4 -0
  185. package/agent-template/.ai/references/catalog/src/server/runtime.ts +86 -0
  186. package/agent-template/.ai/references/catalog/src/services/catalog-service.ts +306 -0
  187. package/agent-template/.ai/references/catalog/src/services/database-repository.ts +440 -0
  188. package/agent-template/.ai/references/catalog/src/services/index.ts +4 -0
  189. package/agent-template/.ai/references/catalog/src/services/migration.ts +171 -0
  190. package/agent-template/.ai/references/catalog/src/services/repository.ts +36 -0
  191. package/agent-template/.ai/references/catalog/src/services/target-idempotency.ts +59 -0
  192. package/agent-template/.ai/references/catalog/tests/agent-tools.test.ts +277 -0
  193. package/agent-template/.ai/references/catalog/tests/endpoints.test.ts +320 -0
  194. package/agent-template/.ai/references/catalog/tests/idempotency.test.ts +297 -0
  195. package/agent-template/.ai/references/catalog/tests/migrations.test.ts +149 -0
  196. package/agent-template/.ai/references/catalog/tests/module.test.ts +271 -0
  197. package/agent-template/.ai/references/catalog/tests/support/database.ts +76 -0
  198. package/agent-template/.ai/references/catalog/translations/en.json +101 -0
  199. package/agent-template/.ai/references/catalog/translations/pl.json +101 -0
  200. package/agent-template/.ai/references/catalog/tsconfig.json +15 -0
  201. package/agent-template/.ai/references/catalog/vitest.config.ts +16 -0
  202. package/agent-template/.ai/references/catalog.provenance.json +55 -0
  203. package/agent-template/.ai/rules/flowdular.md +86 -0
  204. package/agent-template/.ai/skills/README.md +36 -0
  205. package/agent-template/.ai/skills/agent-tool-design/SKILL.md +209 -0
  206. package/agent-template/.ai/skills/auth-security-review/SKILL.md +96 -0
  207. package/agent-template/.ai/skills/auto-review/SKILL.md +112 -0
  208. package/agent-template/.ai/skills/bug-hunt/SKILL.md +110 -0
  209. package/agent-template/.ai/skills/business-agent-design/SKILL.md +188 -0
  210. package/agent-template/.ai/skills/cli-extension/SKILL.md +114 -0
  211. package/agent-template/.ai/skills/core-extend/SKILL.md +104 -0
  212. package/agent-template/.ai/skills/database-adapter/SKILL.md +204 -0
  213. package/agent-template/.ai/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  214. package/agent-template/.ai/skills/migration-authoring/SKILL.md +167 -0
  215. package/agent-template/.ai/skills/module-new/SKILL.md +180 -0
  216. package/agent-template/.ai/skills/module-update/SKILL.md +100 -0
  217. package/agent-template/.ai/skills/perf-audit/SKILL.md +105 -0
  218. package/agent-template/.ai/skills/release-eject-pr/SKILL.md +113 -0
  219. package/agent-template/.ai/skills/spec-approval/SKILL.md +112 -0
  220. package/agent-template/.ai/skills/test-hardening/SKILL.md +86 -0
  221. package/agent-template/.ai/skills/translations-i18n/SKILL.md +85 -0
  222. package/agent-template/.ai/skills/ux-design/SKILL.md +97 -0
  223. package/agent-template/.ai/skills/variables/SKILL.md +164 -0
  224. package/agent-template/.ai/skills/workflow-development/SKILL.md +199 -0
  225. package/agent-template/.claude/skills/agent-tool-design/SKILL.md +203 -0
  226. package/agent-template/.claude/skills/auth-security-review/SKILL.md +90 -0
  227. package/agent-template/.claude/skills/auto-review/SKILL.md +103 -0
  228. package/agent-template/.claude/skills/bug-hunt/SKILL.md +104 -0
  229. package/agent-template/.claude/skills/business-agent-design/SKILL.md +182 -0
  230. package/agent-template/.claude/skills/cli-extension/SKILL.md +108 -0
  231. package/agent-template/.claude/skills/core-extend/SKILL.md +99 -0
  232. package/agent-template/.claude/skills/database-adapter/SKILL.md +198 -0
  233. package/agent-template/.claude/skills/database-adapter/references/first-run-and-matrix.md +105 -0
  234. package/agent-template/.claude/skills/migration-authoring/SKILL.md +161 -0
  235. package/agent-template/.claude/skills/module-new/SKILL.md +171 -0
  236. package/agent-template/.claude/skills/module-update/SKILL.md +91 -0
  237. package/agent-template/.claude/skills/perf-audit/SKILL.md +98 -0
  238. package/agent-template/.claude/skills/release-eject-pr/SKILL.md +107 -0
  239. package/agent-template/.claude/skills/spec-approval/SKILL.md +106 -0
  240. package/agent-template/.claude/skills/test-hardening/SKILL.md +79 -0
  241. package/agent-template/.claude/skills/translations-i18n/SKILL.md +78 -0
  242. package/agent-template/.claude/skills/ux-design/SKILL.md +92 -0
  243. package/agent-template/.claude/skills/variables/SKILL.md +156 -0
  244. package/agent-template/.claude/skills/workflow-development/SKILL.md +192 -0
  245. package/agent-template/AGENTS.md +77 -0
  246. package/agent-template/CLAUDE.md +77 -0
  247. package/agent-template/docs/adr/0001-development-reload.md +16 -0
  248. package/agent-template/docs/adr/0002-durable-agent-execution.md +21 -0
  249. package/agent-template/docs/adr/0003-module-settings.md +22 -0
  250. package/agent-template/docs/adr/0004-enterprise-access-and-audit.md +36 -0
  251. package/agent-template/docs/adr/0005-sandbox-runtime-and-coding-agents.md +81 -0
  252. package/agent-template/docs/adr/0006-agentic-workflows.md +1702 -0
  253. package/agent-template/docs/adr/0007-module-owned-agents.md +429 -0
  254. package/agent-template/docs/adr/0008-database-adapter-contract.md +90 -0
  255. package/agent-template/docs/agent-contract.md +45 -0
  256. package/agent-template/docs/configuration.md +122 -0
  257. package/agent-template/docs/database-adapters.md +346 -0
  258. package/agent-template/docs/design-system.md +217 -0
  259. package/agent-template/docs/modules.md +146 -0
  260. package/agent-template/platform/scripts/build.mjs +38 -0
  261. package/agent-template/rulesync.jsonc +11 -0
  262. package/dist/bin.js +3 -1
  263. package/package.json +3 -2
  264. package/template/default/.prettierignore +9 -0
  265. package/template/default/README.md +12 -0
  266. package/template/default/flowdular.json +3 -3
  267. package/template/default/modules/example/package.json +1 -1
  268. package/template/default/package.json +6 -2
  269. package/template/default/platform/octane.config.ts +17 -6
  270. package/template/default/platform/package.json +3 -2
  271. package/template/default/platform/scripts/dev.mjs +39 -6
@@ -0,0 +1,217 @@
1
+ # Flowdular design system
2
+
3
+ Identity 1.0 (2026-08-31). The implementation reference for humans and agents:
4
+ shared primitives, tokens, and the rules for using them.
5
+
6
+ ## Where things live
7
+
8
+ - `packages/ui` (`@flowdular/sdk/ui`): the only source of visual primitives.
9
+ Design tokens (`src/styles/tokens.css`), base styles, `ui-*` component
10
+ classes, TSRX components, icons, and the brand mark. Fonts (IBM Plex Sans
11
+ Variable, IBM Plex Mono) are self-hosted through `@fontsource` packages.
12
+ - `packages/client`: the application shell (sidebar, topbar, command palette,
13
+ dashboard, contribution outlets). Shell-only layout lives in
14
+ `src/shell/shell.css`.
15
+ - Modules: compose screens from `@flowdular/sdk/ui`. Module CSS may only add
16
+ module-specific composites built on the tokens (example:
17
+ `modules/agents/src/client/agents.css`).
18
+ - `platform/public`: `favicon.svg`, `og.png` (1200x630 Open Graph image).
19
+ - Brand mark geometry is generated: `node packages/ui/scripts/gen-mark.mjs`
20
+ rewrites `packages/ui/src/brand/mark.ts` from the weave parameters.
21
+
22
+ ## Rules
23
+
24
+ 1. Primitives first. Use a `ui-*` class or an exported component before
25
+ writing any new visual code.
26
+ 2. Colors, fonts, sizes, radii, and shadows come only from tokens
27
+ (`var(--...)`). No hex values in shell or module CSS.
28
+ 3. Never restyle or override a `ui-*` class outside `packages/ui`.
29
+ 4. A missing primitive is added per use case as a module-local component built
30
+ on the tokens, and flagged as a promotion candidate for `packages/ui`.
31
+ 5. Blue means action and selection. Green, amber, and red mean state. Copper
32
+ is reserved for the brand (mark, splash, sign-in) and is never a button or
33
+ a state color.
34
+ 6. Minimum text size is 12 px (`--text-sm`); labels use `--text-xs` uppercase.
35
+ Numbers in tables and KPIs are tabular (`.num`, `ui-kpi__value`).
36
+ 7. Layout containment is owned by the primitives, not by the screen. Children
37
+ of `ui-view`, `ui-two-col`, `ui-grid-2`, and `ui-kpi-grid` are shrinkable
38
+ tracks, long words wrap, and the workspace never scrolls horizontally. Wide
39
+ content scrolls inside its own container (`ui-table-wrap`), so one long
40
+ value can never push the page sideways.
41
+ 8. `Kpi` is a stat tile. Its value is a number or a short state word; addresses,
42
+ identifiers, and paths belong in `note` or a `ui-mono` line.
43
+ 9. A screen never splits its width between records and a form. Records own the
44
+ page; creating and editing happens in a `Drawer`.
45
+ 10. `Tag` carries state or a value with meaning (a status, a count, a scope).
46
+ Never decoration: no "Secure", "Master data", or "Suggested setup" badges.
47
+ A card head is a title, a one-line description in its `small`, and at most
48
+ one right-aligned cluster (`ui-card__actions`: a count, a state, buttons).
49
+ 11. A row is title and description on the left and its controls on one line on
50
+ the right, vertically centered (`SettingRow`). The row title is the label;
51
+ the control inside carries `aria-label`, never a second visible label.
52
+ 12. Large sets are summarized where they are read (`ScopeSummary`, grouped by
53
+ module) and edited in full only inside the drawer (`CheckGrid`).
54
+ 13. Destructive actions close a drawer in their own `ui-form__section--danger`:
55
+ one title, one line of consequence, one `Button variant="danger"`. They are
56
+ never mixed into a status row.
57
+ 14. Menus (workspace switcher, account menu, session actions) are `ui-menu`
58
+ with `ui-menu__item` rows: 40 px, 10 px inset, the same hover and selected
59
+ background, a 32 px avatar, two lines of text, and the trailing check
60
+ pushed to the right edge.
61
+
62
+ ## Screen pattern
63
+
64
+ Every record screen is built the same way, so a user who learns one learns all
65
+ of them:
66
+
67
+ ```text
68
+ PageHeader eyebrow, title, description, [Refresh] [+ New ...]
69
+ Alert only when the last action failed
70
+ TableCard
71
+ ui-card__head title, count, SearchField and Filters on one line
72
+ Table the records, full width
73
+ ui-note the constraint worth stating (permissions, boundaries)
74
+ Drawer the create or edit form, opened from the header or a row
75
+ ```
76
+
77
+ `TableCard` is the default for a record screen. It owns the card, the one-line
78
+ head (title, `count`, and the `search` and `filters` slots inside
79
+ `ui-card__filters`), the `Table`, and the optional `ui-note` footer, so every
80
+ screen shows the same head, loading row, empty state, and filtered-empty
81
+ message. A screen passes data and slots, never table markup. Row actions are
82
+ compact, visible buttons in a narrow trailing column with an accessible but
83
+ visually empty header. The column is part of the same `colgroup` in loading,
84
+ empty and populated states, so widths do not drift. `Table` on its own covers
85
+ what needs a bare table, such as the list side of a master-detail screen.
86
+
87
+ `Table` is backed by the official `@octanejs/tanstack-table` adapter. Modules
88
+ still use the smaller Flowdular `Table` and `TableCard` contract from
89
+ `@flowdular/sdk/ui`; they never import TanStack directly. The shared primitive owns
90
+ the TanStack features, row model, header model and cell rendering so every
91
+ screen keeps the same states, widths and actions.
92
+
93
+ Every column declares a semantic CSS `width`. Give the primary record and its
94
+ description the largest share, medium shares to dates and identifiers, and the
95
+ smallest share to counts and lifecycle state. In a table with row actions, data
96
+ columns normally add up to about 90 percent; the shared 160 px action column
97
+ uses the rest. In a read-only table, data columns add up to 100 percent. The
98
+ table keeps these widths in loading, empty and populated states and scrolls
99
+ horizontally below its minimum readable width.
100
+
101
+ The drawer holds one `ui-drawer__form`: fields scroll inside
102
+ `ui-drawer__body`, and the primary action stays pinned in `ui-drawer__foot`.
103
+ Escape and the scrim close it. Master-detail screens that only read (agent runs,
104
+ the playground) keep `ui-two-col`; the list side is a `ui-table` whose open
105
+ record carries `is-selected`.
106
+
107
+ A drawer that edits several independent things (a member, a module) stacks
108
+ `ui-form__section` blocks inside its `ui-form`: an uppercase title and one-line
109
+ description in `ui-form__section-head`, then the fields and a right-aligned
110
+ `ui-form__actions` row with one primary per section. An input paired with one
111
+ action (a temporary password and its Reset) sits in a `ui-control-row`. The
112
+ danger section comes last, and the foot then keeps only Close.
113
+
114
+ Administration > Settings holds only workspace settings: full-width cards
115
+ (Workspace, Preferences), each `SettingRow` one setting. A module's declared
116
+ settings are edited in its Drawer under Administration > Modules, as
117
+ `SettingRow`s inside the drawer's Settings `ui-form__section`; a module
118
+ without settings shows a one-line empty state there.
119
+
120
+ ## Components
121
+
122
+ | Component | Use |
123
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
124
+ | `Button` | Actions: `variant` primary, secondary (default), ghost, danger; `size` sm, md, lg; `block` |
125
+ | `FormField` | Label + control + help or error. Put `ui-input`, `ui-select`, or `ui-textarea` inside |
126
+ | `VariableTextarea` | Multiline template field: `value`, `onInput`, `variables` (scope-filtered `VariableDefinition[]`), `sampleValues`, `label`, `name`; a `braces` menu inserts `{{ key }}` and tokens highlight as pills (error pill when unknown). Presentational, never fetches |
127
+ | `VariableInput` | Single-line variant of `VariableTextarea` with the same props |
128
+ | `VariableSelect` | Native select that stores either a literal option value or one allowed `{{ key }}` token. Takes scope-filtered `variables`, `sampleValues`, literal `options`, `value`, `onInput`, `name`, `label`, and native required/disabled state. It preserves keyboard, validation, accessibility, and `FormData` semantics and never fetches or resolves data |
129
+ | `Tag` | Status and metadata: `tone` neutral, success, warning, danger, info, ink; `dot` adds a state dot; `mono` |
130
+ | `Kpi` | Stat tile: `label`, `value`, `unit`, `badge`, `note`, `href`, `linkLabel` |
131
+ | `Chart` | Token-driven Chart.js wrapper on a client-only canvas: `type` area, bar, line; `data`, `series` (`key`, `label`, `token`), `xKey`, `height`, `title`, `xTickFormatter`; series colors come from `--chart-1..5`; shows an EmptyState for empty or all-zero data |
132
+ | `Table` | The one data table, backed by `@octanejs/tanstack-table`: `columns` (`key`, `header`, required `width`, `numeric`, `cell`), `rows`, `rowKey`, `status` idle/loading, `loadingLabel`, `empty` and `emptyFiltered` picked by `filtered`, `actions(row): TableAction[]`, `actionsLabel`, optional stable `actionsWidth` (160 px by default, 280 px for two actions), `onSelect` with `selectedKey`, `caption`; fixed layout and `colgroup` keep columns stable across states |
133
+ | `TableCard` | The record card around `Table`: `title`, `count`, the `head`, `search`, and `filters` head slots, `before` and `after` around the table, `note` with `noteIcon` as the footer |
134
+ | `PageHeader` | Every view starts with it: `eyebrow`, `title`, `description`; children render as right-side actions |
135
+ | `EmptyState` | `icon`, `title`, children, optional `code` |
136
+ | `Alert` | Inline message: `tone` danger (default), warning, info |
137
+ | `Drawer` | Editor panel over the records: `open`, `title`, `subtitle`, `width` md/lg, `onClose` |
138
+ | `SearchField` | Filter control for a panel head: `value`, `placeholder`, `label`, `onInput` |
139
+ | `CheckGrid` | Grouped multi-select for scopes, tools, and long option sets: `groups` (`label`, `options` of `value`, `label`, `hint`), `value`, `mono`, `disabled`, `onChange` |
140
+ | `ScopeSummary` | Read-only summary of `module.entity.action` scopes: one row per module, one chip per entity with its actions: `scopes`, `labels` (module id to display name) |
141
+ | `SettingRow` | One setting: `label`, `description` (node, one line), `scopeLabel` (small neutral tag), `status` (`ok`, `message` of the last save), children as the control cluster |
142
+ | `Avatar` | Initials from `name`: `square` for organizations, round for people; `large` in profile and account headers |
143
+ | `Switch` | Boolean setting that applies on its own (no form submit): `checked`, `label` as the accessible name, `disabled`, `onChange` |
144
+ | `ConfirmDialog` | One question before an irreversible action: `open`, `title`, children, `confirmLabel`, `tone` danger (default) or primary, `busy`, `onConfirm`, `onCancel` |
145
+ | `Icon` | Stroke icon by `name` from `ICON_PATHS`; `size` 18 default, 16 in controls, 14 in `Button size="sm"`; `strokeWidth` 1.75 default |
146
+ | `BrandMark` | The weave: `size`, `signature` (copper weft, large brand moments only), `tone` brand, current, inverse |
147
+
148
+ `Drawer` takes one child, a `ui-drawer__form` (fields in `ui-drawer__body`, actions in `ui-drawer__foot`) or a plain `ui-drawer__body`; it closes on Escape and on the scrim. `SearchField` carries no visible label, so pass `label` as its accessible name. `FormField` renders `error` in place of `help` and marks it `role="alert"`. `SettingRow` is presentation only: the caller owns the draft value, the save call, and passes the result back as `status`. `ScopeSummary` is the read side of `CheckGrid`; both keep the first-seen module order, and `summarizeScopes` is exported for callers that need the grouping without the markup.
149
+
150
+ Icon names (`packages/ui/src/icons/Icon.tsrx`): `dashboard`, `parties`, `catalog`,
151
+ `user`, `users`, `shield`, `code`, `modules`, `file-text`, `play`, `bot`,
152
+ `flask`, `activity`, `plug`, `search`, `chevron-down`, `chevrons-up-down`,
153
+ `plus`, `panel-left`, `check`, `filter`, `download`, `more`, `external`,
154
+ `alert`, `x`, `sign-out`, `refresh`, `help`, `key`, `settings`, `braces`. An unknown name renders
155
+ `modules` without a warning; a new icon is one 24x24 stroke path added there.
156
+
157
+ ## Classes
158
+
159
+ - Layout: `ui-view`, `ui-two-col` (+`--wide-aside`), `ui-grid-2`,
160
+ `ui-kpi-grid`, `ui-tag-cloud`, `ui-section-head` (an `h2` with actions
161
+ inside a view)
162
+ - Surfaces: `ui-card` (+`__head`, `__title` with a `small` description,
163
+ `__actions` for the right-aligned cluster, `__body`), `ui-toolbar`
164
+ (+`__spacer` to push actions right; a bare `ui-input` or `ui-select` inside
165
+ it takes the button height and an `aria-label`)
166
+ - Data: `ui-table` (+`ui-table-wrap`, `ui-table__empty`, `ui-table__actions`
167
+ for the component-owned trailing button column, `ui-table__state` for a dot plus label,
168
+ `ui-table__placeholder` for the loading and empty rows inside the table,
169
+ `.num`, row states `is-clickable` and `is-selected`), `ui-cell`
170
+ (+`ui-cell__muted`), `ui-mono`, `ui-code`
171
+ - Forms: `ui-form` (+`__row`, `__row--4`, `__foot`, `__actions`, `__section`
172
+ with `__section-head` (`b` title, `small` description) and
173
+ `__section--danger`), `ui-control-row` (a growing control beside one fixed
174
+ button), `ui-choices` (a short wrapping row of `ui-checkbox`), `ui-input`
175
+ (+`--error`), `ui-select`, `ui-textarea` (+`--error`), `ui-checkbox`,
176
+ `ui-label`, `ui-help` (+`--error`)
177
+ - Drawer: `ui-drawer__form` (scrolling body plus pinned footer),
178
+ `ui-drawer__body`, `ui-drawer__foot`
179
+ - Settings rows inside a `ui-card` or a drawer `ui-form__section`, rendered
180
+ by `SettingRow`: `ui-setting`
181
+ (+`__text` for title, scope tag, and help, `__control` for the one-line
182
+ control cluster, `__status` (+`--error`) for the inline result)
183
+ - Buttons: `ui-btn` with `--primary`, `--secondary`, `--ghost`, `--danger`,
184
+ `--sm`, `--lg`, `--block`, and `--icon` for an icon-only square button
185
+ (the `Button` component renders all but `--icon`)
186
+ - Bits: `ui-kbd`, `ui-dot` (+`--muted`), `ui-note`, `ui-menu` (+`__label`,
187
+ `__section` for a static identity or connection block, `__item`,
188
+ `__item--active`, `__item--danger`, `__sep`), `ui-icon`
189
+
190
+ Rendered by components, not written by hand: `ui-page-head*`, `ui-search`,
191
+ `ui-field`, `ui-switch` (+`--on`), `ui-dialog` (+`__panel`, `__title`,
192
+ `__body`, `__actions`), `ui-empty` (+`__icon`), `ui-alert` (+`--danger`, `--warning`,
193
+ `--info`), `ui-tag` (+tone and `--mono`), `ui-kpi` (+`__label`, `__value`,
194
+ `__note`, `__link`), `ui-avatar` (+`--sq`, `--lg`), `ui-checks` (+`__group`,
195
+ `__head`, `__count`, `__all`, `__items`, `__option`), `ui-scopes` (+`__row`,
196
+ `__chip`), `ui-drawer-slot`, `ui-drawer` (+`__panel`, `__panel--lg`, `__head`,
197
+ `__close`), `ui-varfield` (+`__control`, `__highlight`, `__input`, `__pill`
198
+ (+`--error`), `__trigger`, `__menu`, `__value`, `__empty`; the overlay layer
199
+ that highlights `{{ key }}` tokens, rendered by `VariableTextarea` and
200
+ `VariableInput`).
201
+
202
+ ## Token cheat sheet
203
+
204
+ - Surfaces: `--bg`, `--surface`, `--surface-2`; lines: `--line`, `--line-2`
205
+ - Text: `--ink`, `--ink-2` (labels), `--ink-3` (descriptions), `--ink-4`
206
+ (placeholders only, below AA for text)
207
+ - Action: `--primary`, `--primary-hover`, `--primary-soft`, `--primary-tint`,
208
+ `--focus`
209
+ - State: `--success`, `--warning`, `--danger` with `-bg` and `-line` pairs
210
+ - Brand: `--brand`, `--brand-weft` (copper)
211
+ - Type: `--font-sans`, `--font-mono`, `--text-xs` 11 to `--text-display` 36
212
+ - Dimensions: `--sidebar-w` 260, `--rail-w` 60, `--topbar-h` 52, `--control-h`
213
+ 36, `--button-h` 32, `--row-h` 44, radii `--r-sm` 4, `--r` 6, `--r-md` 8,
214
+ `--r-lg` 12
215
+
216
+ Components reference the semantic layer only, so a dark theme is one token
217
+ override block, not a rewrite.
@@ -0,0 +1,146 @@
1
+ # Modules
2
+
3
+ A module is a self-contained slice of the product: its own permissions,
4
+ endpoints, migrations, services, screens, translations and tests, wired into the
5
+ platform without touching a core file. `.ai/references/catalog` is the pinned reference
6
+ implementation; copy its shape.
7
+
8
+ ## Lifecycle
9
+
10
+ ```text
11
+ approved spec -> module new -> implement -> gates -> module enable -> verify
12
+ ```
13
+
14
+ ### 1. Specification
15
+
16
+ A module is created only from a `spec/module.yaml` with `status: approved`. The
17
+ spec is the contract: `permissions[].id` equal the constants in
18
+ `src/acl/permissions.ts`, and those permissions are exactly what
19
+ `auth sync-scopes` grants. An agent never approves a spec on its own judgment.
20
+
21
+ ```bash
22
+ pnpm flowdular spec validate --all
23
+ ```
24
+
25
+ ### 2. Scaffold
26
+
27
+ ```bash
28
+ pnpm flowdular module new sales.orders \
29
+ --spec modules/sales-orders/spec/module.yaml # dry run
30
+ pnpm flowdular module new sales.orders \
31
+ --spec modules/sales-orders/spec/module.yaml --apply
32
+ ```
33
+
34
+ The scaffold derives everything from the spec: `platform.server` and
35
+ `platform.client` flags from the capabilities, `src/platform.ts` and
36
+ `src/client/index.ts` with the canonical `createServerComposition` and
37
+ `createClientContribution` entries, one `defineEndpoint` per
38
+ `<ns>.<entity>.read` (list) and `.manage` (create) permission of the first
39
+ entity, and, with the `database` capability, an asynchronous repository on the
40
+ `@flowdular/sdk/database` provider, a runtime that acquires and releases its lease,
41
+ and `migrations/0001_*.up.sql` and `.down.sql` with the tenant table and its
42
+ forced row-level security block. The contract is in
43
+ [Database adapters](database-adapters.md) and the `database-adapter` skill.
44
+
45
+ Files are written through the workspace Prettier, so the format gate passes
46
+ without a rewrite. A directory that already holds `spec/module.yaml` or
47
+ `translations/**` is extended, not rejected, and a failed run leaves nothing
48
+ behind.
49
+
50
+ ### 3. Implement
51
+
52
+ Rules that bite first (the full contract is in [../AGENTS.md](../AGENTS.md)):
53
+
54
+ - Tenant id comes only from `principalFromContext(octane)!.tenantId`; every
55
+ query on a tenant-owned table filters by `tenant_id`.
56
+ - Every endpoint is `defineEndpoint` with an explicit permission; every mutation
57
+ starts with `sessionMutationDenial(octane, auth)`.
58
+ - Numbered `migrations/000N_*.up.sql` files are the schema source and are
59
+ immutable once applied; add a new additive migration instead of editing one.
60
+ - Repositories acquire their database through `context.databases`, keep service
61
+ and endpoint callers asynchronous, run every operation inside
62
+ `database.transaction(..., { tenantId, access })`, and ship explicit
63
+ PostgreSQL SQL plus migration adoption checks.
64
+ - UI is built only from `@flowdular/sdk/ui` components, `ui-*` classes and tokens
65
+ ([design-system.md](design-system.md)).
66
+ - Cross-module operations go through a typed public service registered in
67
+ `context.capabilities`, never another module's database.
68
+ - Every imported package is declared in the module `package.json`; relative
69
+ imports carry `.ts` or `.tsrx`.
70
+
71
+ ### 4. Validate
72
+
73
+ ```bash
74
+ pnpm flowdular module validate
75
+ pnpm --filter @flowdular/module-<dir> typecheck
76
+ pnpm --filter @flowdular/module-<dir> test
77
+ ```
78
+
79
+ `module validate` checks more than the schema: `platform.server` requires
80
+ `src/platform.ts` and a `./platform` export, `platform.client` requires
81
+ `src/client/index.ts` and a `./client` export, and every declared locale needs a
82
+ `translations/<locale>.json` with the same key set as the others (an error).
83
+ `module.json` version drift against `specVersion`, or a locale missing from
84
+ `flowdular.json`, is reported as a warning.
85
+
86
+ ### 5. Enable
87
+
88
+ ```bash
89
+ pnpm flowdular module enable sales.orders --apply
90
+ pnpm flowdular module disable sales.orders --apply
91
+ ```
92
+
93
+ `enable` resolves the module's complete dependency closure, writes every newly
94
+ enabled module to `flowdular.json` in deterministic dependency-first order, adds
95
+ the required packages to `platform/package.json`, runs `pnpm install` when a
96
+ package is not linked yet, and regenerates
97
+ `platform/src/generated/modules.{server,client}.ts`. With `--apply` it also
98
+ grants the scopes declared by each newly enabled module to every workspace owner
99
+ through `auth sync-scopes`; a failed grant is reported as
100
+ `MODULE_SCOPES_SYNC_FAILED`, and when `auth.core` is unavailable the grant is
101
+ skipped with a warning.
102
+
103
+ `disable` refuses while another enabled module depends on the target, then
104
+ removes it and regenerates. `system.core` and `auth.core` are protected.
105
+
106
+ A running `pnpm dev` picks the change up live: the octane plugin reloads server
107
+ routes when the generated composition changes and the client hot-reloads, so no
108
+ rebuild is needed. `pnpm dev` and `pnpm build` run the sync automatically.
109
+
110
+ ## Files the CLI owns
111
+
112
+ Never edit these by hand:
113
+
114
+ - `flowdular.json` `modules.enabled`
115
+ - `platform/package.json` dependencies
116
+ - `platform/src/generated/**`
117
+ - `platform/octane.config.ts` and `platform/src/App.tsrx`
118
+
119
+ ## Module settings
120
+
121
+ Modules can also contribute standalone public or protected web pages outside the
122
+ workspace shell. See [Module web surfaces](module-web-surfaces.md) for page
123
+ entries, layouts, tenant-bound path mounts, loaders and access rules.
124
+
125
+ Settings are declared with `defineModuleSettings` from `@flowdular/sdk/kernel`,
126
+ returned as `settings` from the composition, read live with
127
+ `context.settings.get(tenantId, '<module>.core', key)`, and rendered in that
128
+ module's drawer under Administration, Modules. Administration, Settings holds
129
+ only workspace and organization settings.
130
+
131
+ ## Adding a CLI command
132
+
133
+ Module commands live in `src/cli/commands.json` and `src/cli/index.ts`,
134
+ metadata-identical, inside the module namespace. See
135
+ [cli-extensions.md](cli-extensions.md).
136
+
137
+ ## Guided procedures
138
+
139
+ Each change class has a canonical skill in [`.ai/skills`](../.ai/skills).
140
+ RuleSync generates the discovery copies for supported coding agents:
141
+ `module-new`, `module-update`, `migration-authoring`, `ux-design`,
142
+ `database-adapter`, `translations-i18n`, `auth-security-review`,
143
+ `test-hardening`, `cli-extension`, `agent-tool-design`,
144
+ `business-agent-design`, `workflow-development`, `release-eject-pr`.
145
+
146
+ Official business modules are maintained outside core. See [module distribution](module-distribution.md) for install, update, lock verification and release checks.
@@ -0,0 +1,38 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdtempSync, rmSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+
7
+ const stateDirectory = mkdtempSync(join(tmpdir(), 'flowdular-build-'));
8
+ const buildSecret = () => randomBytes(32).toString('base64');
9
+
10
+ /* The Octane plugin evaluates the server composition while bundling it. Give
11
+ that build-time process isolated state and ephemeral keys, without using deployment database settings or encryption keys. The emitted server still reads its real
12
+ production environment when it starts. */
13
+ const environment = {
14
+ ...process.env,
15
+ /* A production bundle is evaluated while it is built, but the build must not
16
+ connect to the deployment database. The embedded engine writes into the
17
+ throwaway state directory below; runtime still reads its real adapter. */
18
+ FD_ENV: 'development',
19
+ FD_INTERNAL_BUILD: 'true',
20
+ FD_DATABASE_ADAPTER: 'pglite',
21
+ FD_DATABASE_PGLITE_DIRECTORY: join(stateDirectory, 'pglite'),
22
+ FD_AGENT_CREDENTIAL_KEY: buildSecret(),
23
+ FD_AGENT_RUN_GRANT_KEY: buildSecret(),
24
+ FD_AUTOMATIONS_CREDENTIAL_KEY: buildSecret(),
25
+ FD_WORKFLOWS_PAYLOAD_KEY: buildSecret(),
26
+ FD_WORKFLOWS_CURSOR_KEY: buildSecret(),
27
+ };
28
+
29
+ try {
30
+ const result = spawnSync('vite', ['build'], {
31
+ env: environment,
32
+ stdio: 'inherit',
33
+ });
34
+ if (result.error) throw result.error;
35
+ process.exitCode = result.status ?? 1;
36
+ } finally {
37
+ rmSync(stateDirectory, { recursive: true, force: true });
38
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://github.com/dyoshikawa/rulesync/releases/latest/download/config-schema.json",
3
+ "inputRoots": [".ai"],
4
+ "outputRoots": ["."],
5
+ "targets": ["codexcli", "claudecode"],
6
+ "features": ["rules", "skills"],
7
+ "delete": true,
8
+ "verbose": false,
9
+ "silent": false,
10
+ "global": false,
11
+ }
package/dist/bin.js CHANGED
@@ -438,7 +438,9 @@ async function scaffold(request) {
438
438
  `${directory} is not empty. Pass --force to scaffold into it anyway.`
439
439
  );
440
440
  }
441
- const files = await copyTemplate(template, directory);
441
+ const agentTemplate = resolve2(templatesRoot(), "..", "agent-template");
442
+ await assertTemplateExists(agentTemplate, "agent guidance");
443
+ const files = await copyTemplate(template, directory) + await copyTemplate(agentTemplate, directory);
442
444
  await rewritePackageName(directory, name);
443
445
  await writeFile(
444
446
  join2(directory, ".env"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-flowdular",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "description": "Scaffold a Flowdular application: the platform, one example module and the secrets a fresh install needs.",
6
6
  "license": "MIT",
@@ -25,7 +25,8 @@
25
25
  "dist",
26
26
  "template",
27
27
  "README.md",
28
- "assets"
28
+ "assets",
29
+ "agent-template"
29
30
  ],
30
31
  "engines": {
31
32
  "node": ">=22.22.2"
@@ -0,0 +1,9 @@
1
+ node_modules/
2
+ dist/
3
+ pnpm-lock.yaml
4
+ .flowdular/
5
+ AGENTS.md
6
+ CLAUDE.md
7
+ .agents/skills/
8
+ .claude/skills/
9
+ .ai/references/
@@ -27,6 +27,18 @@ install. Data lives under `.flowdular/data`.
27
27
  | `flowdular.json` | Enabled modules and locales, owned by the CLI |
28
28
  | `.env` | The keys generated for this app. Never commit it |
29
29
 
30
+ ## Work with coding agents
31
+
32
+ `AGENTS.md` and `CLAUDE.md` introduce the application contract. `.ai` contains the
33
+ editable rules, skills, role prompts, policies, blueprints and reference module.
34
+ Codex and Claude Code discover generated skills in `.agents/skills` and
35
+ `.claude/skills`. Supporting guides are in `docs`.
36
+
37
+ After editing `.ai/rules` or `.ai/skills`, run `pnpm rules:generate`.
38
+ `pnpm rules:check` detects drift and also runs as part of `pnpm verify`.
39
+ Extend local modules using the published `@flowdular/sdk` imports. Installed
40
+ SDK source is reference material and must not be edited in `node_modules`.
41
+
30
42
  ## Build your first module
31
43
 
32
44
  ```bash
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "locales": ["en", "pl"],
25
25
  "agent": {
26
- "policy": "platform/node_modules/@flowdular/sdk/.ai/policies/capabilities.yaml",
27
- "modelRouting": "platform/node_modules/@flowdular/sdk/.ai/policies/model-routing.yaml",
28
- "blueprints": "platform/node_modules/@flowdular/sdk/.ai/blueprints"
26
+ "policy": ".ai/policies/capabilities.yaml",
27
+ "modelRouting": ".ai/policies/model-routing.yaml",
28
+ "blueprints": ".ai/blueprints"
29
29
  }
30
30
  }
@@ -16,7 +16,7 @@
16
16
  "dependencies": {
17
17
  "octane": "0.1.51",
18
18
  "segment-state": "0.2.0",
19
- "@flowdular/sdk": "0.2.2"
19
+ "@flowdular/sdk": "0.2.3"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@tsrx/typescript-plugin": "0.3.120",
@@ -16,11 +16,15 @@
16
16
  "flowdular": "flowdular",
17
17
  "cl": "flowdular",
18
18
  "doctor": "flowdular doctor",
19
- "verify": "pnpm typecheck && pnpm test && flowdular module validate && pnpm format:check"
19
+ "verify": "pnpm rules:check && pnpm typecheck && pnpm test && flowdular module validate && pnpm format:check",
20
+ "rules:generate": "rulesync generate",
21
+ "rules:check": "rulesync generate --check",
22
+ "build": "flowdular module sync --apply && pnpm --filter @app/platform build"
20
23
  },
21
24
  "devDependencies": {
22
25
  "@tsrx/prettier-plugin": "0.3.120",
23
26
  "prettier": "3.6.2",
24
- "flowdular": "0.2.2"
27
+ "flowdular": "0.2.3",
28
+ "rulesync": "16.21.0"
25
29
  }
26
30
  }
@@ -34,9 +34,13 @@ function checkedRoutes<T extends Parameters<typeof assertRouteConflicts>[0]>(
34
34
 
35
35
  const SHELL = ['App', '/src/App.tsrx'] as const;
36
36
  const workspaceRoot = resolve(import.meta.dirname, '..');
37
+ const building = process.env.FD_INTERNAL_BUILD === 'true';
37
38
 
38
39
  const databases = createPlatformDatabaseProvider(
39
- databaseProviderConfigFromEnvironment(process.env, workspaceRoot),
40
+ databaseProviderConfigFromEnvironment(
41
+ building ? { ...process.env, NODE_ENV: 'development' } : process.env,
42
+ workspaceRoot,
43
+ ),
40
44
  );
41
45
  const configuredApplicationPath = validateApplicationPath(
42
46
  process.env.FD_APPLICATION_PATH ?? applicationBasePath,
@@ -68,9 +72,11 @@ agentDefinitions.seal();
68
72
 
69
73
  /* check() proves the runtime role holds neither SUPERUSER nor BYPASSRLS before
70
74
  any module reads a row. */
71
- await databases.check();
72
- for (const composition of moduleCompositions) await composition.prepare?.();
73
- for (const composition of moduleCompositions) composition.start?.();
75
+ if (!building) {
76
+ await databases.check();
77
+ for (const composition of moduleCompositions) await composition.prepare?.();
78
+ for (const composition of moduleCompositions) composition.start?.();
79
+ }
74
80
 
75
81
  let stopping = false;
76
82
  const shutdown = async () => {
@@ -83,8 +89,13 @@ const shutdown = async () => {
83
89
  await authRuntime.dispose();
84
90
  await databases.dispose();
85
91
  };
86
- process.once('SIGINT', () => void shutdown());
87
- process.once('SIGTERM', () => void shutdown());
92
+ // Bundling needs route declarations without background work or retained leases.
93
+ if (building) {
94
+ await shutdown();
95
+ } else {
96
+ process.once('SIGINT', () => void shutdown());
97
+ process.once('SIGTERM', () => void shutdown());
98
+ }
88
99
 
89
100
  export default defineConfig({
90
101
  middlewares: [authRuntime.middleware],
@@ -6,7 +6,8 @@
6
6
  "scripts": {
7
7
  "dev": "node scripts/dev.mjs",
8
8
  "preview": "octane-preview --host 127.0.0.1 --port 4310 --strictPort",
9
- "typecheck": "tsrx-tsc --noEmit -p tsconfig.json"
9
+ "typecheck": "tsrx-tsc --noEmit -p tsconfig.json",
10
+ "build": "node scripts/build.mjs"
10
11
  },
11
12
  "dependencies": {
12
13
  "@app/module-example": "workspace:*",
@@ -14,7 +15,7 @@
14
15
  "@octanejs/vite-plugin": "0.1.51",
15
16
  "octane": "0.1.51",
16
17
  "pg": "8.23.0",
17
- "@flowdular/sdk": "0.2.2"
18
+ "@flowdular/sdk": "0.2.3"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@octanejs/app-core": "0.0.47",