@open-mercato/cli 0.6.7 → 0.6.8-canary.320.1.bf889f49e4

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 (335) hide show
  1. package/.turbo/turbo-build.log +77 -4
  2. package/AGENTS.md +6 -1
  3. package/build.mjs +68 -11
  4. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +32 -88
  5. package/dist/agentic/codex/enforcement-rules.md +2 -16
  6. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +19 -50
  7. package/dist/agentic/cursor/rules/entity-guard.mdc +9 -21
  8. package/dist/agentic/cursor/rules/generated-guard.mdc +3 -5
  9. package/dist/agentic/cursor/rules/open-mercato.mdc +3 -29
  10. package/dist/agentic/guides/ai-workflows.md +76 -0
  11. package/dist/agentic/guides/architecture.md +107 -0
  12. package/dist/agentic/guides/backend-ui.md +86 -0
  13. package/dist/agentic/guides/contracts.md +92 -0
  14. package/dist/agentic/guides/extensions.md +121 -0
  15. package/dist/agentic/guides/framework-extension-points.md +36 -0
  16. package/dist/agentic/guides/integrations.md +81 -0
  17. package/dist/agentic/guides/module-facts.json +116757 -3951
  18. package/dist/agentic/guides/module-system.md +12 -127
  19. package/dist/agentic/guides/modules/ai_assistant.md +227 -28
  20. package/dist/agentic/guides/modules/api_docs.md +58 -2
  21. package/dist/agentic/guides/modules/api_keys.md +92 -7
  22. package/dist/agentic/guides/modules/attachments.md +119 -14
  23. package/dist/agentic/guides/modules/audit_logs.md +131 -10
  24. package/dist/agentic/guides/modules/auth.md +276 -33
  25. package/dist/agentic/guides/modules/business_rules.md +149 -14
  26. package/dist/agentic/guides/modules/catalog.md +482 -43
  27. package/dist/agentic/guides/modules/channel_gmail.md +82 -3
  28. package/dist/agentic/guides/modules/channel_imap.md +82 -3
  29. package/dist/agentic/guides/modules/checkout.md +305 -27
  30. package/dist/agentic/guides/modules/communication_channels.md +315 -33
  31. package/dist/agentic/guides/modules/configs.md +104 -8
  32. package/dist/agentic/guides/modules/content.md +57 -2
  33. package/dist/agentic/guides/modules/currencies.md +152 -17
  34. package/dist/agentic/guides/modules/customer_accounts.md +387 -45
  35. package/dist/agentic/guides/modules/customers.md +746 -85
  36. package/dist/agentic/guides/modules/dashboards.md +155 -10
  37. package/dist/agentic/guides/modules/data_sync.md +149 -16
  38. package/dist/agentic/guides/modules/design_system.md +102 -0
  39. package/dist/agentic/guides/modules/dictionaries.md +107 -12
  40. package/dist/agentic/guides/modules/directory.md +148 -15
  41. package/dist/agentic/guides/modules/entities.md +145 -13
  42. package/dist/agentic/guides/modules/events.md +59 -2
  43. package/dist/agentic/guides/modules/feature_toggles.md +119 -9
  44. package/dist/agentic/guides/modules/gateway_stripe.md +92 -4
  45. package/dist/agentic/guides/modules/generators.md +45 -2
  46. package/dist/agentic/guides/modules/inbox_ops.md +207 -27
  47. package/dist/agentic/guides/modules/integrations.md +149 -16
  48. package/dist/agentic/guides/modules/messages.md +223 -24
  49. package/dist/agentic/guides/modules/notifications.md +96 -8
  50. package/dist/agentic/guides/modules/onboarding.md +77 -6
  51. package/dist/agentic/guides/modules/payment_gateways.md +168 -21
  52. package/dist/agentic/guides/modules/perspectives.md +77 -7
  53. package/dist/agentic/guides/modules/planner.md +136 -18
  54. package/dist/agentic/guides/modules/portal.md +93 -2
  55. package/dist/agentic/guides/modules/progress.md +104 -14
  56. package/dist/agentic/guides/modules/query_index.md +154 -15
  57. package/dist/agentic/guides/modules/record_locks.md +206 -21
  58. package/dist/agentic/guides/modules/resources.md +197 -30
  59. package/dist/agentic/guides/modules/sales.md +687 -84
  60. package/dist/agentic/guides/modules/scheduler.md +133 -14
  61. package/dist/agentic/guides/modules/search.md +170 -6
  62. package/dist/agentic/guides/modules/security.md +294 -35
  63. package/dist/agentic/guides/modules/shipping_carriers.md +134 -18
  64. package/dist/agentic/guides/modules/sso.md +151 -26
  65. package/dist/agentic/guides/modules/staff.md +372 -57
  66. package/dist/agentic/guides/modules/storage_s3.md +95 -5
  67. package/dist/agentic/guides/modules/sync_akeneo.md +85 -3
  68. package/dist/agentic/guides/modules/sync_excel.md +75 -6
  69. package/dist/agentic/guides/modules/system_status_overlays.md +60 -2
  70. package/dist/agentic/guides/modules/translations.md +104 -10
  71. package/dist/agentic/guides/modules/webhooks.md +203 -24
  72. package/dist/agentic/guides/modules/wms.md +469 -47
  73. package/dist/agentic/guides/modules/workflows.md +302 -43
  74. package/dist/agentic/guides/reference-module-facts.json +6942 -0
  75. package/dist/agentic/guides/reference-modules/example.md +462 -0
  76. package/dist/agentic/guides/spec-delivery.md +56 -0
  77. package/dist/agentic/guides/testing-debugging.md +80 -0
  78. package/dist/agentic/guides/upstream/AGENTS.md +300 -0
  79. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +334 -0
  80. package/dist/agentic/guides/upstream/manifest.json +8 -0
  81. package/dist/agentic/shared/AGENTS.md.template +120 -311
  82. package/dist/agentic/shared/ai/agentic.config.json +2 -0
  83. package/dist/agentic/shared/ai/harness/README.md +50 -0
  84. package/dist/agentic/shared/ai/harness/RELEASE.md +59 -0
  85. package/dist/agentic/shared/ai/harness/cases.json +20596 -0
  86. package/dist/agentic/shared/ai/harness/cases.schema.json +196 -0
  87. package/dist/agentic/shared/ai/harness/design-system-inventory.json +6326 -0
  88. package/dist/agentic/shared/ai/harness/fixtures/index.json +51 -0
  89. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +166 -0
  90. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +21 -0
  91. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +96 -0
  92. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +172 -0
  93. package/dist/agentic/shared/ai/harness/knowledge-change.schema.json +228 -0
  94. package/dist/agentic/shared/ai/harness/release-matrix.json +163 -0
  95. package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
  96. package/dist/agentic/shared/ai/harness/result.schema.json +136 -0
  97. package/dist/agentic/shared/ai/harness/routing-response.schema.json +22 -0
  98. package/dist/agentic/shared/ai/harness/source-link-inventory.json +1706 -0
  99. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
  100. package/dist/agentic/shared/ai/harness/validators.json +82 -0
  101. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +2121 -0
  102. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
  103. package/dist/agentic/shared/ai/harness/writable-spec-oracles.mjs +602 -0
  104. package/dist/agentic/shared/ai/lessons/_template.md +16 -0
  105. package/dist/agentic/shared/ai/lessons.md +26 -3
  106. package/dist/agentic/shared/ai/review-checklist.md +36 -0
  107. package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +21 -0
  108. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
  109. package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +98 -0
  110. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +21 -241
  111. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +31 -0
  112. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
  113. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +15 -0
  114. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
  115. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
  116. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
  117. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
  118. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
  119. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
  120. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
  121. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
  122. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
  123. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
  124. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +17 -601
  125. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +21 -0
  126. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +15 -0
  127. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +16 -0
  128. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
  129. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +15 -310
  130. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +19 -0
  131. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +31 -0
  132. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +100 -0
  133. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
  134. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/knowledge-change.md +133 -0
  135. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
  136. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
  137. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
  138. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
  139. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
  140. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +18 -0
  141. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
  142. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +33 -152
  143. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +33 -0
  144. package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +40 -0
  145. package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +27 -0
  146. package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +24 -0
  147. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +25 -708
  148. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
  149. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +25 -0
  150. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
  151. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
  152. package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +34 -0
  153. package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +4 -0
  154. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +11 -0
  155. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +31 -0
  156. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +39 -0
  157. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +43 -0
  158. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +11 -0
  159. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
  160. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +32 -0
  161. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +172 -0
  162. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +14 -0
  163. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
  164. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +40 -0
  165. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
  166. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
  167. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
  168. package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +41 -0
  169. package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +19 -0
  170. package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +44 -0
  171. package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +39 -0
  172. package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +20 -0
  173. package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +57 -0
  174. package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +11 -0
  175. package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +486 -0
  176. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +20 -843
  177. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +42 -0
  178. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +27 -0
  179. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
  180. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +43 -0
  181. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
  182. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
  183. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
  184. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +17 -467
  185. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +29 -0
  186. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
  187. package/dist/agentic/shared/ai/skills/tiers.json +143 -21
  188. package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
  189. package/dist/agentic/shared/ai/specs/2026-08-06-reference-module-activation.md +248 -0
  190. package/dist/agentic/shared/ai/specs/README.md +4 -3
  191. package/dist/agentic/shared/ai/specs/SPEC-000-template.md +226 -10
  192. package/dist/agentic/shared/ai/trackers/github.md +108 -4
  193. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +224 -0
  194. package/dist/agentic/shared/scripts/check-lessons.mjs +178 -0
  195. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +3812 -0
  196. package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
  197. package/dist/agentic/shared/scripts/framework-context.mjs +888 -0
  198. package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
  199. package/dist/agentic/shared/scripts/install-skills.sh +4 -694
  200. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
  201. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1774 -0
  202. package/dist/agentic/shared/scripts/validate-knowledge-change.mjs +1172 -0
  203. package/dist/bin.js +32 -34
  204. package/dist/bin.js.map +2 -2
  205. package/dist/lib/__integration__/TC-INT-008.spec.js +88 -8
  206. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  207. package/dist/lib/agentic-init.js +13 -3
  208. package/dist/lib/agentic-init.js.map +2 -2
  209. package/dist/lib/agentic-setup.js +434 -186
  210. package/dist/lib/agentic-setup.js.map +2 -2
  211. package/dist/lib/cli-bootstrap-mode.js +32 -0
  212. package/dist/lib/cli-bootstrap-mode.js.map +7 -0
  213. package/dist/lib/dev-supervisor-manifest.js +105 -0
  214. package/dist/lib/dev-supervisor-manifest.js.map +7 -0
  215. package/dist/lib/generate-watch-events.js +15 -0
  216. package/dist/lib/generate-watch-events.js.map +2 -2
  217. package/dist/lib/generators/entity-ids.js +11 -24
  218. package/dist/lib/generators/entity-ids.js.map +2 -2
  219. package/dist/lib/generators/extensions/injection-widgets.js +20 -0
  220. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  221. package/dist/lib/generators/module-di.js +10 -23
  222. package/dist/lib/generators/module-di.js.map +2 -2
  223. package/dist/lib/generators/module-entities.js +10 -23
  224. package/dist/lib/generators/module-entities.js.map +2 -2
  225. package/dist/lib/generators/module-extension-facts.js +1882 -0
  226. package/dist/lib/generators/module-extension-facts.js.map +7 -0
  227. package/dist/lib/generators/module-fact-sources.js +70 -0
  228. package/dist/lib/generators/module-fact-sources.js.map +7 -0
  229. package/dist/lib/generators/module-facts-discovery.js +64 -7
  230. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  231. package/dist/lib/generators/module-facts.js +1913 -52
  232. package/dist/lib/generators/module-facts.js.map +3 -3
  233. package/dist/lib/generators/module-override-targets.js +712 -0
  234. package/dist/lib/generators/module-override-targets.js.map +7 -0
  235. package/dist/lib/generators/module-registry.js +405 -36
  236. package/dist/lib/generators/module-registry.js.map +2 -2
  237. package/dist/lib/generators/route-manifest-shards.js +170 -0
  238. package/dist/lib/generators/route-manifest-shards.js.map +7 -0
  239. package/dist/lib/in-process-generate-watcher.js +12 -3
  240. package/dist/lib/in-process-generate-watcher.js.map +2 -2
  241. package/dist/lib/load-env.js +24 -0
  242. package/dist/lib/load-env.js.map +7 -0
  243. package/dist/lib/queue-worker-supervisor.js.map +2 -2
  244. package/dist/lib/resolver.js +28 -3
  245. package/dist/lib/resolver.js.map +2 -2
  246. package/dist/lib/telemetry-init.js +358 -0
  247. package/dist/lib/telemetry-init.js.map +7 -0
  248. package/dist/lib/testing/integration.js +5 -2
  249. package/dist/lib/testing/integration.js.map +2 -2
  250. package/dist/lib/utils.js +15 -8
  251. package/dist/lib/utils.js.map +2 -2
  252. package/dist/mercato.js +35 -9
  253. package/dist/mercato.js.map +2 -2
  254. package/package.json +13 -11
  255. package/src/__tests__/mercato.test.ts +144 -0
  256. package/src/bin.ts +60 -42
  257. package/src/lib/__integration__/TC-INT-008.spec.ts +107 -9
  258. package/src/lib/__tests__/agentic-init.test.ts +41 -5
  259. package/src/lib/__tests__/agentic-setup.ownership.test.ts +386 -0
  260. package/src/lib/__tests__/cli-bootstrap-mode.test.ts +22 -0
  261. package/src/lib/__tests__/content-stable-writes.test.ts +74 -0
  262. package/src/lib/__tests__/dev-supervisor-manifest.test.ts +131 -0
  263. package/src/lib/__tests__/generate-watch-events.test.ts +76 -0
  264. package/src/lib/__tests__/in-process-generate-watcher.test.ts +52 -1
  265. package/src/lib/__tests__/injection-widget-id-validation.test.ts +184 -0
  266. package/src/lib/__tests__/load-env.test.ts +65 -0
  267. package/src/lib/__tests__/queue-worker-supervisor.test.ts +33 -0
  268. package/src/lib/__tests__/resolver.enterprise.test.ts +50 -0
  269. package/src/lib/__tests__/telemetry-init.test.ts +298 -0
  270. package/src/lib/agentic-init.ts +15 -3
  271. package/src/lib/agentic-setup.ts +573 -222
  272. package/src/lib/cli-bootstrap-mode.ts +31 -0
  273. package/src/lib/dev-supervisor-manifest.ts +142 -0
  274. package/src/lib/generate-watch-events.ts +14 -0
  275. package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
  276. package/src/lib/generators/__tests__/entity-ids.test.ts +32 -0
  277. package/src/lib/generators/__tests__/helpers/override-target-diagnostic-fixtures.ts +150 -0
  278. package/src/lib/generators/__tests__/module-extension-activations.test.ts +762 -0
  279. package/src/lib/generators/__tests__/module-extension-facts.test.ts +603 -0
  280. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +139 -2
  281. package/src/lib/generators/__tests__/module-facts.computed-di-token.test.ts +88 -0
  282. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
  283. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
  284. package/src/lib/generators/__tests__/module-facts.example-fact-coverage.test.ts +414 -0
  285. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
  286. package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +393 -0
  287. package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +561 -0
  288. package/src/lib/generators/__tests__/module-facts.search-entity-id.test.ts +151 -0
  289. package/src/lib/generators/__tests__/module-facts.source-links.test.ts +160 -0
  290. package/src/lib/generators/__tests__/module-override-targets.diagnostic-wiring.test.ts +92 -0
  291. package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +149 -0
  292. package/src/lib/generators/__tests__/module-override-targets.test.ts +328 -0
  293. package/src/lib/generators/__tests__/module-override-targets.unknown-mode.test.ts +117 -0
  294. package/src/lib/generators/__tests__/module-subset.test.ts +266 -0
  295. package/src/lib/generators/__tests__/output-snapshots.test.ts +3 -3
  296. package/src/lib/generators/__tests__/route-manifest-shards.test.ts +62 -0
  297. package/src/lib/generators/entity-ids.ts +10 -26
  298. package/src/lib/generators/extensions/injection-widgets.ts +51 -0
  299. package/src/lib/generators/module-di.ts +9 -25
  300. package/src/lib/generators/module-entities.ts +9 -25
  301. package/src/lib/generators/module-extension-facts.ts +2472 -0
  302. package/src/lib/generators/module-fact-sources.ts +108 -0
  303. package/src/lib/generators/module-facts-discovery.ts +104 -7
  304. package/src/lib/generators/module-facts.ts +2747 -138
  305. package/src/lib/generators/module-override-targets.ts +907 -0
  306. package/src/lib/generators/module-registry.ts +448 -35
  307. package/src/lib/generators/route-manifest-shards.ts +146 -0
  308. package/src/lib/in-process-generate-watcher.ts +13 -4
  309. package/src/lib/load-env.ts +30 -0
  310. package/src/lib/queue-worker-supervisor.ts +7 -2
  311. package/src/lib/resolver.ts +34 -3
  312. package/src/lib/telemetry-init.ts +461 -0
  313. package/src/lib/testing/__tests__/integration.test.ts +4 -0
  314. package/src/lib/testing/integration.ts +5 -2
  315. package/src/lib/utils.ts +24 -16
  316. package/src/mercato.ts +46 -9
  317. package/dist/agentic/guides/cache.md +0 -45
  318. package/dist/agentic/guides/core.md +0 -453
  319. package/dist/agentic/guides/events.md +0 -117
  320. package/dist/agentic/guides/queue.md +0 -53
  321. package/dist/agentic/guides/search.md +0 -115
  322. package/dist/agentic/guides/shared.md +0 -108
  323. package/dist/agentic/guides/ui.md +0 -347
  324. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
  325. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
  326. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
  327. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
  328. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
  329. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
  330. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
  331. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
  332. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
  333. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
  334. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
  335. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
@@ -4,6 +4,12 @@ import { pathToFileURL } from 'node:url'
4
4
  import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'
5
5
  import ts from 'typescript-js'
6
6
  import type { ModuleEntry, PackageResolver } from '../resolver'
7
+ import {
8
+ DEV_SUPERVISOR_MANIFEST_FILE,
9
+ DEV_SUPERVISOR_MANIFEST_VERSION,
10
+ type DevSupervisorSchedulerStartStatus,
11
+ type DevSupervisorWorkerDescriptor,
12
+ } from '../dev-supervisor-manifest'
7
13
  import {
8
14
  calculateStructureChecksum,
9
15
  toVar,
@@ -67,6 +73,12 @@ import {
67
73
  } from './scanner'
68
74
  import { loadGeneratorExtensions } from './extensions'
69
75
  import type { ModuleScanContext, StandaloneConfigOptions } from './extension'
76
+ import {
77
+ renderRouteManifestShardOutputs,
78
+ renderRouteMetadataOutput,
79
+ routeManifestShardFilePattern,
80
+ type RouteManifestShardEntry,
81
+ } from './route-manifest-shards'
70
82
 
71
83
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
72
84
 
@@ -128,6 +140,10 @@ type CommandLoaderGenerationEntry = {
128
140
  ids: string[]
129
141
  }
130
142
 
143
+ type WorkerGenerationEntry = DevSupervisorWorkerDescriptor & {
144
+ importPath: string
145
+ }
146
+
131
147
  type RuntimeApiMethodMetadata = {
132
148
  requireAuth?: boolean
133
149
  requireRoles?: string[]
@@ -144,6 +160,8 @@ type PageRouteGenerationResult = {
144
160
  eagerRoutes: string[]
145
161
  runtimeRoutes: string[]
146
162
  manifestRoutes: string[]
163
+ manifestShardRoutes: RouteManifestShardEntry[]
164
+ metadataRoutes: RouteManifestShardEntry[]
147
165
  routePatterns: string[]
148
166
  }
149
167
 
@@ -173,6 +191,8 @@ type ApiRouteGenerationResult = {
173
191
  eagerApis: string[]
174
192
  runtimeApis: string[]
175
193
  manifestApis: string[]
194
+ manifestShardApis: RouteManifestShardEntry[]
195
+ metadataApis: RouteManifestShardEntry[]
176
196
  }
177
197
 
178
198
  type SerializablePageMetadata = {
@@ -224,6 +244,8 @@ type SerializableWorkerMetadata = {
224
244
  id?: string
225
245
  queue?: string
226
246
  concurrency?: number
247
+ lockDuration?: number
248
+ maxStalledCount?: number
227
249
  }
228
250
 
229
251
  type PageMetadataManifestLoadResult = {
@@ -1155,7 +1177,7 @@ function collectStringArrayElements(expr: ts.Expression, stringConstants: Map<st
1155
1177
  return values
1156
1178
  }
1157
1179
 
1158
- function extractCommandIdsFromSource(sourcePath: string): string[] {
1180
+ export function extractCommandIdsFromSource(sourcePath: string): string[] {
1159
1181
  const sourceText = fs.readFileSync(sourcePath, 'utf8')
1160
1182
  const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
1161
1183
  const ids = new Set<string>()
@@ -1553,6 +1575,8 @@ function normalizeWorkerMetadata(raw: unknown): SerializableWorkerMetadata | nul
1553
1575
  if (typeof source.id === 'string' && source.id.length > 0) normalized.id = source.id
1554
1576
  if (typeof source.queue === 'string' && source.queue.length > 0) normalized.queue = source.queue
1555
1577
  if (typeof source.concurrency === 'number') normalized.concurrency = source.concurrency
1578
+ if (typeof source.lockDuration === 'number') normalized.lockDuration = source.lockDuration
1579
+ if (typeof source.maxStalledCount === 'number') normalized.maxStalledCount = source.maxStalledCount
1556
1580
  return Object.keys(normalized).length > 0 ? normalized : null
1557
1581
  }
1558
1582
 
@@ -1627,12 +1651,16 @@ function discoverTranslations(roots: ModuleRoots): DiscoveredTranslation[] {
1627
1651
  const locales = new Set<string>()
1628
1652
  if (fs.existsSync(i18nCore)) {
1629
1653
  for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
1630
- if (entry.isFile() && entry.name.endsWith('.json')) locales.add(entry.name.replace(/\.json$/, ''))
1654
+ if (entry.isFile() && /^[a-zA-Z0-9][a-zA-Z0-9_-]*\.json$/.test(entry.name)) {
1655
+ locales.add(entry.name.replace(/\.json$/, ''))
1656
+ }
1631
1657
  }
1632
1658
  }
1633
1659
  if (fs.existsSync(i18nApp)) {
1634
1660
  for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
1635
- if (entry.isFile() && entry.name.endsWith('.json')) locales.add(entry.name.replace(/\.json$/, ''))
1661
+ if (entry.isFile() && /^[a-zA-Z0-9][a-zA-Z0-9_-]*\.json$/.test(entry.name)) {
1662
+ locales.add(entry.name.replace(/\.json$/, ''))
1663
+ }
1636
1664
  }
1637
1665
  }
1638
1666
  return Array.from(locales, (locale) => ({
@@ -1744,6 +1772,8 @@ async function processPageFiles(options: {
1744
1772
  const eagerRoutes: string[] = []
1745
1773
  const runtimeRoutes: string[] = []
1746
1774
  const manifestRoutes: string[] = []
1775
+ const manifestShardRoutes: RouteManifestShardEntry[] = []
1776
+ const metadataRoutes: RouteManifestShardEntry[] = []
1747
1777
  const routePatterns: string[] = []
1748
1778
 
1749
1779
  // Next-style page.* files
@@ -1815,7 +1845,19 @@ async function processPageFiles(options: {
1815
1845
  const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
1816
1846
  eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
1817
1847
  runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
1818
- manifestRoutes.push(`{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`)
1848
+ const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
1849
+ const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
1850
+ manifestRoutes.push(manifestDeclaration)
1851
+ manifestShardRoutes.push({
1852
+ path: routePath,
1853
+ declaration: manifestDeclaration,
1854
+ imports: manifestImportStatement ? [manifestImportStatement] : [],
1855
+ })
1856
+ metadataRoutes.push({
1857
+ path: routePath,
1858
+ declaration: metadataDeclaration,
1859
+ imports: manifestImportStatement ? [manifestImportStatement] : [],
1860
+ })
1819
1861
  routePatterns.push(routePath)
1820
1862
  }
1821
1863
 
@@ -1894,7 +1936,19 @@ async function processPageFiles(options: {
1894
1936
  const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
1895
1937
  eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
1896
1938
  runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
1897
- manifestRoutes.push(`{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`)
1939
+ const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
1940
+ const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
1941
+ manifestRoutes.push(manifestDeclaration)
1942
+ manifestShardRoutes.push({
1943
+ path: routePath,
1944
+ declaration: manifestDeclaration,
1945
+ imports: manifestImportStatement ? [manifestImportStatement] : [],
1946
+ })
1947
+ metadataRoutes.push({
1948
+ path: routePath,
1949
+ declaration: metadataDeclaration,
1950
+ imports: manifestImportStatement ? [manifestImportStatement] : [],
1951
+ })
1898
1952
  routePatterns.push(routePath)
1899
1953
  }
1900
1954
 
@@ -1902,6 +1956,8 @@ async function processPageFiles(options: {
1902
1956
  eagerRoutes,
1903
1957
  runtimeRoutes,
1904
1958
  manifestRoutes,
1959
+ manifestShardRoutes,
1960
+ metadataRoutes,
1905
1961
  routePatterns,
1906
1962
  }
1907
1963
  }
@@ -1918,12 +1974,14 @@ async function processApiRoutes(options: {
1918
1974
  const apiApp = path.join(roots.appBase, 'api')
1919
1975
  const apiPkg = path.join(roots.pkgBase, 'api')
1920
1976
  if (!fs.existsSync(apiApp) && !fs.existsSync(apiPkg)) {
1921
- return { eagerApis: [], runtimeApis: [], manifestApis: [] }
1977
+ return { eagerApis: [], runtimeApis: [], manifestApis: [], manifestShardApis: [], metadataApis: [] }
1922
1978
  }
1923
1979
 
1924
1980
  const eagerApis: string[] = []
1925
1981
  const runtimeApis: string[] = []
1926
1982
  const manifestApis: string[] = []
1983
+ const manifestShardApis: RouteManifestShardEntry[] = []
1984
+ const metadataApis: RouteManifestShardEntry[] = []
1927
1985
 
1928
1986
  // route.* aggregations
1929
1987
  const routeFiles = scanModuleDir(roots, SCAN_CONFIGS.apiRoutes)
@@ -1954,7 +2012,11 @@ async function processApiRoutes(options: {
1954
2012
  eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
1955
2013
  eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
1956
2014
  runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((method) => `${method}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${method}(req, ctx) }`).join(', ')} } }`)
1957
- manifestApis.push(`{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`)
2015
+ const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}] }`
2016
+ const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
2017
+ manifestApis.push(manifestDeclaration)
2018
+ manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
2019
+ metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
1958
2020
  }
1959
2021
 
1960
2022
  // Single files (plain scripts, not route.*, not tests, skip method dirs)
@@ -1986,7 +2048,11 @@ async function processApiRoutes(options: {
1986
2048
  eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
1987
2049
  eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
1988
2050
  runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((entryMethod) => `${entryMethod}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${entryMethod}(req, ctx) }`).join(', ')} } }`)
1989
- manifestApis.push(`{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`)
2051
+ const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}] }`
2052
+ const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
2053
+ manifestApis.push(manifestDeclaration)
2054
+ manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
2055
+ metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
1990
2056
  }
1991
2057
 
1992
2058
  // Legacy per-method
@@ -2028,7 +2094,11 @@ async function processApiRoutes(options: {
2028
2094
  eagerImports.push(buildImportStatement(`${importName}, * as ${metaName}`, importPath))
2029
2095
  eagerApis.push(`{ method: ${toLiteral(method)}, path: (${metaName}.metadata?.path ?? ${toLiteral(routePath)}), handler: ${importName}, metadata: ${metaName}.metadata${docsPart} }`)
2030
2096
  runtimeApis.push(`{ method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, handler: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const handler = ((mod as any).default ?? (mod as any).${method} ?? (mod as any).handler) as any; return handler(req, ctx) }, metadata: ${metadataLiteral} }`)
2031
- manifestApis.push(`{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}], load: async () => ${buildDynamicImportExpression(importPath)} }`)
2097
+ const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}] }`
2098
+ const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}], load: async () => ${buildDynamicImportExpression(importPath)} }`
2099
+ manifestApis.push(manifestDeclaration)
2100
+ manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
2101
+ metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
2032
2102
  }
2033
2103
  }
2034
2104
 
@@ -2036,6 +2106,8 @@ async function processApiRoutes(options: {
2036
2106
  eagerApis,
2037
2107
  runtimeApis,
2038
2108
  manifestApis,
2109
+ manifestShardApis,
2110
+ metadataApis,
2039
2111
  }
2040
2112
  }
2041
2113
 
@@ -2055,7 +2127,7 @@ function processWorkers(discovered: DiscoveredWorker[]): string[] {
2055
2127
  for (const { id, importPath, metadata } of discovered) {
2056
2128
  const workerId = metadata.id ?? id
2057
2129
  workers.push(
2058
- `{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
2130
+ `{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === undefined ? '' : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === undefined ? '' : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
2059
2131
  )
2060
2132
  }
2061
2133
  return workers
@@ -2730,6 +2802,8 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
2730
2802
  { name: 'id', value: workerId },
2731
2803
  { name: 'queue', value: metadata.queue },
2732
2804
  { name: 'concurrency', value: metadata.concurrency ?? 1 },
2805
+ ...(metadata.lockDuration === undefined ? [] : [{ name: 'lockDuration', value: metadata.lockDuration }]),
2806
+ ...(metadata.maxStalledCount === undefined ? [] : [{ name: 'maxStalledCount', value: metadata.maxStalledCount }]),
2733
2807
  {
2734
2808
  name: 'handler',
2735
2809
  value: callExpression(identifier('createLazyModuleWorker'), [
@@ -2745,6 +2819,24 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
2745
2819
  return workers
2746
2820
  }
2747
2821
 
2822
+ function collectWorkerGenerationEntries(
2823
+ discovered: DiscoveredWorker[],
2824
+ moduleId: string,
2825
+ ): WorkerGenerationEntry[] {
2826
+ const workers: WorkerGenerationEntry[] = []
2827
+ for (const { id, importPath, metadata } of discovered) {
2828
+ if (!metadata.queue) continue
2829
+ workers.push({
2830
+ id: metadata.id ?? id,
2831
+ moduleId,
2832
+ queue: metadata.queue,
2833
+ concurrency: metadata.concurrency ?? 1,
2834
+ importPath,
2835
+ })
2836
+ }
2837
+ return workers
2838
+ }
2839
+
2748
2840
  function processTranslationsAst(options: {
2749
2841
  discovered: DiscoveredTranslation[]
2750
2842
  modId: string
@@ -2752,8 +2844,9 @@ function processTranslationsAst(options: {
2752
2844
  pkgImportBase: string
2753
2845
  imports: string[]
2754
2846
  extraImports?: string[]
2847
+ localeOutputs?: Map<string, { imports: string[]; value: WriterFunction }>
2755
2848
  }): GeneratedObjectEntry[] {
2756
- const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
2849
+ const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports, localeOutputs } = options
2757
2850
 
2758
2851
  const translations: GeneratedObjectEntry[] = []
2759
2852
 
@@ -2762,45 +2855,236 @@ function processTranslationsAst(options: {
2762
2855
  if (coreHas && appHas) {
2763
2856
  const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`
2764
2857
  const appName = `T_${toVar(modId)}_${toVar(locale)}_A`
2765
- imports.push(buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`))
2766
- imports.push(buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`))
2767
- extraImports?.push(buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`))
2768
- extraImports?.push(buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`))
2858
+ const localeImports = [
2859
+ buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`),
2860
+ buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`),
2861
+ ]
2862
+ imports.push(...localeImports)
2863
+ extraImports?.push(...localeImports)
2864
+ const value = objectLiteral([
2865
+ { kind: 'spread', value: asExpression(identifier(coreName), 'unknown as Record<string, string>') },
2866
+ { kind: 'spread', value: asExpression(identifier(appName), 'unknown as Record<string, string>') },
2867
+ ])
2769
2868
  translations.push({
2770
2869
  name: JSON.stringify(locale),
2771
- value: objectLiteral([
2772
- { kind: 'spread', value: asExpression(identifier(coreName), 'unknown as Record<string, string>') },
2773
- { kind: 'spread', value: asExpression(identifier(appName), 'unknown as Record<string, string>') },
2774
- ]),
2870
+ value,
2775
2871
  })
2872
+ localeOutputs?.set(locale, { imports: localeImports, value })
2776
2873
  continue
2777
2874
  }
2778
2875
 
2779
2876
  if (appHas) {
2780
2877
  const appName = `T_${toVar(modId)}_${toVar(locale)}_A`
2781
- imports.push(buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`))
2782
- extraImports?.push(buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`))
2878
+ const localeImports = [buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`)]
2879
+ imports.push(...localeImports)
2880
+ extraImports?.push(...localeImports)
2881
+ const value = asExpression(identifier(appName), 'unknown as Record<string, string>')
2783
2882
  translations.push({
2784
2883
  name: JSON.stringify(locale),
2785
- value: asExpression(identifier(appName), 'unknown as Record<string, string>'),
2884
+ value,
2786
2885
  })
2886
+ localeOutputs?.set(locale, { imports: localeImports, value })
2787
2887
  continue
2788
2888
  }
2789
2889
 
2790
2890
  if (coreHas) {
2791
2891
  const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`
2792
- imports.push(buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`))
2793
- extraImports?.push(buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`))
2892
+ const localeImports = [buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`)]
2893
+ imports.push(...localeImports)
2894
+ extraImports?.push(...localeImports)
2895
+ const value = asExpression(identifier(coreName), 'unknown as Record<string, string>')
2794
2896
  translations.push({
2795
2897
  name: JSON.stringify(locale),
2796
- value: asExpression(identifier(coreName), 'unknown as Record<string, string>'),
2898
+ value,
2797
2899
  })
2900
+ localeOutputs?.set(locale, { imports: localeImports, value })
2798
2901
  }
2799
2902
  }
2800
2903
 
2801
2904
  return translations
2802
2905
  }
2803
2906
 
2907
+ function sourceDeclaresCliCommand(filePath: string, commandName: string): boolean {
2908
+ let sourceText: string
2909
+ try {
2910
+ sourceText = fs.readFileSync(filePath, 'utf8')
2911
+ } catch {
2912
+ return false
2913
+ }
2914
+ const sourceFile = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true)
2915
+ const declarations = new Map<string, ts.Expression>()
2916
+ for (const statement of sourceFile.statements) {
2917
+ if (!ts.isVariableStatement(statement)) continue
2918
+ for (const declaration of statement.declarationList.declarations) {
2919
+ if (ts.isIdentifier(declaration.name) && declaration.initializer) {
2920
+ declarations.set(declaration.name.text, declaration.initializer)
2921
+ }
2922
+ }
2923
+ }
2924
+
2925
+ const expressionDeclaresCommand = (expression: ts.Expression, seen = new Set<string>()): boolean => {
2926
+ if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression) || ts.isSatisfiesExpression(expression)) {
2927
+ return expressionDeclaresCommand(expression.expression, seen)
2928
+ }
2929
+ if (ts.isIdentifier(expression)) {
2930
+ if (seen.has(expression.text)) return false
2931
+ const initializer = declarations.get(expression.text)
2932
+ if (!initializer) return false
2933
+ const nextSeen = new Set(seen)
2934
+ nextSeen.add(expression.text)
2935
+ return expressionDeclaresCommand(initializer, nextSeen)
2936
+ }
2937
+ if (ts.isArrayLiteralExpression(expression)) {
2938
+ return expression.elements.some((element) => (
2939
+ ts.isSpreadElement(element)
2940
+ ? expressionDeclaresCommand(element.expression, seen)
2941
+ : expressionDeclaresCommand(element, seen)
2942
+ ))
2943
+ }
2944
+ if (!ts.isObjectLiteralExpression(expression)) return false
2945
+ return expression.properties.some((property) => {
2946
+ if (!ts.isPropertyAssignment(property)) return false
2947
+ const propertyName = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)
2948
+ ? property.name.text
2949
+ : null
2950
+ return propertyName === 'command'
2951
+ && (ts.isStringLiteralLike(property.initializer) || ts.isNoSubstitutionTemplateLiteral(property.initializer))
2952
+ && property.initializer.text === commandName
2953
+ })
2954
+ }
2955
+
2956
+ return sourceFile.statements.some((statement) => (
2957
+ ts.isExportAssignment(statement)
2958
+ && !statement.isExportEquals
2959
+ && expressionDeclaresCommand(statement.expression)
2960
+ ))
2961
+ }
2962
+
2963
+ function appDeclaresProgrammaticDevSupervisorOverrides(appDir: string): boolean {
2964
+ const srcDir = path.join(appDir, 'src')
2965
+ const pending = [srcDir]
2966
+ while (pending.length > 0) {
2967
+ const current = pending.pop()!
2968
+ let entries: fs.Dirent[]
2969
+ try {
2970
+ entries = fs.readdirSync(current, { withFileTypes: true })
2971
+ } catch {
2972
+ continue
2973
+ }
2974
+ for (const entry of entries) {
2975
+ const entryPath = path.join(current, entry.name)
2976
+ if (entry.isDirectory()) {
2977
+ if (entry.name !== '__tests__' && entry.name !== 'node_modules') pending.push(entryPath)
2978
+ continue
2979
+ }
2980
+ if (!/\.[cm]?tsx?$/.test(entry.name) || /(?:^|\.)test\.[cm]?tsx?$/.test(entry.name)) continue
2981
+
2982
+ let sourceText: string
2983
+ try {
2984
+ sourceText = fs.readFileSync(entryPath, 'utf8')
2985
+ } catch {
2986
+ continue
2987
+ }
2988
+ const sourceFile = ts.createSourceFile(entryPath, sourceText, ts.ScriptTarget.Latest, true)
2989
+ const directImports = new Set<string>()
2990
+ const namespaceImports = new Set<string>()
2991
+ for (const statement of sourceFile.statements) {
2992
+ if (
2993
+ !ts.isImportDeclaration(statement)
2994
+ || !ts.isStringLiteralLike(statement.moduleSpecifier)
2995
+ || statement.moduleSpecifier.text !== '@open-mercato/shared/modules/overrides'
2996
+ ) continue
2997
+ const bindings = statement.importClause?.namedBindings
2998
+ if (bindings && ts.isNamespaceImport(bindings)) namespaceImports.add(bindings.name.text)
2999
+ if (bindings && ts.isNamedImports(bindings)) {
3000
+ for (const element of bindings.elements) {
3001
+ const importedName = element.propertyName?.text ?? element.name.text
3002
+ if (importedName === 'applyWorkerOverrides' || importedName === 'applyCliOverrides') {
3003
+ directImports.add(element.name.text)
3004
+ }
3005
+ }
3006
+ }
3007
+ }
3008
+ let found = false
3009
+ const visit = (node: ts.Node): void => {
3010
+ if (found) return
3011
+ if (ts.isCallExpression(node)) {
3012
+ if (ts.isIdentifier(node.expression) && directImports.has(node.expression.text)) {
3013
+ found = true
3014
+ return
3015
+ }
3016
+ if (
3017
+ ts.isPropertyAccessExpression(node.expression)
3018
+ && ts.isIdentifier(node.expression.expression)
3019
+ && namespaceImports.has(node.expression.expression.text)
3020
+ && ['applyWorkerOverrides', 'applyCliOverrides'].includes(node.expression.name.text)
3021
+ ) {
3022
+ found = true
3023
+ return
3024
+ }
3025
+ }
3026
+ ts.forEachChild(node, visit)
3027
+ }
3028
+ visit(sourceFile)
3029
+ if (found) return true
3030
+ }
3031
+ }
3032
+ return false
3033
+ }
3034
+
3035
+ function renderAstI18nLocaleRegistryFile(options: {
3036
+ fileName: string
3037
+ imports: string[]
3038
+ moduleEntries: WriterFunction[]
3039
+ }): string {
3040
+ const sourceFile = createGeneratedSourceFile(options.fileName)
3041
+ addAutoGeneratedComment(sourceFile, 'registry (locale-specific i18n version)')
3042
+ addImportSpec(sourceFile, {
3043
+ moduleSpecifier: '@open-mercato/shared/modules/registry',
3044
+ namedImports: [{ name: 'Module', isTypeOnly: true }],
3045
+ })
3046
+ addImportStatements(sourceFile, options.imports)
3047
+ sourceFile.addVariableStatement({
3048
+ declarationKind: VariableDeclarationKind.Const,
3049
+ isExported: true,
3050
+ declarations: [{
3051
+ name: 'modules',
3052
+ type: 'Module[]',
3053
+ initializer: arrayLiteral(options.moduleEntries, writeValue),
3054
+ }],
3055
+ })
3056
+ sourceFile.addExportAssignment({
3057
+ isExportEquals: false,
3058
+ expression: 'modules',
3059
+ })
3060
+ return getSourceText(sourceFile)
3061
+ }
3062
+
3063
+ function buildI18nLocaleShardFileName(locale: string): string {
3064
+ const safeLocale = locale.replace(/[^a-zA-Z0-9_-]/g, '_')
3065
+ return `modules.i18n.${safeLocale}.generated.ts`
3066
+ }
3067
+
3068
+ function renderI18nLocaleLoadersFile(locales: string[]): string {
3069
+ const cases = locales.map((locale) => {
3070
+ const moduleSpecifier = `./${buildI18nLocaleShardFileName(locale).replace(/\.ts$/, '')}`
3071
+ return ` case ${JSON.stringify(locale)}:\n return import(${JSON.stringify(moduleSpecifier)}).then((entry) => entry.modules)`
3072
+ }).join('\n')
3073
+
3074
+ return `// AUTO-GENERATED by mercato generate registry (locale-specific i18n loaders)\nimport type { Module } from '@open-mercato/shared/modules/registry'\n\nexport async function loadI18nModules(locale: string): Promise<Module[]> {\n switch (locale) {\n${cases ? `${cases}\n` : ''} default:\n return []\n }\n}\n`
3075
+ }
3076
+
3077
+ function removeStaleI18nLocaleShards(outputDir: string, expectedFileNames: Set<string>): void {
3078
+ if (!fs.existsSync(outputDir)) return
3079
+ for (const entry of fs.readdirSync(outputDir, { withFileTypes: true })) {
3080
+ if (!entry.isFile()) continue
3081
+ if (!/^modules\.i18n\..+\.generated\.(?:ts|checksum)$/.test(entry.name)) continue
3082
+ if (entry.name.startsWith('modules.i18n.loaders.generated.')) continue
3083
+ if (expectedFileNames.has(entry.name)) continue
3084
+ fs.unlinkSync(path.join(outputDir, entry.name))
3085
+ }
3086
+ }
3087
+
2804
3088
  function resolveConventionFile(
2805
3089
  resolved: ResolvedFile | null,
2806
3090
  prefix: string,
@@ -2881,6 +3165,10 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
2881
3165
  const frontendRouteManifestDecls: string[] = []
2882
3166
  const backendRouteManifestDecls: string[] = []
2883
3167
  const apiRouteManifestDecls: string[] = []
3168
+ const backendRouteShardEntries: RouteManifestShardEntry[] = []
3169
+ const backendRouteMetadataEntries: RouteManifestShardEntry[] = []
3170
+ const apiRouteShardEntries: RouteManifestShardEntry[] = []
3171
+ const apiRouteMetadataEntries: RouteManifestShardEntry[] = []
2884
3172
  // Mutable ref so extracted helper functions can increment the shared counter
2885
3173
  const importIdRef = { value: 0 }
2886
3174
  const requiresByModule = new Map<string, string[]>()
@@ -3059,6 +3347,10 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3059
3347
  if (fields) fieldsImportName = fields.importName
3060
3348
  }
3061
3349
 
3350
+ const integrationExports = integrationImportName
3351
+ ? `(${integrationImportName} as unknown as { integrations?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]; integration?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition; bundles?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]; bundle?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle })`
3352
+ : null
3353
+
3062
3354
  // 13. Pages: backend
3063
3355
  {
3064
3356
  const beApp = path.join(roots.appBase, 'backend')
@@ -3081,6 +3373,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3081
3373
  backendRoutes.push(...generatedBackendRoutes.eagerRoutes)
3082
3374
  runtimeBackendRoutes.push(...generatedBackendRoutes.runtimeRoutes)
3083
3375
  backendRouteManifestDecls.push(...generatedBackendRoutes.manifestRoutes)
3376
+ backendRouteShardEntries.push(...generatedBackendRoutes.manifestShardRoutes)
3377
+ backendRouteMetadataEntries.push(...generatedBackendRoutes.metadataRoutes)
3084
3378
  for (const pattern of generatedBackendRoutes.routePatterns) {
3085
3379
  assertUniqueBackendRoutePattern(seenBackendRoutePatterns, modId, pattern)
3086
3380
  }
@@ -3101,6 +3395,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3101
3395
  apis.push(...generatedApis.eagerApis)
3102
3396
  runtimeApis.push(...generatedApis.runtimeApis)
3103
3397
  apiRouteManifestDecls.push(...generatedApis.manifestApis)
3398
+ apiRouteShardEntries.push(...generatedApis.manifestShardApis)
3399
+ apiRouteMetadataEntries.push(...generatedApis.metadataApis)
3104
3400
  }
3105
3401
 
3106
3402
  // 15. CLI
@@ -3167,8 +3463,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3167
3463
  ${dashboardWidgets.length ? `dashboardWidgets: [${dashboardWidgets.join(', ')}],` : ''}
3168
3464
  ${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
3169
3465
  ${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
3170
- ${integrationImportName ? `integrations: (( ${integrationImportName}.integrations ?? (${integrationImportName}.integration ? [${integrationImportName}.integration] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
3171
- ${integrationImportName ? `bundles: (( ${integrationImportName}.bundles ?? (${integrationImportName}.bundle ? [${integrationImportName}.bundle] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
3466
+ ${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
3467
+ ${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
3172
3468
  }`)
3173
3469
  runtimeModuleDecls.push(`{
3174
3470
  id: ${toLiteral(modId)},
@@ -3185,8 +3481,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3185
3481
  ${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ''}
3186
3482
  ${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
3187
3483
  ${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
3188
- ${integrationImportName ? `integrations: (( ${integrationImportName}.integrations ?? (${integrationImportName}.integration ? [${integrationImportName}.integration] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
3189
- ${integrationImportName ? `bundles: (( ${integrationImportName}.bundles ?? (${integrationImportName}.bundle ? [${integrationImportName}.bundle] : []) ) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
3484
+ ${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
3485
+ ${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
3190
3486
  }`)
3191
3487
  }
3192
3488
 
@@ -3320,6 +3616,12 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3320
3616
  exportName: 'apiRoutes',
3321
3617
  entries: apiRouteManifestDecls,
3322
3618
  })
3619
+ const routeManifestOutputs = [
3620
+ ...renderRouteManifestShardOutputs('backend', backendRouteShardEntries),
3621
+ ...renderRouteManifestShardOutputs('api', apiRouteShardEntries),
3622
+ renderRouteMetadataOutput('backend', backendRouteMetadataEntries),
3623
+ renderRouteMetadataOutput('api', apiRouteMetadataEntries),
3624
+ ]
3323
3625
  const legacySubscribersOutput = renderAstLegacyAliasFile({
3324
3626
  fileName: 'subscribers.generated.ts',
3325
3627
  exportName: 'moduleSubscribers',
@@ -3367,6 +3669,29 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3367
3669
  writeGeneratedFile({ outFile: frontendRoutesOutFile, checksumFile: frontendRoutesChecksumFile, content: frontendRoutesOutput, structureChecksum, result, quiet })
3368
3670
  writeGeneratedFile({ outFile: backendRoutesOutFile, checksumFile: backendRoutesChecksumFile, content: backendRoutesOutput, structureChecksum, result, quiet })
3369
3671
  writeGeneratedFile({ outFile: apiRoutesOutFile, checksumFile: apiRoutesChecksumFile, content: apiRoutesOutput, structureChecksum, result, quiet })
3672
+ const expectedRouteManifestFiles = new Set(routeManifestOutputs.flatMap(({ fileName }) => [
3673
+ fileName,
3674
+ fileName.replace(/\.ts$/, '.checksum'),
3675
+ ]))
3676
+ if (fs.existsSync(outputDir)) {
3677
+ for (const entry of fs.readdirSync(outputDir, { withFileTypes: true })) {
3678
+ if (!entry.isFile() || !routeManifestShardFilePattern.test(entry.name)) continue
3679
+ if (expectedRouteManifestFiles.has(entry.name)) continue
3680
+ const stalePath = path.join(outputDir, entry.name)
3681
+ fs.unlinkSync(stalePath)
3682
+ result.filesWritten.push(stalePath)
3683
+ }
3684
+ }
3685
+ for (const routeOutput of routeManifestOutputs) {
3686
+ writeGeneratedFile({
3687
+ outFile: path.join(outputDir, routeOutput.fileName),
3688
+ checksumFile: path.join(outputDir, routeOutput.fileName.replace(/\.ts$/, '.checksum')),
3689
+ content: routeOutput.content,
3690
+ structureChecksum,
3691
+ result,
3692
+ quiet,
3693
+ })
3694
+ }
3370
3695
  writeGeneratedFile({ outFile: legacySubscribersOutFile, checksumFile: legacySubscribersChecksumFile, content: legacySubscribersOutput, structureChecksum, result, quiet })
3371
3696
  const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries)
3372
3697
  writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet })
@@ -3403,14 +3728,14 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3403
3728
  {
3404
3729
  const bootstrapPlugins = [...pluginRegistry.values()].filter((p) => p.bootstrapRegistration)
3405
3730
  const allEntryImports: string[] = [
3406
- buildImportStatement(`{ backendRoutes }`, `./backend-routes.generated`),
3731
+ buildImportStatement(`{ backendRouteFacades }`, `./backend-route-shards.generated`),
3407
3732
  buildImportStatement(`{ frontendRoutes }`, `./frontend-routes.generated`),
3408
3733
  ]
3409
3734
  const allRegImports: string[] = [
3410
3735
  `import { registerBackendRouteManifests, registerFrontendRouteManifests } from '@open-mercato/shared/modules/registry'`,
3411
3736
  ]
3412
3737
  const allCalls: string[] = [
3413
- `registerBackendRouteManifests(backendRoutes)`,
3738
+ `registerBackendRouteManifests(backendRouteFacades)`,
3414
3739
  `registerFrontendRouteManifests(frontendRoutes)`,
3415
3740
  ]
3416
3741
  for (const plugin of bootstrapPlugins) {
@@ -3447,6 +3772,8 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3447
3772
  const bootstrapChecksumFile = path.join(outputDir, 'modules.bootstrap.generated.checksum')
3448
3773
  const i18nOutFile = path.join(outputDir, 'modules.i18n.generated.ts')
3449
3774
  const i18nChecksumFile = path.join(outputDir, 'modules.i18n.generated.checksum')
3775
+ const i18nLoadersOutFile = path.join(outputDir, 'modules.i18n.loaders.generated.ts')
3776
+ const i18nLoadersChecksumFile = path.join(outputDir, 'modules.i18n.loaders.generated.checksum')
3450
3777
  const legacyOutFile = path.join(outputDir, 'bootstrap-modules.generated.ts')
3451
3778
  const legacyChecksumFile = path.join(outputDir, 'bootstrap-modules.generated.checksum')
3452
3779
  const enabledIdsOutFile = path.join(outputDir, 'enabled-module-ids.generated.ts')
@@ -3461,6 +3788,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3461
3788
  const moduleDecls: WriterFunction[] = []
3462
3789
  const bootstrapModuleDecls: WriterFunction[] = []
3463
3790
  const i18nModuleDecls: WriterFunction[] = []
3791
+ const i18nLocaleShards = new Map<string, { imports: string[]; moduleDecls: WriterFunction[] }>()
3464
3792
  const importIdRef = { value: 0 }
3465
3793
  const requiresByModule = new Map<string, string[]>()
3466
3794
  const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
@@ -3474,6 +3802,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3474
3802
  const frontendRoutes: WriterFunction[] = []
3475
3803
  const backendRoutes: WriterFunction[] = []
3476
3804
  const translations: GeneratedObjectEntry[] = []
3805
+ const localeTranslations = new Map<string, { imports: string[]; value: WriterFunction }>()
3477
3806
  const subscribers: WriterFunction[] = []
3478
3807
  const workers: WriterFunction[] = []
3479
3808
  let infoImportName: string | null = null
@@ -3602,9 +3931,24 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3602
3931
  pkgImportBase: imps.pkgBase,
3603
3932
  imports,
3604
3933
  extraImports: translationImports,
3934
+ localeOutputs: localeTranslations,
3605
3935
  }))
3606
- bootstrapImports.push(...translationImports)
3607
3936
  i18nImports.push(...translationImports)
3937
+ for (const [locale, localeTranslation] of localeTranslations) {
3938
+ const shard = i18nLocaleShards.get(locale) ?? { imports: [], moduleDecls: [] }
3939
+ shard.imports.push(...localeTranslation.imports)
3940
+ shard.moduleDecls.push(objectLiteral([
3941
+ { name: 'id', value: modId },
3942
+ {
3943
+ name: 'translations',
3944
+ value: objectLiteral([{
3945
+ name: JSON.stringify(locale),
3946
+ value: localeTranslation.value,
3947
+ }]),
3948
+ },
3949
+ ]))
3950
+ i18nLocaleShards.set(locale, shard)
3951
+ }
3608
3952
 
3609
3953
  subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
3610
3954
 
@@ -3720,7 +4064,9 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3720
4064
  }
3721
4065
 
3722
4066
  moduleDecls.push(objectLiteral(routeAwareModuleEntries))
3723
- bootstrapModuleDecls.push(objectLiteral(moduleEntries))
4067
+ bootstrapModuleDecls.push(objectLiteral(moduleEntries.filter(
4068
+ (entry) => entry.kind === 'spread' || entry.name !== 'translations',
4069
+ )))
3724
4070
  i18nModuleDecls.push(objectLiteral(i18nModuleEntries))
3725
4071
  }
3726
4072
 
@@ -3777,6 +4123,41 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
3777
4123
  writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
3778
4124
  writeGeneratedFile({ outFile: bootstrapOutFile, checksumFile: bootstrapChecksumFile, content: bootstrapOutput, structureChecksum, result, quiet })
3779
4125
  writeGeneratedFile({ outFile: i18nOutFile, checksumFile: i18nChecksumFile, content: i18nOutput, structureChecksum, result, quiet })
4126
+ const i18nLocales = [...i18nLocaleShards.keys()].sort((a, b) => a.localeCompare(b))
4127
+ const shardFileNames = new Set<string>()
4128
+ const expectedShardArtifacts = new Set<string>()
4129
+ for (const locale of i18nLocales) {
4130
+ const fileName = buildI18nLocaleShardFileName(locale)
4131
+ if (shardFileNames.has(fileName)) {
4132
+ throw new Error(`Locale names produce the same generated i18n shard file: ${locale}`)
4133
+ }
4134
+ shardFileNames.add(fileName)
4135
+ expectedShardArtifacts.add(fileName)
4136
+ expectedShardArtifacts.add(fileName.replace(/\.ts$/, '.checksum'))
4137
+ const shard = i18nLocaleShards.get(locale)!
4138
+ const content = renderAstI18nLocaleRegistryFile({
4139
+ fileName,
4140
+ imports: shard.imports,
4141
+ moduleEntries: shard.moduleDecls,
4142
+ })
4143
+ writeGeneratedFile({
4144
+ outFile: path.join(outputDir, fileName),
4145
+ checksumFile: path.join(outputDir, fileName.replace(/\.ts$/, '.checksum')),
4146
+ content,
4147
+ structureChecksum,
4148
+ result,
4149
+ quiet,
4150
+ })
4151
+ }
4152
+ removeStaleI18nLocaleShards(outputDir, expectedShardArtifacts)
4153
+ writeGeneratedFile({
4154
+ outFile: i18nLoadersOutFile,
4155
+ checksumFile: i18nLoadersChecksumFile,
4156
+ content: renderI18nLocaleLoadersFile(i18nLocales),
4157
+ structureChecksum,
4158
+ result,
4159
+ quiet,
4160
+ })
3780
4161
  writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet })
3781
4162
 
3782
4163
  const enabledIdsOutput = renderEnabledModuleIdsFile(enabled.map((entry) => entry.id))
@@ -3808,6 +4189,8 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
3808
4189
  const legacyChecksumFile = path.join(outputDir, 'cli-modules.generated.checksum')
3809
4190
  const commandLoadersOutFile = path.join(outputDir, 'command-loaders.generated.ts')
3810
4191
  const commandLoadersChecksumFile = path.join(outputDir, 'command-loaders.generated.checksum')
4192
+ const devSupervisorOutFile = path.join(outputDir, DEV_SUPERVISOR_MANIFEST_FILE)
4193
+ const devSupervisorChecksumFile = path.join(outputDir, 'dev-supervisor.generated.checksum')
3811
4194
 
3812
4195
  const enabled = discovery.enabled
3813
4196
  const imports: string[] = []
@@ -3816,9 +4199,13 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
3816
4199
  const importIdRef = { value: 0 }
3817
4200
  const requiresByModule = new Map<string, string[]>()
3818
4201
  const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
4202
+ const devSupervisorWorkers: DevSupervisorWorkerDescriptor[] = []
4203
+ let schedulerStartStatus: DevSupervisorSchedulerStartStatus = 'missing-module'
4204
+ let requiresFullBootstrap = enabled.some((entry) => entry.devSupervisorRequiresFullBootstrap === true)
4205
+ || appDeclaresProgrammaticDevSupervisorOverrides(resolver.getAppDir())
3819
4206
 
3820
4207
  for (const discovered of discovery.modules) {
3821
- const { modId, roots, imps, appImportBase } = discovered
4208
+ const { modId, imps, appImportBase } = discovered
3822
4209
  commandLoaderEntries.push(...discovered.commandLoaderEntries)
3823
4210
 
3824
4211
  let cliImportName: string | null = null
@@ -3910,11 +4297,20 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
3910
4297
 
3911
4298
  // CLI
3912
4299
  {
4300
+ if (modId === 'scheduler') schedulerStartStatus = 'missing-cli'
3913
4301
  const cliResolved = discovered.resolve('cli.ts')
3914
4302
  if (cliResolved) {
3915
4303
  const importName = `CLI_${toVar(modId)}`
3916
4304
  imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)))
3917
4305
  cliImportName = importName
4306
+ if (modId === 'scheduler') {
4307
+ if (sourceDeclaresCliCommand(cliResolved.absolutePath, 'start')) {
4308
+ schedulerStartStatus = 'ok'
4309
+ } else {
4310
+ schedulerStartStatus = 'missing-command'
4311
+ requiresFullBootstrap = true
4312
+ }
4313
+ }
3918
4314
  }
3919
4315
  }
3920
4316
 
@@ -3931,7 +4327,10 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
3931
4327
  subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
3932
4328
 
3933
4329
  // Workers
3934
- workers.push(...processWorkersAst(await discovered.getWorkers()))
4330
+ const discoveredWorkers = await discovered.getWorkers()
4331
+ const workerGenerationEntries = collectWorkerGenerationEntries(discoveredWorkers, modId)
4332
+ workers.push(...processWorkersAst(discoveredWorkers))
4333
+ devSupervisorWorkers.push(...workerGenerationEntries.map(({ importPath: _importPath, ...worker }) => worker))
3935
4334
 
3936
4335
  // Dashboard widgets
3937
4336
  {
@@ -4096,6 +4495,20 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
4096
4495
  const structureChecksum = discovery.getStructureChecksum()
4097
4496
  writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
4098
4497
  writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet })
4498
+ const devSupervisorOutput = `${JSON.stringify({
4499
+ version: DEV_SUPERVISOR_MANIFEST_VERSION,
4500
+ workers: devSupervisorWorkers,
4501
+ schedulerStartStatus,
4502
+ requiresFullBootstrap,
4503
+ }, null, 2)}\n`
4504
+ writeGeneratedFile({
4505
+ outFile: devSupervisorOutFile,
4506
+ checksumFile: devSupervisorChecksumFile,
4507
+ content: devSupervisorOutput,
4508
+ structureChecksum,
4509
+ result,
4510
+ quiet,
4511
+ })
4099
4512
  const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries)
4100
4513
  writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet })
4101
4514