@open-mercato/cli 0.6.7 → 0.6.8-canary.319.1.5b4be4bc52

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 (287) hide show
  1. package/.turbo/turbo-build.log +77 -4
  2. package/build.mjs +68 -11
  3. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +32 -88
  4. package/dist/agentic/codex/enforcement-rules.md +2 -16
  5. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +19 -50
  6. package/dist/agentic/cursor/rules/entity-guard.mdc +9 -21
  7. package/dist/agentic/cursor/rules/generated-guard.mdc +3 -5
  8. package/dist/agentic/cursor/rules/open-mercato.mdc +3 -29
  9. package/dist/agentic/guides/ai-workflows.md +76 -0
  10. package/dist/agentic/guides/architecture.md +107 -0
  11. package/dist/agentic/guides/backend-ui.md +84 -0
  12. package/dist/agentic/guides/contracts.md +92 -0
  13. package/dist/agentic/guides/extensions.md +121 -0
  14. package/dist/agentic/guides/framework-extension-points.md +36 -0
  15. package/dist/agentic/guides/integrations.md +81 -0
  16. package/dist/agentic/guides/module-facts.json +116757 -3951
  17. package/dist/agentic/guides/module-system.md +12 -127
  18. package/dist/agentic/guides/modules/ai_assistant.md +227 -28
  19. package/dist/agentic/guides/modules/api_docs.md +58 -2
  20. package/dist/agentic/guides/modules/api_keys.md +92 -7
  21. package/dist/agentic/guides/modules/attachments.md +119 -14
  22. package/dist/agentic/guides/modules/audit_logs.md +131 -10
  23. package/dist/agentic/guides/modules/auth.md +276 -33
  24. package/dist/agentic/guides/modules/business_rules.md +149 -14
  25. package/dist/agentic/guides/modules/catalog.md +482 -43
  26. package/dist/agentic/guides/modules/channel_gmail.md +82 -3
  27. package/dist/agentic/guides/modules/channel_imap.md +82 -3
  28. package/dist/agentic/guides/modules/checkout.md +305 -27
  29. package/dist/agentic/guides/modules/communication_channels.md +315 -33
  30. package/dist/agentic/guides/modules/configs.md +104 -8
  31. package/dist/agentic/guides/modules/content.md +57 -2
  32. package/dist/agentic/guides/modules/currencies.md +152 -17
  33. package/dist/agentic/guides/modules/customer_accounts.md +387 -45
  34. package/dist/agentic/guides/modules/customers.md +746 -85
  35. package/dist/agentic/guides/modules/dashboards.md +155 -10
  36. package/dist/agentic/guides/modules/data_sync.md +149 -16
  37. package/dist/agentic/guides/modules/design_system.md +102 -0
  38. package/dist/agentic/guides/modules/dictionaries.md +107 -12
  39. package/dist/agentic/guides/modules/directory.md +148 -15
  40. package/dist/agentic/guides/modules/entities.md +145 -13
  41. package/dist/agentic/guides/modules/events.md +59 -2
  42. package/dist/agentic/guides/modules/feature_toggles.md +119 -9
  43. package/dist/agentic/guides/modules/gateway_stripe.md +92 -4
  44. package/dist/agentic/guides/modules/generators.md +45 -2
  45. package/dist/agentic/guides/modules/inbox_ops.md +207 -27
  46. package/dist/agentic/guides/modules/integrations.md +149 -16
  47. package/dist/agentic/guides/modules/messages.md +223 -24
  48. package/dist/agentic/guides/modules/notifications.md +96 -8
  49. package/dist/agentic/guides/modules/onboarding.md +77 -6
  50. package/dist/agentic/guides/modules/payment_gateways.md +168 -21
  51. package/dist/agentic/guides/modules/perspectives.md +77 -7
  52. package/dist/agentic/guides/modules/planner.md +136 -18
  53. package/dist/agentic/guides/modules/portal.md +93 -2
  54. package/dist/agentic/guides/modules/progress.md +104 -14
  55. package/dist/agentic/guides/modules/query_index.md +154 -15
  56. package/dist/agentic/guides/modules/record_locks.md +206 -21
  57. package/dist/agentic/guides/modules/resources.md +197 -30
  58. package/dist/agentic/guides/modules/sales.md +687 -84
  59. package/dist/agentic/guides/modules/scheduler.md +133 -14
  60. package/dist/agentic/guides/modules/search.md +170 -6
  61. package/dist/agentic/guides/modules/security.md +294 -35
  62. package/dist/agentic/guides/modules/shipping_carriers.md +134 -18
  63. package/dist/agentic/guides/modules/sso.md +151 -26
  64. package/dist/agentic/guides/modules/staff.md +372 -57
  65. package/dist/agentic/guides/modules/storage_s3.md +95 -5
  66. package/dist/agentic/guides/modules/sync_akeneo.md +85 -3
  67. package/dist/agentic/guides/modules/sync_excel.md +75 -6
  68. package/dist/agentic/guides/modules/system_status_overlays.md +60 -2
  69. package/dist/agentic/guides/modules/translations.md +104 -10
  70. package/dist/agentic/guides/modules/webhooks.md +203 -24
  71. package/dist/agentic/guides/modules/wms.md +469 -47
  72. package/dist/agentic/guides/modules/workflows.md +302 -43
  73. package/dist/agentic/guides/reference-module-facts.json +6370 -0
  74. package/dist/agentic/guides/reference-modules/example.md +451 -0
  75. package/dist/agentic/guides/spec-delivery.md +42 -0
  76. package/dist/agentic/guides/testing-debugging.md +80 -0
  77. package/dist/agentic/guides/upstream/AGENTS.md +299 -0
  78. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +316 -0
  79. package/dist/agentic/guides/upstream/manifest.json +8 -0
  80. package/dist/agentic/shared/AGENTS.md.template +120 -311
  81. package/dist/agentic/shared/ai/agentic.config.json +2 -0
  82. package/dist/agentic/shared/ai/harness/README.md +50 -0
  83. package/dist/agentic/shared/ai/harness/RELEASE.md +57 -0
  84. package/dist/agentic/shared/ai/harness/cases.json +15050 -0
  85. package/dist/agentic/shared/ai/harness/cases.schema.json +188 -0
  86. package/dist/agentic/shared/ai/harness/fixtures/index.json +51 -0
  87. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +166 -0
  88. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +21 -0
  89. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +96 -0
  90. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +172 -0
  91. package/dist/agentic/shared/ai/harness/knowledge-change.schema.json +228 -0
  92. package/dist/agentic/shared/ai/harness/release-matrix.json +163 -0
  93. package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
  94. package/dist/agentic/shared/ai/harness/result.schema.json +109 -0
  95. package/dist/agentic/shared/ai/harness/routing-response.schema.json +22 -0
  96. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
  97. package/dist/agentic/shared/ai/harness/validators.json +82 -0
  98. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +2121 -0
  99. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
  100. package/dist/agentic/shared/ai/harness/writable-spec-oracles.mjs +412 -0
  101. package/dist/agentic/shared/ai/lessons/_template.md +16 -0
  102. package/dist/agentic/shared/ai/lessons.md +26 -3
  103. package/dist/agentic/shared/ai/review-checklist.md +36 -0
  104. package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +21 -0
  105. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
  106. package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +98 -0
  107. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +21 -241
  108. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +31 -0
  109. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
  110. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +15 -0
  111. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
  112. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
  113. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
  114. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
  115. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
  116. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
  117. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
  118. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
  119. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
  120. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
  121. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +17 -601
  122. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +21 -0
  123. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +15 -0
  124. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +16 -0
  125. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
  126. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +15 -310
  127. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +19 -0
  128. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +31 -0
  129. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +100 -0
  130. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
  131. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/knowledge-change.md +115 -0
  132. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
  133. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
  134. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
  135. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
  136. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
  137. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +18 -0
  138. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
  139. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +33 -152
  140. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +33 -0
  141. package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +40 -0
  142. package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +27 -0
  143. package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +24 -0
  144. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +25 -708
  145. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
  146. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +25 -0
  147. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
  148. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
  149. package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +34 -0
  150. package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +4 -0
  151. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +11 -0
  152. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +31 -0
  153. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +39 -0
  154. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +43 -0
  155. package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +11 -0
  156. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
  157. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +32 -0
  158. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +172 -0
  159. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +14 -0
  160. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
  161. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +40 -0
  162. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
  163. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
  164. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
  165. package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +41 -0
  166. package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +19 -0
  167. package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +44 -0
  168. package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +39 -0
  169. package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +20 -0
  170. package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +57 -0
  171. package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +11 -0
  172. package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +486 -0
  173. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +20 -843
  174. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +42 -0
  175. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +27 -0
  176. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
  177. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +43 -0
  178. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
  179. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
  180. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
  181. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +17 -467
  182. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +29 -0
  183. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
  184. package/dist/agentic/shared/ai/skills/tiers.json +143 -21
  185. package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
  186. package/dist/agentic/shared/ai/specs/README.md +4 -3
  187. package/dist/agentic/shared/ai/specs/SPEC-000-template.md +226 -10
  188. package/dist/agentic/shared/ai/trackers/github.md +108 -4
  189. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +224 -0
  190. package/dist/agentic/shared/scripts/check-lessons.mjs +178 -0
  191. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +3585 -0
  192. package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
  193. package/dist/agentic/shared/scripts/framework-context.mjs +888 -0
  194. package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
  195. package/dist/agentic/shared/scripts/install-skills.sh +4 -694
  196. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
  197. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1774 -0
  198. package/dist/agentic/shared/scripts/validate-knowledge-change.mjs +911 -0
  199. package/dist/bin.js +13 -1
  200. package/dist/bin.js.map +2 -2
  201. package/dist/lib/__integration__/TC-INT-008.spec.js +88 -8
  202. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  203. package/dist/lib/agentic-init.js +13 -3
  204. package/dist/lib/agentic-init.js.map +2 -2
  205. package/dist/lib/agentic-setup.js +434 -186
  206. package/dist/lib/agentic-setup.js.map +2 -2
  207. package/dist/lib/generators/extensions/injection-widgets.js +20 -0
  208. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  209. package/dist/lib/generators/module-extension-facts.js +1872 -0
  210. package/dist/lib/generators/module-extension-facts.js.map +7 -0
  211. package/dist/lib/generators/module-fact-sources.js +70 -0
  212. package/dist/lib/generators/module-fact-sources.js.map +7 -0
  213. package/dist/lib/generators/module-facts-discovery.js +64 -7
  214. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  215. package/dist/lib/generators/module-facts.js +1629 -52
  216. package/dist/lib/generators/module-facts.js.map +3 -3
  217. package/dist/lib/generators/module-override-targets.js +688 -0
  218. package/dist/lib/generators/module-override-targets.js.map +7 -0
  219. package/dist/lib/generators/module-registry.js +11 -5
  220. package/dist/lib/generators/module-registry.js.map +2 -2
  221. package/dist/lib/load-env.js +24 -0
  222. package/dist/lib/load-env.js.map +7 -0
  223. package/dist/lib/resolver.js +2 -0
  224. package/dist/lib/resolver.js.map +2 -2
  225. package/dist/lib/telemetry-init.js +358 -0
  226. package/dist/lib/telemetry-init.js.map +7 -0
  227. package/dist/lib/testing/integration.js +5 -2
  228. package/dist/lib/testing/integration.js.map +2 -2
  229. package/dist/mercato.js +23 -1
  230. package/dist/mercato.js.map +2 -2
  231. package/package.json +13 -11
  232. package/src/bin.ts +33 -1
  233. package/src/lib/__integration__/TC-INT-008.spec.ts +107 -9
  234. package/src/lib/__tests__/agentic-init.test.ts +41 -5
  235. package/src/lib/__tests__/agentic-setup.ownership.test.ts +386 -0
  236. package/src/lib/__tests__/injection-widget-id-validation.test.ts +184 -0
  237. package/src/lib/__tests__/load-env.test.ts +65 -0
  238. package/src/lib/__tests__/telemetry-init.test.ts +298 -0
  239. package/src/lib/agentic-init.ts +15 -3
  240. package/src/lib/agentic-setup.ts +573 -222
  241. package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
  242. package/src/lib/generators/__tests__/module-extension-activations.test.ts +762 -0
  243. package/src/lib/generators/__tests__/module-extension-facts.test.ts +603 -0
  244. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +139 -2
  245. package/src/lib/generators/__tests__/module-facts.computed-di-token.test.ts +88 -0
  246. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
  247. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
  248. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
  249. package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +391 -0
  250. package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +561 -0
  251. package/src/lib/generators/__tests__/module-facts.search-entity-id.test.ts +151 -0
  252. package/src/lib/generators/__tests__/module-facts.source-links.test.ts +160 -0
  253. package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +149 -0
  254. package/src/lib/generators/__tests__/module-override-targets.test.ts +328 -0
  255. package/src/lib/generators/__tests__/module-subset.test.ts +18 -0
  256. package/src/lib/generators/extensions/injection-widgets.ts +51 -0
  257. package/src/lib/generators/module-extension-facts.ts +2433 -0
  258. package/src/lib/generators/module-fact-sources.ts +108 -0
  259. package/src/lib/generators/module-facts-discovery.ts +104 -7
  260. package/src/lib/generators/module-facts.ts +2387 -138
  261. package/src/lib/generators/module-override-targets.ts +863 -0
  262. package/src/lib/generators/module-registry.ts +16 -6
  263. package/src/lib/load-env.ts +30 -0
  264. package/src/lib/resolver.ts +3 -0
  265. package/src/lib/telemetry-init.ts +461 -0
  266. package/src/lib/testing/__tests__/integration.test.ts +4 -0
  267. package/src/lib/testing/integration.ts +5 -2
  268. package/src/mercato.ts +26 -1
  269. package/dist/agentic/guides/cache.md +0 -45
  270. package/dist/agentic/guides/core.md +0 -453
  271. package/dist/agentic/guides/events.md +0 -117
  272. package/dist/agentic/guides/queue.md +0 -53
  273. package/dist/agentic/guides/search.md +0 -115
  274. package/dist/agentic/guides/shared.md +0 -108
  275. package/dist/agentic/guides/ui.md +0 -347
  276. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
  277. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
  278. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
  279. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
  280. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
  281. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
  282. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
  283. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
  284. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
  285. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
  286. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
  287. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
@@ -0,0 +1,391 @@
1
+ import fs from 'node:fs'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+ import {
5
+ assertPackageModuleFactsOnly,
6
+ assertPortableSourceRoot,
7
+ computeModuleSourceFingerprint,
8
+ computeModuleTaxonomyFingerprint,
9
+ extractAllModuleFacts,
10
+ extractLocalReferenceModuleFacts,
11
+ extractModuleFacts,
12
+ renderModuleFactsJson,
13
+ renderReferenceModuleFactsJson,
14
+ toModuleFactsJsonEntry,
15
+ type ModuleFactSource,
16
+ } from '../module-facts'
17
+ import {
18
+ appendLocalReferenceModuleSource,
19
+ discoverLocalReferenceModuleSource,
20
+ } from '../module-facts-discovery'
21
+
22
+ function findRepoRoot(): string {
23
+ let dir = __dirname
24
+ for (let depth = 0; depth < 10; depth += 1) {
25
+ if (fs.existsSync(path.join(dir, 'packages', 'core', 'src', 'modules'))) return dir
26
+ dir = path.dirname(dir)
27
+ }
28
+ throw new Error('[internal] could not locate repo root from the test directory')
29
+ }
30
+
31
+ function writeFile(filePath: string, contents: string): void {
32
+ fs.mkdirSync(path.dirname(filePath), { recursive: true })
33
+ fs.writeFileSync(filePath, contents)
34
+ }
35
+
36
+ /**
37
+ * A package-provided module that owns an event, so an app-local contribution targeting it
38
+ * exercises real cross-module correlation instead of a self-contained stub.
39
+ */
40
+ function writePackageModule(moduleRoot: string): void {
41
+ writeFile(
42
+ path.join(moduleRoot, 'index.ts'),
43
+ "export const metadata = { name: 'alpha', title: 'Alpha', description: 'Package module' }\n",
44
+ )
45
+ writeFile(
46
+ path.join(moduleRoot, 'events.ts'),
47
+ "export const events = [{ id: 'alpha.thing.created', label: 'Thing Created', entity: 'thing', category: 'crud' }]\n",
48
+ )
49
+ writeFile(
50
+ path.join(moduleRoot, 'acl.ts'),
51
+ "export const features = [{ id: 'alpha.view', title: 'View alpha', module: 'alpha' }]\n",
52
+ )
53
+ }
54
+
55
+ /** An app-local module whose subscriber contributes to the package module's event. */
56
+ function writeLocalModule(moduleRoot: string): void {
57
+ writeFile(
58
+ path.join(moduleRoot, 'index.ts'),
59
+ "export const metadata = { name: 'demo_local', title: 'Demo Local', description: 'App-local reference' }\n",
60
+ )
61
+ writeFile(
62
+ path.join(moduleRoot, 'acl.ts'),
63
+ "export const features = [{ id: 'demo_local.view', title: 'View demo', module: 'demo_local' }]\n",
64
+ )
65
+ writeFile(
66
+ path.join(moduleRoot, 'events.ts'),
67
+ "export const events = [{ id: 'demo_local.pinged', label: 'Pinged', entity: 'ping', category: 'crud' }]\n",
68
+ )
69
+ writeFile(
70
+ path.join(moduleRoot, 'subscribers', 'on-alpha-thing.ts'),
71
+ [
72
+ "export const metadata = { event: 'alpha.thing.created', id: 'demo_local:on-alpha-thing', persistent: false }",
73
+ 'export default async function handler(): Promise<void> {}',
74
+ '',
75
+ ].join('\n'),
76
+ )
77
+ writeFile(
78
+ path.join(moduleRoot, '__tests__', 'excluded.test.ts'),
79
+ "it('is excluded from the source fingerprint', () => { expect(true).toBe(true) })\n",
80
+ )
81
+ }
82
+
83
+ describe('local-reference module fact emission', () => {
84
+ let tmp: string
85
+ let appRoot: string
86
+ let packageSources: ModuleFactSource[]
87
+ let reference: ModuleFactSource
88
+
89
+ beforeAll(() => {
90
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'module-facts-local-reference-'))
91
+ appRoot = path.join(tmp, 'app')
92
+ const packageModuleRoot = path.join(appRoot, 'node_modules', '@acme', 'alpha-pkg', 'src', 'modules', 'alpha')
93
+ writePackageModule(packageModuleRoot)
94
+ writeLocalModule(path.join(appRoot, 'src', 'modules', 'demo_local'))
95
+ packageSources = [{
96
+ moduleId: 'alpha',
97
+ moduleRoot: packageModuleRoot,
98
+ from: '@acme/alpha-pkg',
99
+ packageVersion: '1.2.3',
100
+ }]
101
+ const discovered = discoverLocalReferenceModuleSource({ appRoot, moduleId: 'demo_local' })
102
+ if (!discovered) throw new Error('[internal] fixture local module was not discovered')
103
+ reference = discovered
104
+ })
105
+
106
+ afterAll(() => {
107
+ fs.rmSync(tmp, { recursive: true, force: true })
108
+ })
109
+
110
+ it('discovers the app-local module with portable local-reference provenance', () => {
111
+ expect(reference).toEqual({
112
+ moduleId: 'demo_local',
113
+ moduleRoot: path.join(appRoot, 'src', 'modules', 'demo_local'),
114
+ portableSourceRoot: 'src/modules/demo_local',
115
+ sourceKind: 'local-reference',
116
+ })
117
+ expect(discoverLocalReferenceModuleSource({ appRoot, moduleId: 'absent' })).toBeNull()
118
+ })
119
+
120
+ it('leaves the normal package sidecar byte-identical when the reference bundle is produced', () => {
121
+ const before = renderModuleFactsJson(extractAllModuleFacts({ sources: packageSources }).factsByModule)
122
+ extractLocalReferenceModuleFacts({ packageSources, reference })
123
+ const after = renderModuleFactsJson(extractAllModuleFacts({ sources: packageSources }).factsByModule)
124
+
125
+ expect(after).toBe(before)
126
+ const parsed = JSON.parse(before) as Record<string, Record<string, unknown>>
127
+ expect(Object.keys(parsed)).toEqual(['alpha'])
128
+ expect(parsed.alpha.sourceRoot).toBe('node_modules/@acme/alpha-pkg/src/modules/alpha')
129
+ // The emitted package entry is a STABLE generated-file contract
130
+ // (BACKWARD_COMPATIBILITY.md §14): this slice may add keys to the reference
131
+ // projection but must add none — including `sourceKind` — to a package entry.
132
+ expect(Object.keys(parsed.alpha)).toEqual([
133
+ 'title',
134
+ 'description',
135
+ 'coreVersion',
136
+ 'sourcePackage',
137
+ 'sourceVersion',
138
+ 'sourceRoot',
139
+ 'entities',
140
+ 'events',
141
+ 'aclFeatures',
142
+ 'apiRoutes',
143
+ 'diTokens',
144
+ 'searchEntities',
145
+ 'hostTokens',
146
+ 'notifications',
147
+ 'cli',
148
+ 'backendPages',
149
+ 'frontendPages',
150
+ 'cliCommands',
151
+ 'aiTools',
152
+ 'aiAgents',
153
+ 'extensionSurfaces',
154
+ 'factSources',
155
+ 'ownedContracts',
156
+ 'overrideTargets',
157
+ ])
158
+ })
159
+
160
+ it('resolves the local contribution inside the disposable batch without touching normal output', () => {
161
+ const { entry } = extractLocalReferenceModuleFacts({ packageSources, reference })
162
+ const contribution = entry.facts.extensionSurfaces?.contributions
163
+ .find((candidate) => candidate.id === 'demo_local:on-alpha-thing')
164
+ expect(contribution?.targets).toEqual([
165
+ expect.objectContaining({ id: 'alpha.thing.created', resolution: 'fact-ref' }),
166
+ ])
167
+
168
+ const activatedAlpha = extractAllModuleFacts({
169
+ sources: appendLocalReferenceModuleSource(packageSources, reference),
170
+ }).factsByModule.alpha
171
+ const activatedIncoming = activatedAlpha.extensionSurfaces?.incoming ?? []
172
+ expect(activatedIncoming.map((incoming) => incoming.contributionId)).toContain('demo_local:on-alpha-thing')
173
+
174
+ const normalAlpha = extractAllModuleFacts({ sources: packageSources }).factsByModule.alpha
175
+ expect(normalAlpha.extensionSurfaces?.incoming ?? []).toEqual([])
176
+ })
177
+
178
+ it('emits the reference bundle discriminators and never a node_modules path', () => {
179
+ const { entry, markdown } = extractLocalReferenceModuleFacts({ packageSources, reference })
180
+ expect(entry.moduleId).toBe('demo_local')
181
+ expect(entry.projectionKind).toBe('activated-reference')
182
+ expect(entry.sourceKind).toBe('local-reference')
183
+ expect(entry.runtimeSelected).toBe(false)
184
+ expect(entry.facts.sourceRoot).toBe('src/modules/demo_local')
185
+ expect(entry.facts.sourceKind).toBe('local-reference')
186
+
187
+ const serialized = renderReferenceModuleFactsJson({ demo_local: entry })
188
+ expect(serialized.endsWith('\n')).toBe(true)
189
+ expect(serialized).not.toContain('node_modules')
190
+ expect(JSON.parse(serialized)).toEqual({ demo_local: entry })
191
+
192
+ expect(markdown).not.toContain('node_modules')
193
+ for (const target of [...markdown.matchAll(/\]\(\.\.\/\.\.\/\.\.\/([^)#]+)(?:#L\d+)?\)/g)].map((match) => match[1])) {
194
+ expect(target.startsWith('src/modules/demo_local/')).toBe(true)
195
+ expect(fs.existsSync(path.join(appRoot, target))).toBe(true)
196
+ }
197
+ })
198
+
199
+ it('states the opt-in boundary and both fingerprints in the reference markdown header', () => {
200
+ const { entry, markdown } = extractLocalReferenceModuleFacts({ packageSources, reference })
201
+ const [heading, stamp, notice, sourceRootLine] = markdown.split('\n')
202
+ expect(heading).toBe('# demo_local — module facts (generated reference projection, do not edit)')
203
+ expect(stamp).toContain('generated from local reference src/modules/demo_local')
204
+ expect(stamp).toContain(entry.sourceFingerprint)
205
+ expect(stamp).toContain(entry.taxonomyFingerprint)
206
+ expect(notice).toContain('not selected by the current runtime')
207
+ expect(notice).toContain('only after opt-in')
208
+ expect(sourceRootLine).toBe('Source root: src/modules/demo_local')
209
+
210
+ const packageMarkdown = extractAllModuleFacts({ sources: packageSources }).markdownByModule.alpha
211
+ expect(packageMarkdown.split('\n')[0]).toBe('# alpha — module facts (generated, do not edit)')
212
+ expect(packageMarkdown).toContain('generated from @acme/alpha-pkg 1.2.3')
213
+ expect(packageMarkdown).not.toContain('after opt-in')
214
+ })
215
+
216
+ it('rejects a duplicate module id before the local reference is assigned', () => {
217
+ const collidingPackage: ModuleFactSource[] = [
218
+ ...packageSources,
219
+ { moduleId: 'demo_local', moduleRoot: '/somewhere/pkg/src/modules/demo_local', from: '@acme/demo-pkg' },
220
+ ]
221
+ expect(() => appendLocalReferenceModuleSource(collidingPackage, reference))
222
+ .toThrow(/local reference module "demo_local" collides with the module provided by @acme\/demo-pkg/)
223
+ expect(() => extractLocalReferenceModuleFacts({ packageSources: collidingPackage, reference }))
224
+ .toThrow(/collides with the module provided by/)
225
+ })
226
+
227
+ it('refuses a reference source that is not declared portable and local', () => {
228
+ expect(() => extractLocalReferenceModuleFacts({
229
+ packageSources,
230
+ reference: { ...reference, sourceKind: undefined },
231
+ })).toThrow(/must declare sourceKind "local-reference"/)
232
+ expect(() => extractLocalReferenceModuleFacts({
233
+ packageSources,
234
+ reference: { ...reference, portableSourceRoot: undefined },
235
+ })).toThrow(/must declare portableSourceRoot/)
236
+ for (const invalid of ['/abs/modules/demo', 'C:/modules/demo', 'src\\modules\\demo', '../modules/demo', '']) {
237
+ expect(() => assertPortableSourceRoot('demo_local', invalid))
238
+ .toThrow(/must be a relative POSIX app path/)
239
+ }
240
+ })
241
+
242
+ it('fails the build when an app-local module reaches the normal package output', () => {
243
+ const activated = extractAllModuleFacts({
244
+ sources: appendLocalReferenceModuleSource(packageSources, reference),
245
+ })
246
+ expect(() => assertPackageModuleFactsOnly(activated.factsByModule))
247
+ .toThrow(/must not contain app-local modules: demo_local \(src\/modules\/demo_local\)/)
248
+ expect(() => assertPackageModuleFactsOnly({
249
+ alpha: { ...activated.factsByModule.alpha, sourceRoot: 'src/modules/alpha' },
250
+ })).toThrow(/must not contain app-local modules: alpha \(src\/modules\/alpha\)/)
251
+ expect(() => assertPackageModuleFactsOnly(
252
+ extractAllModuleFacts({ sources: packageSources }).factsByModule,
253
+ )).not.toThrow()
254
+ })
255
+
256
+ it('keeps the strict unresolved-target policy for normal output and collects it for the projection', () => {
257
+ const danglingRoot = path.join(appRoot, 'src', 'modules', 'demo_dangling')
258
+ writeLocalModule(danglingRoot)
259
+ writeFile(
260
+ path.join(danglingRoot, 'subscribers', 'on-missing.ts'),
261
+ [
262
+ "export const metadata = { event: 'demo_dangling.never.declared', id: 'demo_dangling:on-missing', persistent: false }",
263
+ 'export default async function handler(): Promise<void> {}',
264
+ '',
265
+ ].join('\n'),
266
+ )
267
+ const dangling: ModuleFactSource = {
268
+ moduleId: 'demo_dangling',
269
+ moduleRoot: danglingRoot,
270
+ portableSourceRoot: 'src/modules/demo_dangling',
271
+ sourceKind: 'local-reference',
272
+ }
273
+
274
+ expect(() => extractAllModuleFacts({ sources: appendLocalReferenceModuleSource(packageSources, dangling) }))
275
+ .toThrow(/unresolved first-party extension targets: demo_dangling:demo_dangling:on-missing:demo_dangling.never.declared/)
276
+
277
+ const { entry, unresolvedTargets } = extractLocalReferenceModuleFacts({
278
+ packageSources,
279
+ reference: dangling,
280
+ })
281
+ expect(unresolvedTargets).toEqual([
282
+ 'demo_dangling:demo_dangling:on-missing:demo_dangling.never.declared',
283
+ ])
284
+ expect(entry.facts.extensionSurfaces?.unresolved.map((item) => item.key))
285
+ .toContain('demo_dangling:on-missing:demo_dangling.never.declared')
286
+ })
287
+
288
+ it('fingerprints the emitted source tree and the taxonomy independently', () => {
289
+ const first = extractLocalReferenceModuleFacts({ packageSources, reference }).entry
290
+ expect(first.sourceFingerprint).toMatch(/^[0-9a-f]{64}$/)
291
+ expect(first.taxonomyFingerprint).toMatch(/^[0-9a-f]{64}$/)
292
+ expect(first.sourceFingerprint).not.toBe(first.taxonomyFingerprint)
293
+
294
+ const testFilePath = path.join(reference.moduleRoot, '__tests__', 'excluded.test.ts')
295
+ fs.writeFileSync(testFilePath, "it('still excluded', () => { expect(1).toBe(1) })\n")
296
+ expect(computeModuleSourceFingerprint(reference.moduleRoot, 'src/modules/demo_local'))
297
+ .toBe(first.sourceFingerprint)
298
+
299
+ const aclPath = path.join(reference.moduleRoot, 'acl.ts')
300
+ const originalAcl = fs.readFileSync(aclPath, 'utf8')
301
+ try {
302
+ fs.writeFileSync(
303
+ aclPath,
304
+ [
305
+ "export const features = [",
306
+ " { id: 'demo_local.view', title: 'View demo', module: 'demo_local' },",
307
+ " { id: 'demo_local.manage', title: 'Manage demo', module: 'demo_local' },",
308
+ ']',
309
+ '',
310
+ ].join('\n'),
311
+ )
312
+ const changed = extractLocalReferenceModuleFacts({ packageSources, reference }).entry
313
+ expect(changed.sourceFingerprint).not.toBe(first.sourceFingerprint)
314
+ expect(changed.taxonomyFingerprint).not.toBe(first.taxonomyFingerprint)
315
+ expect(changed.facts.aclFeatures).toEqual(['demo_local.view', 'demo_local.manage'])
316
+ } finally {
317
+ fs.writeFileSync(aclPath, originalAcl)
318
+ }
319
+
320
+ const restored = extractLocalReferenceModuleFacts({ packageSources, reference }).entry
321
+ expect(restored.sourceFingerprint).toBe(first.sourceFingerprint)
322
+ expect(restored.taxonomyFingerprint).toBe(first.taxonomyFingerprint)
323
+ })
324
+
325
+ it('canonicalizes the taxonomy fingerprint across key and set ordering but not across values', () => {
326
+ const { entry } = extractLocalReferenceModuleFacts({ packageSources, reference })
327
+ const reordered = {
328
+ ...entry.facts,
329
+ aclFeatures: [...entry.facts.aclFeatures].reverse(),
330
+ coreVersion: '99.99.99',
331
+ sourceVersion: 'ignored-by-taxonomy',
332
+ }
333
+ expect(computeModuleTaxonomyFingerprint(reordered)).toBe(entry.taxonomyFingerprint)
334
+
335
+ const renamed = { ...entry.facts, aclFeatures: ['demo_local.renamed'] }
336
+ expect(computeModuleTaxonomyFingerprint(renamed)).not.toBe(entry.taxonomyFingerprint)
337
+
338
+ const baseline = {
339
+ ...entry.facts,
340
+ apiRoutes: [{ path: '/demo/things', methods: ['GET', 'POST'], sourcePath: 'src/modules/demo_local/api/things/route.ts' }],
341
+ }
342
+ const structurallyReordered = {
343
+ ...entry.facts,
344
+ apiRoutes: [{ sourcePath: 'src/modules/demo_local/api/things/route.ts', methods: ['POST', 'GET'], path: '/demo/things' }],
345
+ }
346
+ expect(computeModuleTaxonomyFingerprint(structurallyReordered)).toBe(computeModuleTaxonomyFingerprint(baseline))
347
+ const methodRemoved = {
348
+ ...entry.facts,
349
+ apiRoutes: [{ path: '/demo/things', methods: ['GET'], sourcePath: 'src/modules/demo_local/api/things/route.ts' }],
350
+ }
351
+ expect(computeModuleTaxonomyFingerprint(methodRemoved)).not.toBe(computeModuleTaxonomyFingerprint(baseline))
352
+
353
+ const movedBetweenSets = { ...entry.facts, aclFeatures: [], notifications: [...entry.facts.aclFeatures] }
354
+ expect(computeModuleTaxonomyFingerprint(movedBetweenSets)).not.toBe(entry.taxonomyFingerprint)
355
+ })
356
+ })
357
+
358
+ describe('local-reference projection of the canonical example module', () => {
359
+ const repoRoot = findRepoRoot()
360
+ const templateRoot = path.join(repoRoot, 'packages', 'create-app', 'template')
361
+ const authoringRoot = path.join(repoRoot, 'apps', 'mercato')
362
+
363
+ it('emits every example fact under the portable app-local root', () => {
364
+ const reference = discoverLocalReferenceModuleSource({ appRoot: templateRoot, moduleId: 'example' })
365
+ expect(reference).not.toBeNull()
366
+ const facts = extractModuleFacts({
367
+ moduleId: 'example',
368
+ moduleRoot: reference!.moduleRoot,
369
+ portableSourceRoot: reference!.portableSourceRoot,
370
+ sourceKind: reference!.sourceKind,
371
+ })
372
+ expect(facts.sourceRoot).toBe('src/modules/example')
373
+ expect(facts.sourceKind).toBe('local-reference')
374
+
375
+ const serialized = JSON.stringify(toModuleFactsJsonEntry(facts))
376
+ expect(serialized).not.toContain('node_modules')
377
+ for (const sourcePath of [...serialized.matchAll(/"(?:source)?[Pp]ath":"([^"]+\.tsx?)"/g)].map((m) => m[1])) {
378
+ expect(sourcePath.startsWith('src/modules/example/')).toBe(true)
379
+ expect(fs.existsSync(path.join(templateRoot, sourcePath))).toBe(true)
380
+ }
381
+ })
382
+
383
+ it('fingerprints the authoring and template example trees identically', () => {
384
+ const authoring = discoverLocalReferenceModuleSource({ appRoot: authoringRoot, moduleId: 'example' })
385
+ const template = discoverLocalReferenceModuleSource({ appRoot: templateRoot, moduleId: 'example' })
386
+ expect(authoring).not.toBeNull()
387
+ expect(template).not.toBeNull()
388
+ expect(computeModuleSourceFingerprint(authoring!.moduleRoot, 'src/modules/example'))
389
+ .toBe(computeModuleSourceFingerprint(template!.moduleRoot, 'src/modules/example'))
390
+ })
391
+ })