@open-mercato/cli 0.6.7-develop.6685.1.77c0a5591b → 0.6.7-develop.6687.1.46a258e592

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 (215) hide show
  1. package/.turbo/turbo-build.log +2 -3
  2. package/build.mjs +21 -5
  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 +80 -0
  12. package/dist/agentic/guides/contracts.md +92 -0
  13. package/dist/agentic/guides/extensions.md +104 -0
  14. package/dist/agentic/guides/integrations.md +81 -0
  15. package/dist/agentic/guides/module-facts.json +217 -81
  16. package/dist/agentic/guides/module-system.md +12 -127
  17. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  18. package/dist/agentic/guides/modules/api_docs.md +1 -1
  19. package/dist/agentic/guides/modules/api_keys.md +1 -1
  20. package/dist/agentic/guides/modules/attachments.md +2 -2
  21. package/dist/agentic/guides/modules/audit_logs.md +2 -2
  22. package/dist/agentic/guides/modules/auth.md +1 -1
  23. package/dist/agentic/guides/modules/business_rules.md +1 -1
  24. package/dist/agentic/guides/modules/catalog.md +5 -5
  25. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  26. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  27. package/dist/agentic/guides/modules/checkout.md +1 -1
  28. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  29. package/dist/agentic/guides/modules/configs.md +1 -1
  30. package/dist/agentic/guides/modules/content.md +1 -1
  31. package/dist/agentic/guides/modules/currencies.md +1 -1
  32. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  33. package/dist/agentic/guides/modules/customers.md +2 -2
  34. package/dist/agentic/guides/modules/dashboards.md +1 -1
  35. package/dist/agentic/guides/modules/data_sync.md +1 -1
  36. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  37. package/dist/agentic/guides/modules/directory.md +1 -1
  38. package/dist/agentic/guides/modules/entities.md +2 -2
  39. package/dist/agentic/guides/modules/events.md +1 -1
  40. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  41. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  42. package/dist/agentic/guides/modules/generators.md +1 -1
  43. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  44. package/dist/agentic/guides/modules/integrations.md +1 -1
  45. package/dist/agentic/guides/modules/messages.md +1 -1
  46. package/dist/agentic/guides/modules/notifications.md +1 -1
  47. package/dist/agentic/guides/modules/onboarding.md +1 -1
  48. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  49. package/dist/agentic/guides/modules/perspectives.md +1 -1
  50. package/dist/agentic/guides/modules/planner.md +1 -1
  51. package/dist/agentic/guides/modules/portal.md +1 -1
  52. package/dist/agentic/guides/modules/progress.md +1 -1
  53. package/dist/agentic/guides/modules/query_index.md +2 -2
  54. package/dist/agentic/guides/modules/record_locks.md +1 -1
  55. package/dist/agentic/guides/modules/resources.md +1 -1
  56. package/dist/agentic/guides/modules/sales.md +17 -17
  57. package/dist/agentic/guides/modules/scheduler.md +1 -1
  58. package/dist/agentic/guides/modules/search.md +1 -1
  59. package/dist/agentic/guides/modules/security.md +1 -1
  60. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  61. package/dist/agentic/guides/modules/sso.md +1 -1
  62. package/dist/agentic/guides/modules/staff.md +2 -2
  63. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  64. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  65. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  66. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  67. package/dist/agentic/guides/modules/translations.md +1 -1
  68. package/dist/agentic/guides/modules/webhooks.md +2 -2
  69. package/dist/agentic/guides/modules/wms.md +2 -2
  70. package/dist/agentic/guides/modules/workflows.md +1 -1
  71. package/dist/agentic/guides/testing-debugging.md +74 -0
  72. package/dist/agentic/guides/upstream/AGENTS.md +297 -0
  73. package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +303 -0
  74. package/dist/agentic/guides/upstream/manifest.json +8 -0
  75. package/dist/agentic/shared/AGENTS.md.template +123 -311
  76. package/dist/agentic/shared/ai/agentic.config.json +1 -0
  77. package/dist/agentic/shared/ai/harness/README.md +48 -0
  78. package/dist/agentic/shared/ai/harness/RELEASE.md +57 -0
  79. package/dist/agentic/shared/ai/harness/cases.json +13487 -0
  80. package/dist/agentic/shared/ai/harness/cases.schema.json +132 -0
  81. package/dist/agentic/shared/ai/harness/fixtures/index.json +49 -0
  82. package/dist/agentic/shared/ai/harness/fixtures/seeds.json +162 -0
  83. package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +20 -0
  84. package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +43 -0
  85. package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +110 -0
  86. package/dist/agentic/shared/ai/harness/release-matrix.json +133 -0
  87. package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
  88. package/dist/agentic/shared/ai/harness/result.schema.json +76 -0
  89. package/dist/agentic/shared/ai/harness/routing-response.schema.json +12 -0
  90. package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
  91. package/dist/agentic/shared/ai/harness/validators.json +78 -0
  92. package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +1768 -0
  93. package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
  94. package/dist/agentic/shared/ai/review-checklist.md +36 -0
  95. package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
  96. package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +20 -241
  97. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +16 -0
  98. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
  99. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +13 -0
  100. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
  101. package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
  102. package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
  103. package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
  104. package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
  105. package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
  106. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
  107. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
  108. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
  109. package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
  110. package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +16 -601
  111. package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +19 -0
  112. package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +13 -0
  113. package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +14 -0
  114. package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
  115. package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +14 -310
  116. package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +17 -0
  117. package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +28 -0
  118. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +89 -0
  119. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
  120. package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
  121. package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
  122. package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
  123. package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
  124. package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
  125. package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +17 -0
  126. package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
  127. package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +15 -156
  128. package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +12 -0
  129. package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +24 -708
  130. package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
  131. package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +14 -0
  132. package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
  133. package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
  134. package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
  135. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +19 -0
  136. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +107 -0
  137. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +12 -0
  138. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
  139. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +21 -0
  140. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
  141. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
  142. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
  143. package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +19 -843
  144. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +18 -0
  145. package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +25 -0
  146. package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
  147. package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +38 -0
  148. package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
  149. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
  150. package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
  151. package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +16 -467
  152. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +16 -0
  153. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
  154. package/dist/agentic/shared/ai/skills/tiers.json +137 -20
  155. package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
  156. package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +174 -0
  157. package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +2783 -0
  158. package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
  159. package/dist/agentic/shared/scripts/framework-context.mjs +894 -0
  160. package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
  161. package/dist/agentic/shared/scripts/install-skills.sh +4 -694
  162. package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
  163. package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1761 -0
  164. package/dist/lib/__integration__/TC-INT-008.spec.js +87 -8
  165. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  166. package/dist/lib/agentic-init.js +13 -3
  167. package/dist/lib/agentic-init.js.map +2 -2
  168. package/dist/lib/agentic-setup.js +418 -186
  169. package/dist/lib/agentic-setup.js.map +2 -2
  170. package/dist/lib/generators/extensions/injection-widgets.js +20 -0
  171. package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
  172. package/dist/lib/generators/module-facts-discovery.js +41 -7
  173. package/dist/lib/generators/module-facts-discovery.js.map +2 -2
  174. package/dist/lib/generators/module-facts.js +65 -17
  175. package/dist/lib/generators/module-facts.js.map +2 -2
  176. package/dist/lib/generators/module-registry.js +5 -4
  177. package/dist/lib/generators/module-registry.js.map +2 -2
  178. package/dist/lib/resolver.js +2 -0
  179. package/dist/lib/resolver.js.map +2 -2
  180. package/package.json +5 -5
  181. package/src/lib/__integration__/TC-INT-008.spec.ts +103 -8
  182. package/src/lib/__tests__/agentic-init.test.ts +41 -5
  183. package/src/lib/__tests__/agentic-setup.ownership.test.ts +380 -0
  184. package/src/lib/__tests__/injection-widget-id-validation.test.ts +184 -0
  185. package/src/lib/agentic-init.ts +15 -3
  186. package/src/lib/agentic-setup.ts +526 -224
  187. package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +6 -0
  188. package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
  189. package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
  190. package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
  191. package/src/lib/generators/__tests__/module-subset.test.ts +18 -0
  192. package/src/lib/generators/extensions/injection-widgets.ts +51 -0
  193. package/src/lib/generators/module-facts-discovery.ts +58 -7
  194. package/src/lib/generators/module-facts.ts +84 -20
  195. package/src/lib/generators/module-registry.ts +8 -4
  196. package/src/lib/resolver.ts +3 -0
  197. package/dist/agentic/guides/cache.md +0 -45
  198. package/dist/agentic/guides/core.md +0 -453
  199. package/dist/agentic/guides/events.md +0 -117
  200. package/dist/agentic/guides/queue.md +0 -53
  201. package/dist/agentic/guides/search.md +0 -115
  202. package/dist/agentic/guides/shared.md +0 -108
  203. package/dist/agentic/guides/ui.md +0 -347
  204. package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
  205. package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
  206. package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
  207. package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
  208. package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
  209. package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
  210. package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
  211. package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
  212. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
  213. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
  214. package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
  215. package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
@@ -238,6 +238,7 @@ function discoverPackagesInMonorepo(rootDir) {
238
238
  if (fs.existsSync(modulesPath)) {
239
239
  packages.push({
240
240
  name: pkgJson.name || `@open-mercato/${entry.name}`,
241
+ version: typeof pkgJson.version === "string" ? pkgJson.version : null,
241
242
  path: pkgPath,
242
243
  modulesPath
243
244
  });
@@ -265,6 +266,7 @@ function discoverPackagesInNodeModules(rootDir) {
265
266
  if (fs.existsSync(modulesPath)) {
266
267
  packages.push({
267
268
  name: pkgJson.name || `@open-mercato/${entry.name}`,
269
+ version: typeof pkgJson.version === "string" ? pkgJson.version : null,
268
270
  path: pkgPath,
269
271
  modulesPath
270
272
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/resolver.ts"],
4
- "sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport ts from 'typescript-js'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\n\n/**\n * Resolved execution environment for the CLI.\n * Produced once by resolveEnvironment() and consumed by all subsystems.\n * Eliminates per-subsystem isMonorepo() branching and hardcoded path segments.\n */\nexport type CliEnvironment = {\n /** Whether the CLI is running inside a Yarn/npm workspace monorepo. */\n mode: 'monorepo' | 'standalone'\n /** Workspace or project root (where package.json / node_modules live). */\n rootDir: string\n /** Next.js application directory (contains src/, package.json, next.config.*). */\n appDir: string\n /**\n * Resolve the root directory of an installed @open-mercato package.\n * Monorepo: packages/<pkg>/ Standalone: node_modules/<pkg>/\n */\n packageRoot: (packageName: string) => string\n}\n\nexport type ModuleEntry = {\n id: string\n from?: '@open-mercato/core' | '@app' | string\n}\n\nexport type PackageInfo = {\n name: string\n path: string\n modulesPath: string\n}\n\nexport interface PackageResolver {\n isMonorepo(): boolean\n getRootDir(): string\n getAppDir(): string\n getOutputDir(): string\n getModulesConfigPath(): string\n discoverPackages(): PackageInfo[]\n loadEnabledModules(): ModuleEntry[]\n getModulePaths(entry: ModuleEntry): { appBase: string; pkgBase: string }\n getModuleImportBase(entry: ModuleEntry): { appBase: string; pkgBase: string }\n getPackageOutputDir(packageName: string): string\n getPackageRoot(from?: string): string\n}\n\nfunction pkgDirFor(rootDir: string, from?: string, isMonorepo = true): string {\n if (!isMonorepo) {\n const pkgName = from || '@open-mercato/core'\n const pkgRoot = path.join(rootDir, 'node_modules', pkgName)\n const distModules = path.join(pkgRoot, 'dist', 'modules')\n if (fs.existsSync(distModules)) return distModules\n return path.join(pkgRoot, 'src', 'modules')\n }\n\n // Monorepo mode - read from src/modules (TypeScript source)\n if (!from || from === '@open-mercato/core') {\n return path.resolve(rootDir, 'packages/core/src/modules')\n }\n // Support other local packages like '@open-mercato/onboarding' => packages/onboarding/src/modules\n const m = from.match(/^@open-mercato\\/(.+)$/)\n if (m) {\n return path.resolve(rootDir, `packages/${m[1]}/src/modules`)\n }\n // Fallback to core modules path\n return path.resolve(rootDir, 'packages/core/src/modules')\n}\n\nfunction pkgRootFor(rootDir: string, from?: string, isMonorepo = true): string {\n if (!isMonorepo) {\n const pkgName = from || '@open-mercato/core'\n return path.join(rootDir, 'node_modules', pkgName)\n }\n\n if (!from || from === '@open-mercato/core') {\n return path.resolve(rootDir, 'packages/core')\n }\n const m = from.match(/^@open-mercato\\/(.+)$/)\n if (m) {\n return path.resolve(rootDir, `packages/${m[1]}`)\n }\n return path.resolve(rootDir, 'packages/core')\n}\n\nfunction parseModuleEntryFromObjectLiteral(node: ts.ObjectLiteralExpression): ModuleEntry | null {\n let id: string | null = null\n let from: string | null = null\n for (const property of node.properties) {\n if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) continue\n const key = property.name.text\n if (key === 'id' && ts.isStringLiteralLike(property.initializer)) {\n id = property.initializer.text\n }\n if (key === 'from' && ts.isStringLiteralLike(property.initializer)) {\n from = property.initializer.text\n }\n }\n if (!id) return null\n return { id, from: from ?? '@open-mercato/core' }\n}\n\nfunction parseProcessEnvAccess(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n): { matched: boolean; value: string | undefined } {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name)) {\n const target = node.expression\n if (\n ts.isPropertyAccessExpression(target)\n && ts.isIdentifier(target.expression)\n && target.expression.text === 'process'\n && target.name.text === 'env'\n ) {\n return { matched: true, value: env[node.name.text] }\n }\n }\n if (\n ts.isElementAccessExpression(node)\n && ts.isPropertyAccessExpression(node.expression)\n && ts.isIdentifier(node.expression.expression)\n && node.expression.expression.text === 'process'\n && node.expression.name.text === 'env'\n && ts.isStringLiteralLike(node.argumentExpression)\n ) {\n return { matched: true, value: env[node.argumentExpression.text] }\n }\n return { matched: false, value: undefined }\n}\n\nfunction evaluateStaticExpression(node: ts.Expression, env: NodeJS.ProcessEnv): unknown {\n return evaluateStaticExpressionWithScope(node, env, new Map())\n}\n\nfunction evaluateStaticExpressionWithScope(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n scope: Map<string, unknown>,\n): unknown {\n if (ts.isParenthesizedExpression(node)) return evaluateStaticExpressionWithScope(node.expression, env, scope)\n if (ts.isIdentifier(node)) {\n return scope.get(node.text)\n }\n if (ts.isStringLiteralLike(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text\n if (ts.isNumericLiteral(node)) return Number(node.text)\n if (node.kind === ts.SyntaxKind.TrueKeyword) return true\n if (node.kind === ts.SyntaxKind.FalseKeyword) return false\n if (node.kind === ts.SyntaxKind.NullKeyword) return null\n\n const envAccess = parseProcessEnvAccess(node, env)\n if (envAccess.matched) return envAccess.value\n\n if (ts.isPropertyAccessExpression(node)) {\n const target = evaluateStaticExpressionWithScope(node.expression, env, scope)\n if (target && typeof target === 'object' && node.name.text in target) {\n return (target as Record<string, unknown>)[node.name.text]\n }\n return undefined\n }\n\n if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken) {\n return !Boolean(evaluateStaticExpressionWithScope(node.operand, env, scope))\n }\n\n if (ts.isBinaryExpression(node)) {\n if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {\n return Boolean(evaluateStaticExpressionWithScope(node.left, env, scope))\n && Boolean(evaluateStaticExpressionWithScope(node.right, env, scope))\n }\n if (node.operatorToken.kind === ts.SyntaxKind.BarBarToken) {\n return Boolean(evaluateStaticExpressionWithScope(node.left, env, scope))\n || Boolean(evaluateStaticExpressionWithScope(node.right, env, scope))\n }\n if (node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken) {\n return evaluateStaticExpressionWithScope(node.left, env, scope) === evaluateStaticExpressionWithScope(node.right, env, scope)\n }\n if (node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken) {\n return evaluateStaticExpressionWithScope(node.left, env, scope) !== evaluateStaticExpressionWithScope(node.right, env, scope)\n }\n }\n\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'parseBooleanWithDefault') {\n const rawValueNode = node.arguments[0]\n const fallbackNode = node.arguments[1]\n const rawValue = rawValueNode ? evaluateStaticExpressionWithScope(rawValueNode, env, scope) : undefined\n const fallbackValue = fallbackNode ? evaluateStaticExpressionWithScope(fallbackNode, env, scope) : false\n return parseBooleanWithDefault(typeof rawValue === 'string' ? rawValue : undefined, Boolean(fallbackValue))\n }\n\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === 'some') {\n const target = evaluateStaticExpressionWithScope(node.expression.expression, env, scope)\n const predicate = node.arguments[0]\n if (!Array.isArray(target) || !predicate) return undefined\n\n return target.some((entry) => {\n if (!ts.isArrowFunction(predicate) && !ts.isFunctionExpression(predicate)) return false\n\n const localScope = new Map(scope)\n const parameter = predicate.parameters[0]\n if (parameter && ts.isIdentifier(parameter.name)) {\n localScope.set(parameter.name.text, entry)\n }\n\n if (ts.isBlock(predicate.body)) {\n const returnStatement = predicate.body.statements.find((statement): statement is ts.ReturnStatement =>\n ts.isReturnStatement(statement),\n )\n if (!returnStatement?.expression) return false\n return Boolean(evaluateStaticExpressionWithScope(returnStatement.expression, env, localScope))\n }\n\n return Boolean(evaluateStaticExpressionWithScope(predicate.body, env, localScope))\n })\n }\n\n return undefined\n}\n\nfunction evaluateStaticCondition(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n scope: Map<string, unknown>,\n): boolean {\n const evaluated = evaluateStaticExpressionWithScope(node, env, scope)\n return Boolean(evaluated)\n}\n\nfunction collectPushEntriesFromStatement(\n statement: ts.Statement,\n env: NodeJS.ProcessEnv,\n targetVariableName: string,\n scope: Map<string, unknown>,\n): ModuleEntry[] {\n if (ts.isBlock(statement)) {\n return statement.statements.flatMap((child) => collectPushEntriesFromStatement(child, env, targetVariableName, scope))\n }\n\n if (ts.isIfStatement(statement)) {\n if (evaluateStaticCondition(statement.expression, env, scope)) {\n return collectPushEntriesFromStatement(statement.thenStatement, env, targetVariableName, scope)\n }\n if (statement.elseStatement) {\n return collectPushEntriesFromStatement(statement.elseStatement, env, targetVariableName, scope)\n }\n return []\n }\n\n if (!ts.isExpressionStatement(statement)) return []\n const expression = statement.expression\n if (!ts.isCallExpression(expression)) return []\n if (!ts.isPropertyAccessExpression(expression.expression)) return []\n const pushTarget = expression.expression.expression\n const pushMethod = expression.expression.name\n if (!ts.isIdentifier(pushTarget) || pushTarget.text !== targetVariableName) return []\n if (pushMethod.text !== 'push') return []\n\n return expression.arguments.flatMap((argument) => {\n if (!ts.isObjectLiteralExpression(argument)) return []\n const entry = parseModuleEntryFromObjectLiteral(argument)\n return entry ? [entry] : []\n })\n}\n\nfunction parseModulesFromSource(source: string, env: NodeJS.ProcessEnv = process.env): ModuleEntry[] {\n const sourceFile = ts.createSourceFile('modules.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const modules: ModuleEntry[] = []\n const variableName = 'enabledModules'\n const scope = new Map<string, unknown>()\n let foundDeclaration = false\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue\n if (declaration.name.text === variableName) {\n if (!declaration.initializer || !ts.isArrayLiteralExpression(declaration.initializer)) continue\n const fromArray = declaration.initializer.elements.flatMap((element) => {\n if (!ts.isObjectLiteralExpression(element)) return []\n const entry = parseModuleEntryFromObjectLiteral(element)\n return entry ? [entry] : []\n })\n modules.push(...fromArray)\n scope.set(variableName, [...modules])\n foundDeclaration = true\n continue\n }\n if (!declaration.initializer) continue\n scope.set(\n declaration.name.text,\n evaluateStaticExpressionWithScope(declaration.initializer, env, scope),\n )\n }\n continue\n }\n if (!foundDeclaration) continue\n const pushedEntries = collectPushEntriesFromStatement(statement, env, variableName, scope)\n if (pushedEntries.length > 0) {\n modules.push(...pushedEntries)\n scope.set(variableName, [...modules])\n }\n }\n\n return modules\n}\n\nfunction readEnabledModulesFromConfig(cfgPath: string): ModuleEntry[] {\n const source = fs.readFileSync(cfgPath, 'utf8')\n return parseModulesFromSource(source)\n}\n\nfunction loadEnabledModulesFromConfig(appDir: string): ModuleEntry[] {\n const cfgPath = path.resolve(appDir, 'src/modules.ts')\n if (fs.existsSync(cfgPath)) {\n try {\n const loadedModules = readEnabledModulesFromConfig(cfgPath)\n if (loadedModules.length > 0) return loadedModules\n } catch (error) {\n console.warn(\n '[resolver] Failed to read enabled modules from src/modules.ts, falling back to src/modules scan:',\n error,\n )\n }\n }\n // Fallback: scan src/modules/* to keep backward compatibility\n const modulesRoot = path.resolve(appDir, 'src/modules')\n if (!fs.existsSync(modulesRoot)) return []\n const scannedModules = fs\n .readdirSync(modulesRoot, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => ({ id: e.name, from: '@app' as const }))\n\n return scannedModules\n}\n\nfunction discoverPackagesInMonorepo(rootDir: string): PackageInfo[] {\n const packagesDir = path.join(rootDir, 'packages')\n if (!fs.existsSync(packagesDir)) return []\n\n const packages: PackageInfo[] = []\n const entries = fs.readdirSync(packagesDir, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const pkgPath = path.join(packagesDir, entry.name)\n const pkgJsonPath = path.join(pkgPath, 'package.json')\n\n if (!fs.existsSync(pkgJsonPath)) continue\n\n try {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))\n // Read from src/modules (TypeScript source)\n const modulesPath = path.join(pkgPath, 'src', 'modules')\n\n if (fs.existsSync(modulesPath)) {\n packages.push({\n name: pkgJson.name || `@open-mercato/${entry.name}`,\n path: pkgPath,\n modulesPath,\n })\n }\n } catch {\n // Skip invalid packages\n }\n }\n\n return packages\n}\n\nfunction discoverPackagesInNodeModules(rootDir: string): PackageInfo[] {\n const nodeModulesPath = path.join(rootDir, 'node_modules', '@open-mercato')\n if (!fs.existsSync(nodeModulesPath)) return []\n\n const packages: PackageInfo[] = []\n const entries = fs.readdirSync(nodeModulesPath, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const pkgPath = path.join(nodeModulesPath, entry.name)\n const pkgJsonPath = path.join(pkgPath, 'package.json')\n\n if (!fs.existsSync(pkgJsonPath)) continue\n\n try {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))\n const distModulesPath = path.join(pkgPath, 'dist', 'modules')\n const srcModulesPath = path.join(pkgPath, 'src', 'modules')\n const modulesPath = fs.existsSync(distModulesPath) ? distModulesPath : srcModulesPath\n\n if (fs.existsSync(modulesPath)) {\n packages.push({\n name: pkgJson.name || `@open-mercato/${entry.name}`,\n path: pkgPath,\n modulesPath,\n })\n }\n } catch {\n // Skip invalid packages\n }\n }\n\n return packages\n}\n\nfunction detectAppDir(rootDir: string, isMonorepo: boolean): string {\n if (!isMonorepo) {\n // Production mode: app is at root\n return rootDir\n }\n\n // Monorepo mode: look for app in apps/mercato/ or apps/app/\n const mercatoApp = path.join(rootDir, 'apps', 'mercato')\n if (fs.existsSync(mercatoApp)) {\n return mercatoApp\n }\n\n const defaultApp = path.join(rootDir, 'apps', 'app')\n if (fs.existsSync(defaultApp)) {\n return defaultApp\n }\n\n // Fallback: check if apps directory exists and has any app\n const appsDir = path.join(rootDir, 'apps')\n if (fs.existsSync(appsDir)) {\n const entries = fs.readdirSync(appsDir, { withFileTypes: true })\n const appEntry = entries.find(\n (e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'docs'\n )\n if (appEntry) {\n return path.join(appsDir, appEntry.name)\n }\n }\n\n // Final fallback for legacy structure: root is the app\n return rootDir\n}\n\nfunction findNodeModulesRoot(startDir: string): string | null {\n // Walk up to find node_modules/@open-mercato/core\n let dir = startDir\n while (dir !== path.dirname(dir)) {\n const corePkgPath = path.join(dir, 'node_modules', '@open-mercato', 'core')\n if (fs.existsSync(corePkgPath)) {\n return dir\n }\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction detectMonorepoFromNodeModules(appDir: string): { isMonorepo: boolean; monorepoRoot: string | null; nodeModulesRoot: string | null } {\n // Find where node_modules/@open-mercato/core is located (may be hoisted)\n const nodeModulesRoot = findNodeModulesRoot(appDir)\n if (!nodeModulesRoot) {\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot: null }\n }\n\n const corePkgPath = path.join(nodeModulesRoot, 'node_modules', '@open-mercato', 'core')\n\n try {\n const stat = fs.lstatSync(corePkgPath)\n if (stat.isSymbolicLink()) {\n // It's a symlink - we're in monorepo dev mode\n // Resolve the symlink to find the monorepo root\n const realPath = fs.realpathSync(corePkgPath)\n // realPath is something like /path/to/monorepo/packages/core\n // monorepo root is 2 levels up\n const monorepoRoot = path.dirname(path.dirname(realPath))\n return { isMonorepo: true, monorepoRoot, nodeModulesRoot }\n }\n // It's a real directory - production mode\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot }\n } catch {\n // Package doesn't exist yet or error reading - assume production mode\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot }\n }\n}\n\nexport function createResolver(cwd: string = process.cwd()): PackageResolver {\n // First detect if we're in a monorepo by checking if node_modules packages are symlinks\n const { isMonorepo: _isMonorepo, monorepoRoot, nodeModulesRoot } = detectMonorepoFromNodeModules(cwd)\n // In workspaces with hoisted real directories, package sources live under the discovered node_modules root.\n const rootDir = monorepoRoot ?? nodeModulesRoot ?? cwd\n\n // shouldResolveAppFromRoot: true when we have a workspace/install root that differs from cwd\n // (monorepo symlinks detected, or node_modules root found above cwd)\n const shouldResolveAppFromRoot =\n _isMonorepo || (nodeModulesRoot !== null && path.resolve(nodeModulesRoot) !== path.resolve(cwd))\n\n // The app directory depends on context:\n // - In monorepo: use detectAppDir to find apps/mercato or similar\n // - When symlinks not detected (e.g. Docker volume node_modules): still use apps/mercato if present at rootDir\n // - Otherwise: app is at cwd\n const candidateAppDir = shouldResolveAppFromRoot ? detectAppDir(rootDir, true) : rootDir\n const appDir =\n _isMonorepo\n ? candidateAppDir\n : shouldResolveAppFromRoot && candidateAppDir !== rootDir && fs.existsSync(candidateAppDir)\n ? candidateAppDir\n : cwd\n\n return {\n isMonorepo: () => _isMonorepo,\n\n getRootDir: () => rootDir,\n\n getAppDir: () => appDir,\n\n getOutputDir: () => {\n // Output is ALWAYS .mercato/generated relative to app directory\n return path.join(appDir, '.mercato', 'generated')\n },\n\n getModulesConfigPath: () => path.join(appDir, 'src', 'modules.ts'),\n\n discoverPackages: () => {\n return _isMonorepo\n ? discoverPackagesInMonorepo(rootDir)\n : discoverPackagesInNodeModules(rootDir)\n },\n\n loadEnabledModules: () => loadEnabledModulesFromConfig(appDir),\n\n getModulePaths: (entry: ModuleEntry) => {\n const appBase = path.resolve(appDir, 'src/modules', entry.id)\n const pkgModulesRoot = pkgDirFor(rootDir, entry.from, _isMonorepo)\n const pkgBase = path.join(pkgModulesRoot, entry.id)\n return { appBase, pkgBase }\n },\n\n getModuleImportBase: (entry: ModuleEntry) => {\n // Prefer @app overrides at import-time; fall back to provided package alias\n const from = entry.from || '@open-mercato/core'\n return {\n appBase: `@/modules/${entry.id}`,\n pkgBase: `${from}/modules/${entry.id}`,\n }\n },\n\n getPackageOutputDir: (packageName: string) => {\n if (packageName === '@app') {\n // App output goes to .mercato/generated\n return path.join(appDir, '.mercato', 'generated')\n }\n const pkgRoot = pkgRootFor(rootDir, packageName, _isMonorepo)\n return path.join(pkgRoot, 'generated')\n },\n\n getPackageRoot: (from?: string) => {\n return pkgRootFor(rootDir, from, _isMonorepo)\n },\n }\n}\n\n/**\n * Resolve the CLI execution environment as a plain value-object.\n * Call once at subsystem init; use the returned object for all path decisions.\n */\nexport function resolveEnvironment(cwd: string = process.cwd()): CliEnvironment {\n const resolver = createResolver(cwd)\n const _isMonorepo = resolver.isMonorepo()\n const rootDir = resolver.getRootDir()\n const appDir = resolver.getAppDir()\n return {\n mode: _isMonorepo ? 'monorepo' : 'standalone',\n rootDir,\n appDir,\n packageRoot: (packageName: string) => pkgRootFor(rootDir, packageName, _isMonorepo),\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport ts from 'typescript-js'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\n\n/**\n * Resolved execution environment for the CLI.\n * Produced once by resolveEnvironment() and consumed by all subsystems.\n * Eliminates per-subsystem isMonorepo() branching and hardcoded path segments.\n */\nexport type CliEnvironment = {\n /** Whether the CLI is running inside a Yarn/npm workspace monorepo. */\n mode: 'monorepo' | 'standalone'\n /** Workspace or project root (where package.json / node_modules live). */\n rootDir: string\n /** Next.js application directory (contains src/, package.json, next.config.*). */\n appDir: string\n /**\n * Resolve the root directory of an installed @open-mercato package.\n * Monorepo: packages/<pkg>/ Standalone: node_modules/<pkg>/\n */\n packageRoot: (packageName: string) => string\n}\n\nexport type ModuleEntry = {\n id: string\n from?: '@open-mercato/core' | '@app' | string\n}\n\nexport type PackageInfo = {\n name: string\n version?: string | null\n path: string\n modulesPath: string\n}\n\nexport interface PackageResolver {\n isMonorepo(): boolean\n getRootDir(): string\n getAppDir(): string\n getOutputDir(): string\n getModulesConfigPath(): string\n discoverPackages(): PackageInfo[]\n loadEnabledModules(): ModuleEntry[]\n getModulePaths(entry: ModuleEntry): { appBase: string; pkgBase: string }\n getModuleImportBase(entry: ModuleEntry): { appBase: string; pkgBase: string }\n getPackageOutputDir(packageName: string): string\n getPackageRoot(from?: string): string\n}\n\nfunction pkgDirFor(rootDir: string, from?: string, isMonorepo = true): string {\n if (!isMonorepo) {\n const pkgName = from || '@open-mercato/core'\n const pkgRoot = path.join(rootDir, 'node_modules', pkgName)\n const distModules = path.join(pkgRoot, 'dist', 'modules')\n if (fs.existsSync(distModules)) return distModules\n return path.join(pkgRoot, 'src', 'modules')\n }\n\n // Monorepo mode - read from src/modules (TypeScript source)\n if (!from || from === '@open-mercato/core') {\n return path.resolve(rootDir, 'packages/core/src/modules')\n }\n // Support other local packages like '@open-mercato/onboarding' => packages/onboarding/src/modules\n const m = from.match(/^@open-mercato\\/(.+)$/)\n if (m) {\n return path.resolve(rootDir, `packages/${m[1]}/src/modules`)\n }\n // Fallback to core modules path\n return path.resolve(rootDir, 'packages/core/src/modules')\n}\n\nfunction pkgRootFor(rootDir: string, from?: string, isMonorepo = true): string {\n if (!isMonorepo) {\n const pkgName = from || '@open-mercato/core'\n return path.join(rootDir, 'node_modules', pkgName)\n }\n\n if (!from || from === '@open-mercato/core') {\n return path.resolve(rootDir, 'packages/core')\n }\n const m = from.match(/^@open-mercato\\/(.+)$/)\n if (m) {\n return path.resolve(rootDir, `packages/${m[1]}`)\n }\n return path.resolve(rootDir, 'packages/core')\n}\n\nfunction parseModuleEntryFromObjectLiteral(node: ts.ObjectLiteralExpression): ModuleEntry | null {\n let id: string | null = null\n let from: string | null = null\n for (const property of node.properties) {\n if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) continue\n const key = property.name.text\n if (key === 'id' && ts.isStringLiteralLike(property.initializer)) {\n id = property.initializer.text\n }\n if (key === 'from' && ts.isStringLiteralLike(property.initializer)) {\n from = property.initializer.text\n }\n }\n if (!id) return null\n return { id, from: from ?? '@open-mercato/core' }\n}\n\nfunction parseProcessEnvAccess(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n): { matched: boolean; value: string | undefined } {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.name)) {\n const target = node.expression\n if (\n ts.isPropertyAccessExpression(target)\n && ts.isIdentifier(target.expression)\n && target.expression.text === 'process'\n && target.name.text === 'env'\n ) {\n return { matched: true, value: env[node.name.text] }\n }\n }\n if (\n ts.isElementAccessExpression(node)\n && ts.isPropertyAccessExpression(node.expression)\n && ts.isIdentifier(node.expression.expression)\n && node.expression.expression.text === 'process'\n && node.expression.name.text === 'env'\n && ts.isStringLiteralLike(node.argumentExpression)\n ) {\n return { matched: true, value: env[node.argumentExpression.text] }\n }\n return { matched: false, value: undefined }\n}\n\nfunction evaluateStaticExpression(node: ts.Expression, env: NodeJS.ProcessEnv): unknown {\n return evaluateStaticExpressionWithScope(node, env, new Map())\n}\n\nfunction evaluateStaticExpressionWithScope(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n scope: Map<string, unknown>,\n): unknown {\n if (ts.isParenthesizedExpression(node)) return evaluateStaticExpressionWithScope(node.expression, env, scope)\n if (ts.isIdentifier(node)) {\n return scope.get(node.text)\n }\n if (ts.isStringLiteralLike(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text\n if (ts.isNumericLiteral(node)) return Number(node.text)\n if (node.kind === ts.SyntaxKind.TrueKeyword) return true\n if (node.kind === ts.SyntaxKind.FalseKeyword) return false\n if (node.kind === ts.SyntaxKind.NullKeyword) return null\n\n const envAccess = parseProcessEnvAccess(node, env)\n if (envAccess.matched) return envAccess.value\n\n if (ts.isPropertyAccessExpression(node)) {\n const target = evaluateStaticExpressionWithScope(node.expression, env, scope)\n if (target && typeof target === 'object' && node.name.text in target) {\n return (target as Record<string, unknown>)[node.name.text]\n }\n return undefined\n }\n\n if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken) {\n return !Boolean(evaluateStaticExpressionWithScope(node.operand, env, scope))\n }\n\n if (ts.isBinaryExpression(node)) {\n if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {\n return Boolean(evaluateStaticExpressionWithScope(node.left, env, scope))\n && Boolean(evaluateStaticExpressionWithScope(node.right, env, scope))\n }\n if (node.operatorToken.kind === ts.SyntaxKind.BarBarToken) {\n return Boolean(evaluateStaticExpressionWithScope(node.left, env, scope))\n || Boolean(evaluateStaticExpressionWithScope(node.right, env, scope))\n }\n if (node.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken) {\n return evaluateStaticExpressionWithScope(node.left, env, scope) === evaluateStaticExpressionWithScope(node.right, env, scope)\n }\n if (node.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken) {\n return evaluateStaticExpressionWithScope(node.left, env, scope) !== evaluateStaticExpressionWithScope(node.right, env, scope)\n }\n }\n\n if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'parseBooleanWithDefault') {\n const rawValueNode = node.arguments[0]\n const fallbackNode = node.arguments[1]\n const rawValue = rawValueNode ? evaluateStaticExpressionWithScope(rawValueNode, env, scope) : undefined\n const fallbackValue = fallbackNode ? evaluateStaticExpressionWithScope(fallbackNode, env, scope) : false\n return parseBooleanWithDefault(typeof rawValue === 'string' ? rawValue : undefined, Boolean(fallbackValue))\n }\n\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === 'some') {\n const target = evaluateStaticExpressionWithScope(node.expression.expression, env, scope)\n const predicate = node.arguments[0]\n if (!Array.isArray(target) || !predicate) return undefined\n\n return target.some((entry) => {\n if (!ts.isArrowFunction(predicate) && !ts.isFunctionExpression(predicate)) return false\n\n const localScope = new Map(scope)\n const parameter = predicate.parameters[0]\n if (parameter && ts.isIdentifier(parameter.name)) {\n localScope.set(parameter.name.text, entry)\n }\n\n if (ts.isBlock(predicate.body)) {\n const returnStatement = predicate.body.statements.find((statement): statement is ts.ReturnStatement =>\n ts.isReturnStatement(statement),\n )\n if (!returnStatement?.expression) return false\n return Boolean(evaluateStaticExpressionWithScope(returnStatement.expression, env, localScope))\n }\n\n return Boolean(evaluateStaticExpressionWithScope(predicate.body, env, localScope))\n })\n }\n\n return undefined\n}\n\nfunction evaluateStaticCondition(\n node: ts.Expression,\n env: NodeJS.ProcessEnv,\n scope: Map<string, unknown>,\n): boolean {\n const evaluated = evaluateStaticExpressionWithScope(node, env, scope)\n return Boolean(evaluated)\n}\n\nfunction collectPushEntriesFromStatement(\n statement: ts.Statement,\n env: NodeJS.ProcessEnv,\n targetVariableName: string,\n scope: Map<string, unknown>,\n): ModuleEntry[] {\n if (ts.isBlock(statement)) {\n return statement.statements.flatMap((child) => collectPushEntriesFromStatement(child, env, targetVariableName, scope))\n }\n\n if (ts.isIfStatement(statement)) {\n if (evaluateStaticCondition(statement.expression, env, scope)) {\n return collectPushEntriesFromStatement(statement.thenStatement, env, targetVariableName, scope)\n }\n if (statement.elseStatement) {\n return collectPushEntriesFromStatement(statement.elseStatement, env, targetVariableName, scope)\n }\n return []\n }\n\n if (!ts.isExpressionStatement(statement)) return []\n const expression = statement.expression\n if (!ts.isCallExpression(expression)) return []\n if (!ts.isPropertyAccessExpression(expression.expression)) return []\n const pushTarget = expression.expression.expression\n const pushMethod = expression.expression.name\n if (!ts.isIdentifier(pushTarget) || pushTarget.text !== targetVariableName) return []\n if (pushMethod.text !== 'push') return []\n\n return expression.arguments.flatMap((argument) => {\n if (!ts.isObjectLiteralExpression(argument)) return []\n const entry = parseModuleEntryFromObjectLiteral(argument)\n return entry ? [entry] : []\n })\n}\n\nfunction parseModulesFromSource(source: string, env: NodeJS.ProcessEnv = process.env): ModuleEntry[] {\n const sourceFile = ts.createSourceFile('modules.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const modules: ModuleEntry[] = []\n const variableName = 'enabledModules'\n const scope = new Map<string, unknown>()\n let foundDeclaration = false\n\n for (const statement of sourceFile.statements) {\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue\n if (declaration.name.text === variableName) {\n if (!declaration.initializer || !ts.isArrayLiteralExpression(declaration.initializer)) continue\n const fromArray = declaration.initializer.elements.flatMap((element) => {\n if (!ts.isObjectLiteralExpression(element)) return []\n const entry = parseModuleEntryFromObjectLiteral(element)\n return entry ? [entry] : []\n })\n modules.push(...fromArray)\n scope.set(variableName, [...modules])\n foundDeclaration = true\n continue\n }\n if (!declaration.initializer) continue\n scope.set(\n declaration.name.text,\n evaluateStaticExpressionWithScope(declaration.initializer, env, scope),\n )\n }\n continue\n }\n if (!foundDeclaration) continue\n const pushedEntries = collectPushEntriesFromStatement(statement, env, variableName, scope)\n if (pushedEntries.length > 0) {\n modules.push(...pushedEntries)\n scope.set(variableName, [...modules])\n }\n }\n\n return modules\n}\n\nfunction readEnabledModulesFromConfig(cfgPath: string): ModuleEntry[] {\n const source = fs.readFileSync(cfgPath, 'utf8')\n return parseModulesFromSource(source)\n}\n\nfunction loadEnabledModulesFromConfig(appDir: string): ModuleEntry[] {\n const cfgPath = path.resolve(appDir, 'src/modules.ts')\n if (fs.existsSync(cfgPath)) {\n try {\n const loadedModules = readEnabledModulesFromConfig(cfgPath)\n if (loadedModules.length > 0) return loadedModules\n } catch (error) {\n console.warn(\n '[resolver] Failed to read enabled modules from src/modules.ts, falling back to src/modules scan:',\n error,\n )\n }\n }\n // Fallback: scan src/modules/* to keep backward compatibility\n const modulesRoot = path.resolve(appDir, 'src/modules')\n if (!fs.existsSync(modulesRoot)) return []\n const scannedModules = fs\n .readdirSync(modulesRoot, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !e.name.startsWith('.'))\n .map((e) => ({ id: e.name, from: '@app' as const }))\n\n return scannedModules\n}\n\nfunction discoverPackagesInMonorepo(rootDir: string): PackageInfo[] {\n const packagesDir = path.join(rootDir, 'packages')\n if (!fs.existsSync(packagesDir)) return []\n\n const packages: PackageInfo[] = []\n const entries = fs.readdirSync(packagesDir, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const pkgPath = path.join(packagesDir, entry.name)\n const pkgJsonPath = path.join(pkgPath, 'package.json')\n\n if (!fs.existsSync(pkgJsonPath)) continue\n\n try {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))\n // Read from src/modules (TypeScript source)\n const modulesPath = path.join(pkgPath, 'src', 'modules')\n\n if (fs.existsSync(modulesPath)) {\n packages.push({\n name: pkgJson.name || `@open-mercato/${entry.name}`,\n version: typeof pkgJson.version === 'string' ? pkgJson.version : null,\n path: pkgPath,\n modulesPath,\n })\n }\n } catch {\n // Skip invalid packages\n }\n }\n\n return packages\n}\n\nfunction discoverPackagesInNodeModules(rootDir: string): PackageInfo[] {\n const nodeModulesPath = path.join(rootDir, 'node_modules', '@open-mercato')\n if (!fs.existsSync(nodeModulesPath)) return []\n\n const packages: PackageInfo[] = []\n const entries = fs.readdirSync(nodeModulesPath, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const pkgPath = path.join(nodeModulesPath, entry.name)\n const pkgJsonPath = path.join(pkgPath, 'package.json')\n\n if (!fs.existsSync(pkgJsonPath)) continue\n\n try {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))\n const distModulesPath = path.join(pkgPath, 'dist', 'modules')\n const srcModulesPath = path.join(pkgPath, 'src', 'modules')\n const modulesPath = fs.existsSync(distModulesPath) ? distModulesPath : srcModulesPath\n\n if (fs.existsSync(modulesPath)) {\n packages.push({\n name: pkgJson.name || `@open-mercato/${entry.name}`,\n version: typeof pkgJson.version === 'string' ? pkgJson.version : null,\n path: pkgPath,\n modulesPath,\n })\n }\n } catch {\n // Skip invalid packages\n }\n }\n\n return packages\n}\n\nfunction detectAppDir(rootDir: string, isMonorepo: boolean): string {\n if (!isMonorepo) {\n // Production mode: app is at root\n return rootDir\n }\n\n // Monorepo mode: look for app in apps/mercato/ or apps/app/\n const mercatoApp = path.join(rootDir, 'apps', 'mercato')\n if (fs.existsSync(mercatoApp)) {\n return mercatoApp\n }\n\n const defaultApp = path.join(rootDir, 'apps', 'app')\n if (fs.existsSync(defaultApp)) {\n return defaultApp\n }\n\n // Fallback: check if apps directory exists and has any app\n const appsDir = path.join(rootDir, 'apps')\n if (fs.existsSync(appsDir)) {\n const entries = fs.readdirSync(appsDir, { withFileTypes: true })\n const appEntry = entries.find(\n (e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'docs'\n )\n if (appEntry) {\n return path.join(appsDir, appEntry.name)\n }\n }\n\n // Final fallback for legacy structure: root is the app\n return rootDir\n}\n\nfunction findNodeModulesRoot(startDir: string): string | null {\n // Walk up to find node_modules/@open-mercato/core\n let dir = startDir\n while (dir !== path.dirname(dir)) {\n const corePkgPath = path.join(dir, 'node_modules', '@open-mercato', 'core')\n if (fs.existsSync(corePkgPath)) {\n return dir\n }\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction detectMonorepoFromNodeModules(appDir: string): { isMonorepo: boolean; monorepoRoot: string | null; nodeModulesRoot: string | null } {\n // Find where node_modules/@open-mercato/core is located (may be hoisted)\n const nodeModulesRoot = findNodeModulesRoot(appDir)\n if (!nodeModulesRoot) {\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot: null }\n }\n\n const corePkgPath = path.join(nodeModulesRoot, 'node_modules', '@open-mercato', 'core')\n\n try {\n const stat = fs.lstatSync(corePkgPath)\n if (stat.isSymbolicLink()) {\n // It's a symlink - we're in monorepo dev mode\n // Resolve the symlink to find the monorepo root\n const realPath = fs.realpathSync(corePkgPath)\n // realPath is something like /path/to/monorepo/packages/core\n // monorepo root is 2 levels up\n const monorepoRoot = path.dirname(path.dirname(realPath))\n return { isMonorepo: true, monorepoRoot, nodeModulesRoot }\n }\n // It's a real directory - production mode\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot }\n } catch {\n // Package doesn't exist yet or error reading - assume production mode\n return { isMonorepo: false, monorepoRoot: null, nodeModulesRoot }\n }\n}\n\nexport function createResolver(cwd: string = process.cwd()): PackageResolver {\n // First detect if we're in a monorepo by checking if node_modules packages are symlinks\n const { isMonorepo: _isMonorepo, monorepoRoot, nodeModulesRoot } = detectMonorepoFromNodeModules(cwd)\n // In workspaces with hoisted real directories, package sources live under the discovered node_modules root.\n const rootDir = monorepoRoot ?? nodeModulesRoot ?? cwd\n\n // shouldResolveAppFromRoot: true when we have a workspace/install root that differs from cwd\n // (monorepo symlinks detected, or node_modules root found above cwd)\n const shouldResolveAppFromRoot =\n _isMonorepo || (nodeModulesRoot !== null && path.resolve(nodeModulesRoot) !== path.resolve(cwd))\n\n // The app directory depends on context:\n // - In monorepo: use detectAppDir to find apps/mercato or similar\n // - When symlinks not detected (e.g. Docker volume node_modules): still use apps/mercato if present at rootDir\n // - Otherwise: app is at cwd\n const candidateAppDir = shouldResolveAppFromRoot ? detectAppDir(rootDir, true) : rootDir\n const appDir =\n _isMonorepo\n ? candidateAppDir\n : shouldResolveAppFromRoot && candidateAppDir !== rootDir && fs.existsSync(candidateAppDir)\n ? candidateAppDir\n : cwd\n\n return {\n isMonorepo: () => _isMonorepo,\n\n getRootDir: () => rootDir,\n\n getAppDir: () => appDir,\n\n getOutputDir: () => {\n // Output is ALWAYS .mercato/generated relative to app directory\n return path.join(appDir, '.mercato', 'generated')\n },\n\n getModulesConfigPath: () => path.join(appDir, 'src', 'modules.ts'),\n\n discoverPackages: () => {\n return _isMonorepo\n ? discoverPackagesInMonorepo(rootDir)\n : discoverPackagesInNodeModules(rootDir)\n },\n\n loadEnabledModules: () => loadEnabledModulesFromConfig(appDir),\n\n getModulePaths: (entry: ModuleEntry) => {\n const appBase = path.resolve(appDir, 'src/modules', entry.id)\n const pkgModulesRoot = pkgDirFor(rootDir, entry.from, _isMonorepo)\n const pkgBase = path.join(pkgModulesRoot, entry.id)\n return { appBase, pkgBase }\n },\n\n getModuleImportBase: (entry: ModuleEntry) => {\n // Prefer @app overrides at import-time; fall back to provided package alias\n const from = entry.from || '@open-mercato/core'\n return {\n appBase: `@/modules/${entry.id}`,\n pkgBase: `${from}/modules/${entry.id}`,\n }\n },\n\n getPackageOutputDir: (packageName: string) => {\n if (packageName === '@app') {\n // App output goes to .mercato/generated\n return path.join(appDir, '.mercato', 'generated')\n }\n const pkgRoot = pkgRootFor(rootDir, packageName, _isMonorepo)\n return path.join(pkgRoot, 'generated')\n },\n\n getPackageRoot: (from?: string) => {\n return pkgRootFor(rootDir, from, _isMonorepo)\n },\n }\n}\n\n/**\n * Resolve the CLI execution environment as a plain value-object.\n * Call once at subsystem init; use the returned object for all path decisions.\n */\nexport function resolveEnvironment(cwd: string = process.cwd()): CliEnvironment {\n const resolver = createResolver(cwd)\n const _isMonorepo = resolver.isMonorepo()\n const rootDir = resolver.getRootDir()\n const appDir = resolver.getAppDir()\n return {\n mode: _isMonorepo ? 'monorepo' : 'standalone',\n rootDir,\n appDir,\n packageRoot: (packageName: string) => pkgRootFor(rootDir, packageName, _isMonorepo),\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.6.7-develop.6685.1.77c0a5591b",
3
+ "version": "0.6.7-develop.6687.1.46a258e592",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,8 +60,8 @@
60
60
  "@mikro-orm/decorators": "^7.1.5",
61
61
  "@mikro-orm/migrations": "^7.1.5",
62
62
  "@mikro-orm/postgresql": "^7.1.5",
63
- "@open-mercato/queue": "0.6.7-develop.6685.1.77c0a5591b",
64
- "@open-mercato/shared": "0.6.7-develop.6685.1.77c0a5591b",
63
+ "@open-mercato/queue": "0.6.7-develop.6687.1.46a258e592",
64
+ "@open-mercato/shared": "0.6.7-develop.6687.1.46a258e592",
65
65
  "cross-spawn": "^7.0.6",
66
66
  "pg": "8.22.0",
67
67
  "semver": "^7.8.5",
@@ -72,10 +72,10 @@
72
72
  "typescript-js": "npm:typescript@6.0.3"
73
73
  },
74
74
  "peerDependencies": {
75
- "@open-mercato/shared": "0.6.7-develop.6685.1.77c0a5591b"
75
+ "@open-mercato/shared": "0.6.7-develop.6687.1.46a258e592"
76
76
  },
77
77
  "devDependencies": {
78
- "@open-mercato/shared": "0.6.7-develop.6685.1.77c0a5591b",
78
+ "@open-mercato/shared": "0.6.7-develop.6687.1.46a258e592",
79
79
  "@types/jest": "^30.0.0",
80
80
  "jest": "^30.4.2",
81
81
  "ts-jest": "^29.4.11"
@@ -14,6 +14,8 @@ const cliIntegrationRunnerPath = path.join(cliDir, 'src', 'lib', 'testing', 'int
14
14
  const standaloneTemplatePackageJsonPath = path.join(repoRoot, 'packages', 'create-app', 'template', 'package.json.template')
15
15
  const agenticRoot = path.join(repoRoot, 'packages', 'create-app', 'agentic')
16
16
  const packagesRoot = path.join(repoRoot, 'packages')
17
+ const coreVersion = JSON.parse(fs.readFileSync(path.join(packagesRoot, 'core', 'package.json'), 'utf8')).version as string
18
+ const UNROUTED_PACKAGE_GUIDES = new Set(['cache', 'core', 'events', 'queue', 'search', 'shared', 'ui'])
17
19
 
18
20
  // Modules the standalone fixture enables in src/modules.ts. Both are on the
19
21
  // fact-sheet allowlist, so agentic:init must ship exactly their fact-sheets
@@ -24,7 +26,7 @@ function normalizePath(value: string): string {
24
26
  return value.split(path.sep).join('/')
25
27
  }
26
28
 
27
- function runCommand(command: string, args: string[], cwd: string): string {
29
+ function runCommand(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv = {}): string {
28
30
  return execFileSync(command, args, {
29
31
  cwd,
30
32
  encoding: 'utf8',
@@ -36,6 +38,7 @@ function runCommand(command: string, args: string[], cwd: string): string {
36
38
  // whose external step (`npx skills add`) needs the network. Local tier
37
39
  // symlinks are still installed.
38
40
  OM_SKIP_EXTERNAL_SKILLS: '1',
41
+ ...env,
39
42
  },
40
43
  })
41
44
  }
@@ -61,16 +64,48 @@ function createStandaloneFixture(rootDir: string): string {
61
64
  {
62
65
  name: 'sample-store',
63
66
  private: true,
67
+ dependencies: { '@open-mercato/core': coreVersion },
64
68
  },
65
69
  null,
66
70
  2,
67
71
  ),
68
72
  )
69
- const moduleEntries = FIXTURE_ENABLED_MODULES.map((moduleId) => ` { id: '${moduleId}' },`).join('\n')
73
+ const moduleEntries = FIXTURE_ENABLED_MODULES
74
+ .map((moduleId) => ` { id: '${moduleId}', from: '@open-mercato/core' },`)
75
+ .join('\n')
70
76
  writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [\n${moduleEntries}\n]\n`)
71
77
  return appDir
72
78
  }
73
79
 
80
+ function installFakeFrameworkPackage(appDir: string): string {
81
+ const packageRoot = path.join(appDir, 'node_modules', '@open-mercato', 'core')
82
+ writeFile(path.join(packageRoot, 'package.json'), JSON.stringify({
83
+ name: '@open-mercato/core',
84
+ version: coreVersion,
85
+ type: 'module',
86
+ exports: { '.': './dist/index.js' },
87
+ }))
88
+ writeFile(path.join(packageRoot, 'dist', 'index.js'), 'export {}\n')
89
+ writeFile(path.join(packageRoot, 'AGENTS.md'), '# Installed core instructions\n')
90
+ for (const moduleId of FIXTURE_ENABLED_MODULES) {
91
+ writeFile(path.join(packageRoot, 'src', 'modules', moduleId, 'AGENTS.md'), `# Installed ${moduleId} instructions\n`)
92
+ writeFile(
93
+ path.join(packageRoot, 'src', 'modules', moduleId, 'data', 'entities.ts'),
94
+ `export class ${moduleId === 'customers' ? 'Person' : 'Sale'} {}\n`,
95
+ )
96
+ }
97
+ return packageRoot
98
+ }
99
+
100
+ function snapshotTextFiles(rootDir: string): Record<string, string> {
101
+ return Object.fromEntries(
102
+ listRelativeFiles(rootDir).map((relativePath) => [
103
+ relativePath,
104
+ fs.readFileSync(path.join(rootDir, relativePath), 'utf8'),
105
+ ]),
106
+ )
107
+ }
108
+
74
109
  function listRelativeFiles(rootDir: string): string[] {
75
110
  if (!fs.existsSync(rootDir)) {
76
111
  return []
@@ -194,7 +229,7 @@ function expectedGuideOutputNames(): string[] {
194
229
 
195
230
  for (const packageName of fs.readdirSync(packagesRoot)) {
196
231
  const packageGuide = path.join(packagesRoot, packageName, 'agentic', 'standalone-guide.md')
197
- if (fs.existsSync(packageGuide)) {
232
+ if (fs.existsSync(packageGuide) && !UNROUTED_PACKAGE_GUIDES.has(packageName)) {
198
233
  collected.add(`${packageName}.md`)
199
234
  }
200
235
 
@@ -216,6 +251,9 @@ function expectedGuideOutputNames(): string[] {
216
251
  // fixture's enabled modules. The legacy core.<module>.md redirect stubs are no longer
217
252
  // emitted (#3754).
218
253
  collected.add('module-facts.json')
254
+ collected.add('upstream/AGENTS.md')
255
+ collected.add('upstream/BACKWARD_COMPATIBILITY.md')
256
+ collected.add('upstream/manifest.json')
219
257
  for (const moduleId of FIXTURE_ENABLED_MODULES) {
220
258
  collected.add(normalizePath(path.join('modules', `${moduleId}.md`)))
221
259
  }
@@ -262,14 +300,17 @@ test.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding asset
262
300
 
263
301
  const agentsSource = fs.readFileSync(path.join(appDir, 'AGENTS.md'), 'utf8')
264
302
  expect(agentsSource).toContain('<!-- CODEX_ENFORCEMENT_RULES_START -->')
265
- expect(agentsSource).toContain('.ai/guides/core.md')
303
+ expect(agentsSource).toContain('.ai/guides/upstream/BACKWARD_COMPATIBILITY.md')
266
304
 
267
- // The Module-Specific Guides marker block lists exactly the enabled modules'
268
- // fact-sheets (enabled ∩ allowlist), not the full bundled set.
305
+ // The Module-Specific Guides marker block is a compact enabled-module ID
306
+ // index (enabled ∩ bundled) plus one progressively loaded path pattern.
269
307
  for (const moduleId of FIXTURE_ENABLED_MODULES) {
270
- expect(agentsSource).toContain(`.ai/guides/modules/${moduleId}.md`)
308
+ expect(agentsSource).toContain(`\`${moduleId}\``)
271
309
  }
272
- expect(agentsSource).not.toContain('.ai/guides/modules/auth.md')
310
+ expect(agentsSource).toContain('`.ai/guides/modules/<id>.md`')
311
+ expect(agentsSource.match(/\.ai\/guides\/modules\//g)).toHaveLength(1)
312
+ expect(agentsSource).not.toContain('`auth`')
313
+ expect(agentsSource).not.toContain('Core CRM capabilities')
273
314
 
274
315
  const specsReadmeSource = fs.readFileSync(path.join(appDir, '.ai', 'specs', 'README.md'), 'utf8')
275
316
  expect(specsReadmeSource).toContain('sample-store')
@@ -308,4 +349,58 @@ test.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding asset
308
349
  fs.rmSync(tempRoot, { recursive: true, force: true })
309
350
  }
310
351
  })
352
+
353
+ test('emits a runnable exact-version framework context escape hatch for an installed package', () => {
354
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-framework-context-'))
355
+
356
+ try {
357
+ const appDir = createStandaloneFixture(tempRoot)
358
+ const packageRoot = installFakeFrameworkPackage(appDir)
359
+ const resolvedPackageRoot = fs.realpathSync(packageRoot)
360
+ const packageBefore = snapshotTextFiles(packageRoot)
361
+
362
+ runMercato(['agentic:init', '--tool=codex'], appDir)
363
+ const generatedScript = path.join(appDir, 'scripts', 'framework-context.mjs')
364
+ expect(fs.existsSync(generatedScript)).toBe(true)
365
+
366
+ const output = runCommand(
367
+ process.execPath,
368
+ [generatedScript, '--module', 'customers', '--query', 'Person', '--json'],
369
+ appDir,
370
+ // The generated standalone helper must not depend on a globally
371
+ // installed ripgrep binary; process.execPath is already absolute.
372
+ { PATH: '', Path: '' },
373
+ )
374
+ const context = JSON.parse(output) as {
375
+ module: string
376
+ package: { name: string; version: string; root: string }
377
+ sourceKind: string
378
+ sourceRoot: string
379
+ materializedSource: string
380
+ instructions: Array<{ kind: string; path: string | null; materializedPath?: string }>
381
+ boundedSearch: { status: string; matches: number; maxMatches: number; result: string }
382
+ warnings: string[]
383
+ }
384
+
385
+ expect(context.module).toBe('customers')
386
+ expect(context.package).toEqual({ name: '@open-mercato/core', version: coreVersion, root: resolvedPackageRoot })
387
+ expect(context.sourceKind).toBe('source')
388
+ expect(normalizePath(context.sourceRoot)).toBe(normalizePath(path.join(resolvedPackageRoot, 'src', 'modules', 'customers')))
389
+ expect(context.instructions.filter((entry) => entry.path).map((entry) => entry.kind)).toEqual([
390
+ 'standalone-root',
391
+ 'upstream-bc',
392
+ 'package',
393
+ 'module-1',
394
+ 'upstream-root',
395
+ ])
396
+ expect(context.instructions.filter((entry) => entry.path).every((entry) => entry.materializedPath)).toBe(true)
397
+ expect(context.boundedSearch).toMatchObject({ status: 'matched', matches: 1, maxMatches: 200 })
398
+ expect(fs.existsSync(path.join(appDir, context.materializedSource))).toBe(true)
399
+ expect(fs.existsSync(path.join(appDir, context.boundedSearch.result))).toBe(true)
400
+ expect(context.warnings.some((warning) => warning.includes('Generated facts for customers are stale'))).toBe(false)
401
+ expect(snapshotTextFiles(packageRoot)).toEqual(packageBefore)
402
+ } finally {
403
+ fs.rmSync(tempRoot, { recursive: true, force: true })
404
+ }
405
+ })
311
406
  })
@@ -17,7 +17,11 @@ const loadRunAgenticInit = async ({
17
17
  }: {
18
18
  existingPaths: Set<string>
19
19
  questionAnswer?: string
20
- runAgenticSetupImplementation?: (targetDir: string, ask: (question: string) => Promise<string>, options?: { tool?: string; force?: boolean }) => Promise<void>
20
+ runAgenticSetupImplementation?: (
21
+ targetDir: string,
22
+ ask: (question: string) => Promise<string>,
23
+ options?: { tool?: string; force?: boolean; updateHarness?: boolean },
24
+ ) => Promise<void>
21
25
  }): Promise<AgenticInitTestContext> => {
22
26
  jest.resetModules()
23
27
 
@@ -136,6 +140,22 @@ describe('runAgenticInit', () => {
136
140
  expect(testContext.runAgenticSetup).not.toHaveBeenCalled()
137
141
  })
138
142
 
143
+ it('rejects force and ownership-aware update together before setup', async () => {
144
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
145
+ const testContext = await loadRunAgenticInit({
146
+ existingPaths: new Set<string>([appModulesPath]),
147
+ })
148
+
149
+ const exitCode = await testContext.runAgenticInit(['--force', '--update-harness'])
150
+
151
+ expect(exitCode).toBe(1)
152
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
153
+ '❌ --force and --update-harness are mutually exclusive',
154
+ )
155
+ expect(testContext.createInterface).not.toHaveBeenCalled()
156
+ expect(testContext.runAgenticSetup).not.toHaveBeenCalled()
157
+ })
158
+
139
159
  it('warns and exits early when relevant agentic files already exist without force', async () => {
140
160
  const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation()
141
161
  const testContext = await loadRunAgenticInit({
@@ -150,7 +170,7 @@ describe('runAgenticInit', () => {
150
170
  expect(consoleLogSpy.mock.calls.flat()).toEqual(expect.arrayContaining([
151
171
  '⚠️ Agentic files already exist:',
152
172
  ' • .codex/mcp.json.example',
153
- 'Run with --force to regenerate from current templates.',
173
+ 'Run with --update-harness to preserve local edits, or --force to replace generated files.',
154
174
  ]))
155
175
  })
156
176
 
@@ -160,7 +180,7 @@ describe('runAgenticInit', () => {
160
180
  questionAnswer: ' cursor ',
161
181
  runAgenticSetupImplementation: async (currentTargetDir, ask, options) => {
162
182
  expect(currentTargetDir).toBe(targetDir)
163
- expect(options).toEqual({ tool: undefined, force: undefined })
183
+ expect(options).toEqual({ tool: undefined, force: undefined, updateHarness: undefined })
164
184
  await expect(ask('Select a tool')).resolves.toBe('cursor')
165
185
  },
166
186
  })
@@ -188,7 +208,7 @@ describe('runAgenticInit', () => {
188
208
  expect(testContext.runAgenticSetup).toHaveBeenCalledWith(
189
209
  targetDir,
190
210
  expect.any(Function),
191
- { tool: 'codex', force: undefined },
211
+ { tool: 'codex', force: undefined, updateHarness: undefined },
192
212
  )
193
213
  expect(consoleLogSpy.mock.calls.flat()).not.toContain('⚠️ Agentic files already exist:')
194
214
  expect(testContext.closeInterface).toHaveBeenCalledTimes(1)
@@ -205,7 +225,23 @@ describe('runAgenticInit', () => {
205
225
  expect(testContext.runAgenticSetup).toHaveBeenCalledWith(
206
226
  targetDir,
207
227
  expect.any(Function),
208
- { tool: 'codex', force: true },
228
+ { tool: 'codex', force: true, updateHarness: undefined },
229
+ )
230
+ expect(testContext.closeInterface).toHaveBeenCalledTimes(1)
231
+ })
232
+
233
+ it('bypasses overwrite warnings and requests an ownership-aware update', async () => {
234
+ const testContext = await loadRunAgenticInit({
235
+ existingPaths: new Set<string>([appModulesPath, codexConfigPath]),
236
+ })
237
+
238
+ const exitCode = await testContext.runAgenticInit(['--tool=codex', '--update-harness'])
239
+
240
+ expect(exitCode).toBe(0)
241
+ expect(testContext.runAgenticSetup).toHaveBeenCalledWith(
242
+ targetDir,
243
+ expect.any(Function),
244
+ { tool: 'codex', force: undefined, updateHarness: true },
209
245
  )
210
246
  expect(testContext.closeInterface).toHaveBeenCalledTimes(1)
211
247
  })