@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7

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 (278) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/build.mjs +7 -24
  3. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
  4. package/dist/agentic/codex/enforcement-rules.md +16 -2
  5. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
  6. package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
  7. package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
  8. package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
  9. package/dist/agentic/guides/cache.md +45 -0
  10. package/dist/agentic/guides/core.md +453 -0
  11. package/dist/agentic/guides/events.md +117 -0
  12. package/dist/agentic/guides/module-facts.json +3833 -115419
  13. package/dist/agentic/guides/module-system.md +127 -12
  14. package/dist/agentic/guides/modules/ai_assistant.md +28 -227
  15. package/dist/agentic/guides/modules/api_docs.md +2 -58
  16. package/dist/agentic/guides/modules/api_keys.md +7 -92
  17. package/dist/agentic/guides/modules/attachments.md +14 -119
  18. package/dist/agentic/guides/modules/audit_logs.md +10 -131
  19. package/dist/agentic/guides/modules/auth.md +33 -276
  20. package/dist/agentic/guides/modules/business_rules.md +14 -149
  21. package/dist/agentic/guides/modules/catalog.md +43 -475
  22. package/dist/agentic/guides/modules/channel_gmail.md +3 -82
  23. package/dist/agentic/guides/modules/channel_imap.md +3 -82
  24. package/dist/agentic/guides/modules/checkout.md +27 -299
  25. package/dist/agentic/guides/modules/communication_channels.md +33 -315
  26. package/dist/agentic/guides/modules/configs.md +8 -104
  27. package/dist/agentic/guides/modules/content.md +2 -57
  28. package/dist/agentic/guides/modules/currencies.md +17 -152
  29. package/dist/agentic/guides/modules/customer_accounts.md +45 -387
  30. package/dist/agentic/guides/modules/customers.md +85 -746
  31. package/dist/agentic/guides/modules/dashboards.md +10 -155
  32. package/dist/agentic/guides/modules/data_sync.md +16 -149
  33. package/dist/agentic/guides/modules/dictionaries.md +12 -107
  34. package/dist/agentic/guides/modules/directory.md +15 -148
  35. package/dist/agentic/guides/modules/entities.md +13 -145
  36. package/dist/agentic/guides/modules/events.md +2 -59
  37. package/dist/agentic/guides/modules/feature_toggles.md +9 -119
  38. package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
  39. package/dist/agentic/guides/modules/generators.md +2 -45
  40. package/dist/agentic/guides/modules/inbox_ops.md +27 -207
  41. package/dist/agentic/guides/modules/integrations.md +16 -146
  42. package/dist/agentic/guides/modules/messages.md +24 -223
  43. package/dist/agentic/guides/modules/notifications.md +8 -96
  44. package/dist/agentic/guides/modules/onboarding.md +6 -77
  45. package/dist/agentic/guides/modules/payment_gateways.md +21 -164
  46. package/dist/agentic/guides/modules/perspectives.md +7 -77
  47. package/dist/agentic/guides/modules/planner.md +18 -136
  48. package/dist/agentic/guides/modules/portal.md +2 -93
  49. package/dist/agentic/guides/modules/progress.md +14 -104
  50. package/dist/agentic/guides/modules/query_index.md +15 -154
  51. package/dist/agentic/guides/modules/record_locks.md +21 -206
  52. package/dist/agentic/guides/modules/resources.md +30 -197
  53. package/dist/agentic/guides/modules/sales.md +84 -678
  54. package/dist/agentic/guides/modules/scheduler.md +14 -133
  55. package/dist/agentic/guides/modules/search.md +6 -170
  56. package/dist/agentic/guides/modules/security.md +35 -294
  57. package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
  58. package/dist/agentic/guides/modules/sso.md +26 -151
  59. package/dist/agentic/guides/modules/staff.md +57 -369
  60. package/dist/agentic/guides/modules/storage_s3.md +5 -95
  61. package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
  62. package/dist/agentic/guides/modules/sync_excel.md +6 -75
  63. package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
  64. package/dist/agentic/guides/modules/translations.md +10 -104
  65. package/dist/agentic/guides/modules/webhooks.md +24 -203
  66. package/dist/agentic/guides/modules/wms.md +46 -441
  67. package/dist/agentic/guides/modules/workflows.md +43 -302
  68. package/dist/agentic/guides/queue.md +53 -0
  69. package/dist/agentic/guides/search.md +115 -0
  70. package/dist/agentic/guides/shared.md +108 -0
  71. package/dist/agentic/guides/ui.md +347 -0
  72. package/dist/agentic/shared/AGENTS.md.template +311 -124
  73. package/dist/agentic/shared/ai/agentic.config.json +0 -2
  74. package/dist/agentic/shared/ai/lessons.md +3 -26
  75. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
  76. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
  77. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
  78. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
  79. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
  80. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
  81. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
  82. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
  83. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
  84. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
  85. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
  86. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
  87. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
  88. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
  89. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
  90. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
  91. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
  92. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
  93. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
  94. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
  95. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
  96. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
  97. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
  98. package/dist/agentic/shared/ai/skills/tiers.json +21 -143
  99. package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
  100. package/dist/agentic/shared/ai/specs/README.md +3 -4
  101. package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
  102. package/dist/agentic/shared/ai/trackers/github.md +4 -108
  103. package/dist/agentic/shared/scripts/install-skills.sh +694 -4
  104. package/dist/bin.js +1 -13
  105. package/dist/bin.js.map +2 -2
  106. package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
  107. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  108. package/dist/lib/agentic-init.js +3 -13
  109. package/dist/lib/agentic-init.js.map +2 -2
  110. package/dist/lib/agentic-setup.js +186 -418
  111. package/dist/lib/agentic-setup.js.map +2 -2
  112. package/dist/lib/generators/extensions/injection-widgets.js +0 -20
  113. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  114. package/dist/lib/generators/module-facts-discovery.js +7 -41
  115. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  116. package/dist/lib/generators/module-facts.js +45 -1387
  117. package/dist/lib/generators/module-facts.js.map +3 -3
  118. package/dist/lib/generators/module-registry.js +5 -11
  119. package/dist/lib/generators/module-registry.js.map +2 -2
  120. package/dist/lib/resolver.js +0 -2
  121. package/dist/lib/resolver.js.map +2 -2
  122. package/dist/lib/testing/integration.js +0 -5
  123. package/dist/lib/testing/integration.js.map +2 -2
  124. package/dist/mercato.js +1 -23
  125. package/dist/mercato.js.map +2 -2
  126. package/package.json +11 -13
  127. package/src/bin.ts +1 -33
  128. package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
  129. package/src/lib/__tests__/agentic-init.test.ts +5 -41
  130. package/src/lib/agentic-init.ts +3 -15
  131. package/src/lib/agentic-setup.ts +224 -530
  132. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
  133. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
  134. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
  135. package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
  136. package/src/lib/generators/extensions/injection-widgets.ts +0 -51
  137. package/src/lib/generators/module-facts-discovery.ts +7 -58
  138. package/src/lib/generators/module-facts.ts +46 -1851
  139. package/src/lib/generators/module-registry.ts +6 -16
  140. package/src/lib/resolver.ts +0 -3
  141. package/src/lib/testing/__tests__/integration.test.ts +0 -4
  142. package/src/lib/testing/integration.ts +0 -5
  143. package/src/mercato.ts +1 -26
  144. package/dist/agentic/guides/ai-workflows.md +0 -76
  145. package/dist/agentic/guides/architecture.md +0 -107
  146. package/dist/agentic/guides/backend-ui.md +0 -80
  147. package/dist/agentic/guides/contracts.md +0 -92
  148. package/dist/agentic/guides/extensions.md +0 -121
  149. package/dist/agentic/guides/framework-extension-points.md +0 -36
  150. package/dist/agentic/guides/integrations.md +0 -81
  151. package/dist/agentic/guides/modules/design_system.md +0 -102
  152. package/dist/agentic/guides/spec-delivery.md +0 -22
  153. package/dist/agentic/guides/testing-debugging.md +0 -80
  154. package/dist/agentic/guides/upstream/AGENTS.md +0 -298
  155. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
  156. package/dist/agentic/guides/upstream/manifest.json +0 -8
  157. package/dist/agentic/shared/ai/harness/README.md +0 -50
  158. package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
  159. package/dist/agentic/shared/ai/harness/cases.json +0 -13680
  160. package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
  161. package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
  162. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
  163. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
  164. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
  165. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
  166. package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
  167. package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
  168. package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
  169. package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
  170. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
  171. package/dist/agentic/shared/ai/harness/validators.json +0 -78
  172. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
  173. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
  174. package/dist/agentic/shared/ai/lessons/_template.md +0 -16
  175. package/dist/agentic/shared/ai/review-checklist.md +0 -36
  176. package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
  177. package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
  178. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
  179. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
  180. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
  181. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
  182. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
  183. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
  184. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
  185. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
  186. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
  187. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
  188. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
  189. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
  190. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
  191. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
  192. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
  193. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
  194. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
  195. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
  196. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
  197. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
  198. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
  199. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
  200. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
  201. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
  202. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
  203. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
  204. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
  205. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
  206. package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
  207. package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
  208. package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
  209. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
  210. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
  211. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
  212. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
  213. package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
  214. package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
  215. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
  216. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
  217. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
  218. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
  219. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
  220. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
  221. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
  222. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
  223. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
  224. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
  225. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
  226. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
  227. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
  228. package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
  229. package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
  230. package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
  231. package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
  232. package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
  233. package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
  234. package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
  235. package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
  236. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
  237. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
  238. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
  239. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
  240. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
  241. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
  242. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
  243. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
  244. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
  245. package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
  246. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
  247. package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
  248. package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
  249. package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
  250. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
  251. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
  252. package/dist/lib/generators/module-extension-facts.js +0 -1840
  253. package/dist/lib/generators/module-extension-facts.js.map +0 -7
  254. package/dist/lib/generators/module-fact-sources.js +0 -70
  255. package/dist/lib/generators/module-fact-sources.js.map +0 -7
  256. package/dist/lib/generators/module-override-targets.js +0 -688
  257. package/dist/lib/generators/module-override-targets.js.map +0 -7
  258. package/dist/lib/load-env.js +0 -24
  259. package/dist/lib/load-env.js.map +0 -7
  260. package/dist/lib/telemetry-init.js +0 -358
  261. package/dist/lib/telemetry-init.js.map +0 -7
  262. package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
  263. package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
  264. package/src/lib/__tests__/load-env.test.ts +0 -65
  265. package/src/lib/__tests__/telemetry-init.test.ts +0 -298
  266. package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
  267. package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
  268. package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
  269. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
  270. package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
  271. package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
  272. package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
  273. package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
  274. package/src/lib/generators/module-extension-facts.ts +0 -2365
  275. package/src/lib/generators/module-fact-sources.ts +0 -108
  276. package/src/lib/generators/module-override-targets.ts +0 -863
  277. package/src/lib/load-env.ts +0 -30
  278. package/src/lib/telemetry-init.ts +0 -461
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/agentic-setup.ts"],
4
- "sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n readdirSync,\n realpathSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { createHash } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { tmpdir } from 'node:os'\nimport { join, dirname, basename, relative, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Project, SyntaxKind } from 'ts-morph'\n\nconst moduleDir = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), moduleDir is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst bundledAgenticDir = join(moduleDir, '..', 'agentic')\nconst AGENTIC_DIR = existsSync(bundledAgenticDir)\n ? bundledAgenticDir\n : join(moduleDir, '..', '..', '..', 'create-app', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n updateHarness?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\ninterface HarnessManifestFile {\n path: string\n sha256: string\n source: string\n userEditable: boolean\n}\n\ninterface HarnessManifest {\n version: number\n generator: string\n files: HarnessManifestFile[]\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Module fact-sheet selection (mirrors packages/create-app/src/setup/tools/shared.ts) \u2500\u2500\n\n// AST-parse the static `enabledModules` array literal in the app's src/modules.ts\n// and collect each entry's `id`. Only the static literal is read (conditional\n// .push()/spread entries are intentionally not seen \u2014 see spec D6).\nfunction readEnabledModuleIds(modulesPath: string): { parsed: boolean; ids: string[] } {\n if (!existsSync(modulesPath)) return { parsed: false, ids: [] }\n try {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile('modules.ts', readFileSync(modulesPath, 'utf-8'))\n const declaration = sourceFile.getVariableDeclaration('enabledModules')\n const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) return { parsed: false, ids: [] }\n const ids: string[] = []\n for (const element of arrayLiteral.getElements()) {\n const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!objectLiteral) continue\n const idProperty = objectLiteral.getProperty('id')?.asKind(SyntaxKind.PropertyAssignment)\n const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue()\n if (idValue) ids.push(idValue)\n }\n return { parsed: true, ids }\n } catch {\n return { parsed: false, ids: [] }\n }\n}\n\n// Resolve which per-module fact-sheets to ship: the intersection of the bundled\n// fact-sheets (the D5 allowlist, materialized by build.mjs) with the app's enabled\n// modules. Falls back to the full bundled set when the enabled set cannot be read\n// (R5 \u2014 degraded, never empty).\nfunction selectModuleFactSheets(targetDir: string, modulesSubdir: string): string[] {\n const available = existsSync(modulesSubdir)\n ? readdirSync(modulesSubdir)\n .filter((file) => file.endsWith('.md'))\n .map((file) => file.replace(/\\.md$/, ''))\n : []\n if (available.length === 0) return []\n const parsed = readEnabledModuleIds(join(targetDir, 'src', 'modules.ts'))\n if (!parsed.parsed) return available\n const enabled = new Set(parsed.ids)\n const selected = available.filter((moduleId) => enabled.has(moduleId))\n return selected\n}\n\nconst MODULE_GUIDES_START = '<!-- om:module-guides:start -->'\nconst MODULE_GUIDES_END = '<!-- om:module-guides:end -->'\n\nexport function renderModuleGuidesBlock(selected: string[]): string {\n if (selected.length === 0) return '_No module fact-sheets are bundled for this app._'\n return [\n `Enabled module facts: ${selected.map((moduleId) => `\\`${moduleId}\\``).join(',')}.`,\n '',\n 'Load `.ai/guides/modules/<id>.md` only for a named or targeted installed module/host; never preload all module facts.',\n ].join('\\n')\n}\n\n// Regenerate the marker-delimited Module-Specific Guides block in the written\n// AGENTS.md from the selected module set. Replaces strictly between the markers so\n// surrounding prose is untouched and repeat runs are idempotent.\nfunction injectModuleGuides(\n agentsMdPath: string,\n selected: string[],\n): void {\n if (!existsSync(agentsMdPath)) return\n const content = readFileSync(agentsMdPath, 'utf-8')\n const startIndex = content.indexOf(MODULE_GUIDES_START)\n const endIndex = content.indexOf(MODULE_GUIDES_END)\n if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {\n console.warn(\n `[agentic] Module-Specific Guides markers (${MODULE_GUIDES_START} \u2026 ${MODULE_GUIDES_END}) not found in ${agentsMdPath}; the per-module guide list was not generated.`,\n )\n return\n }\n const before = content.slice(0, startIndex + MODULE_GUIDES_START.length)\n const after = content.slice(endIndex)\n const next = `${before}\\n${renderModuleGuidesBlock(selected)}\\n${after}`\n if (next !== content) writeFileSync(agentsMdPath, next)\n}\n\nconst TEXT_EXTENSIONS = new Set(['.cjs', '.json', '.md', '.mdc', '.mjs', '.sh', '.ts', '.txt'])\n\nfunction isTextAsset(path: string): boolean {\n const dot = path.lastIndexOf('.')\n return dot === -1 || TEXT_EXTENSIONS.has(path.slice(dot))\n}\n\nfunction listFiles(root: string): string[] {\n if (!existsSync(root)) return []\n const files: string[] = []\n for (const entry of readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n const absolute = join(root, entry.name)\n if (entry.isDirectory()) files.push(...listFiles(absolute))\n else if (entry.isFile()) files.push(absolute)\n }\n return files\n}\n\nfunction copyTree(sourceRoot: string, destinationRoot: string, config: AgenticConfig): void {\n for (const sourcePath of listFiles(sourceRoot)) {\n const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath))\n ensureDir(destinationPath)\n if (isTextAsset(sourcePath)) {\n writeFileSync(destinationPath, resolvePlaceholders(readFileSync(sourcePath, 'utf8'), config))\n } else {\n copyFileSync(sourcePath, destinationPath)\n }\n if (process.platform !== 'win32') chmodSync(destinationPath, statSync(sourcePath).mode & 0o777)\n }\n}\n\nfunction hashFile(path: string): string {\n return createHash('sha256').update(readFileSync(path)).digest('hex')\n}\n\nfunction canonicalHarnessRoot(root: string): string {\n const resolved = resolve(root)\n if (!existsSync(resolved)) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n const canonical = realpathSync(resolved)\n const entry = lstatSync(canonical, { throwIfNoEntry: false })\n if (!entry || !entry.isDirectory()) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n return canonical\n}\n\n/**\n * Validate a managed path without following any link below the canonical app\n * root. A lexical containment check alone is insufficient: `app/.ai -> /tmp`\n * would otherwise make an apparently safe update write outside the app.\n */\nfunction assertManagedPath(root: string, path: string, options: { leaf?: 'file' | 'any' } = {}): void {\n const absolutePath = resolve(path)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n throw new Error(`Harness-managed path escapes its root: ${absolutePath}`)\n }\n if (normalizedRelative === '') return\n\n const components = normalizedRelative.split(sep).filter(Boolean)\n let current = root\n for (let index = 0; index < components.length; index += 1) {\n current = join(current, components[index])\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) return\n if (entry.isSymbolicLink()) {\n throw new Error(`Harness-managed path contains a symbolic-link component: ${current}`)\n }\n const isLeaf = index === components.length - 1\n if (!isLeaf && !entry.isDirectory()) {\n throw new Error(`Harness-managed path component is not a directory: ${current}`)\n }\n if (isLeaf && options.leaf === 'file' && !entry.isFile()) {\n throw new Error(`Harness-managed file is not a regular file: ${current}`)\n }\n }\n}\n\nfunction ensureManagedParent(root: string, filePath: string): void {\n const parent = dirname(filePath)\n const normalizedRelative = relative(root, parent)\n if (normalizedRelative === '..' || normalizedRelative.startsWith(`..${sep}`)) {\n throw new Error(`Harness-managed path escapes its root: ${filePath}`)\n }\n let current = root\n for (const component of normalizedRelative.split(sep).filter(Boolean)) {\n assertManagedPath(root, current)\n current = join(current, component)\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) mkdirSync(current)\n const created = lstatSync(current, { throwIfNoEntry: false })\n if (!created || created.isSymbolicLink() || !created.isDirectory()) {\n throw new Error(`Harness-managed path component is not a real directory: ${current}`)\n }\n }\n}\n\nfunction harnessGeneratorId(): string {\n try {\n const upstream = JSON.parse(readFileSync(join(GUIDES_DIR, 'upstream', 'manifest.json'), 'utf8')) as {\n generator?: unknown\n }\n const generator = typeof upstream.generator === 'string' ? upstream.generator : ''\n const version = generator.slice(generator.lastIndexOf('@') + 1)\n if (version && version !== generator) return `open-mercato-agentic@${version}`\n } catch {\n // Source-mode tests may not have built upstream snapshots yet.\n }\n return 'open-mercato-agentic@unknown'\n}\n\nfunction externalSkillNames(targetDir: string): Set<string> {\n try {\n const tiers = JSON.parse(readFileSync(join(targetDir, '.ai', 'skills', 'tiers.json'), 'utf8')) as {\n external?: { skills?: unknown }\n }\n return new Set(Array.isArray(tiers.external?.skills) ? tiers.external.skills.filter((name): name is string => typeof name === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nfunction atomicCopyFile(sourcePath: string, destinationPath: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n copyFileSync(sourcePath, temporaryPath)\n if (process.platform !== 'win32') chmodSync(temporaryPath, statSync(sourcePath).mode & 0o777)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction atomicWriteFile(destinationPath: string, content: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n writeFileSync(temporaryPath, content)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction resolveManifestPath(root: string, relativePath: string): string | null {\n if (!relativePath || relativePath.includes('\\0')) return null\n const absolutePath = resolve(root, relativePath)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '' ||\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n return null\n }\n return absolutePath\n}\n\nfunction normalizeManifestRelativePath(path: string): string {\n return path.replace(/\\\\/g, '/')\n}\n\nfunction readHarnessManifest(manifestPath: string): HarnessManifest | null {\n if (!existsSync(manifestPath)) return null\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as Partial<HarnessManifest>\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.generator !== 'string' ||\n !Array.isArray(parsed.files)\n ) {\n return null\n }\n const files: HarnessManifestFile[] = []\n for (const entry of parsed.files) {\n if (\n !entry ||\n typeof entry.path !== 'string' ||\n typeof entry.sha256 !== 'string' ||\n !/^[a-f0-9]{64}$/.test(entry.sha256) ||\n typeof entry.source !== 'string' ||\n typeof entry.userEditable !== 'boolean'\n ) {\n return null\n }\n files.push({ ...entry, path: normalizeManifestRelativePath(entry.path) })\n }\n return { version: parsed.version, generator: parsed.generator, files }\n } catch {\n return null\n }\n}\n\nfunction targetPathsForTree(sourceRoot: string, destinationRoot: string): string[] {\n return listFiles(sourceRoot).map((sourcePath) => join(destinationRoot, relative(sourceRoot, sourcePath)))\n}\n\nfunction finalizeHarnessManifest(config: AgenticConfig, selectedTools: string[]): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n const paths = new Set<string>([\n join(targetDir, 'AGENTS.md'),\n ...targetPathsForTree(join(srcDir, 'ai'), join(targetDir, '.ai')),\n ...targetPathsForTree(join(srcDir, 'scripts'), join(targetDir, 'scripts')),\n ])\n for (const file of readdirSync(GUIDES_DIR)) {\n if (file.endsWith('.md') || file === 'module-facts.json') paths.add(join(targetDir, '.ai', 'guides', file))\n }\n for (const file of listFiles(join(GUIDES_DIR, 'upstream'))) {\n paths.add(join(targetDir, '.ai', 'guides', 'upstream', relative(join(GUIDES_DIR, 'upstream'), file)))\n }\n for (const moduleId of selectedModules) paths.add(join(targetDir, '.ai', 'guides', 'modules', `${moduleId}.md`))\n if (selectedTools.includes('claude-code')) {\n paths.add(join(targetDir, 'CLAUDE.md'))\n paths.add(join(targetDir, '.claude', 'settings.json'))\n paths.add(join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n paths.add(join(targetDir, '.mcp.json.example'))\n }\n if (selectedTools.includes('codex')) paths.add(join(targetDir, '.codex', 'mcp.json.example'))\n if (selectedTools.includes('cursor')) {\n for (const file of listFiles(join(AGENTIC_DIR, 'cursor'))) {\n const rel = relative(join(AGENTIC_DIR, 'cursor'), file)\n paths.add(join(targetDir, '.cursor', rel))\n }\n }\n const manifestPath = join(targetDir, '.ai', 'harness', 'manifest.json')\n const externalSkills = externalSkillNames(targetDir)\n paths.delete(manifestPath)\n const files = [...paths]\n .filter((path) => existsSync(path))\n .sort((left, right) => left.localeCompare(right))\n .map((path) => {\n const relativePath = normalizeManifestRelativePath(relative(targetDir, path))\n const skillName = relativePath.match(/^\\.ai\\/skills\\/([^/]+)\\//)?.[1]\n return {\n path: relativePath,\n sha256: hashFile(path),\n source: skillName ? (externalSkills.has(skillName) ? 'external-override' : 'local-skill') : 'generated',\n userEditable:\n relativePath === 'AGENTS.md'\n || relativePath === '.ai/agentic.config.json'\n || relativePath === '.ai/lessons.md'\n || relativePath.startsWith('.ai/lessons/'),\n }\n })\n atomicWriteFile(\n manifestPath,\n `${JSON.stringify({ version: 1, generator: harnessGeneratorId(), files }, null, 2)}\\n`,\n )\n}\n\n/**\n * Publish a fully generated harness candidate using the previous ownership\n * manifest as the only source of ownership. Modified owned files and exact-path\n * collisions with unknown files stay untouched; their candidate is written next\n * to them as `<path>.incoming` for explicit review.\n */\nexport type HarnessUpdateConflict = { path: string; candidate: string | null }\n\nfunction preserveIncomingCandidate(\n targetRoot: string,\n destinationPath: string,\n sourcePath: string,\n relativePath: string,\n): string {\n for (let suffix = 1; ; suffix += 1) {\n const label = suffix === 1 ? '.incoming' : `.incoming.${suffix}`\n const candidatePath = `${destinationPath}${label}`\n assertManagedPath(targetRoot, candidatePath, { leaf: 'file' })\n if (!existsSync(candidatePath)) {\n atomicCopyFile(sourcePath, candidatePath, targetRoot)\n return `${relativePath}${label}`\n }\n if (hashFile(candidatePath) === hashFile(sourcePath)) return `${relativePath}${label}`\n }\n}\n\nexport function applyHarnessUpdate(\n targetDir: string,\n stagingDir: string,\n options: { force?: boolean } = {},\n): HarnessUpdateConflict[] {\n const targetRoot = canonicalHarnessRoot(targetDir)\n const stagingRoot = canonicalHarnessRoot(stagingDir)\n const targetManifestPath = join(targetRoot, '.ai', 'harness', 'manifest.json')\n const stagingManifestPath = join(stagingRoot, '.ai', 'harness', 'manifest.json')\n assertManagedPath(targetRoot, targetManifestPath, { leaf: 'file' })\n assertManagedPath(stagingRoot, stagingManifestPath, { leaf: 'file' })\n const candidateManifest = readHarnessManifest(stagingManifestPath)\n if (!candidateManifest) {\n throw new Error('Generated harness candidate has a missing or invalid ownership manifest.')\n }\n\n const previousManifest = readHarnessManifest(targetManifestPath)\n const previousFiles = new Map(previousManifest?.files.map((entry) => [entry.path, entry]) ?? [])\n const candidatePaths = new Set(candidateManifest.files.map((entry) => entry.path))\n const candidates: Array<{\n entry: HarnessManifestFile\n sourcePath: string\n destinationPath: string\n }> = []\n\n // Validate the complete candidate before writing anything into the app.\n for (const entry of candidateManifest.files) {\n const sourcePath = resolveManifestPath(stagingRoot, entry.path)\n const destinationPath = resolveManifestPath(targetRoot, entry.path)\n if (sourcePath) assertManagedPath(stagingRoot, sourcePath, { leaf: 'file' })\n if (destinationPath) assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n if (!sourcePath || !destinationPath || !existsSync(sourcePath) || hashFile(sourcePath) !== entry.sha256) {\n throw new Error(`Generated harness candidate is invalid for ${JSON.stringify(entry.path)}.`)\n }\n candidates.push({ entry, sourcePath, destinationPath })\n }\n\n const conflicts: HarnessUpdateConflict[] = []\n for (const { entry, sourcePath, destinationPath } of candidates) {\n if (options.force) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n if (!existsSync(destinationPath)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const currentHash = hashFile(destinationPath)\n const previousEntry = previousFiles.get(entry.path)\n if (currentHash === entry.sha256 || (previousEntry && currentHash === previousEntry.sha256)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const candidate = preserveIncomingCandidate(targetRoot, destinationPath, sourcePath, entry.path)\n conflicts.push({ path: entry.path, candidate })\n }\n\n const retainedRetiredEntries: HarnessManifestFile[] = []\n for (const previousEntry of previousManifest?.files ?? []) {\n if (candidatePaths.has(previousEntry.path)) continue\n const destinationPath = resolveManifestPath(targetRoot, previousEntry.path)\n if (!destinationPath || !existsSync(destinationPath)) continue\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n let unchanged = false\n try {\n unchanged = hashFile(destinationPath) === previousEntry.sha256\n } catch {\n // A user may replace a generated file with another filesystem object.\n // Preserve it and retain the ownership tombstone for a later review.\n }\n if (unchanged) {\n assertManagedPath(targetRoot, dirname(destinationPath))\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n rmSync(destinationPath, { force: true })\n } else {\n retainedRetiredEntries.push(previousEntry)\n conflicts.push({ path: previousEntry.path, candidate: null })\n }\n }\n\n // The candidate hashes deliberately remain in the manifest for conflicts. If\n // the user accepts an .incoming file, a later update can recognize it as an\n // unmodified owned file. Until then the hash mismatch keeps preserving it.\n const finalManifest: HarnessManifest = {\n ...candidateManifest,\n files: [...candidateManifest.files, ...retainedRetiredEntries],\n }\n atomicWriteFile(targetManifestPath, `${JSON.stringify(finalManifest, null, 2)}\\n`, targetRoot)\n return conflicts\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // Resolve which per-module fact-sheets this app gets (enabled \u2229 bundled allowlist).\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n\n // One recursive mapping mirrors create-app's shared emitter.\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n copyTree(join(srcDir, 'ai'), join(targetDir, '.ai'), config)\n copyTree(join(srcDir, 'scripts'), join(targetDir, 'scripts'), config)\n\n // Routed conceptual guides are copied wholesale (framework-wide). Per-module\n // fact-sheets (.ai/guides/modules/<module>.md) are filtered to the app's enabled\n // module set; the combined module-facts.json sidecar is copied as-is.\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n\n const moduleFactsPath = join(GUIDES_DIR, 'module-facts.json')\n if (existsSync(moduleFactsPath)) {\n const destPath = join(guidesDestDir, 'module-facts.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsPath, destPath)\n }\n\n\n copyTree(join(GUIDES_DIR, 'upstream'), join(guidesDestDir, 'upstream'), config)\n\n const modulesSubdir = join(GUIDES_DIR, 'modules')\n for (const moduleId of selectedModules) {\n const destPath = join(guidesDestDir, 'modules', `${moduleId}.md`)\n ensureDir(destPath)\n copyFileSync(join(modulesSubdir, `${moduleId}.md`), destPath)\n }\n }\n\n injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules)\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // The installer exclusively owns Claude's per-skill compatibility links.\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // No .codex/skills directory: Codex reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // No .cursor/skills directory: Cursor reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nfunction persistedAgentSelection(targetDir: string): string[] | null {\n const selectableIds = SELECTABLE.map((tool) => tool.id)\n const tiersPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n try {\n const tiers = JSON.parse(readFileSync(tiersPath, 'utf8')) as { agents?: { ignore?: unknown } }\n if (Array.isArray(tiers.agents?.ignore)\n && tiers.agents.ignore.every((id): id is string => typeof id === 'string')) {\n const ignored = new Set(tiers.agents.ignore)\n return selectableIds.filter((id) => !ignored.has(id))\n }\n } catch {\n // Fall through to the ownership manifest and existing generated assets.\n }\n\n const manifest = readHarnessManifest(join(targetDir, '.ai', 'harness', 'manifest.json'))\n const owned = new Set(manifest?.files.map((entry) => entry.path) ?? [])\n const selected = SELECTABLE.filter((tool) => {\n if (tool.id === 'claude-code') {\n return owned.has('CLAUDE.md') || owned.has('.claude/settings.json')\n || existsSync(join(targetDir, 'CLAUDE.md')) || existsSync(join(targetDir, '.claude', 'settings.json'))\n }\n if (tool.id === 'codex') {\n return owned.has('.codex/mcp.json.example') || existsSync(join(targetDir, '.codex', 'mcp.json.example'))\n }\n return owned.has('.cursor/hooks.json') || existsSync(join(targetDir, '.cursor', 'hooks.json'))\n }).map((tool) => tool.id)\n return selected.length > 0 ? selected : null\n}\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else if (options?.updateHarness) {\n selectedIds = persistedAgentSelection(targetDir) ?? await promptSelection(ask)\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n const stagingDir = mkdtempSync(join(tmpdir(), 'open-mercato-harness-'))\n try {\n const modulesSourcePath = join(targetDir, 'src', 'modules.ts')\n const modulesCandidatePath = join(stagingDir, 'src', 'modules.ts')\n if (existsSync(modulesSourcePath)) {\n ensureDir(modulesCandidatePath)\n copyFileSync(modulesSourcePath, modulesCandidatePath)\n }\n\n const stagingConfig: AgenticConfig = {\n projectName: config.projectName,\n targetDir: stagingDir,\n }\n generateHarness(stagingConfig, selectedIds)\n const conflicts = applyHarnessUpdate(targetDir, stagingDir, {\n force: options?.force,\n })\n if (conflicts.length > 0) {\n console.warn('')\n console.warn(' \u26A0 Preserved locally modified harness files:')\n for (const conflict of conflicts) {\n const detail = conflict.candidate\n ? `candidate: ${conflict.candidate}`\n : 'retired asset kept because it has local changes'\n console.warn(` \u2022 ${conflict.path} (${detail})`)\n }\n }\n } finally {\n rmSync(stagingDir, { recursive: true, force: true })\n }\n\n installSkills(targetDir)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n console.log(' .ai/agentic.config.json ships preconfigured (GitHub tracker, labels off);')\n console.log(' run /om-setup-agent-pipeline in your agent CLI to tailor labels, QA gate,')\n console.log(' tracker, or validation commands. Re-run `yarn install-skills` anytime to')\n console.log(' refresh the external open-mercato/skills subset.')\n console.log('')\n}\n\nfunction generateHarness(config: AgenticConfig, selectedIds: string[]): void {\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n persistAgentSelection(config.targetDir, selectedIds)\n finalizeHarnessManifest(config, selectedIds)\n}\n\n/**\n * Persist the agent selection so later `yarn install-skills` runs keep honoring\n * it: agents the user did not pick go into `agents.ignore` in tiers.json and\n * never get a skills directory of their own.\n */\nfunction persistAgentSelection(targetDir: string, selectedIds: string[]): void {\n const manifestPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n if (!existsSync(manifestPath)) return\n const ignore = SELECTABLE.map((tool) => tool.id).filter((id) => !selectedIds.includes(id))\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<string, unknown>\n if (ignore.length > 0) {\n manifest.agents = { ignore }\n } else {\n delete manifest.agents\n }\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n}\n\nfunction installSkills(targetDir: string): void {\n const installScript = join(targetDir, 'scripts', 'install-skills.mjs')\n if (!existsSync(installScript)) return\n console.log('')\n console.log(' Installing agent skills (local tiers + external open-mercato/skills subset)...')\n const result = spawnSync(process.execPath, [installScript], { cwd: targetDir, stdio: 'inherit' })\n if (result.error || result.status !== 0) {\n console.log(' \u26A0 Skill installation did not complete; run `yarn install-skills` inside the app when online.')\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, symlinkSync, lstatSync, unlinkSync, readdirSync } from 'node:fs'\nimport { spawnSync } from 'node:child_process'\nimport { join, dirname, basename } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Project, SyntaxKind } from 'ts-morph'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), __dirname is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst AGENTIC_DIR = join(__dirname, '..', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Module fact-sheet selection (mirrors packages/create-app/src/setup/tools/shared.ts) \u2500\u2500\n\n// AST-parse the static `enabledModules` array literal in the app's src/modules.ts\n// and collect each entry's `id`. Only the static literal is read (conditional\n// .push()/spread entries are intentionally not seen \u2014 see spec D6).\nfunction readEnabledModuleIds(modulesPath: string): string[] {\n if (!existsSync(modulesPath)) return []\n try {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile('modules.ts', readFileSync(modulesPath, 'utf-8'))\n const declaration = sourceFile.getVariableDeclaration('enabledModules')\n const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) return []\n const ids: string[] = []\n for (const element of arrayLiteral.getElements()) {\n const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!objectLiteral) continue\n const idProperty = objectLiteral.getProperty('id')?.asKind(SyntaxKind.PropertyAssignment)\n const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue()\n if (idValue) ids.push(idValue)\n }\n return ids\n } catch {\n return []\n }\n}\n\n// Resolve which per-module fact-sheets to ship: the intersection of the bundled\n// fact-sheets (the D5 allowlist, materialized by build.mjs) with the app's enabled\n// modules. Falls back to the full bundled set when the enabled set cannot be read\n// (R5 \u2014 degraded, never empty).\nfunction selectModuleFactSheets(targetDir: string, modulesSubdir: string): string[] {\n const available = existsSync(modulesSubdir)\n ? readdirSync(modulesSubdir)\n .filter((file) => file.endsWith('.md'))\n .map((file) => file.replace(/\\.md$/, ''))\n : []\n if (available.length === 0) return []\n const enabled = new Set(readEnabledModuleIds(join(targetDir, 'src', 'modules.ts')))\n const selected = available.filter((moduleId) => enabled.has(moduleId))\n return selected.length > 0 ? selected : available\n}\n\nconst MODULE_GUIDES_START = '<!-- om:module-guides:start -->'\nconst MODULE_GUIDES_END = '<!-- om:module-guides:end -->'\n\n// Read each module's guide label from the bundled `module-facts.json` (emitted by\n// build.mjs from the generator's extraction of each module's own `metadata`). The\n// label falls back description \u2192 title \u2192 generic, so the CLI never re-declares\n// specific module names or descriptions. A missing/malformed sidecar degrades to an\n// empty map (generic labels), never a throw.\nfunction readModuleGuideLabels(guidesDir: string): Record<string, string> {\n const factsPath = join(guidesDir, 'module-facts.json')\n if (!existsSync(factsPath)) return {}\n try {\n const parsed = JSON.parse(readFileSync(factsPath, 'utf-8')) as Record<\n string,\n { description?: unknown; title?: unknown }\n >\n const labels: Record<string, string> = {}\n for (const [moduleId, entry] of Object.entries(parsed)) {\n const label =\n (entry && typeof entry.description === 'string' && entry.description) ||\n (entry && typeof entry.title === 'string' && entry.title) ||\n ''\n if (label) labels[moduleId] = label\n }\n return labels\n } catch {\n return {}\n }\n}\n\nfunction renderModuleGuidesBlock(selected: string[], labels: Record<string, string>): string {\n if (selected.length === 0) return '_No module fact-sheets are bundled for this app._'\n const rows = selected.map((moduleId) => {\n const label = labels[moduleId] ?? `Use the ${moduleId} module`\n return `| ${label} | \\`.ai/guides/modules/${moduleId}.md\\` |`\n })\n return ['| Task | Load |', '|---|---|', ...rows].join('\\n')\n}\n\n// Regenerate the marker-delimited Module-Specific Guides block in the written\n// AGENTS.md from the selected module set. Replaces strictly between the markers so\n// surrounding prose is untouched and repeat runs are idempotent.\nfunction injectModuleGuides(\n agentsMdPath: string,\n selected: string[],\n labels: Record<string, string> = {},\n): void {\n if (!existsSync(agentsMdPath)) return\n const content = readFileSync(agentsMdPath, 'utf-8')\n const startIndex = content.indexOf(MODULE_GUIDES_START)\n const endIndex = content.indexOf(MODULE_GUIDES_END)\n if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {\n console.warn(\n `[agentic] Module-Specific Guides markers (${MODULE_GUIDES_START} \u2026 ${MODULE_GUIDES_END}) not found in ${agentsMdPath}; the per-module guide list was not generated.`,\n )\n return\n }\n const before = content.slice(0, startIndex + MODULE_GUIDES_START.length)\n const after = content.slice(endIndex)\n const next = `${before}\\n${renderModuleGuidesBlock(selected, labels)}\\n${after}`\n if (next !== content) writeFileSync(agentsMdPath, next)\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // Resolve which per-module fact-sheets this app gets (enabled \u2229 bundled allowlist).\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n const moduleGuideLabels = readModuleGuideLabels(GUIDES_DIR)\n\n // AGENTS.md\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules, moduleGuideLabels)\n\n // .ai/ structure\n writeTemplate(srcDir, 'ai/specs/README.md', join(targetDir, '.ai', 'specs', 'README.md'), config)\n copyFile(srcDir, 'ai/specs/SPEC-000-template.md', join(targetDir, '.ai', 'specs', 'SPEC-000-template.md'))\n copyFile(srcDir, 'ai/lessons.md', join(targetDir, '.ai', 'lessons.md'))\n\n // .ai/skills/ \u2014 the shared skills-mixin manifest + tracker + external installer.\n // Skills owned by the external open-mercato/skills collection (code review, spec\n // writing, integration tests, prepare-issue, the auto-* PR family) are NOT copied\n // here; the user installs them with `yarn install-skills` (npx skills add). Only\n // standalone-only + kept-local skills and repo-local override folders are copied.\n copyFile(srcDir, 'ai/skills/tiers.json', join(targetDir, '.ai', 'skills', 'tiers.json'))\n copyFile(srcDir, 'ai/skills/tiers.schema.json', join(targetDir, '.ai', 'skills', 'tiers.schema.json'))\n copyFile(srcDir, 'ai/agentic.config.json', join(targetDir, '.ai', 'agentic.config.json'))\n copyFile(srcDir, 'ai/trackers/github.md', join(targetDir, '.ai', 'trackers', 'github.md'))\n copyFile(srcDir, 'scripts/install-skills.sh', join(targetDir, 'scripts', 'install-skills.sh'))\n\n copyFile(\n srcDir,\n 'ai/skills/om-backend-ui-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-backend-ui-design/references/ui-components.md',\n join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'references', 'ui-components.md'),\n )\n copyFile(srcDir, 'ai/skills/om-integration-builder/SKILL.md', join(targetDir, '.ai', 'skills', 'om-integration-builder', 'SKILL.md'))\n if (existsSync(join(srcDir, 'ai', 'skills', 'om-integration-builder', 'STANDALONE.md'))) {\n copyFile(\n srcDir,\n 'ai/skills/om-integration-builder/STANDALONE.md',\n join(targetDir, '.ai', 'skills', 'om-integration-builder', 'STANDALONE.md'),\n )\n }\n copyFile(\n srcDir,\n 'ai/skills/om-integration-builder/references/adapter-contracts.md',\n join(targetDir, '.ai', 'skills', 'om-integration-builder', 'references', 'adapter-contracts.md'),\n )\n if (existsSync(join(srcDir, 'ai', 'skills', 'om-integration-builder', 'STANDALONE.md'))) {\n copyFile(\n srcDir,\n 'ai/skills/om-integration-builder/STANDALONE.md',\n join(targetDir, '.ai', 'skills', 'om-integration-builder', 'STANDALONE.md'),\n )\n }\n\n copyFile(\n srcDir,\n 'ai/skills/om-system-extension/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-system-extension', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-system-extension/references/extension-contracts.md',\n join(targetDir, '.ai', 'skills', 'om-system-extension', 'references', 'extension-contracts.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/references/naming-conventions.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'naming-conventions.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/references/navigation-patterns.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'navigation-patterns.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-troubleshooter/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-troubleshooter/references/diagnostic-commands.md',\n join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'references', 'diagnostic-commands.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-eject-and-customize/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-eject-and-customize', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-data-model-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-data-model-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md',\n join(targetDir, '.ai', 'skills', 'om-data-model-design', 'references', 'mikro-orm-cheatsheet.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-implement-spec/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-implement-spec', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-help/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-help', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-help/references/skills-catalog.md',\n join(targetDir, '.ai', 'skills', 'om-help', 'references', 'skills-catalog.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-help/references/workflow-sequences.md',\n join(targetDir, '.ai', 'skills', 'om-help', 'references', 'workflow-sequences.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-auto-upgrade-0.4.10-to-0.5.0', 'SKILL.md'),\n )\n\n // Slim repo-local OVERRIDE folders (SKILL.md only) for the external auto-* PR\n // family + single autofix skill. The workflow bodies live in open-mercato/skills\n // (installed via `yarn install-skills`); these overrides adjust them for a\n // standalone app and are read on top of the external skill's built-in workflow.\n // om-prepare-test-env's override carries environment knowledge (cross-platform\n // mercato CLI runner commands) rather than tracker adjustments.\n for (const autoSkill of [\n 'om-auto-create-pr',\n 'om-auto-continue-pr',\n 'om-auto-create-pr-loop',\n 'om-auto-continue-pr-loop',\n 'om-auto-review-pr',\n 'om-auto-fix-issue',\n 'om-prepare-test-env',\n ]) {\n if (!existsSync(join(srcDir, 'ai', 'skills', autoSkill, 'SKILL.md'))) {\n continue\n }\n copyFile(\n srcDir,\n `ai/skills/${autoSkill}/SKILL.md`,\n join(targetDir, '.ai', 'skills', autoSkill, 'SKILL.md'),\n )\n }\n\n copyFile(\n srcDir,\n 'ai/skills/om-trim-unused-modules/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-trim-unused-modules', 'SKILL.md'),\n )\n\n copyFile(srcDir, 'ai/qa/tests/playwright.config.ts', join(targetDir, '.ai', 'qa', 'tests', 'playwright.config.ts'))\n\n // Package & conceptual guides are copied wholesale (framework-wide). Per-module\n // fact-sheets (.ai/guides/modules/<module>.md) are filtered to the app's enabled\n // module set; the combined module-facts.json sidecar is copied as-is.\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n\n const moduleFactsPath = join(GUIDES_DIR, 'module-facts.json')\n if (existsSync(moduleFactsPath)) {\n const destPath = join(guidesDestDir, 'module-facts.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsPath, destPath)\n }\n\n const modulesSubdir = join(GUIDES_DIR, 'modules')\n for (const moduleId of selectedModules) {\n const destPath = join(guidesDestDir, 'modules', `${moduleId}.md`)\n ensureDir(destPath)\n copyFileSync(join(modulesSubdir, `${moduleId}.md`), destPath)\n }\n }\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // Symlink .claude/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.claude', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // No .codex/skills directory: Codex reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // No .cursor/skills directory: Cursor reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\nfunction ensureSkillsLink(linkPath: string, target: string): void {\n ensureDir(linkPath)\n if (existsSync(linkPath) && !lstatSync(linkPath).isSymbolicLink()) {\n return\n }\n if (lstatSync(linkPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n unlinkSync(linkPath)\n }\n symlinkSync(target, linkPath)\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n persistAgentSelection(targetDir, selectedIds)\n installSkills(targetDir)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n console.log(' .ai/agentic.config.json ships preconfigured (GitHub tracker, labels off);')\n console.log(' run /om-setup-agent-pipeline in your agent CLI to tailor labels, QA gate,')\n console.log(' tracker, or validation commands. Re-run `yarn install-skills` anytime to')\n console.log(' refresh the external open-mercato/skills subset.')\n console.log('')\n}\n\n/**\n * Persist the agent selection so later `yarn install-skills` runs keep honoring\n * it: agents the user did not pick go into `agents.ignore` in tiers.json and\n * never get a skills directory of their own.\n */\nfunction persistAgentSelection(targetDir: string, selectedIds: string[]): void {\n const manifestPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n if (!existsSync(manifestPath)) return\n const ignore = SELECTABLE.map((tool) => tool.id).filter((id) => !selectedIds.includes(id))\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<string, unknown>\n if (ignore.length > 0) {\n manifest.agents = { ignore }\n } else {\n delete manifest.agents\n }\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n}\n\nfunction installSkills(targetDir: string): void {\n const installScript = join(targetDir, 'scripts', 'install-skills.sh')\n if (!existsSync(installScript)) return\n console.log('')\n console.log(' Installing agent skills (local tiers + external open-mercato/skills subset)...')\n const result = spawnSync('sh', [installScript], { cwd: targetDir, stdio: 'inherit' })\n if (result.error || result.status !== 0) {\n console.log(' \u26A0 Skill installation did not complete; run `yarn install-skills` inside the app when online.')\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -140,23 +140,9 @@ function resolveScannedWidgetPath(roots, fromApp, relPath) {
140
140
  const base = fromApp ? roots.appBase : resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase;
141
141
  return path.join(base, "widgets", "injection", ...relPath.split("/"));
142
142
  }
143
- function reportUnresolvableWidgetReferences(widgetEntries, tableWidgetRefs) {
144
- const declaredIds = /* @__PURE__ */ new Set();
145
- for (const entry of widgetEntries.values()) {
146
- if (entry.widgetId) declaredIds.add(entry.widgetId);
147
- }
148
- for (const [widgetId, modules] of Array.from(tableWidgetRefs.entries()).sort(([a], [b]) => a.localeCompare(b))) {
149
- if (declaredIds.has(widgetId)) continue;
150
- const owners = Array.from(modules).sort((left, right) => left.localeCompare(right)).join(", ");
151
- console.warn(
152
- `[generate] \u26A0 Injection table in "${owners}" references widget id "${widgetId}", but no scanned widget declares it \u2014 that spot will render nothing. Check the id against the widget's metadata.id, and that the widget lives in a file the scanner reads (widgets/injection/**/widget.ts|tsx \u2014 note that widget.client.tsx alone is not scanned).`
153
- );
154
- }
155
- }
156
143
  function createInjectionWidgetsExtension() {
157
144
  const widgetEntries = /* @__PURE__ */ new Map();
158
145
  const tableEntries = [];
159
- const tableWidgetRefs = /* @__PURE__ */ new Map();
160
146
  return {
161
147
  id: "registry.injection-widgets",
162
148
  outputFiles: ["injection-widgets.generated.ts", "injection-tables.generated.ts"],
@@ -185,11 +171,6 @@ function createInjectionWidgetsExtension() {
185
171
  if (moduleWidgetEntries.length === 1 && tableWidgetIds.length === 1 && !moduleWidgetEntries[0].widgetId) {
186
172
  moduleWidgetEntries[0].widgetId = tableWidgetIds[0];
187
173
  }
188
- for (const widgetId of tableWidgetIds) {
189
- const modules = tableWidgetRefs.get(widgetId) ?? /* @__PURE__ */ new Set();
190
- modules.add(ctx.moduleId);
191
- tableWidgetRefs.set(widgetId, modules);
192
- }
193
174
  for (const entry of moduleWidgetEntries) {
194
175
  const existing = widgetEntries.get(entry.key);
195
176
  if (!existing || existing.source !== "app" && entry.source === "app") {
@@ -205,7 +186,6 @@ function createInjectionWidgetsExtension() {
205
186
  }
206
187
  },
207
188
  generateOutput() {
208
- reportUnresolvableWidgetReferences(widgetEntries, tableWidgetRefs);
209
189
  const widgetDecls = Array.from(widgetEntries.entries()).sort(([left], [right]) => left.localeCompare(right)).map(
210
190
  ([, entry]) => objectLiteral([
211
191
  { name: "moduleId", value: entry.moduleId },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/generators/extensions/injection-widgets.ts"],
4
- "sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport ts from 'typescript-js'\nimport type { GeneratorExtension } from '../extension'\nimport { resolveStandaloneSourceMirrorBase, scanModuleDir, SCAN_CONFIGS, type ModuleRoots } from '../scanner'\nimport {\n arrayLiteral,\n arrowFunction,\n identifier,\n methodCall,\n nullishCoalesce,\n objectLiteral,\n propertyAccess,\n writeValue,\n} from '../ast'\nimport { dynamicImportExpression, emptyObject, namespaceFallback, namespaceImportSpec, renderGeneratedTsSource } from './shared'\n\ntype InjectionWidgetEntry = {\n moduleId: string\n key: string\n source: 'app' | 'package'\n importPath: string\n widgetId?: string\n}\n\ntype InjectionTableEntry = {\n moduleId: string\n importName: string\n importPath: string\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression\n while (\n ts.isParenthesizedExpression(current)\n || ts.isAsExpression(current)\n || ts.isTypeAssertionExpression(current)\n || ts.isSatisfiesExpression(current)\n ) {\n current = current.expression\n }\n return current\n}\n\nfunction getPropertyNameText(name: ts.PropertyName): string | null {\n if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) {\n return name.text\n }\n return null\n}\n\nfunction collectObjectDeclarations(sourceFile: ts.SourceFile): Map<string, ts.ObjectLiteralExpression> {\n const declarations = new Map<string, ts.ObjectLiteralExpression>()\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n const initializer = unwrapExpression(declaration.initializer)\n if (ts.isObjectLiteralExpression(initializer)) {\n declarations.set(declaration.name.text, initializer)\n }\n }\n }\n return declarations\n}\n\nfunction resolveObjectExpression(\n expression: ts.Expression,\n declarations: Map<string, ts.ObjectLiteralExpression>,\n): ts.ObjectLiteralExpression | null {\n const unwrapped = unwrapExpression(expression)\n if (ts.isObjectLiteralExpression(unwrapped)) return unwrapped\n if (ts.isIdentifier(unwrapped)) return declarations.get(unwrapped.text) ?? null\n return null\n}\n\nfunction getObjectPropertyExpression(object: ts.ObjectLiteralExpression, propertyName: string): ts.Expression | null {\n for (const property of object.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n if (getPropertyNameText(property.name) === propertyName) return property.initializer\n }\n return null\n}\n\nfunction getStringPropertyValue(object: ts.ObjectLiteralExpression, propertyName: string): string | null {\n const expression = getObjectPropertyExpression(object, propertyName)\n if (!expression) return null\n const unwrapped = unwrapExpression(expression)\n if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) return unwrapped.text\n return null\n}\n\nfunction extractMetadataId(object: ts.ObjectLiteralExpression): string | null {\n const metadata = getObjectPropertyExpression(object, 'metadata')\n if (!metadata) return null\n const unwrapped = unwrapExpression(metadata)\n if (!ts.isObjectLiteralExpression(unwrapped)) return null\n return getStringPropertyValue(unwrapped, 'id')\n}\n\nfunction extractWidgetMetadataId(absolutePath: string): string | null {\n try {\n const source = fs.readFileSync(absolutePath, 'utf8')\n const sourceFile = ts.createSourceFile(absolutePath, source, ts.ScriptTarget.Latest, true)\n const declarations = collectObjectDeclarations(sourceFile)\n\n for (const statement of sourceFile.statements) {\n if (!ts.isExportAssignment(statement) || statement.isExportEquals) continue\n const object = resolveObjectExpression(statement.expression, declarations)\n if (!object) continue\n const id = extractMetadataId(object)\n if (id) return id\n }\n\n for (const object of declarations.values()) {\n const id = extractMetadataId(object)\n if (id) return id\n }\n } catch {\n return null\n }\n return null\n}\n\nfunction collectWidgetIdsFromTableValue(\n value: ts.Expression,\n declarations: Map<string, ts.ObjectLiteralExpression>,\n ids: Set<string>,\n) {\n const expression = unwrapExpression(value)\n if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {\n ids.add(expression.text)\n return\n }\n if (ts.isArrayLiteralExpression(expression)) {\n for (const element of expression.elements) {\n if (ts.isExpression(element)) collectWidgetIdsFromTableValue(element, declarations, ids)\n }\n return\n }\n const object = resolveObjectExpression(expression, declarations)\n if (!object) return\n const widgetId = getStringPropertyValue(object, 'widgetId')\n if (widgetId) ids.add(widgetId)\n}\n\nfunction extractInjectionTableWidgetIds(absolutePath: string): string[] {\n try {\n const source = fs.readFileSync(absolutePath, 'utf8')\n const sourceFile = ts.createSourceFile(absolutePath, source, ts.ScriptTarget.Latest, true)\n const declarations = collectObjectDeclarations(sourceFile)\n let tableObject: ts.ObjectLiteralExpression | null = null\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || declaration.name.text !== 'injectionTable' || !declaration.initializer) {\n continue\n }\n tableObject = resolveObjectExpression(declaration.initializer, declarations)\n }\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n tableObject ??= resolveObjectExpression(statement.expression, declarations)\n }\n }\n\n if (!tableObject) return []\n const ids = new Set<string>()\n for (const property of tableObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n collectWidgetIdsFromTableValue(property.initializer, declarations, ids)\n }\n return Array.from(ids)\n } catch {\n return []\n }\n}\n\nfunction resolveScannedWidgetPath(roots: ModuleRoots, fromApp: boolean, relPath: string): string {\n const base = fromApp ? roots.appBase : (resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase)\n return path.join(base, 'widgets', 'injection', ...relPath.split('/'))\n}\n\n/**\n * A widget's `metadata.id` and the injection-table entry that mounts it are two hand-typed string\n * literals in two different files, and nothing links them. A typo in either fails silently: the spot\n * resolves to no widget and nothing is logged, so it only surfaces as \"why isn't my widget\n * rendering\" during manual QA.\n *\n * Reports table entries whose `widgetId` no scanned widget declares. Diagnostics only \u2014 generated\n * output is unchanged and the build is not failed, since a table entry may legitimately point at a\n * widget supplied by a module that is not enabled in this app.\n *\n * Deliberately one-directional. The mirror check (\"a widget nothing references is never mounted\")\n * cannot be done reliably yet: `extractInjectionTableWidgetIds` only reads statically-analyzable\n * object literals, so a table assembled by composition or computation contributes **no** visible\n * ids \u2014 `example` exports `cond ? { ...a, ...b } : a` and `translations` exports\n * `buildInjectionTable()`, and both would have every one of their widgets reported as unreferenced.\n * Under-reporting is harmless in the direction implemented here (a reference the extractor never saw\n * cannot produce a warning) but fatal in the other. Teaching the extractor to resolve spreads,\n * conditionals and call expressions is the prerequisite for adding it.\n */\nfunction reportUnresolvableWidgetReferences(\n widgetEntries: Map<string, InjectionWidgetEntry>,\n tableWidgetRefs: Map<string, Set<string>>,\n): void {\n const declaredIds = new Set<string>()\n for (const entry of widgetEntries.values()) {\n if (entry.widgetId) declaredIds.add(entry.widgetId)\n }\n\n for (const [widgetId, modules] of Array.from(tableWidgetRefs.entries()).sort(([a], [b]) => a.localeCompare(b))) {\n if (declaredIds.has(widgetId)) continue\n const owners = Array.from(modules).sort((left, right) => left.localeCompare(right)).join(', ')\n console.warn(\n `[generate] \u26A0 Injection table in \"${owners}\" references widget id \"${widgetId}\", but no scanned ` +\n 'widget declares it \u2014 that spot will render nothing. Check the id against the widget\\'s ' +\n 'metadata.id, and that the widget lives in a file the scanner reads ' +\n '(widgets/injection/**/widget.ts|tsx \u2014 note that widget.client.tsx alone is not scanned).',\n )\n }\n}\n\nexport function createInjectionWidgetsExtension(): GeneratorExtension {\n const widgetEntries = new Map<string, InjectionWidgetEntry>()\n const tableEntries: InjectionTableEntry[] = []\n // widgetId -> module ids whose injection table references it. Collected across every module so a\n // table may legitimately reference a widget another module owns.\n const tableWidgetRefs = new Map<string, Set<string>>()\n\n return {\n id: 'registry.injection-widgets',\n outputFiles: ['injection-widgets.generated.ts', 'injection-tables.generated.ts'],\n scanModule(ctx) {\n const files = scanModuleDir(ctx.roots, SCAN_CONFIGS.injectionWidgets)\n const moduleWidgetEntries: InjectionWidgetEntry[] = []\n for (const { relPath, fromApp } of files) {\n const segments = relPath.split('/')\n const file = segments.pop() ?? ''\n const base = file.replace(/\\.(t|j)sx?$/, '')\n const importPath = ctx.sanitizeGeneratedModuleSpecifier(\n `${fromApp ? ctx.imps.appBase : ctx.imps.pkgBase}/widgets/injection/${[...segments, base].join('/')}`\n )\n const key = [ctx.moduleId, ...segments, base].filter(Boolean).join(':')\n const entry: InjectionWidgetEntry = {\n moduleId: ctx.moduleId,\n key,\n source: fromApp ? 'app' : 'package',\n importPath,\n widgetId: extractWidgetMetadataId(resolveScannedWidgetPath(ctx.roots, fromApp, relPath)) ?? undefined,\n }\n moduleWidgetEntries.push(entry)\n }\n\n const table = ctx.resolveModuleFile(ctx.roots, ctx.imps, 'widgets/injection-table.ts')\n const tableWidgetIds = table ? extractInjectionTableWidgetIds(table.absolutePath) : []\n if (moduleWidgetEntries.length === 1 && tableWidgetIds.length === 1 && !moduleWidgetEntries[0].widgetId) {\n moduleWidgetEntries[0].widgetId = tableWidgetIds[0]\n }\n\n for (const widgetId of tableWidgetIds) {\n const modules = tableWidgetRefs.get(widgetId) ?? new Set<string>()\n modules.add(ctx.moduleId)\n tableWidgetRefs.set(widgetId, modules)\n }\n\n for (const entry of moduleWidgetEntries) {\n const existing = widgetEntries.get(entry.key)\n if (!existing || (existing.source !== 'app' && entry.source === 'app')) {\n widgetEntries.set(entry.key, entry)\n }\n }\n\n if (table) {\n tableEntries.push({\n moduleId: ctx.moduleId,\n importName: `InjTable_${ctx.moduleId.replace(/[^a-zA-Z0-9_]/g, '_')}_${ctx.importIdRef.value++}`,\n importPath: ctx.sanitizeGeneratedModuleSpecifier(table.importPath),\n })\n }\n },\n generateOutput() {\n reportUnresolvableWidgetReferences(widgetEntries, tableWidgetRefs)\n\n const widgetDecls = Array.from(widgetEntries.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([, entry]) =>\n objectLiteral([\n { name: 'moduleId', value: entry.moduleId },\n { name: 'key', value: entry.key },\n { name: 'source', value: entry.source },\n ...(entry.widgetId ? [{ name: 'widgetId', value: entry.widgetId }] : []),\n {\n name: 'loader',\n value: arrowFunction({\n body: methodCall(dynamicImportExpression(entry.importPath), 'then', [\n arrowFunction({\n parameters: ['mod'],\n body: nullishCoalesce([\n propertyAccess(identifier('mod'), 'default'),\n identifier('mod'),\n ]),\n }),\n ]),\n }),\n },\n ]),\n )\n\n const widgetsOutput = renderGeneratedTsSource({\n fileName: 'injection-widgets.generated.ts',\n imports: [\n { namedImports: [{ name: 'ModuleInjectionWidgetEntry', isTypeOnly: true }], moduleSpecifier: '@open-mercato/shared/modules/registry' },\n ],\n build(sourceFile) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'injectionWidgetEntries',\n type: 'ModuleInjectionWidgetEntry[]',\n initializer: arrayLiteral(widgetDecls, writeValue),\n },\n ],\n })\n },\n })\n\n const tableImports = tableEntries.map((entry) => namespaceImportSpec(entry.importName, entry.importPath))\n const tableDecls = tableEntries.map((entry) =>\n objectLiteral([\n { name: 'moduleId', value: entry.moduleId },\n {\n name: 'table',\n value: namespaceFallback({\n importName: entry.importName,\n members: ['default', 'injectionTable'],\n fallback: emptyObject(),\n castType: 'ModuleInjectionTable',\n }),\n },\n ]),\n )\n const tablesOutput = renderGeneratedTsSource({\n fileName: 'injection-tables.generated.ts',\n imports: [\n { namedImports: [{ name: 'ModuleInjectionTable', isTypeOnly: true }], moduleSpecifier: '@open-mercato/shared/modules/widgets/injection' },\n ...tableImports,\n ],\n build(sourceFile) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'injectionTables',\n type: 'Array<{ moduleId: string; table: ModuleInjectionTable }>',\n initializer: arrayLiteral(tableDecls, writeValue),\n },\n ],\n })\n },\n })\n\n return new Map([\n ['injection-widgets.generated.ts', widgetsOutput],\n ['injection-tables.generated.ts', tablesOutput],\n ])\n },\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport ts from 'typescript-js'\nimport type { GeneratorExtension } from '../extension'\nimport { resolveStandaloneSourceMirrorBase, scanModuleDir, SCAN_CONFIGS, type ModuleRoots } from '../scanner'\nimport {\n arrayLiteral,\n arrowFunction,\n identifier,\n methodCall,\n nullishCoalesce,\n objectLiteral,\n propertyAccess,\n writeValue,\n} from '../ast'\nimport { dynamicImportExpression, emptyObject, namespaceFallback, namespaceImportSpec, renderGeneratedTsSource } from './shared'\n\ntype InjectionWidgetEntry = {\n moduleId: string\n key: string\n source: 'app' | 'package'\n importPath: string\n widgetId?: string\n}\n\ntype InjectionTableEntry = {\n moduleId: string\n importName: string\n importPath: string\n}\n\nfunction unwrapExpression(expression: ts.Expression): ts.Expression {\n let current = expression\n while (\n ts.isParenthesizedExpression(current)\n || ts.isAsExpression(current)\n || ts.isTypeAssertionExpression(current)\n || ts.isSatisfiesExpression(current)\n ) {\n current = current.expression\n }\n return current\n}\n\nfunction getPropertyNameText(name: ts.PropertyName): string | null {\n if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name)) {\n return name.text\n }\n return null\n}\n\nfunction collectObjectDeclarations(sourceFile: ts.SourceFile): Map<string, ts.ObjectLiteralExpression> {\n const declarations = new Map<string, ts.ObjectLiteralExpression>()\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n const initializer = unwrapExpression(declaration.initializer)\n if (ts.isObjectLiteralExpression(initializer)) {\n declarations.set(declaration.name.text, initializer)\n }\n }\n }\n return declarations\n}\n\nfunction resolveObjectExpression(\n expression: ts.Expression,\n declarations: Map<string, ts.ObjectLiteralExpression>,\n): ts.ObjectLiteralExpression | null {\n const unwrapped = unwrapExpression(expression)\n if (ts.isObjectLiteralExpression(unwrapped)) return unwrapped\n if (ts.isIdentifier(unwrapped)) return declarations.get(unwrapped.text) ?? null\n return null\n}\n\nfunction getObjectPropertyExpression(object: ts.ObjectLiteralExpression, propertyName: string): ts.Expression | null {\n for (const property of object.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n if (getPropertyNameText(property.name) === propertyName) return property.initializer\n }\n return null\n}\n\nfunction getStringPropertyValue(object: ts.ObjectLiteralExpression, propertyName: string): string | null {\n const expression = getObjectPropertyExpression(object, propertyName)\n if (!expression) return null\n const unwrapped = unwrapExpression(expression)\n if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) return unwrapped.text\n return null\n}\n\nfunction extractMetadataId(object: ts.ObjectLiteralExpression): string | null {\n const metadata = getObjectPropertyExpression(object, 'metadata')\n if (!metadata) return null\n const unwrapped = unwrapExpression(metadata)\n if (!ts.isObjectLiteralExpression(unwrapped)) return null\n return getStringPropertyValue(unwrapped, 'id')\n}\n\nfunction extractWidgetMetadataId(absolutePath: string): string | null {\n try {\n const source = fs.readFileSync(absolutePath, 'utf8')\n const sourceFile = ts.createSourceFile(absolutePath, source, ts.ScriptTarget.Latest, true)\n const declarations = collectObjectDeclarations(sourceFile)\n\n for (const statement of sourceFile.statements) {\n if (!ts.isExportAssignment(statement) || statement.isExportEquals) continue\n const object = resolveObjectExpression(statement.expression, declarations)\n if (!object) continue\n const id = extractMetadataId(object)\n if (id) return id\n }\n\n for (const object of declarations.values()) {\n const id = extractMetadataId(object)\n if (id) return id\n }\n } catch {\n return null\n }\n return null\n}\n\nfunction collectWidgetIdsFromTableValue(\n value: ts.Expression,\n declarations: Map<string, ts.ObjectLiteralExpression>,\n ids: Set<string>,\n) {\n const expression = unwrapExpression(value)\n if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {\n ids.add(expression.text)\n return\n }\n if (ts.isArrayLiteralExpression(expression)) {\n for (const element of expression.elements) {\n if (ts.isExpression(element)) collectWidgetIdsFromTableValue(element, declarations, ids)\n }\n return\n }\n const object = resolveObjectExpression(expression, declarations)\n if (!object) return\n const widgetId = getStringPropertyValue(object, 'widgetId')\n if (widgetId) ids.add(widgetId)\n}\n\nfunction extractInjectionTableWidgetIds(absolutePath: string): string[] {\n try {\n const source = fs.readFileSync(absolutePath, 'utf8')\n const sourceFile = ts.createSourceFile(absolutePath, source, ts.ScriptTarget.Latest, true)\n const declarations = collectObjectDeclarations(sourceFile)\n let tableObject: ts.ObjectLiteralExpression | null = null\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || declaration.name.text !== 'injectionTable' || !declaration.initializer) {\n continue\n }\n tableObject = resolveObjectExpression(declaration.initializer, declarations)\n }\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n tableObject ??= resolveObjectExpression(statement.expression, declarations)\n }\n }\n\n if (!tableObject) return []\n const ids = new Set<string>()\n for (const property of tableObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n collectWidgetIdsFromTableValue(property.initializer, declarations, ids)\n }\n return Array.from(ids)\n } catch {\n return []\n }\n}\n\nfunction resolveScannedWidgetPath(roots: ModuleRoots, fromApp: boolean, relPath: string): string {\n const base = fromApp ? roots.appBase : (resolveStandaloneSourceMirrorBase(roots.pkgBase) ?? roots.pkgBase)\n return path.join(base, 'widgets', 'injection', ...relPath.split('/'))\n}\n\nexport function createInjectionWidgetsExtension(): GeneratorExtension {\n const widgetEntries = new Map<string, InjectionWidgetEntry>()\n const tableEntries: InjectionTableEntry[] = []\n\n return {\n id: 'registry.injection-widgets',\n outputFiles: ['injection-widgets.generated.ts', 'injection-tables.generated.ts'],\n scanModule(ctx) {\n const files = scanModuleDir(ctx.roots, SCAN_CONFIGS.injectionWidgets)\n const moduleWidgetEntries: InjectionWidgetEntry[] = []\n for (const { relPath, fromApp } of files) {\n const segments = relPath.split('/')\n const file = segments.pop() ?? ''\n const base = file.replace(/\\.(t|j)sx?$/, '')\n const importPath = ctx.sanitizeGeneratedModuleSpecifier(\n `${fromApp ? ctx.imps.appBase : ctx.imps.pkgBase}/widgets/injection/${[...segments, base].join('/')}`\n )\n const key = [ctx.moduleId, ...segments, base].filter(Boolean).join(':')\n const entry: InjectionWidgetEntry = {\n moduleId: ctx.moduleId,\n key,\n source: fromApp ? 'app' : 'package',\n importPath,\n widgetId: extractWidgetMetadataId(resolveScannedWidgetPath(ctx.roots, fromApp, relPath)) ?? undefined,\n }\n moduleWidgetEntries.push(entry)\n }\n\n const table = ctx.resolveModuleFile(ctx.roots, ctx.imps, 'widgets/injection-table.ts')\n const tableWidgetIds = table ? extractInjectionTableWidgetIds(table.absolutePath) : []\n if (moduleWidgetEntries.length === 1 && tableWidgetIds.length === 1 && !moduleWidgetEntries[0].widgetId) {\n moduleWidgetEntries[0].widgetId = tableWidgetIds[0]\n }\n\n for (const entry of moduleWidgetEntries) {\n const existing = widgetEntries.get(entry.key)\n if (!existing || (existing.source !== 'app' && entry.source === 'app')) {\n widgetEntries.set(entry.key, entry)\n }\n }\n\n if (table) {\n tableEntries.push({\n moduleId: ctx.moduleId,\n importName: `InjTable_${ctx.moduleId.replace(/[^a-zA-Z0-9_]/g, '_')}_${ctx.importIdRef.value++}`,\n importPath: ctx.sanitizeGeneratedModuleSpecifier(table.importPath),\n })\n }\n },\n generateOutput() {\n const widgetDecls = Array.from(widgetEntries.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([, entry]) =>\n objectLiteral([\n { name: 'moduleId', value: entry.moduleId },\n { name: 'key', value: entry.key },\n { name: 'source', value: entry.source },\n ...(entry.widgetId ? [{ name: 'widgetId', value: entry.widgetId }] : []),\n {\n name: 'loader',\n value: arrowFunction({\n body: methodCall(dynamicImportExpression(entry.importPath), 'then', [\n arrowFunction({\n parameters: ['mod'],\n body: nullishCoalesce([\n propertyAccess(identifier('mod'), 'default'),\n identifier('mod'),\n ]),\n }),\n ]),\n }),\n },\n ]),\n )\n\n const widgetsOutput = renderGeneratedTsSource({\n fileName: 'injection-widgets.generated.ts',\n imports: [\n { namedImports: [{ name: 'ModuleInjectionWidgetEntry', isTypeOnly: true }], moduleSpecifier: '@open-mercato/shared/modules/registry' },\n ],\n build(sourceFile) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'injectionWidgetEntries',\n type: 'ModuleInjectionWidgetEntry[]',\n initializer: arrayLiteral(widgetDecls, writeValue),\n },\n ],\n })\n },\n })\n\n const tableImports = tableEntries.map((entry) => namespaceImportSpec(entry.importName, entry.importPath))\n const tableDecls = tableEntries.map((entry) =>\n objectLiteral([\n { name: 'moduleId', value: entry.moduleId },\n {\n name: 'table',\n value: namespaceFallback({\n importName: entry.importName,\n members: ['default', 'injectionTable'],\n fallback: emptyObject(),\n castType: 'ModuleInjectionTable',\n }),\n },\n ]),\n )\n const tablesOutput = renderGeneratedTsSource({\n fileName: 'injection-tables.generated.ts',\n imports: [\n { namedImports: [{ name: 'ModuleInjectionTable', isTypeOnly: true }], moduleSpecifier: '@open-mercato/shared/modules/widgets/injection' },\n ...tableImports,\n ],\n build(sourceFile) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'injectionTables',\n type: 'Array<{ moduleId: string; table: ModuleInjectionTable }>',\n initializer: arrayLiteral(tableDecls, writeValue),\n },\n ],\n })\n },\n })\n\n return new Map([\n ['injection-widgets.generated.ts', widgetsOutput],\n ['injection-tables.generated.ts', tablesOutput],\n ])\n },\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -18,42 +18,13 @@ function hasReadableModuleSource(moduleRoot) {
18
18
  }
19
19
  return false;
20
20
  }
21
- function resolveDuplicateModuleIds(sources, resolver) {
22
- const sourcesByModule = /* @__PURE__ */ new Map();
23
- for (const source of sources) {
24
- const matches = sourcesByModule.get(source.moduleId) ?? [];
25
- matches.push(source);
26
- sourcesByModule.set(source.moduleId, matches);
27
- }
28
- const duplicates = [...sourcesByModule.entries()].filter(([, matches]) => matches.length > 1);
29
- if (duplicates.length === 0) return sources;
30
- const selectedProviders = /* @__PURE__ */ new Map();
31
- const implicitCoreSelections = /* @__PURE__ */ new Set();
32
- for (const entry of resolver.loadEnabledModules()) {
33
- const providers = selectedProviders.get(entry.id) ?? /* @__PURE__ */ new Set();
34
- providers.add(entry.from ?? "@open-mercato/core");
35
- selectedProviders.set(entry.id, providers);
36
- if (entry.from === void 0) implicitCoreSelections.add(entry.id);
37
- }
38
- const selectedSources = /* @__PURE__ */ new Map();
39
- for (const [moduleId, matches] of duplicates) {
40
- const providers = [...new Set(matches.map((source) => source.from ?? "<unknown>"))].sort((left, right) => left.localeCompare(right));
41
- const configuredProviders = [...selectedProviders.get(moduleId) ?? []].sort((left, right) => left.localeCompare(right));
42
- const selected = configuredProviders.length === 1 ? matches.filter((source) => source.from === configuredProviders[0]) : [];
43
- if (selected.length !== 1) {
44
- const configured = configuredProviders.length > 0 ? implicitCoreSelections.has(moduleId) ? '; src/modules.ts omits "from", which defaults to @open-mercato/core' : `; src/modules.ts selects ${configuredProviders.join(", ")}` : "; src/modules.ts does not select a provider";
45
- throw new Error(
46
- `[module-facts] duplicate module id "${moduleId}" is provided by ${providers.join(", ")}${configured}. Select exactly one matching provider in src/modules.ts.`
47
- );
48
- }
49
- selectedSources.set(moduleId, selected[0]);
50
- }
51
- const emitted = /* @__PURE__ */ new Set();
21
+ function dedupeById(sources) {
22
+ const seen = /* @__PURE__ */ new Set();
52
23
  const result = [];
53
24
  for (const source of sources) {
54
- if (emitted.has(source.moduleId)) continue;
55
- emitted.add(source.moduleId);
56
- result.push(selectedSources.get(source.moduleId) ?? source);
25
+ if (seen.has(source.moduleId)) continue;
26
+ seen.add(source.moduleId);
27
+ result.push(source);
57
28
  }
58
29
  return result;
59
30
  }
@@ -63,15 +34,10 @@ function discoverPackageModuleSources(resolver) {
63
34
  for (const discovered of discoverModulesInPackage(pkg.path)) {
64
35
  const moduleRoot = path.join(pkg.modulesPath, discovered.moduleId);
65
36
  if (!hasReadableModuleSource(moduleRoot)) continue;
66
- sources.push({
67
- moduleId: discovered.moduleId,
68
- moduleRoot,
69
- from: pkg.name,
70
- packageVersion: pkg.version ?? null
71
- });
37
+ sources.push({ moduleId: discovered.moduleId, moduleRoot, from: pkg.name });
72
38
  }
73
39
  }
74
- return resolveDuplicateModuleIds(sources, resolver);
40
+ return dedupeById(sources);
75
41
  }
76
42
  export {
77
43
  discoverPackageModuleSources,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/generators/module-facts-discovery.ts"],
4
- "sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { PackageResolver } from '../resolver'\nimport { discoverModulesInPackage } from '../module-package'\nimport type { ModuleFactSource } from './module-facts'\n\nconst READABLE_CONVENTION_FILES = [\n 'index',\n 'acl',\n 'events',\n 'di',\n path.join('data', 'entities'),\n path.join('db', 'entities'),\n]\n\n/**\n * True when the module directory exposes at least one recognised convention file as\n * TypeScript source. This is the auto-discovery boundary that skips `.js`-only\n * installs (standalone `node_modules/@open-mercato/<pkg>/dist/modules`) \u2014 the extractor's\n * ts-morph reader only parses `.ts`/`.tsx`, so a `.js`-only root would yield empty facts.\n */\nexport function hasReadableModuleSource(moduleRoot: string): boolean {\n if (!fs.existsSync(moduleRoot)) return false\n for (const basename of READABLE_CONVENTION_FILES) {\n for (const extension of ['.ts', '.tsx']) {\n if (fs.existsSync(path.join(moduleRoot, `${basename}${extension}`))) return true\n }\n }\n return false\n}\n\nfunction resolveDuplicateModuleIds(\n sources: ModuleFactSource[],\n resolver: PackageResolver,\n): ModuleFactSource[] {\n const sourcesByModule = new Map<string, ModuleFactSource[]>()\n for (const source of sources) {\n const matches = sourcesByModule.get(source.moduleId) ?? []\n matches.push(source)\n sourcesByModule.set(source.moduleId, matches)\n }\n\n const duplicates = [...sourcesByModule.entries()].filter(([, matches]) => matches.length > 1)\n if (duplicates.length === 0) return sources\n\n const selectedProviders = new Map<string, Set<string>>()\n const implicitCoreSelections = new Set<string>()\n for (const entry of resolver.loadEnabledModules()) {\n const providers = selectedProviders.get(entry.id) ?? new Set<string>()\n providers.add(entry.from ?? '@open-mercato/core')\n selectedProviders.set(entry.id, providers)\n if (entry.from === undefined) implicitCoreSelections.add(entry.id)\n }\n\n const selectedSources = new Map<string, ModuleFactSource>()\n for (const [moduleId, matches] of duplicates) {\n const providers = [...new Set(matches.map((source) => source.from ?? '<unknown>'))]\n .sort((left, right) => left.localeCompare(right))\n const configuredProviders = [...(selectedProviders.get(moduleId) ?? [])]\n .sort((left, right) => left.localeCompare(right))\n const selected = configuredProviders.length === 1\n ? matches.filter((source) => source.from === configuredProviders[0])\n : []\n\n if (selected.length !== 1) {\n const configured = configuredProviders.length > 0\n ? implicitCoreSelections.has(moduleId)\n ? '; src/modules.ts omits \"from\", which defaults to @open-mercato/core'\n : `; src/modules.ts selects ${configuredProviders.join(', ')}`\n : '; src/modules.ts does not select a provider'\n throw new Error(\n `[module-facts] duplicate module id \"${moduleId}\" is provided by ${providers.join(', ')}${configured}. `\n + 'Select exactly one matching provider in src/modules.ts.',\n )\n }\n selectedSources.set(moduleId, selected[0])\n }\n\n const emitted = new Set<string>()\n const result: ModuleFactSource[] = []\n for (const source of sources) {\n if (emitted.has(source.moduleId)) continue\n emitted.add(source.moduleId)\n result.push(selectedSources.get(source.moduleId) ?? source)\n }\n return result\n}\n\n/**\n * Package-scan discovery for the create-app build: every package-provided module\n * across `@open-mercato/*` workspace packages (core plus others), never `apps/*`\n * demo modules. Routes through the resolver rather than hardcoded paths.\n */\nexport function discoverPackageModuleSources(resolver: PackageResolver): ModuleFactSource[] {\n const sources: ModuleFactSource[] = []\n for (const pkg of resolver.discoverPackages()) {\n for (const discovered of discoverModulesInPackage(pkg.path)) {\n const moduleRoot = path.join(pkg.modulesPath, discovered.moduleId)\n if (!hasReadableModuleSource(moduleRoot)) continue\n sources.push({\n moduleId: discovered.moduleId,\n moduleRoot,\n from: pkg.name,\n packageVersion: pkg.version ?? null,\n })\n }\n }\n return resolveDuplicateModuleIds(sources, resolver)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { PackageResolver } from '../resolver'\nimport { discoverModulesInPackage } from '../module-package'\nimport type { ModuleFactSource } from './module-facts'\n\nconst READABLE_CONVENTION_FILES = [\n 'index',\n 'acl',\n 'events',\n 'di',\n path.join('data', 'entities'),\n path.join('db', 'entities'),\n]\n\n/**\n * True when the module directory exposes at least one recognised convention file as\n * TypeScript source. This is the auto-discovery boundary that skips `.js`-only\n * installs (standalone `node_modules/@open-mercato/<pkg>/dist/modules`) \u2014 the extractor's\n * ts-morph reader only parses `.ts`/`.tsx`, so a `.js`-only root would yield empty facts.\n */\nexport function hasReadableModuleSource(moduleRoot: string): boolean {\n if (!fs.existsSync(moduleRoot)) return false\n for (const basename of READABLE_CONVENTION_FILES) {\n for (const extension of ['.ts', '.tsx']) {\n if (fs.existsSync(path.join(moduleRoot, `${basename}${extension}`))) return true\n }\n }\n return false\n}\n\nfunction dedupeById(sources: ModuleFactSource[]): ModuleFactSource[] {\n const seen = new Set<string>()\n const result: ModuleFactSource[] = []\n for (const source of sources) {\n if (seen.has(source.moduleId)) continue\n seen.add(source.moduleId)\n result.push(source)\n }\n return result\n}\n\n/**\n * Package-scan discovery for the create-app build: every package-provided module\n * across `@open-mercato/*` workspace packages (core plus others), never `apps/*`\n * demo modules. Routes through the resolver rather than hardcoded paths.\n */\nexport function discoverPackageModuleSources(resolver: PackageResolver): ModuleFactSource[] {\n const sources: ModuleFactSource[] = []\n for (const pkg of resolver.discoverPackages()) {\n for (const discovered of discoverModulesInPackage(pkg.path)) {\n const moduleRoot = path.join(pkg.modulesPath, discovered.moduleId)\n if (!hasReadableModuleSource(moduleRoot)) continue\n sources.push({ moduleId: discovered.moduleId, moduleRoot, from: pkg.name })\n }\n }\n return dedupeById(sources)\n}\n"],
5
+ "mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,SAAS,gCAAgC;AAGzC,MAAM,4BAA4B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,KAAK,KAAK,QAAQ,UAAU;AAAA,EAC5B,KAAK,KAAK,MAAM,UAAU;AAC5B;AAQO,SAAS,wBAAwB,YAA6B;AACnE,MAAI,CAAC,GAAG,WAAW,UAAU,EAAG,QAAO;AACvC,aAAW,YAAY,2BAA2B;AAChD,eAAW,aAAa,CAAC,OAAO,MAAM,GAAG;AACvC,UAAI,GAAG,WAAW,KAAK,KAAK,YAAY,GAAG,QAAQ,GAAG,SAAS,EAAE,CAAC,EAAG,QAAO;AAAA,IAC9E;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,SAAiD;AACnE,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAA6B,CAAC;AACpC,aAAW,UAAU,SAAS;AAC5B,QAAI,KAAK,IAAI,OAAO,QAAQ,EAAG;AAC/B,SAAK,IAAI,OAAO,QAAQ;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AACA,SAAO;AACT;AAOO,SAAS,6BAA6B,UAA+C;AAC1F,QAAM,UAA8B,CAAC;AACrC,aAAW,OAAO,SAAS,iBAAiB,GAAG;AAC7C,eAAW,cAAc,yBAAyB,IAAI,IAAI,GAAG;AAC3D,YAAM,aAAa,KAAK,KAAK,IAAI,aAAa,WAAW,QAAQ;AACjE,UAAI,CAAC,wBAAwB,UAAU,EAAG;AAC1C,cAAQ,KAAK,EAAE,UAAU,WAAW,UAAU,YAAY,MAAM,IAAI,KAAK,CAAC;AAAA,IAC5E;AAAA,EACF;AACA,SAAO,WAAW,OAAO;AAC3B;",
6
6
  "names": []
7
7
  }