@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
@@ -2,23 +2,6 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import ts from "typescript-js";
4
4
  import { toSnake } from "../utils.js";
5
- import { extractCommandIdsFromSource } from "./module-registry.js";
6
- import { MODULE_CODE_EXTENSIONS } from "./scanner.js";
7
- import {
8
- assertNoUnresolvedExtensionTargets,
9
- correlateIncomingExtensions,
10
- correlateModuleExtensionFacts,
11
- extractActivationTargetOwners,
12
- extractKnownApiRouteIds,
13
- extractKnownCommandIds,
14
- extractModuleExtensionFacts,
15
- renderFrameworkExtensionPointsMarkdown,
16
- withModuleExtensionFactExtractionCache
17
- } from "./module-extension-facts.js";
18
- import {
19
- collectModuleOverrideTargets
20
- } from "./module-override-targets.js";
21
- import { buildFactSourceLookup } from "./module-fact-sources.js";
22
5
  function readSourceFile(filePath) {
23
6
  if (!fs.existsSync(filePath)) return null;
24
7
  const source = fs.readFileSync(filePath, "utf8");
@@ -84,38 +67,10 @@ function collectCustomFieldEntityIds(ceFilePath) {
84
67
  if (!ceFilePath) return result;
85
68
  const sourceFile = readSourceFile(ceFilePath);
86
69
  if (!sourceFile) return result;
87
- const readEntityId = (expression) => {
88
- const current = unwrapExpression(expression);
89
- if (ts.isStringLiteralLike(current)) {
90
- return current.text.includes(":") ? current.text : void 0;
91
- }
92
- const readAccessPath = (candidate) => {
93
- const access = unwrapExpression(candidate);
94
- if (ts.isIdentifier(access)) return [access.text];
95
- if (ts.isPropertyAccessExpression(access)) {
96
- const parent = readAccessPath(access.expression);
97
- return parent ? [...parent, access.name.text] : null;
98
- }
99
- if (ts.isElementAccessExpression(access) && access.argumentExpression) {
100
- const parent = readAccessPath(access.expression);
101
- const key = unwrapExpression(access.argumentExpression);
102
- return parent && ts.isStringLiteralLike(key) ? [...parent, key.text] : null;
103
- }
104
- return null;
105
- };
106
- const accessPath = readAccessPath(current);
107
- if (accessPath?.length === 3 && accessPath[0] === "E") {
108
- return `${accessPath[1]}:${accessPath[2]}`;
109
- }
110
- return void 0;
111
- };
112
70
  const visit = (node) => {
113
71
  if (ts.isObjectLiteralExpression(node)) {
114
- const initializer = getObjectPropertyInitializer(node, "id");
115
- if (initializer) {
116
- const id = readEntityId(initializer);
117
- if (id) result.add(id);
118
- }
72
+ const id = readStringPropertyInitializer(node, "id");
73
+ if (id && id.includes(":")) result.add(id);
119
74
  }
120
75
  node.forEachChild(visit);
121
76
  };
@@ -257,11 +212,7 @@ function extractEvents(eventsFilePath) {
257
212
  category: category ?? null,
258
213
  entity: entity ?? null
259
214
  };
260
- const clientBroadcast = readBooleanPropertyInitializer(element, "clientBroadcast");
261
- const portalBroadcast = readBooleanPropertyInitializer(element, "portalBroadcast");
262
215
  if (label !== void 0) fact.label = label;
263
- if (clientBroadcast !== void 0) fact.clientBroadcast = clientBroadcast;
264
- if (portalBroadcast !== void 0) fact.portalBroadcast = portalBroadcast;
265
216
  facts.push(fact);
266
217
  }
267
218
  return facts;
@@ -351,9 +302,9 @@ function parseApiRouteEntry(entryLiteral) {
351
302
  }
352
303
  }
353
304
  }
354
- return { path: routePath, methods, auth, sourcePath: null };
305
+ return { path: routePath, methods, auth };
355
306
  }
356
- function extractApiRoutes(moduleId, registrySource, registryDescription, routeSourcePaths, warnings) {
307
+ function extractApiRoutes(moduleId, registrySource, registryDescription, warnings) {
357
308
  if (registrySource == null) {
358
309
  warnings.push(`[module-facts] module registry unavailable (${registryDescription}); API route auth omitted for ${moduleId}`);
359
310
  return [];
@@ -377,7 +328,7 @@ function extractApiRoutes(moduleId, registrySource, registryDescription, routeSo
377
328
  const route = parseApiRouteEntry(element);
378
329
  if (route && !seenPaths.has(route.path)) {
379
330
  seenPaths.add(route.path);
380
- routes.push({ ...route, sourcePath: routeSourcePaths.get(route.path) ?? null });
331
+ routes.push(route);
381
332
  }
382
333
  }
383
334
  }
@@ -525,195 +476,31 @@ function extractCli(cliFilePath, warnings) {
525
476
  function listSourceFilesRecursive(directory) {
526
477
  const files = [];
527
478
  for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
528
- if (entry.name === "__tests__" || entry.name === "__mocks__" || entry.name === "node_modules") continue;
479
+ if (entry.name === "__tests__" || entry.name === "node_modules") continue;
529
480
  const fullPath = path.join(directory, entry.name);
530
481
  if (entry.isDirectory()) {
531
482
  files.push(...listSourceFilesRecursive(fullPath));
532
- } else if (/\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts") && !/\.(?:test|spec)\.tsx?$/.test(entry.name)) {
483
+ } else if (/\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
533
484
  files.push(fullPath);
534
485
  }
535
486
  }
536
487
  return files;
537
488
  }
538
- function toPortableSourceRoot(moduleId, sourcePackage) {
539
- return path.posix.join("node_modules", sourcePackage ?? "@open-mercato/core", "src", "modules", moduleId);
540
- }
541
- function toPortableSourcePath(moduleRoot, sourceRoot, filePath) {
542
- const relativePath = path.relative(moduleRoot, filePath).split(path.sep).join("/");
543
- return path.posix.join(sourceRoot, relativePath);
544
- }
545
- function sourceHasDefaultExport(sourceFile) {
546
- return sourceFile.statements.some((statement) => {
547
- if (ts.isExportAssignment(statement) && !statement.isExportEquals) return true;
548
- if (!ts.isFunctionDeclaration(statement) && !ts.isClassDeclaration(statement)) return false;
549
- return statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
550
- });
551
- }
552
- function readRouteMetadataPath(sourceFile) {
553
- const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
554
- return metadata ? readStringPropertyInitializer(metadata, "path") ?? null : null;
555
- }
556
- function extractApiRouteSourcePaths(moduleId, moduleRoot, sourceRoot) {
557
- const apiRoot = path.join(moduleRoot, "api");
558
- const sources = /* @__PURE__ */ new Map();
559
- if (!fs.existsSync(apiRoot)) return sources;
560
- const methodDirectories = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete"]);
561
- for (const filePath of listSourceFilesRecursive(apiRoot)) {
562
- const relativePath = path.relative(apiRoot, filePath).split(path.sep).join("/");
563
- const segments = relativePath.split("/");
564
- const fileName = segments.pop();
565
- const fileStem = fileName.replace(/\.tsx?$/, "");
566
- let routeSegments;
567
- if (fileStem === "route") {
568
- routeSegments = segments;
569
- } else if (segments[0] && methodDirectories.has(segments[0].toLowerCase())) {
570
- routeSegments = [...segments.slice(1), fileStem];
571
- } else {
572
- routeSegments = [...segments, fileStem];
573
- }
574
- const defaultPath = `/${[moduleId, ...routeSegments].filter(Boolean).join("/")}`;
575
- const sourceFile = readSourceFile(filePath);
576
- const routePath = sourceFile ? readRouteMetadataPath(sourceFile) ?? defaultPath : defaultPath;
577
- sources.set(routePath, toPortableSourcePath(moduleRoot, sourceRoot, filePath));
578
- }
579
- return sources;
580
- }
581
- function extractModulePages(moduleId, moduleRoot, sourceRoot, surface) {
582
- const pageRoot = path.join(moduleRoot, surface);
583
- if (!fs.existsSync(pageRoot)) return [];
584
- const pages = [];
585
- const seen = /* @__PURE__ */ new Set();
586
- for (const filePath of listSourceFilesRecursive(pageRoot)) {
587
- if (!filePath.endsWith(".tsx")) continue;
588
- const relativePath = path.relative(pageRoot, filePath).split(path.sep).join("/");
589
- const segments = relativePath.split("/");
590
- const fileName = segments.pop();
591
- const fileStem = fileName.replace(/\.tsx$/, "");
592
- const isModernPage = fileStem === "page";
593
- if (!isModernPage && (fileStem === "meta" || fileStem.endsWith(".meta") || /^[A-Z]/.test(fileStem))) continue;
594
- const sourceFile = readSourceFile(filePath);
595
- if (!sourceFile || !sourceHasDefaultExport(sourceFile)) continue;
596
- const routeSegments = isModernPage ? segments : [...segments, fileStem];
597
- const routePath = surface === "frontend" ? `/${routeSegments.filter(Boolean).join("/")}` : isModernPage ? `/backend/${routeSegments.join("/") || moduleId}` : `/backend/${routeSegments[0] === moduleId ? routeSegments.filter(Boolean).join("/") : [moduleId, ...routeSegments].filter(Boolean).join("/")}`;
598
- if (seen.has(routePath)) continue;
599
- seen.add(routePath);
600
- const metadataFilePath = resolvePageMetadataFile(path.dirname(filePath));
601
- const metadataSourceFile = metadataFilePath ? readSourceFile(metadataFilePath) : sourceFile;
602
- const metadata = metadataSourceFile ? readPageMetadata(metadataSourceFile) : void 0;
603
- pages.push({
604
- path: routePath,
605
- sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, filePath),
606
- ...metadataFilePath ? { metadataSourcePath: toPortableSourcePath(moduleRoot, sourceRoot, metadataFilePath) } : {},
607
- ...metadata ? { metadata } : {}
608
- });
609
- }
610
- return pages.sort((left, right) => left.path.localeCompare(right.path));
611
- }
612
- function findAncestorVariableDeclaration(node) {
613
- let current = node.parent;
614
- while (current) {
615
- if (ts.isVariableDeclaration(current)) return current;
616
- current = current.parent;
617
- }
618
- return null;
619
- }
620
- function findAncestorCallExpression(node) {
621
- let current = node.parent;
622
- while (current) {
623
- if (ts.isCallExpression(current)) return current;
624
- if (ts.isVariableDeclaration(current) || ts.isStatement(current)) return null;
625
- current = current.parent;
626
- }
627
- return null;
628
- }
629
- function extractNamedAiFacts(filePaths, moduleRoot, sourceRoot, propertyName) {
630
- const facts = [];
631
- const seen = /* @__PURE__ */ new Set();
632
- for (const filePath of filePaths) {
633
- const sourceFile = readSourceFile(filePath);
634
- if (!sourceFile) continue;
635
- const initializers = buildVariableInitializerMap(sourceFile);
636
- const readDefinitionValue = (objectLiteral) => {
637
- const initializer = getObjectPropertyInitializer(objectLiteral, propertyName);
638
- if (!initializer) return void 0;
639
- const resolved = unwrapExpression(initializer);
640
- if (ts.isStringLiteralLike(resolved)) return resolved.text;
641
- if (ts.isIdentifier(resolved)) {
642
- const declarationInitializer = initializers.get(resolved.text);
643
- if (declarationInitializer) {
644
- const declarationValue = unwrapExpression(declarationInitializer);
645
- if (ts.isStringLiteralLike(declarationValue)) return declarationValue.text;
646
- }
647
- }
648
- return void 0;
649
- };
650
- const visit = (node) => {
651
- if (ts.isObjectLiteralExpression(node)) {
652
- const value = readDefinitionValue(node);
653
- if (value && !seen.has(value)) {
654
- const declaration = findAncestorVariableDeclaration(node);
655
- const declarationName = declaration && ts.isIdentifier(declaration.name) ? declaration.name.text : "";
656
- const declarationType = declaration?.type?.getText(sourceFile) ?? "";
657
- const call = findAncestorCallExpression(node);
658
- const callee = call?.expression.getText(sourceFile) ?? "";
659
- const isDefinition = propertyName === "name" ? /AiTool/.test(declarationType) || /tool$/i.test(declarationName) || /AiTool/.test(callee) : /AiAgentDefinition/.test(declarationType) || /agent$/i.test(declarationName) || /defineAiAgent/.test(callee);
660
- if (isDefinition) {
661
- seen.add(value);
662
- facts.push({
663
- value,
664
- sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, filePath)
665
- });
666
- }
667
- }
668
- }
669
- node.forEachChild(visit);
670
- };
671
- sourceFile.forEachChild(visit);
672
- }
673
- return facts.sort((left, right) => left.value.localeCompare(right.value));
674
- }
675
- function extractAiTools(moduleRoot, sourceRoot) {
676
- const files = /* @__PURE__ */ new Set();
677
- const rootFile = resolveConventionFile(moduleRoot, "ai-tools");
678
- if (rootFile) files.add(rootFile);
679
- const toolsDirectory = path.join(moduleRoot, "ai-tools");
680
- if (fs.existsSync(toolsDirectory)) {
681
- for (const filePath of listSourceFilesRecursive(toolsDirectory)) files.add(filePath);
682
- }
683
- return extractNamedAiFacts([...files], moduleRoot, sourceRoot, "name").map((fact) => ({ name: fact.value, sourcePath: fact.sourcePath }));
684
- }
685
- function extractAiAgents(moduleRoot, sourceRoot) {
686
- const agentsFile = resolveConventionFile(moduleRoot, "ai-agents");
687
- if (!agentsFile) return [];
688
- return extractNamedAiFacts([agentsFile], moduleRoot, sourceRoot, "id").map((fact) => ({ id: fact.value, sourcePath: fact.sourcePath }));
689
- }
690
- function extractTableIds(moduleRoot) {
691
- if (!fs.existsSync(moduleRoot)) return [];
489
+ function extractTableIds(backendDir) {
490
+ if (!fs.existsSync(backendDir)) return [];
692
491
  const tableIds = [];
693
492
  const seen = /* @__PURE__ */ new Set();
694
- const collectLiteralValues = (expression) => {
695
- const current = unwrapExpression(expression);
696
- if (ts.isStringLiteralLike(current)) return [current.text];
697
- if (ts.isConditionalExpression(current)) {
698
- return [
699
- ...collectLiteralValues(current.whenTrue),
700
- ...collectLiteralValues(current.whenFalse)
701
- ];
702
- }
703
- return [];
704
- };
705
- for (const filePath of listSourceFilesRecursive(moduleRoot)) {
493
+ for (const filePath of listSourceFilesRecursive(backendDir)) {
706
494
  const sourceFile = readSourceFile(filePath);
707
495
  if (!sourceFile) continue;
708
496
  const visit = (node) => {
709
497
  if (ts.isPropertyAssignment(node)) {
710
498
  const propertyName = getPropertyName(node);
711
- if (propertyName === "tableId" || propertyName === "extensionTableId") {
712
- for (const value of collectLiteralValues(node.initializer)) {
713
- if (value && !seen.has(value)) {
714
- seen.add(value);
715
- tableIds.push(value);
716
- }
499
+ if ((propertyName === "tableId" || propertyName === "extensionTableId") && ts.isStringLiteralLike(node.initializer)) {
500
+ const value = node.initializer.text;
501
+ if (value && !seen.has(value)) {
502
+ seen.add(value);
503
+ tableIds.push(value);
717
504
  }
718
505
  }
719
506
  }
@@ -738,587 +525,12 @@ function extractModuleMeta(indexFilePath) {
738
525
  description: readStringPropertyInitializer(metadata, "description") ?? null
739
526
  };
740
527
  }
741
- function nodeLine(sourceFile, node) {
742
- return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
743
- }
744
- function readPropertyNameText(name) {
745
- if (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) return name.text;
746
- return void 0;
747
- }
748
- function readMethodBearingPropertyNames(objectLiteral) {
749
- const names = [];
750
- for (const property of objectLiteral.properties) {
751
- if (ts.isMethodDeclaration(property)) {
752
- const name = readPropertyNameText(property.name);
753
- if (name) names.push(name);
754
- continue;
755
- }
756
- if (ts.isPropertyAssignment(property)) {
757
- const name = readPropertyNameText(property.name);
758
- if (!name) continue;
759
- const initializer = unwrapExpression(property.initializer);
760
- if (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) names.push(name);
761
- }
762
- }
763
- return names.sort((left, right) => left.localeCompare(right));
764
- }
765
- function readObjectKeyNames(objectLiteral) {
766
- const names = [];
767
- for (const property of objectLiteral.properties) {
768
- const name = getPropertyName(property);
769
- if (name) names.push(name);
770
- }
771
- return names.sort((left, right) => left.localeCompare(right));
772
- }
773
- function mapDiRegistrationKind(base) {
774
- switch (base) {
775
- case "asFunction":
776
- return "function";
777
- case "asClass":
778
- return "class";
779
- case "asValue":
780
- return "value";
781
- case "aliasTo":
782
- return "alias";
783
- default:
784
- return null;
785
- }
786
- }
787
- function readDiChainMetadata(initializer) {
788
- const result = {};
789
- let current = unwrapExpression(initializer);
790
- while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
791
- const method = current.expression.name.text;
792
- if ((method === "singleton" || method === "scoped" || method === "transient") && !result.lifetime) {
793
- result.lifetime = method;
794
- } else if (method === "proxy" && !result.injectionMode) {
795
- result.injectionMode = "proxy";
796
- } else if (method === "classic" && !result.injectionMode) {
797
- result.injectionMode = "classic";
798
- }
799
- current = unwrapExpression(current.expression.expression);
800
- }
801
- return result;
802
- }
803
- function readDiProviderSymbol(initializer, kind) {
804
- let current = unwrapExpression(initializer);
805
- while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
806
- current = unwrapExpression(current.expression.expression);
807
- }
808
- if (!ts.isCallExpression(current)) return void 0;
809
- const argument = current.arguments[0];
810
- if (!argument) return void 0;
811
- if (kind === "value") return void 0;
812
- if (kind === "alias" && ts.isStringLiteralLike(argument)) return argument.text;
813
- if ((kind === "function" || kind === "class") && ts.isIdentifier(argument)) return argument.text;
814
- return void 0;
815
- }
816
- function extractDiRegistrationFacts(diFilePath, sourcePath) {
817
- if (!diFilePath) return { facts: [], unresolvedTokens: [] };
818
- const sourceFile = readSourceFile(diFilePath);
819
- if (!sourceFile) return { facts: [], unresolvedTokens: [] };
820
- const facts = [];
821
- const unresolvedTokens = [];
822
- const visit = (node) => {
823
- if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "register") {
824
- const argument = node.arguments[0];
825
- if (argument && ts.isObjectLiteralExpression(argument)) {
826
- for (const property of argument.properties) {
827
- if (!ts.isPropertyAssignment(property)) continue;
828
- const token = getPropertyName(property);
829
- if (!token) continue;
830
- const kind = mapDiRegistrationKind(detectAwilixRegistrationKind(property.initializer));
831
- if (!kind) {
832
- if (!unresolvedTokens.includes(token)) unresolvedTokens.push(token);
833
- continue;
834
- }
835
- const chain = readDiChainMetadata(property.initializer);
836
- const providerSymbol = readDiProviderSymbol(property.initializer, kind);
837
- facts.push({
838
- token,
839
- registrationKind: kind,
840
- ...providerSymbol ? { providerSymbol } : {},
841
- ...chain.lifetime ? { lifetime: chain.lifetime } : {},
842
- ...chain.injectionMode ? { injectionMode: chain.injectionMode } : {},
843
- source: { sourcePath, exportName: token, line: nodeLine(sourceFile, property) }
844
- });
845
- }
846
- }
847
- }
848
- node.forEachChild(visit);
849
- };
850
- sourceFile.forEachChild(visit);
851
- return { facts, unresolvedTokens };
852
- }
853
- function deriveLegacyDiTokens(facts) {
854
- const tokens = [];
855
- const seen = /* @__PURE__ */ new Set();
856
- for (const fact of facts) {
857
- if (fact.registrationKind !== "function" && fact.registrationKind !== "class") continue;
858
- if (seen.has(fact.token)) continue;
859
- seen.add(fact.token);
860
- tokens.push(fact.token);
861
- }
862
- return tokens;
863
- }
864
- function dedupeOwnedContractFacts(facts) {
865
- const byId = /* @__PURE__ */ new Map();
866
- for (const fact of facts) {
867
- const existing = byId.get(fact.id);
868
- if (!existing) {
869
- byId.set(fact.id, fact);
870
- continue;
871
- }
872
- if (fact.source.sourcePath.localeCompare(existing.source.sourcePath) < 0) byId.set(fact.id, fact);
873
- }
874
- return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
875
- }
876
- const PAGE_CONTEXT_VALUES = /* @__PURE__ */ new Set(["main", "admin", "settings", "profile"]);
877
- function readAliasedStringProperty(metadata, preferred, fallback) {
878
- return readStringPropertyInitializer(metadata, preferred) ?? readStringPropertyInitializer(metadata, fallback);
879
- }
880
- function readNumericProperty(metadata, propertyName) {
881
- const initializer = getObjectPropertyInitializer(metadata, propertyName);
882
- if (!initializer || !ts.isNumericLiteral(initializer)) return void 0;
883
- return Number(initializer.text);
884
- }
885
- function readPageMetadata(sourceFile) {
886
- const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
887
- if (!metadata) return void 0;
888
- const result = {};
889
- const requireAuth = readBooleanPropertyInitializer(metadata, "requireAuth");
890
- if (requireAuth !== void 0) result.requireAuth = requireAuth;
891
- const requireCustomerAuth = readBooleanPropertyInitializer(metadata, "requireCustomerAuth");
892
- if (requireCustomerAuth !== void 0) result.requireCustomerAuth = requireCustomerAuth;
893
- const requireFeatures = readStringArrayPropertyInitializer(metadata, "requireFeatures");
894
- if (requireFeatures && requireFeatures.length > 0) result.requireFeatures = requireFeatures;
895
- const requireCustomerFeatures = readStringArrayPropertyInitializer(metadata, "requireCustomerFeatures");
896
- if (requireCustomerFeatures && requireCustomerFeatures.length > 0) {
897
- result.requireCustomerFeatures = requireCustomerFeatures;
898
- }
899
- const navHidden = readBooleanPropertyInitializer(metadata, "navHidden");
900
- if (navHidden !== void 0) result.navHidden = navHidden;
901
- const navGroup = readAliasedStringProperty(metadata, "pageGroup", "group");
902
- if (navGroup) result.navGroup = navGroup;
903
- const navGroupKey = readAliasedStringProperty(metadata, "pageGroupKey", "groupKey");
904
- if (navGroupKey) result.navGroupKey = navGroupKey;
905
- const navOrder = readNumericProperty(metadata, "pageOrder") ?? readNumericProperty(metadata, "order");
906
- if (navOrder !== void 0) result.navOrder = navOrder;
907
- const pageContext = readStringPropertyInitializer(metadata, "pageContext");
908
- if (pageContext && PAGE_CONTEXT_VALUES.has(pageContext)) {
909
- result.pageContext = pageContext;
910
- }
911
- return Object.keys(result).length > 0 ? result : void 0;
912
- }
913
- function resolvePageMetadataFile(pageDirectory) {
914
- for (const baseName of ["page.meta", "meta"]) {
915
- for (const extension of MODULE_CODE_EXTENSIONS) {
916
- const candidate = path.join(pageDirectory, `${baseName}${extension}`);
917
- if (fs.existsSync(candidate)) return candidate;
918
- }
919
- }
920
- return null;
921
- }
922
- function extractModuleMetadataContract(indexFilePath, moduleId, sourcePath) {
923
- if (!indexFilePath || !sourcePath) return null;
924
- const sourceFile = readSourceFile(indexFilePath);
925
- if (!sourceFile) return null;
926
- const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
927
- if (!metadata) return null;
928
- const facts = {};
929
- const name = readStringPropertyInitializer(metadata, "name");
930
- if (name) facts.name = name;
931
- const version = readStringPropertyInitializer(metadata, "version");
932
- if (version) facts.version = version;
933
- const requires = readStringArrayPropertyInitializer(metadata, "requires");
934
- if (requires && requires.length > 0) facts.requires = requires;
935
- const ejectable = readBooleanPropertyInitializer(metadata, "ejectable");
936
- if (ejectable !== void 0) facts.ejectable = ejectable;
937
- return {
938
- kind: "module-metadata",
939
- id: moduleId,
940
- source: { sourcePath, exportName: "metadata", line: nodeLine(sourceFile, metadata) },
941
- ...Object.keys(facts).length > 0 ? { metadata: facts } : {}
942
- };
943
- }
944
- function extractCommandContractCandidates(moduleId, moduleRoot, sourceRoot) {
945
- const commandsRoot = path.join(moduleRoot, "commands");
946
- if (!fs.existsSync(commandsRoot)) return [];
947
- const candidates = [];
948
- for (const filePath of listSourceFilesRecursive(commandsRoot)) {
949
- if (path.basename(filePath).replace(/\.tsx?$/, "") === "interceptors") continue;
950
- const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
951
- for (const id of extractCommandIdsFromSource(filePath)) candidates.push({ id, sourcePath });
952
- }
953
- return candidates;
954
- }
955
- function deriveWorkerId(moduleId, workersRoot, filePath) {
956
- const relativePath = path.relative(workersRoot, filePath).split(path.sep).join("/");
957
- const segments = relativePath.split("/");
958
- const fileName = segments.pop();
959
- const fileStem = fileName.replace(/\.tsx?$/, "");
960
- return [moduleId, "workers", ...segments, fileStem].filter(Boolean).join(":");
961
- }
962
- function readResolvedStringProperty(objectLiteral, propertyName, initializers) {
963
- const initializer = getObjectPropertyInitializer(objectLiteral, propertyName);
964
- if (!initializer) return void 0;
965
- const resolved = unwrapExpression(initializer);
966
- if (ts.isStringLiteralLike(resolved)) return resolved.text;
967
- if (ts.isIdentifier(resolved)) {
968
- const declaration = initializers.get(resolved.text);
969
- if (declaration) {
970
- const declarationValue = unwrapExpression(declaration);
971
- if (ts.isStringLiteralLike(declarationValue)) return declarationValue.text;
972
- }
973
- }
974
- return void 0;
975
- }
976
- function extractWorkerContracts(moduleId, moduleRoot, sourceRoot) {
977
- const workersRoot = path.join(moduleRoot, "workers");
978
- if (!fs.existsSync(workersRoot)) return { facts: [], unresolved: [] };
979
- const facts = [];
980
- const unresolved = [];
981
- for (const filePath of listSourceFilesRecursive(workersRoot)) {
982
- const sourceFile = readSourceFile(filePath);
983
- if (!sourceFile) continue;
984
- const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
985
- if (!metadata) continue;
986
- const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
987
- const source = { sourcePath, exportName: "metadata", line: nodeLine(sourceFile, metadata) };
988
- const initializers = buildVariableInitializerMap(sourceFile);
989
- const workerId = readResolvedStringProperty(metadata, "id", initializers) ?? deriveWorkerId(moduleId, workersRoot, filePath);
990
- const hasQueueProperty = getObjectPropertyInitializer(metadata, "queue") !== void 0;
991
- const queue = readResolvedStringProperty(metadata, "queue", initializers);
992
- if (!hasQueueProperty) {
993
- unresolved.push({ code: "unresolved-static-contract", kind: "worker", id: workerId, source });
994
- continue;
995
- }
996
- const workerMetadata = {};
997
- if (queue) workerMetadata.queue = queue;
998
- else unresolved.push({ code: "unresolved-static-contract", kind: "worker", id: workerId, source });
999
- const name = readResolvedStringProperty(metadata, "name", initializers);
1000
- if (name) workerMetadata.name = name;
1001
- const concurrencyInitializer = getObjectPropertyInitializer(metadata, "concurrency");
1002
- if (concurrencyInitializer && ts.isNumericLiteral(concurrencyInitializer)) {
1003
- workerMetadata.concurrency = Number(concurrencyInitializer.text);
1004
- }
1005
- facts.push({
1006
- kind: "worker",
1007
- id: workerId,
1008
- source,
1009
- ...Object.keys(workerMetadata).length > 0 ? { metadata: workerMetadata } : {}
1010
- });
1011
- }
1012
- return { facts: dedupeOwnedContractFacts(facts), unresolved };
1013
- }
1014
- function extractPageMiddlewareContracts(moduleRoot, sourceRoot) {
1015
- const facts = [];
1016
- const unresolved = [];
1017
- for (const surface of ["backend", "frontend"]) {
1018
- const filePath = resolveConventionFile(path.join(moduleRoot, surface), "middleware");
1019
- if (!filePath) continue;
1020
- const sourceFile = readSourceFile(filePath);
1021
- if (!sourceFile) continue;
1022
- const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
1023
- const middlewareArray = findArrayLiteralDeclaration(sourceFile, "middleware") ?? (() => {
1024
- const defaultExport = findDefaultExportExpression(sourceFile);
1025
- return defaultExport ? unwrapArrayLiteral(defaultExport) : null;
1026
- })();
1027
- if (!middlewareArray) continue;
1028
- let index = 0;
1029
- for (const element of middlewareArray.elements) {
1030
- if (!ts.isObjectLiteralExpression(element)) continue;
1031
- const middlewareId = readStringPropertyInitializer(element, "id");
1032
- if (!middlewareId) {
1033
- unresolved.push({
1034
- code: "unresolved-static-contract",
1035
- kind: "page-middleware",
1036
- id: `${sourcePath}#${index}`,
1037
- source: { sourcePath, line: nodeLine(sourceFile, element) }
1038
- });
1039
- index += 1;
1040
- continue;
1041
- }
1042
- const metadata = { surface };
1043
- const mode = readStringPropertyInitializer(element, "mode");
1044
- if (mode) metadata.mode = mode;
1045
- const priorityInitializer = getObjectPropertyInitializer(element, "priority");
1046
- if (priorityInitializer && ts.isNumericLiteral(priorityInitializer)) {
1047
- metadata.priority = Number(priorityInitializer.text);
1048
- }
1049
- facts.push({
1050
- kind: "page-middleware",
1051
- id: middlewareId,
1052
- source: { sourcePath, exportName: "middleware", line: nodeLine(sourceFile, element) },
1053
- metadata
1054
- });
1055
- index += 1;
1056
- }
1057
- }
1058
- return { facts: dedupeOwnedContractFacts(facts), unresolved };
1059
- }
1060
- function extractSetupContract(moduleId, setupFilePath, sourcePath) {
1061
- if (!setupFilePath || !sourcePath) return null;
1062
- const sourceFile = readSourceFile(setupFilePath);
1063
- if (!sourceFile) return null;
1064
- const setupObject = findObjectLiteralDeclaration(sourceFile, "setup") ?? (() => {
1065
- const defaultExport = findDefaultExportExpression(sourceFile);
1066
- if (!defaultExport) return null;
1067
- const unwrapped = unwrapExpression(defaultExport);
1068
- return ts.isObjectLiteralExpression(unwrapped) ? unwrapped : null;
1069
- })();
1070
- if (!setupObject) return null;
1071
- const hooks = readMethodBearingPropertyNames(setupObject);
1072
- const metadata = {};
1073
- if (hooks.length > 0) metadata.hooks = hooks;
1074
- const roleFeatures = getObjectPropertyInitializer(setupObject, "defaultRoleFeatures");
1075
- if (roleFeatures && ts.isObjectLiteralExpression(roleFeatures)) {
1076
- const roles = readObjectKeyNames(roleFeatures);
1077
- if (roles.length > 0) metadata.roles = roles;
1078
- }
1079
- const customerRoleFeatures = getObjectPropertyInitializer(setupObject, "defaultCustomerRoleFeatures");
1080
- if (customerRoleFeatures && ts.isObjectLiteralExpression(customerRoleFeatures)) {
1081
- const customerRoles = readObjectKeyNames(customerRoleFeatures);
1082
- if (customerRoles.length > 0) metadata.customerRoles = customerRoles;
1083
- }
1084
- return {
1085
- kind: "setup",
1086
- id: `${moduleId}:setup`,
1087
- source: { sourcePath, exportName: "setup", line: nodeLine(sourceFile, setupObject) },
1088
- ...Object.keys(metadata).length > 0 ? { metadata } : {}
1089
- };
1090
- }
1091
- function extractEncryptionContracts(encryptionFilePath, sourcePath) {
1092
- if (!encryptionFilePath || !sourcePath) return [];
1093
- const sourceFile = readSourceFile(encryptionFilePath);
1094
- if (!sourceFile) return [];
1095
- const mapsArray = findArrayLiteralDeclaration(sourceFile, "defaultEncryptionMaps") ?? findArrayLiteralDeclaration(sourceFile, "encryptionMaps");
1096
- if (!mapsArray) return [];
1097
- const facts = [];
1098
- for (const element of mapsArray.elements) {
1099
- if (!ts.isObjectLiteralExpression(element)) continue;
1100
- const entityId = readStringPropertyInitializer(element, "entityId");
1101
- if (!entityId) continue;
1102
- const fieldsInitializer = getObjectPropertyInitializer(element, "fields");
1103
- const fields = [];
1104
- if (fieldsInitializer) {
1105
- const fieldsArray = unwrapArrayLiteral(fieldsInitializer);
1106
- if (fieldsArray) {
1107
- for (const fieldElement of fieldsArray.elements) {
1108
- if (!ts.isObjectLiteralExpression(fieldElement)) continue;
1109
- const field = readStringPropertyInitializer(fieldElement, "field");
1110
- if (field) fields.push(field);
1111
- }
1112
- }
1113
- }
1114
- facts.push({
1115
- kind: "encryption",
1116
- id: entityId,
1117
- source: { sourcePath, exportName: "defaultEncryptionMaps", line: nodeLine(sourceFile, element) },
1118
- ...fields.length > 0 ? { metadata: { fields: fields.sort((left, right) => left.localeCompare(right)) } } : {}
1119
- });
1120
- }
1121
- return dedupeOwnedContractFacts(facts);
1122
- }
1123
- function extractCustomEntityContracts(ceFilePath, sourcePath) {
1124
- if (!ceFilePath || !sourcePath) return [];
1125
- const entityIds = [...collectCustomFieldEntityIds(ceFilePath)].sort((left, right) => left.localeCompare(right));
1126
- return entityIds.map((id) => ({
1127
- kind: "custom-entity",
1128
- id,
1129
- source: { sourcePath, exportName: "default" }
1130
- }));
1131
- }
1132
- const AI_OVERRIDE_EXPORTS = [
1133
- { exportName: "aiAgentOverrides", target: "agent" },
1134
- { exportName: "aiToolOverrides", target: "tool" }
1135
- ];
1136
- function extractAiExtensionContracts(moduleRoot, sourceRoot) {
1137
- const facts = [];
1138
- const sources = [
1139
- { basename: "ai-agents", relativeDir: "." },
1140
- { basename: "ai-tools", relativeDir: "." },
1141
- { basename: "ai-agents.extensions", relativeDir: "." },
1142
- { basename: "ai-tools.extensions", relativeDir: "." }
1143
- ];
1144
- for (const entry of sources) {
1145
- const filePath = resolveConventionFile(path.join(moduleRoot, entry.relativeDir), entry.basename);
1146
- if (!filePath) continue;
1147
- const sourceFile = readSourceFile(filePath);
1148
- if (!sourceFile) continue;
1149
- const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
1150
- const extensionsArray = findArrayLiteralDeclaration(sourceFile, "aiAgentExtensions");
1151
- if (extensionsArray) {
1152
- for (const element of extensionsArray.elements) {
1153
- const objectLiteral = ts.isObjectLiteralExpression(element) ? element : ts.isCallExpression(element) && element.arguments[0] && ts.isObjectLiteralExpression(element.arguments[0]) ? element.arguments[0] : null;
1154
- if (!objectLiteral) continue;
1155
- const targetAgentId = readStringPropertyInitializer(objectLiteral, "targetAgentId");
1156
- if (!targetAgentId) continue;
1157
- facts.push({
1158
- kind: "ai-extension",
1159
- id: `agent-extension:${targetAgentId}`,
1160
- source: { sourcePath, exportName: "aiAgentExtensions", line: nodeLine(sourceFile, objectLiteral) },
1161
- metadata: { target: "agent", mode: "extension", targetAgentId }
1162
- });
1163
- }
1164
- }
1165
- for (const { exportName, target } of AI_OVERRIDE_EXPORTS) {
1166
- const overridesObject = findObjectLiteralDeclaration(sourceFile, exportName);
1167
- if (!overridesObject) continue;
1168
- for (const property of overridesObject.properties) {
1169
- const overrideId = getPropertyName(property);
1170
- if (!overrideId) continue;
1171
- facts.push({
1172
- kind: "ai-extension",
1173
- id: `${target}-override:${overrideId}`,
1174
- source: { sourcePath, exportName, line: nodeLine(sourceFile, property) },
1175
- metadata: { target, mode: "override", overrideKey: overrideId }
1176
- });
1177
- }
1178
- }
1179
- }
1180
- return dedupeOwnedContractFacts(facts);
1181
- }
1182
- function extractGeneratorPluginContracts(moduleRoot, sourceRoot) {
1183
- const filePath = resolveConventionFile(moduleRoot, "generators");
1184
- if (!filePath) return { facts: [], unresolved: [] };
1185
- const sourceFile = readSourceFile(filePath);
1186
- if (!sourceFile) return { facts: [], unresolved: [] };
1187
- const pluginsArray = findArrayLiteralDeclaration(sourceFile, "generatorPlugins");
1188
- if (!pluginsArray) return { facts: [], unresolved: [] };
1189
- const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
1190
- const initializers = buildVariableInitializerMap(sourceFile);
1191
- const facts = [];
1192
- const unresolved = [];
1193
- let index = 0;
1194
- for (const element of pluginsArray.elements) {
1195
- const objectLiteral = resolveToObjectLiteral(element, initializers);
1196
- if (!objectLiteral) {
1197
- index += 1;
1198
- continue;
1199
- }
1200
- const pluginId = readStringPropertyInitializer(objectLiteral, "id");
1201
- if (!pluginId) {
1202
- unresolved.push({
1203
- code: "unresolved-static-contract",
1204
- kind: "generator-plugin",
1205
- id: `${sourcePath}#${index}`,
1206
- source: { sourcePath, exportName: "generatorPlugins", line: nodeLine(sourceFile, objectLiteral) }
1207
- });
1208
- index += 1;
1209
- continue;
1210
- }
1211
- const metadata = {};
1212
- const conventionFile = readStringPropertyInitializer(objectLiteral, "conventionFile");
1213
- if (conventionFile) metadata.conventionFile = conventionFile;
1214
- const outputFileName = readStringPropertyInitializer(objectLiteral, "outputFileName");
1215
- if (outputFileName) metadata.outputFileName = outputFileName;
1216
- facts.push({
1217
- kind: "generator-plugin",
1218
- id: pluginId,
1219
- source: { sourcePath, exportName: "generatorPlugins", line: nodeLine(sourceFile, objectLiteral) },
1220
- ...Object.keys(metadata).length > 0 ? { metadata } : {}
1221
- });
1222
- index += 1;
1223
- }
1224
- return { facts: dedupeOwnedContractFacts(facts), unresolved };
1225
- }
1226
- function compareSourceRefs(left, right) {
1227
- return left.sourcePath.localeCompare(right.sourcePath) || (left.line ?? 0) - (right.line ?? 0) || (left.exportName ?? "").localeCompare(right.exportName ?? "");
1228
- }
1229
- function sameSourceRef(left, right) {
1230
- return left.sourcePath === right.sourcePath && (left.line ?? null) === (right.line ?? null) && (left.exportName ?? null) === (right.exportName ?? null);
1231
- }
1232
- function provenanceCandidateOrderKey(candidate) {
1233
- if (candidate.source) {
1234
- return JSON.stringify([
1235
- 0,
1236
- candidate.source.sourcePath,
1237
- candidate.source.line ?? 0,
1238
- candidate.source.exportName ?? ""
1239
- ]);
1240
- }
1241
- return JSON.stringify([1, candidate.factRef?.factSection ?? "", candidate.factRef?.factKey ?? ""]);
1242
- }
1243
- function buildProvenanceIndex(candidates) {
1244
- const grouped = /* @__PURE__ */ new Map();
1245
- for (const candidate of candidates) {
1246
- const key = JSON.stringify([candidate.kind, candidate.id]);
1247
- const group = grouped.get(key) ?? [];
1248
- group.push(candidate);
1249
- grouped.set(key, group);
1250
- }
1251
- const factSources = [];
1252
- const diagnostics = [];
1253
- for (const group of grouped.values()) {
1254
- const sorted = [...group].sort(
1255
- (left, right) => provenanceCandidateOrderKey(left).localeCompare(provenanceCandidateOrderKey(right))
1256
- );
1257
- const canonical = sorted[0];
1258
- factSources.push(
1259
- canonical.factRef ? {
1260
- kind: canonical.kind,
1261
- id: canonical.id,
1262
- factRef: {
1263
- factSection: canonical.factRef.factSection,
1264
- ...canonical.factRef.factKey === canonical.id ? {} : { factKey: canonical.factRef.factKey }
1265
- }
1266
- } : {
1267
- kind: canonical.kind,
1268
- id: canonical.id,
1269
- source: { sourcePath: canonical.source.sourcePath }
1270
- }
1271
- );
1272
- const canonicalKey = provenanceCandidateOrderKey(canonical);
1273
- for (const rejected of sorted.slice(1)) {
1274
- if (provenanceCandidateOrderKey(rejected) === canonicalKey) continue;
1275
- diagnostics.push({
1276
- code: "duplicate-source",
1277
- kind: rejected.kind,
1278
- id: rejected.id,
1279
- ...rejected.source ? { source: rejected.source } : {}
1280
- });
1281
- }
1282
- }
1283
- factSources.sort(
1284
- (left, right) => left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id)
1285
- );
1286
- diagnostics.sort(
1287
- (left, right) => left.code.localeCompare(right.code) || left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id) || compareSourceRefs(left.source ?? { sourcePath: "" }, right.source ?? { sourcePath: "" })
1288
- );
1289
- return { factSources, diagnostics };
1290
- }
1291
- function buildOwnedContracts(families) {
1292
- const result = {};
1293
- for (const [kind, facts] of families) {
1294
- if (facts.length === 0) continue;
1295
- result[kind] = facts.map((fact) => ({
1296
- ...fact,
1297
- source: {
1298
- sourcePath: fact.source.sourcePath,
1299
- ...fact.source.line ? { line: fact.source.line } : {}
1300
- }
1301
- }));
1302
- }
1303
- return Object.keys(result).length > 0 ? result : void 0;
1304
- }
1305
- const CONTRIBUTION_KIND_TO_SOURCE_KIND = {
1306
- subscriber: "subscriber"
1307
- };
1308
- const REGISTRY_TO_SOURCE_KIND = {
1309
- vector: "vector",
1310
- integration: "integration",
1311
- payment: "integration",
1312
- shipping: "integration",
1313
- currency: "integration"
1314
- };
1315
528
  function extractModuleFacts(options) {
1316
- const { moduleId, coreVersion = null, sourcePackage = null, sourceVersion = null } = options;
529
+ const { moduleId, coreVersion = null } = options;
1317
530
  const moduleRoot = options.moduleRoot ?? (options.coreSrcRoot ? path.join(options.coreSrcRoot, moduleId) : null);
1318
531
  if (!moduleRoot) {
1319
532
  throw new Error(`[internal] extractModuleFacts requires moduleRoot or coreSrcRoot for module "${moduleId}"`);
1320
533
  }
1321
- const sourceRoot = toPortableSourceRoot(moduleId, sourcePackage);
1322
534
  const entitiesFilePath = resolveConventionFile(path.join(moduleRoot, "data"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "db"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "data"), "schema");
1323
535
  const ceFilePath = resolveConventionFile(moduleRoot, "ce");
1324
536
  const eventsFilePath = resolveConventionFile(moduleRoot, "events");
@@ -1328,9 +540,7 @@ function extractModuleFacts(options) {
1328
540
  const notificationsFilePath = resolveConventionFile(moduleRoot, "notifications");
1329
541
  const cliFilePath = resolveConventionFile(moduleRoot, "cli");
1330
542
  const indexFilePath = resolveConventionFile(moduleRoot, "index");
1331
- const setupFilePath = resolveConventionFile(moduleRoot, "setup");
1332
- const encryptionFilePath = resolveConventionFile(moduleRoot, "encryption");
1333
- const portableOf = (filePath) => filePath ? toPortableSourcePath(moduleRoot, sourceRoot, filePath) : null;
543
+ const backendDir = path.join(moduleRoot, "backend");
1334
544
  const warnings = [];
1335
545
  const { title, description } = extractModuleMeta(indexFilePath);
1336
546
  const customFieldEntityIds = collectCustomFieldEntityIds(ceFilePath);
@@ -1338,224 +548,20 @@ function extractModuleFacts(options) {
1338
548
  const events = extractEvents(eventsFilePath);
1339
549
  const aclFeatures = extractAclFeatures(aclFilePath);
1340
550
  const { source: registrySource, description: registryDescription } = resolveRegistrySource(options);
1341
- const apiRouteSourcePaths = extractApiRouteSourcePaths(moduleId, moduleRoot, sourceRoot);
1342
- const apiRoutes = extractApiRoutes(moduleId, registrySource, registryDescription, apiRouteSourcePaths, warnings);
1343
- const diRegistrations = extractDiRegistrationFacts(diFilePath, portableOf(diFilePath) ?? "");
1344
- const diTokens = deriveLegacyDiTokens(diRegistrations.facts);
1345
- for (const legacyToken of extractDiTokens(diFilePath)) {
1346
- if (!diTokens.includes(legacyToken)) diTokens.push(legacyToken);
1347
- }
551
+ const apiRoutes = extractApiRoutes(moduleId, registrySource, registryDescription, warnings);
552
+ const diTokens = extractDiTokens(diFilePath);
1348
553
  const searchEntities = extractSearchEntities(searchFilePath, warnings);
1349
554
  const notifications = extractNotifications(notificationsFilePath, warnings);
1350
555
  const cli = extractCli(cliFilePath, warnings);
1351
- const cliCommands = cliFilePath ? cli.map((command) => ({
1352
- command,
1353
- sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, cliFilePath)
1354
- })) : [];
1355
- const backendPages = extractModulePages(moduleId, moduleRoot, sourceRoot, "backend");
1356
- const frontendPages = extractModulePages(moduleId, moduleRoot, sourceRoot, "frontend");
1357
- const aiTools = extractAiTools(moduleRoot, sourceRoot);
1358
- const aiAgents = extractAiAgents(moduleRoot, sourceRoot);
1359
556
  const hostTokens = {
1360
557
  entityIds: extractHostEntityIds(entities),
1361
- tableIds: extractTableIds(moduleRoot)
1362
- };
1363
- const extensionSurfaces = extractModuleExtensionFacts({
1364
- moduleId,
1365
- moduleRoot,
1366
- sourceRoot,
1367
- entities,
1368
- events,
1369
- apiRoutes,
1370
- searchEntities,
1371
- notifications,
1372
- aiTools,
1373
- aiAgents
1374
- });
1375
- const indexSourcePath = portableOf(indexFilePath);
1376
- const diSourcePath = portableOf(diFilePath);
1377
- const moduleMetadataFact = extractModuleMetadataContract(indexFilePath, moduleId, indexSourcePath);
1378
- const commandCandidates = extractCommandContractCandidates(moduleId, moduleRoot, sourceRoot);
1379
- const commandFacts = dedupeOwnedContractFacts(
1380
- commandCandidates.map((candidate) => ({
1381
- kind: "command",
1382
- id: candidate.id,
1383
- source: { sourcePath: candidate.sourcePath }
1384
- }))
1385
- );
1386
- const workers = extractWorkerContracts(moduleId, moduleRoot, sourceRoot);
1387
- const pageMiddleware = extractPageMiddlewareContracts(moduleRoot, sourceRoot);
1388
- const setupFact = extractSetupContract(moduleId, setupFilePath, portableOf(setupFilePath));
1389
- const encryptionFacts = extractEncryptionContracts(encryptionFilePath, portableOf(encryptionFilePath));
1390
- const customEntityFacts = extractCustomEntityContracts(ceFilePath, portableOf(ceFilePath));
1391
- const aiExtensionFacts = extractAiExtensionContracts(moduleRoot, sourceRoot);
1392
- const generatorPlugins = extractGeneratorPluginContracts(moduleRoot, sourceRoot);
1393
- const diContractFacts = dedupeOwnedContractFacts(
1394
- diRegistrations.facts.map((fact) => ({
1395
- kind: "di-registration",
1396
- id: fact.token,
1397
- source: fact.source,
1398
- metadata: {
1399
- registrationKind: fact.registrationKind,
1400
- ...fact.providerSymbol ? { providerSymbol: fact.providerSymbol } : {},
1401
- ...fact.lifetime ? { lifetime: fact.lifetime } : {},
1402
- ...fact.injectionMode ? { injectionMode: fact.injectionMode } : {}
1403
- }
1404
- }))
1405
- );
1406
- const ownedContracts = buildOwnedContracts([
1407
- ["module-metadata", moduleMetadataFact ? [moduleMetadataFact] : []],
1408
- ["command", commandFacts],
1409
- ["worker", workers.facts],
1410
- ["page-middleware", pageMiddleware.facts],
1411
- ["setup", setupFact ? [setupFact] : []],
1412
- ["encryption", encryptionFacts],
1413
- ["di-registration", diContractFacts],
1414
- ["custom-entity", customEntityFacts],
1415
- ["ai-extension", aiExtensionFacts],
1416
- ["generator-plugin", generatorPlugins.facts]
1417
- ]);
1418
- const provenanceCandidates = [];
1419
- const pushSource = (kind, id, source) => {
1420
- provenanceCandidates.push({ kind, id, source });
1421
- };
1422
- const pushRef = (kind, id, source, factSection, factKey) => {
1423
- provenanceCandidates.push({ kind, id, source, factRef: { factSection, factKey } });
1424
- };
1425
- const pushOwnedRefs = (kind, facts2) => {
1426
- for (const fact of facts2) pushRef(kind, fact.id, fact.source, `ownedContracts.${kind}`, fact.id);
558
+ tableIds: extractTableIds(backendDir)
1427
559
  };
1428
- if (moduleMetadataFact) {
1429
- pushRef(
1430
- "module-metadata",
1431
- moduleId,
1432
- moduleMetadataFact.source,
1433
- "ownedContracts.module-metadata",
1434
- moduleMetadataFact.id
1435
- );
1436
- }
1437
- if (entitiesFilePath) {
1438
- const entitiesSourcePath = portableOf(entitiesFilePath);
1439
- for (const entity of entities) {
1440
- pushSource("entity", entity.id, { sourcePath: entitiesSourcePath, exportName: entity.class });
1441
- }
1442
- }
1443
- if (eventsFilePath) {
1444
- const eventsSourcePath = portableOf(eventsFilePath);
1445
- for (const event of events) pushSource("event", event.id, { sourcePath: eventsSourcePath, exportName: "events" });
1446
- }
1447
- if (aclFilePath) {
1448
- const aclSourcePath = portableOf(aclFilePath);
1449
- for (const feature of aclFeatures) pushSource("acl-feature", feature, { sourcePath: aclSourcePath, exportName: "features" });
1450
- }
1451
- for (const route of apiRoutes) {
1452
- if (route.sourcePath) {
1453
- pushRef("api-route", route.path, { sourcePath: route.sourcePath }, "apiRoutes", route.path);
1454
- }
1455
- }
1456
- if (searchFilePath) {
1457
- const searchSourcePath = portableOf(searchFilePath);
1458
- for (const entityId of searchEntities) pushSource("search", entityId, { sourcePath: searchSourcePath, exportName: "searchConfig" });
1459
- }
1460
- if (notificationsFilePath) {
1461
- const notificationsSourcePath = portableOf(notificationsFilePath);
1462
- for (const id of notifications) pushSource("notification", id, { sourcePath: notificationsSourcePath });
1463
- }
1464
- for (const command of cliCommands) {
1465
- pushRef("cli-command", command.command, { sourcePath: command.sourcePath }, "cliCommands", command.command);
1466
- }
1467
- for (const page of backendPages) {
1468
- pushRef("backend-page", page.path, { sourcePath: page.sourcePath }, "backendPages", page.path);
1469
- }
1470
- for (const page of frontendPages) {
1471
- pushRef("frontend-page", page.path, { sourcePath: page.sourcePath }, "frontendPages", page.path);
1472
- }
1473
- for (const tool of aiTools) pushRef("ai-tool", tool.name, { sourcePath: tool.sourcePath }, "aiTools", tool.name);
1474
- for (const agent of aiAgents) pushRef("ai-agent", agent.id, { sourcePath: agent.sourcePath }, "aiAgents", agent.id);
1475
- for (const candidate of commandCandidates) {
1476
- pushRef("command", candidate.id, { sourcePath: candidate.sourcePath }, "ownedContracts.command", candidate.id);
1477
- }
1478
- pushOwnedRefs("worker", workers.facts);
1479
- pushOwnedRefs("page-middleware", pageMiddleware.facts);
1480
- if (setupFact) pushOwnedRefs("setup", [setupFact]);
1481
- pushOwnedRefs("encryption", encryptionFacts);
1482
- for (const fact of diRegistrations.facts) {
1483
- pushRef("di-registration", fact.token, fact.source, "ownedContracts.di-registration", fact.token);
1484
- }
1485
- pushOwnedRefs("custom-entity", customEntityFacts);
1486
- pushOwnedRefs("ai-extension", aiExtensionFacts);
1487
- pushOwnedRefs("generator-plugin", generatorPlugins.facts);
1488
- const contributionRef = (contributionId) => ({
1489
- factSection: "extensionSurfaces.contributions",
1490
- factKey: contributionId
1491
- });
1492
- for (const contribution of extensionSurfaces.contributions) {
1493
- const contributionSource = {
1494
- sourcePath: contribution.source.path,
1495
- ...contribution.source.symbol ? { exportName: contribution.source.symbol } : {}
1496
- };
1497
- const ref = contributionRef(contribution.id);
1498
- if (contribution.kind === "subscriber") {
1499
- pushRef("subscriber", contribution.id, contributionSource, ref.factSection, ref.factKey);
1500
- continue;
1501
- }
1502
- if (contribution.kind === "specialized-registry") {
1503
- const details = contribution.details;
1504
- const sourceKind = details.registry ? REGISTRY_TO_SOURCE_KIND[details.registry] : void 0;
1505
- if (sourceKind) {
1506
- pushRef(
1507
- sourceKind,
1508
- details.registryId ?? contribution.id,
1509
- contributionSource,
1510
- ref.factSection,
1511
- ref.factKey
1512
- );
1513
- }
1514
- continue;
1515
- }
1516
- const mapped = CONTRIBUTION_KIND_TO_SOURCE_KIND[contribution.kind];
1517
- if (mapped) pushRef(mapped, contribution.id, contributionSource, ref.factSection, ref.factKey);
1518
- }
1519
- for (const host of extensionSurfaces.hosts) {
1520
- provenanceCandidates.push({
1521
- kind: "extension-host",
1522
- id: host.key,
1523
- ...host.source.kind === "fact-ref" ? {} : { source: { sourcePath: host.source.path } },
1524
- factRef: { factSection: "extensionSurfaces.hosts", factKey: host.key }
1525
- });
1526
- }
1527
- for (const contribution of extensionSurfaces.contributions) {
1528
- pushRef(
1529
- "extension-contribution",
1530
- contribution.id,
1531
- { sourcePath: contribution.source.path },
1532
- "extensionSurfaces.contributions",
1533
- contribution.id
1534
- );
1535
- }
1536
- const provenance = buildProvenanceIndex(provenanceCandidates);
1537
- const factDiagnostics = [
1538
- ...provenance.diagnostics,
1539
- ...workers.unresolved,
1540
- ...pageMiddleware.unresolved,
1541
- ...generatorPlugins.unresolved,
1542
- ...diRegistrations.unresolvedTokens.map((token) => ({
1543
- code: "unresolved-static-contract",
1544
- kind: "di-registration",
1545
- id: token,
1546
- ...diSourcePath ? { source: { sourcePath: diSourcePath, exportName: token } } : {}
1547
- }))
1548
- ].sort(
1549
- (left, right) => left.code.localeCompare(right.code) || left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id)
1550
- );
1551
- const facts = {
560
+ return {
1552
561
  module: moduleId,
1553
562
  title,
1554
563
  description,
1555
564
  coreVersion,
1556
- sourcePackage,
1557
- sourceVersion,
1558
- sourceRoot,
1559
565
  entities,
1560
566
  events,
1561
567
  aclFeatures,
@@ -1565,54 +571,33 @@ function extractModuleFacts(options) {
1565
571
  hostTokens,
1566
572
  notifications,
1567
573
  cli,
1568
- backendPages,
1569
- frontendPages,
1570
- cliCommands,
1571
- aiTools,
1572
- aiAgents,
1573
- extensionSurfaces,
1574
- ...provenance.factSources.length > 0 ? { factSources: provenance.factSources } : {},
1575
- ...ownedContracts ? { ownedContracts } : {},
1576
- ...factDiagnostics.length > 0 ? { factDiagnostics } : {},
1577
574
  warnings
1578
575
  };
1579
- const overrides = collectModuleOverrideTargets(facts, buildFactSourceLookup(facts));
1580
- if (overrides.overrideTargets.length > 0) facts.overrideTargets = overrides.overrideTargets;
1581
- if (overrides.overrideTargetDiagnostics.length > 0) {
1582
- facts.overrideTargetDiagnostics = overrides.overrideTargetDiagnostics;
1583
- }
1584
- return facts;
1585
576
  }
1586
577
  const EMPTY_SECTION_MARKER = "_none_";
1587
- function renderVersionStamp(coreVersion, sourcePackage, sourceVersion) {
1588
- if (sourcePackage) {
1589
- return `<!-- generated from ${sourcePackage} ${sourceVersion || "<unknown>"}; core ${coreVersion || "<unknown>"} \u2014 R1 staleness stamp -->`;
1590
- }
578
+ function renderVersionStamp(coreVersion) {
1591
579
  const version = coreVersion && coreVersion.length > 0 ? coreVersion : "<unknown>";
1592
580
  return `<!-- generated from @open-mercato/core ${version} \u2014 R1 staleness stamp -->`;
1593
581
  }
1594
- function renderEntitiesSection(entities, lookup) {
582
+ function renderEntitiesSection(entities) {
1595
583
  if (entities.length === 0) return `## Entities
1596
584
 
1597
585
  ${EMPTY_SECTION_MARKER}`;
1598
- const header = "| Entity ID | Class | Table | Editable | CustomFields | Source |";
1599
- const divider = "|---|---|---|---|---|---|";
586
+ const header = "| Entity ID | Class | Table | Editable | CustomFields |";
587
+ const divider = "|---|---|---|---|---|";
1600
588
  const rows = entities.map(
1601
- (entity) => `| ${entity.id} | ${entity.class} | ${entity.table} | ${entity.editable ? "yes" : "no"} | ${entity.customFields ? "yes" : "no"} | ${renderLookedUpSource(lookup, "entity", entity.id)} |`
589
+ (entity) => `| ${entity.id} | ${entity.class} | ${entity.table} | ${entity.editable ? "yes" : "no"} | ${entity.customFields ? "yes" : "no"} |`
1602
590
  );
1603
591
  return ["## Entities", "", header, divider, ...rows].join("\n");
1604
592
  }
1605
- function renderEventsSection(events, lookup) {
593
+ function renderEventsSection(events) {
1606
594
  const heading = `## Events (${events.length})`;
1607
595
  if (events.length === 0) return `${heading}
1608
596
 
1609
597
  ${EMPTY_SECTION_MARKER}`;
1610
- const header = "| ID | Category | Entity | Browser transport | Source |";
1611
- const divider = "|---|---|---|---|---|";
1612
- const rows = events.map((event) => {
1613
- const transports = [event.clientBroadcast ? "client" : null, event.portalBroadcast ? "portal" : null].filter((value) => value !== null);
1614
- return `| ${event.id} | ${event.category ?? "\u2014"} | ${event.entity ?? "\u2014"} | ${transports.join(", ") || "\u2014"} | ${renderLookedUpSource(lookup, "event", event.id)} |`;
1615
- });
598
+ const header = "| ID | Category | Entity |";
599
+ const divider = "|---|---|---|";
600
+ const rows = events.map((event) => `| ${event.id} | ${event.category ?? "\u2014"} | ${event.entity ?? "\u2014"} |`);
1616
601
  return [heading, "", header, divider, ...rows].join("\n");
1617
602
  }
1618
603
  function renderInlineListSection(heading, values) {
@@ -1623,57 +608,6 @@ ${EMPTY_SECTION_MARKER}`;
1623
608
 
1624
609
  ${values.join(" \xB7 ")}`;
1625
610
  }
1626
- function renderSourceLinkedListSection(heading, values, lookup, kind, idColumnLabel) {
1627
- if (values.length === 0) return `${heading}
1628
-
1629
- ${EMPTY_SECTION_MARKER}`;
1630
- const rows = values.map((value) => `| ${value} | ${renderLookedUpSource(lookup, kind, value)} |`);
1631
- return [heading, "", `| ${idColumnLabel} | Source |`, "|---|---|", ...rows].join("\n");
1632
- }
1633
- function renderSourceLink(sourcePath) {
1634
- return `[${sourcePath}](../../../${sourcePath})`;
1635
- }
1636
- function renderSourceRefLink(source) {
1637
- const anchor = source.line ? `#L${source.line}` : "";
1638
- const label = source.line ? `${source.sourcePath}:${source.line}` : source.sourcePath;
1639
- return `[${label}](../../../${source.sourcePath}${anchor})`;
1640
- }
1641
- function renderLookedUpSource(lookup, kind, id) {
1642
- const source = lookup(kind, id);
1643
- return source ? renderSourceRefLink(source) : "\u2014";
1644
- }
1645
- function renderSafeScalar(value) {
1646
- if (value === void 0 || value === null) return "\u2014";
1647
- if (Array.isArray(value)) return value.length > 0 ? value.map((entry) => String(entry)).join(", ") : "\u2014";
1648
- return String(value);
1649
- }
1650
- function renderOwnedContractMetadata(metadata) {
1651
- if (!metadata) return "\u2014";
1652
- const keys = Object.keys(metadata).sort((left, right) => left.localeCompare(right));
1653
- if (keys.length === 0) return "\u2014";
1654
- return keys.map((key) => `${key}=${renderSafeScalar(metadata[key])}`).join("; ");
1655
- }
1656
- function renderOwnedContractSection(heading, facts) {
1657
- if (!facts || facts.length === 0) return "";
1658
- const rows = facts.map(
1659
- (fact) => `| ${fact.id} | ${renderOwnedContractMetadata(fact.metadata)} | ${renderSourceRefLink(fact.source)} |`
1660
- );
1661
- return [heading, "", "| ID | Metadata | Source |", "|---|---|---|", ...rows].join("\n");
1662
- }
1663
- function renderDiRegistrationsSection(facts) {
1664
- if (!facts || facts.length === 0) return "";
1665
- const rows = facts.map((fact) => {
1666
- const metadata = fact.metadata ?? {};
1667
- return `| ${fact.id} | ${renderSafeScalar(metadata.registrationKind)} | ${renderSafeScalar(metadata.lifetime)} | ${renderSafeScalar(metadata.injectionMode)} | ${renderSafeScalar(metadata.providerSymbol)} | ${renderSourceRefLink(fact.source)} |`;
1668
- });
1669
- return [
1670
- "## DI registrations (rich)",
1671
- "",
1672
- "| Token | Kind | Lifetime | Injection | Provider | Source |",
1673
- "|---|---|---|---|---|---|",
1674
- ...rows
1675
- ].join("\n");
1676
- }
1677
611
  function describeAuthRule(rule) {
1678
612
  if (!rule) return "public";
1679
613
  if (rule.requireFeatures && rule.requireFeatures.length > 0) return rule.requireFeatures.join(", ");
@@ -1696,246 +630,42 @@ function renderApiRoutesSection(routes) {
1696
630
  if (routes.length === 0) return `## API routes
1697
631
 
1698
632
  ${EMPTY_SECTION_MARKER}`;
1699
- const header = "| Path | Methods | Auth (per-method requireFeatures) | Source |";
1700
- const divider = "|---|---|---|---|";
633
+ const header = "| Path | Methods | Auth (per-method requireFeatures) |";
634
+ const divider = "|---|---|---|";
1701
635
  const rows = routes.map(
1702
- (route) => `| ${route.path} | ${route.methods.join(" ")} | ${renderApiRouteAuthCell(route)} | ${route.sourcePath ? renderSourceLink(route.sourcePath) : "\u2014"} |`
636
+ (route) => `| ${route.path} | ${route.methods.join(" ")} | ${renderApiRouteAuthCell(route)} |`
1703
637
  );
1704
638
  return ["## API routes", "", header, divider, ...rows].join("\n");
1705
639
  }
1706
- function renderLinkedFactsSection(heading, facts) {
1707
- if (facts.length === 0) return `${heading}
1708
-
1709
- ${EMPTY_SECTION_MARKER}`;
1710
- const rows = facts.map((fact) => `| ${fact.label} | ${renderSourceLink(fact.sourcePath)} |`);
1711
- return [heading, "", "| ID / path | Source |", "|---|---|", ...rows].join("\n");
1712
- }
1713
640
  function renderHostTokensSection(hostTokens) {
1714
641
  const entityIdsLine = hostTokens.entityIds.length > 0 ? hostTokens.entityIds.join(" \xB7 ") : EMPTY_SECTION_MARKER;
1715
642
  const tableIdsLine = hostTokens.tableIds.length > 0 ? hostTokens.tableIds.join(" \xB7 ") : EMPTY_SECTION_MARKER;
1716
643
  return ["## Host extension points", "", `- Entity IDs: ${entityIdsLine}`, `- Table IDs: ${tableIdsLine}`].join("\n");
1717
644
  }
1718
- function renderExtensionHostContext(host) {
1719
- return host.contextContract ?? host.runtimeContract ?? host.scopeContract ?? "\u2014";
1720
- }
1721
- function renderExtensionHostSource(host) {
1722
- if (host.source.kind === "fact-ref") return `${host.source.factSection}:${host.source.factKey}`;
1723
- return renderSourceRefLink({ sourcePath: host.source.path });
1724
- }
1725
- function renderExtensionHostsSection(extensionSurfaces) {
1726
- const boundHosts = extensionSurfaces.hosts.filter((host) => host.bound);
1727
- if (boundHosts.length === 0) return `## UMES hosts
1728
-
1729
- ${EMPTY_SECTION_MARKER}`;
1730
- const rows = boundHosts.map(
1731
- (host) => `| ${host.id} | ${host.family} | ${host.capabilities.join(", ") || "\u2014"} | ${renderExtensionHostContext(host)} | ${host.stability.toUpperCase()} | ${renderExtensionHostSource(host)} |`
1732
- );
1733
- return [
1734
- "## UMES hosts",
1735
- "",
1736
- "| ID / pattern | Family | Supports | Context | Stability | Source |",
1737
- "|---|---|---|---|---|---|",
1738
- ...rows
1739
- ].join("\n");
1740
- }
1741
- function compactContributionDetails(contribution) {
1742
- const details = contribution.details;
1743
- return Object.keys(details).sort((left, right) => left.localeCompare(right)).flatMap((key) => {
1744
- const value = details[key];
1745
- if (value === void 0) return [];
1746
- if (Array.isArray(value)) return [`${key}=${value.join(",") || "none"}`];
1747
- if (value && typeof value === "object") {
1748
- const nested = Object.keys(value).sort((left, right) => left.localeCompare(right)).map((nestedKey) => {
1749
- const nestedValue = value[nestedKey];
1750
- return `${nestedKey}:${Array.isArray(nestedValue) ? nestedValue.join(",") : String(nestedValue)}`;
1751
- });
1752
- return [`${key}={${nested.join(";")}}`];
1753
- }
1754
- return [`${key}=${String(value)}`];
1755
- }).join("; ");
1756
- }
1757
- function renderExtensionContributionsSection(extensionSurfaces) {
1758
- if (extensionSurfaces.contributions.length === 0) return `## UMES contributions
1759
-
1760
- ${EMPTY_SECTION_MARKER}`;
1761
- const rows = extensionSurfaces.contributions.map((contribution) => {
1762
- const targets = contribution.targets.map((entry) => entry.id).join(", ");
1763
- const resolution = contribution.targets.map((entry) => entry.resolution).join(", ");
1764
- const phases = [...contribution.phases ?? [], ...contribution.operations ?? []].join(", ") || "\u2014";
1765
- const source = renderSourceRefLink({ sourcePath: contribution.source.path });
1766
- return `| ${contribution.id} | ${contribution.kind} | ${targets || "\u2014"} | ${phases} | ${compactContributionDetails(contribution)} | ${resolution || "\u2014"} | ${source} |`;
1767
- });
1768
- return [
1769
- "## UMES contributions",
1770
- "",
1771
- "| ID | Kind | Target | Phase / operations | Contract | Resolution | Source |",
1772
- "|---|---|---|---|---|---|---|",
1773
- ...rows
1774
- ].join("\n");
1775
- }
1776
- function renderExtensionDiagnosticsSection(extensionSurfaces) {
1777
- const unbound = extensionSurfaces.hosts.filter((host) => !host.bound);
1778
- if (unbound.length === 0 && extensionSurfaces.unresolved.length === 0) return "";
1779
- const diagnostics = [
1780
- ...unbound.map((host) => `- unbound-helper: ${host.id}`),
1781
- ...extensionSurfaces.unresolved.map((entry) => `- ${entry.reason}: ${entry.key} (${entry.source.path})`)
1782
- ];
1783
- return ["## UMES diagnostics", "", ...diagnostics].join("\n");
1784
- }
1785
- function renderExtensionTargetRef(target) {
1786
- const method = target.method ? ` ${target.method}` : "";
1787
- const owner = target.moduleId ? ` @${target.moduleId}` : "";
1788
- return `${target.kind}:${target.id}${method}${owner}`;
1789
- }
1790
- function renderActivationBindingsSection(extensionSurfaces) {
1791
- const activations = extensionSurfaces.activations ?? [];
1792
- if (activations.length === 0) return `## Active extension bindings
1793
-
1794
- ${EMPTY_SECTION_MARKER}`;
1795
- const rows = activations.map((activation) => {
1796
- const phases = activation.phases && activation.phases.length > 0 ? activation.phases.join(", ") : "\u2014";
1797
- const source = activation.source ? renderSourceRefLink(activation.source) : "\u2014";
1798
- const bridge = activation.bridge ? `${activation.bridge.factSection}:${activation.bridge.factKey}` : "\u2014";
1799
- return `| ${activation.id} | ${activation.kind} | ${renderExtensionTargetRef(activation.host)} | ${activation.contributionKinds.join(", ") || "\u2014"} | ${phases} | ${bridge} | ${source} |`;
1800
- });
1801
- return [
1802
- "## Active extension bindings",
1803
- "",
1804
- "| Activation | Kind | Host | Contribution kinds | Phases | Bridge | Source |",
1805
- "|---|---|---|---|---|---|---|",
1806
- ...rows
1807
- ].join("\n");
1808
- }
1809
- function renderIncomingContributionsSection(extensionSurfaces) {
1810
- const incoming = extensionSurfaces.incoming ?? [];
1811
- if (incoming.length === 0) return `## Incoming installed contributions
1812
-
1813
- ${EMPTY_SECTION_MARKER}`;
1814
- const rows = incoming.map((entry) => {
1815
- const activation = entry.activationId ?? "\u2014";
1816
- const source = entry.source ? renderSourceRefLink(entry.source) : "\u2014";
1817
- return `| ${entry.contributorModuleId} | ${entry.contributionKind} | ${renderExtensionTargetRef(entry.target)} | ${entry.resolution} | ${activation} | ${entry.contributionId} \xB7 ${source} |`;
1818
- });
1819
- return [
1820
- "## Incoming installed contributions",
1821
- "",
1822
- "| Contributor | Kind | Target | Resolution | Activation | Contribution \xB7 Source |",
1823
- "|---|---|---|---|---|---|",
1824
- ...rows
1825
- ].join("\n");
1826
- }
1827
- function renderContributionResolutionsSection(extensionSurfaces, lookup) {
1828
- const resolutions = extensionSurfaces.contributionResolutions ?? [];
1829
- if (resolutions.length === 0) return `## Contribution resolutions
1830
-
1831
- ${EMPTY_SECTION_MARKER}`;
1832
- const rows = resolutions.map((resolution) => {
1833
- const activations = resolution.activationIds.length > 0 ? resolution.activationIds.join(", ") : "\u2014";
1834
- const source = renderLookedUpSource(lookup, "extension-contribution", resolution.contributionId);
1835
- return `| ${resolution.contributionId} | ${renderExtensionTargetRef(resolution.target)} | ${resolution.resolution} | ${activations} | ${source} |`;
1836
- });
1837
- return [
1838
- "## Contribution resolutions",
1839
- "",
1840
- "| Contribution | Target | Resolution | Activations | Source |",
1841
- "|---|---|---|---|---|",
1842
- ...rows
1843
- ].join("\n");
1844
- }
1845
- function renderOverrideTargetPath(target) {
1846
- let display = "overrides";
1847
- for (let index = 0; index < target.path.length; index += 1) {
1848
- const segment = target.path[index];
1849
- const isKeyedTerminal = target.key !== void 0 && index === target.path.length - 1;
1850
- display += isKeyedTerminal ? `[${JSON.stringify(segment)}]` : `.${segment}`;
1851
- }
1852
- return display;
1853
- }
1854
- function renderOverrideTargetsSection(targets) {
1855
- if (!targets || targets.length === 0) return `## Exact override targets
1856
-
1857
- ${EMPTY_SECTION_MARKER}`;
1858
- const header = "| Domain | Path / key | Supported modes | Referenced fact | Source |";
1859
- const divider = "|---|---|---|---|---|";
1860
- const rows = targets.map((target) => {
1861
- const path2 = `\`${renderOverrideTargetPath(target)}\``;
1862
- const modes = target.modes.join(", ") || "\u2014";
1863
- const fact = `${target.factRef.factSection}:${target.factRef.factKey}`;
1864
- return `| ${target.domain} | ${path2} | ${modes} | ${fact} | ${renderSourceRefLink(target.source)} |`;
1865
- });
1866
- return ["## Exact override targets", "", header, divider, ...rows].join("\n");
1867
- }
1868
645
  function renderModuleFactsMarkdown(facts) {
1869
- const extensionSurfaces = facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] };
1870
- const lookup = buildFactSourceLookup(facts);
1871
646
  const sections = [
1872
647
  `# ${facts.module} \u2014 module facts (generated, do not edit)`,
1873
- renderVersionStamp(facts.coreVersion, facts.sourcePackage, facts.sourceVersion),
1874
- `Source root: ${renderSourceLink(facts.sourceRoot)}`,
648
+ renderVersionStamp(facts.coreVersion),
1875
649
  "",
1876
- renderEntitiesSection(facts.entities, lookup),
650
+ renderEntitiesSection(facts.entities),
1877
651
  "",
1878
- renderEventsSection(facts.events, lookup),
652
+ renderEventsSection(facts.events),
1879
653
  "",
1880
- renderSourceLinkedListSection(
1881
- `## ACL features (${facts.aclFeatures.length})`,
1882
- facts.aclFeatures,
1883
- lookup,
1884
- "acl-feature",
1885
- "Feature"
1886
- ),
654
+ renderInlineListSection(`## ACL features (${facts.aclFeatures.length})`, facts.aclFeatures),
1887
655
  "",
1888
656
  renderApiRoutesSection(facts.apiRoutes),
1889
657
  "",
1890
- renderLinkedFactsSection("## Backend pages", facts.backendPages.map((page) => ({ label: page.path, sourcePath: page.sourcePath }))),
1891
- "",
1892
- renderLinkedFactsSection("## Frontend pages", facts.frontendPages.map((page) => ({ label: page.path, sourcePath: page.sourcePath }))),
1893
- "",
1894
- renderSourceLinkedListSection("## DI service tokens", facts.diTokens, lookup, "di-registration", "Token"),
658
+ renderInlineListSection("## DI service tokens", facts.diTokens),
1895
659
  "",
1896
- renderSourceLinkedListSection("## Search entities", facts.searchEntities, lookup, "search", "Entity ID"),
660
+ renderInlineListSection("## Search entities", facts.searchEntities),
1897
661
  "",
1898
662
  renderHostTokensSection(facts.hostTokens),
1899
663
  "",
1900
- renderExtensionHostsSection(extensionSurfaces),
1901
- "",
1902
- renderExtensionContributionsSection(extensionSurfaces),
1903
- "",
1904
- renderActivationBindingsSection(extensionSurfaces),
664
+ renderInlineListSection("## Notifications", facts.notifications),
1905
665
  "",
1906
- renderIncomingContributionsSection(extensionSurfaces),
1907
- "",
1908
- renderContributionResolutionsSection(extensionSurfaces, lookup),
1909
- "",
1910
- renderExtensionDiagnosticsSection(extensionSurfaces),
1911
- "",
1912
- renderSourceLinkedListSection("## Notifications", facts.notifications, lookup, "notification", "Notification ID"),
1913
- "",
1914
- renderLinkedFactsSection("## CLI commands", facts.cliCommands.map((command) => ({ label: command.command, sourcePath: command.sourcePath }))),
1915
- "",
1916
- renderLinkedFactsSection("## AI tools / MCP capabilities", facts.aiTools.map((tool) => ({ label: tool.name, sourcePath: tool.sourcePath }))),
1917
- "",
1918
- renderLinkedFactsSection("## AI agents", facts.aiAgents.map((agent) => ({ label: agent.id, sourcePath: agent.sourcePath }))),
1919
- "",
1920
- renderOverrideTargetsSection(facts.overrideTargets),
666
+ renderInlineListSection("## CLI", facts.cli),
1921
667
  ""
1922
668
  ];
1923
- const owned = facts.ownedContracts ?? {};
1924
- const ownedSections = [
1925
- renderOwnedContractSection("## Owned contract \u2014 module metadata", owned["module-metadata"]),
1926
- renderOwnedContractSection("## Domain commands", owned.command),
1927
- renderOwnedContractSection("## Workers", owned.worker),
1928
- renderOwnedContractSection("## Page middleware", owned["page-middleware"]),
1929
- renderOwnedContractSection("## Setup", owned.setup),
1930
- renderOwnedContractSection("## Encryption", owned.encryption),
1931
- renderDiRegistrationsSection(owned["di-registration"]),
1932
- renderOwnedContractSection("## Custom entities", owned["custom-entity"]),
1933
- renderOwnedContractSection("## AI extensions", owned["ai-extension"]),
1934
- renderOwnedContractSection("## Generator plugins", owned["generator-plugin"])
1935
- ].filter((section) => section.length > 0);
1936
- for (const section of ownedSections) {
1937
- sections.push(section, "");
1938
- }
1939
669
  return sections.join("\n");
1940
670
  }
1941
671
  function toModuleFactsJsonEntry(facts) {
@@ -1943,35 +673,15 @@ function toModuleFactsJsonEntry(facts) {
1943
673
  title: facts.title,
1944
674
  description: facts.description,
1945
675
  coreVersion: facts.coreVersion,
1946
- sourcePackage: facts.sourcePackage,
1947
- sourceVersion: facts.sourceVersion,
1948
- sourceRoot: facts.sourceRoot,
1949
676
  entities: facts.entities,
1950
- events: facts.events.map((event) => ({
1951
- id: event.id,
1952
- category: event.category,
1953
- entity: event.entity,
1954
- ...event.clientBroadcast !== void 0 ? { clientBroadcast: event.clientBroadcast } : {},
1955
- ...event.portalBroadcast !== void 0 ? { portalBroadcast: event.portalBroadcast } : {}
1956
- })),
677
+ events: facts.events.map((event) => ({ id: event.id, category: event.category, entity: event.entity })),
1957
678
  aclFeatures: facts.aclFeatures,
1958
679
  apiRoutes: facts.apiRoutes,
1959
680
  diTokens: facts.diTokens,
1960
681
  searchEntities: facts.searchEntities,
1961
682
  hostTokens: facts.hostTokens,
1962
683
  notifications: facts.notifications,
1963
- cli: facts.cli,
1964
- backendPages: facts.backendPages,
1965
- frontendPages: facts.frontendPages,
1966
- cliCommands: facts.cliCommands,
1967
- aiTools: facts.aiTools,
1968
- aiAgents: facts.aiAgents,
1969
- ...facts.extensionSurfaces ? { extensionSurfaces: facts.extensionSurfaces } : {},
1970
- ...facts.factSources && facts.factSources.length > 0 ? { factSources: facts.factSources } : {},
1971
- ...facts.ownedContracts && Object.keys(facts.ownedContracts).length > 0 ? { ownedContracts: facts.ownedContracts } : {},
1972
- ...facts.factDiagnostics && facts.factDiagnostics.length > 0 ? { factDiagnostics: facts.factDiagnostics } : {},
1973
- ...facts.overrideTargets && facts.overrideTargets.length > 0 ? { overrideTargets: facts.overrideTargets } : {},
1974
- ...facts.overrideTargetDiagnostics && facts.overrideTargetDiagnostics.length > 0 ? { overrideTargetDiagnostics: facts.overrideTargetDiagnostics } : {}
684
+ cli: facts.cli
1975
685
  };
1976
686
  }
1977
687
  function buildModuleFactsJsonObject(factsByModule) {
@@ -1986,9 +696,6 @@ function renderModuleFactsJson(factsByModule) {
1986
696
  `;
1987
697
  }
1988
698
  function extractAllModuleFacts(options) {
1989
- return withModuleExtensionFactExtractionCache(() => extractAllModuleFactsWithCache(options));
1990
- }
1991
- function extractAllModuleFactsWithCache(options) {
1992
699
  const sources = options.sources ? [...options.sources] : options.coreSrcRoot ? (options.moduleIds ?? []).map((moduleId) => ({
1993
700
  moduleId,
1994
701
  moduleRoot: path.join(options.coreSrcRoot, moduleId)
@@ -2001,63 +708,14 @@ function extractAllModuleFactsWithCache(options) {
2001
708
  moduleId: source.moduleId,
2002
709
  moduleRoot: source.moduleRoot,
2003
710
  coreVersion: options.coreVersion ?? null,
2004
- sourcePackage: source.from ?? null,
2005
- sourceVersion: source.packageVersion ?? null,
2006
711
  registryPath: options.registryPath ?? null,
2007
712
  registrySource: options.registrySource ?? null
2008
713
  });
2009
714
  factsByModule[source.moduleId] = facts;
715
+ markdownByModule[source.moduleId] = renderModuleFactsMarkdown(facts);
2010
716
  warnings.push(...facts.warnings);
2011
717
  }
2012
- const surfacesByModule = Object.fromEntries(
2013
- Object.entries(factsByModule).map(([moduleId, facts]) => [
2014
- moduleId,
2015
- facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] }
2016
- ])
2017
- );
2018
- const correlated = correlateModuleExtensionFacts({
2019
- surfacesByModule,
2020
- entityIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.entities.map((entity) => entity.id))),
2021
- eventIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.events.map((event) => event.id))),
2022
- apiRoutes: /* @__PURE__ */ new Set([
2023
- ...Object.values(factsByModule).flatMap((facts) => facts.apiRoutes.map((route) => route.path)),
2024
- ...sources.flatMap((source) => extractKnownApiRouteIds(source.moduleId, source.moduleRoot))
2025
- ]),
2026
- commandIds: new Set(sources.flatMap((source) => extractKnownCommandIds(source.moduleId, source.moduleRoot)))
2027
- });
2028
- assertNoUnresolvedExtensionTargets(correlated);
2029
- const apiRouteOwners = /* @__PURE__ */ new Map();
2030
- const commandOwners = /* @__PURE__ */ new Map();
2031
- for (const source of [...sources].sort((left, right) => left.moduleId.localeCompare(right.moduleId))) {
2032
- const facts = factsByModule[source.moduleId];
2033
- const sourceRoot = facts ? facts.sourceRoot : source.moduleId;
2034
- const owners = extractActivationTargetOwners({
2035
- moduleId: source.moduleId,
2036
- moduleRoot: source.moduleRoot,
2037
- sourceRoot
2038
- });
2039
- for (const route of owners.apiRoutes) {
2040
- if (!apiRouteOwners.has(route.id)) {
2041
- apiRouteOwners.set(route.id, { moduleId: source.moduleId, source: route.source, bridges: route.bridges });
2042
- }
2043
- }
2044
- for (const command of owners.commands) {
2045
- if (!commandOwners.has(command.id)) commandOwners.set(command.id, { moduleId: source.moduleId, source: command.source });
2046
- }
2047
- }
2048
- const withIncoming = correlateIncomingExtensions({
2049
- surfacesByModule: correlated,
2050
- apiRouteOwners,
2051
- commandOwners
2052
- });
2053
- for (const moduleId of Object.keys(factsByModule).sort((left, right) => left.localeCompare(right))) {
2054
- factsByModule[moduleId].extensionSurfaces = withIncoming[moduleId];
2055
- markdownByModule[moduleId] = renderModuleFactsMarkdown(factsByModule[moduleId]);
2056
- warnings.push(...correlated[moduleId].unresolved.map(
2057
- (entry) => `[module-facts] ${moduleId} ${entry.reason}: ${entry.key} (${entry.source.path})`
2058
- ));
2059
- }
2060
- return { factsByModule, markdownByModule, warnings, frameworkMarkdown: renderFrameworkExtensionPointsMarkdown() };
718
+ return { factsByModule, markdownByModule, warnings };
2061
719
  }
2062
720
  export {
2063
721
  buildModuleFactsJsonObject,