@open-mercato/cli 0.6.8-develop.6969.1.7a32706312 → 0.6.8-develop.6972.1.275e435508

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 (84) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/agentic/claude-code/hooks/gate-evidence.ts +269 -0
  3. package/dist/agentic/claude-code/settings.json +21 -0
  4. package/dist/agentic/codex/hooks/gate-evidence.mjs +199 -0
  5. package/dist/agentic/codex/hooks.json +29 -0
  6. package/dist/agentic/cursor/hooks/gate-evidence.mjs +181 -0
  7. package/dist/agentic/cursor/hooks.json +10 -0
  8. package/dist/agentic/guides/module-facts.json +112 -112
  9. package/dist/agentic/guides/module-facts.v2.json +112 -112
  10. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  11. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  12. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  13. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  14. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  15. package/dist/agentic/guides/modules/auth/index.md +1 -1
  16. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  17. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  18. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  19. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  20. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  21. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  22. package/dist/agentic/guides/modules/configs/index.md +1 -1
  23. package/dist/agentic/guides/modules/content/index.md +1 -1
  24. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  25. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  26. package/dist/agentic/guides/modules/customers/index.md +1 -1
  27. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  28. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  29. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  30. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  31. package/dist/agentic/guides/modules/directory/index.md +1 -1
  32. package/dist/agentic/guides/modules/entities/index.md +1 -1
  33. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  34. package/dist/agentic/guides/modules/events/index.md +1 -1
  35. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  36. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  37. package/dist/agentic/guides/modules/generators/index.md +1 -1
  38. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  39. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  40. package/dist/agentic/guides/modules/messages/index.md +1 -1
  41. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  42. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  43. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  44. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  45. package/dist/agentic/guides/modules/planner/index.md +1 -1
  46. package/dist/agentic/guides/modules/portal/index.md +1 -1
  47. package/dist/agentic/guides/modules/progress/index.md +1 -1
  48. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  49. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  50. package/dist/agentic/guides/modules/resources/index.md +1 -1
  51. package/dist/agentic/guides/modules/sales/index.md +1 -1
  52. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  53. package/dist/agentic/guides/modules/search/index.md +1 -1
  54. package/dist/agentic/guides/modules/security/index.md +1 -1
  55. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  56. package/dist/agentic/guides/modules/sso/index.md +1 -1
  57. package/dist/agentic/guides/modules/staff/index.md +1 -1
  58. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  59. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  60. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  61. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  62. package/dist/agentic/guides/modules/translations/index.md +1 -1
  63. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  64. package/dist/agentic/guides/modules/wms/index.md +1 -1
  65. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  66. package/dist/agentic/guides/reference-module-facts.json +1 -1
  67. package/dist/agentic/guides/upstream/manifest.json +1 -1
  68. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +13 -0
  69. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +22 -0
  70. package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +20 -0
  71. package/dist/lib/agentic-setup.js +8 -2
  72. package/dist/lib/agentic-setup.js.map +2 -2
  73. package/dist/lib/generators/module-di.js +25 -1
  74. package/dist/lib/generators/module-di.js.map +2 -2
  75. package/dist/lib/generators/module-registry.js +61 -15
  76. package/dist/lib/generators/module-registry.js.map +2 -2
  77. package/dist/lib/generators/openapi.js +3 -1
  78. package/dist/lib/generators/openapi.js.map +2 -2
  79. package/package.json +6 -6
  80. package/src/lib/agentic-setup.ts +17 -2
  81. package/src/lib/generators/__tests__/silent-convention-warnings.test.ts +154 -0
  82. package/src/lib/generators/module-di.ts +35 -0
  83. package/src/lib/generators/module-registry.ts +93 -7
  84. package/src/lib/generators/openapi.ts +5 -1
@@ -1359,6 +1359,7 @@ function collectCommandLoaderEntries(
1359
1359
  roots: ModuleRoots,
1360
1360
  imps: ModuleImports,
1361
1361
  modId: string,
1362
+ quiet = false,
1362
1363
  ): CommandLoaderGenerationEntry[] {
1363
1364
  const files = scanModuleDir(roots, COMMAND_SCAN_CONFIG)
1364
1365
  const entries: CommandLoaderGenerationEntry[] = []
@@ -1369,11 +1370,13 @@ function collectCommandLoaderEntries(
1369
1370
  const logicalKey = stripModuleCodeExtension(file.relPath)
1370
1371
  const basename = path.basename(logicalKey)
1371
1372
  if (basename === 'shared' || basename === 'factory') continue
1373
+ const ids = extractCommandIdsFromSource(resolved.absolutePath)
1374
+ if (ids.length > 0) warnIfRegisterCommandNotAtImportTime(resolved.absolutePath, quiet)
1372
1375
  entries.push({
1373
1376
  moduleId: modId,
1374
1377
  key: `${modId}:commands:${logicalKey}`,
1375
1378
  importPath: resolved.importPath,
1376
- ids: extractCommandIdsFromSource(resolved.absolutePath),
1379
+ ids,
1377
1380
  })
1378
1381
  }
1379
1382
  return entries
@@ -1464,6 +1467,78 @@ function findExistingModuleFileByBaseNames(baseDir: string, relativeBaseNames: s
1464
1467
  return null
1465
1468
  }
1466
1469
 
1470
+ const warnedConventionPaths = new Set<string>()
1471
+
1472
+ /**
1473
+ * Clears the once-per-path warning ledger.
1474
+ *
1475
+ * A single `yarn generate` runs three registry emitters over one discovery, and each of them
1476
+ * walks the same frontend and backend page files, so an unguarded warning would print the
1477
+ * same line up to six times. A diagnostic that repeats is a diagnostic that gets skimmed
1478
+ * past, so each offending path is named once per run and the ledger resets when the run's
1479
+ * discovery is built.
1480
+ */
1481
+ export function resetConventionWarnings(): void {
1482
+ warnedConventionPaths.clear()
1483
+ }
1484
+
1485
+ function alreadyWarned(sourcePath: string): boolean {
1486
+ if (warnedConventionPaths.has(sourcePath)) return true
1487
+ warnedConventionPaths.add(sourcePath)
1488
+ return false
1489
+ }
1490
+
1491
+ /**
1492
+ * Warns when a discovered page metadata file exports no `metadata` binding.
1493
+ *
1494
+ * Both page-route emitters read `<module>.metadata` off the imported file. When the author
1495
+ * named the export something else — `meta` is the common near-miss — that read yields
1496
+ * `undefined`, the route still generates, and every declaration in the file is dropped.
1497
+ * `requireAuth` and `requireFeatures` are among them, so the page ships with no
1498
+ * authorization gate and nothing in the build says so. The warning names that consequence
1499
+ * because the rule alone ("export `metadata`") does not convey why it matters.
1500
+ */
1501
+ export function warnIfPageMetaMissingMetadataExport(metaPath: string | null, quiet = false): void {
1502
+ if (!metaPath || quiet) return
1503
+ if (hasNamedExport(metaPath, 'metadata')) return
1504
+ if (alreadyWarned(metaPath)) return
1505
+ console.warn(
1506
+ `[generate] ⚠ Page metadata file exports no 'metadata' — page metadata is dropped, `
1507
+ + `including requireAuth/requireFeatures, so the page renders with NO authorization gate: ${metaPath}`,
1508
+ )
1509
+ }
1510
+
1511
+ /**
1512
+ * Warns when a `commands/*.ts` file registers commands only from inside a function.
1513
+ *
1514
+ * Command discovery extracts ids statically and emits a lazy loader per file; the loader
1515
+ * resolves a command by importing that file and relying on `registerCommand(...)` running as
1516
+ * an import-time side effect. When every call sits inside a function body that nothing
1517
+ * invokes, the ids still appear in the generated manifest but the handlers never register,
1518
+ * so the command bus reports the command as unknown at runtime.
1519
+ *
1520
+ * Heuristic and deliberately conservative: it only fires when the file contains at least one
1521
+ * `registerCommand(` call and none of them is at top level (column 0), which is how every
1522
+ * correct module writes them.
1523
+ */
1524
+ export function warnIfRegisterCommandNotAtImportTime(sourcePath: string, quiet = false): void {
1525
+ if (quiet) return
1526
+ let source = ''
1527
+ try {
1528
+ source = fs.readFileSync(sourcePath, 'utf8')
1529
+ } catch {
1530
+ return
1531
+ }
1532
+ if (!/\bregisterCommand\s*\(/.test(source)) return
1533
+ const hasTopLevelCall = /^registerCommand\s*\(/m.test(source)
1534
+ if (hasTopLevelCall) return
1535
+ if (alreadyWarned(sourcePath)) return
1536
+ console.warn(
1537
+ `[generate] ⚠ registerCommand(...) is never called at import time — these command ids will `
1538
+ + `appear in the manifest but the handlers will not register at runtime: ${sourcePath}`,
1539
+ )
1540
+ }
1541
+
1467
1542
  function toModuleImportSubpath(filePath: string, baseDir: string): string {
1468
1543
  const relativePath = path.relative(baseDir, filePath).replace(/\\/g, '/')
1469
1544
  return stripModuleCodeExtension(relativePath)
@@ -1797,7 +1872,9 @@ function discoverTranslations(roots: ModuleRoots): DiscoveredTranslation[] {
1797
1872
 
1798
1873
  async function createModuleRegistryDiscovery(
1799
1874
  resolver: PackageResolver,
1875
+ quiet = false,
1800
1876
  ): Promise<ModuleRegistryDiscovery> {
1877
+ resetConventionWarnings()
1801
1878
  const enabled = resolver.loadEnabledModules()
1802
1879
  const modules: ModuleRegistryDiscoveryEntry[] = []
1803
1880
  const trackedRoots = new Set<string>()
@@ -1829,7 +1906,7 @@ async function createModuleRegistryDiscovery(
1829
1906
  resolve,
1830
1907
  frontendFiles: scanModuleDir(roots, SCAN_CONFIGS.frontendPages),
1831
1908
  backendFiles: scanModuleDir(roots, SCAN_CONFIGS.backendPages),
1832
- commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId),
1909
+ commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId, quiet),
1833
1910
  getSubscribers: () => subscribers ??= discoverSubscribers(roots, imps, modId),
1834
1911
  getWorkers: () => workers ??= discoverWorkers(roots, imps, modId),
1835
1912
  translations: discoverTranslations(roots),
@@ -1891,8 +1968,9 @@ async function processPageFiles(options: {
1891
1968
  runtimeImports: string[]
1892
1969
  manifestImports?: string[]
1893
1970
  importIdRef: { value: number }
1971
+ quiet?: boolean
1894
1972
  }): Promise<PageRouteGenerationResult> {
1895
- const { files, type, modId, appDir, pkgDir, appImportBase, pkgImportBase, eagerImports, runtimeImports, manifestImports, importIdRef } = options
1973
+ const { files, type, modId, appDir, pkgDir, appImportBase, pkgImportBase, eagerImports, runtimeImports, manifestImports, importIdRef, quiet } = options
1896
1974
  const metaPrefix = type === 'frontend' ? 'M' : 'BM'
1897
1975
  const eagerRoutes: string[] = []
1898
1976
  const runtimeRoutes: string[] = []
@@ -1918,6 +1996,7 @@ async function processPageFiles(options: {
1918
1996
  const sourceFile = findExistingModuleFile(moduleBaseDir, pageFile)
1919
1997
  if (!sourceFile || !hasDefaultExport(sourceFile)) continue
1920
1998
  const metaPath = findExistingModuleFileByBaseNames(moduleBaseDir, ['page.meta', 'meta'])
1999
+ warnIfPageMetaMissingMetadataExport(metaPath, quiet)
1921
2000
  let metaExpr = 'undefined'
1922
2001
  let runtimeMetaExpr = 'undefined'
1923
2002
  let manifestMetaExpr = 'undefined'
@@ -2764,6 +2843,7 @@ async function processPageFilesAst(options: {
2764
2843
  pkgImportBase: string
2765
2844
  imports: string[]
2766
2845
  importIdRef: { value: number }
2846
+ quiet?: boolean
2767
2847
  }): Promise<{ routes: WriterFunction[]; routePatterns: string[] }> {
2768
2848
  const {
2769
2849
  files,
@@ -2775,6 +2855,7 @@ async function processPageFilesAst(options: {
2775
2855
  pkgImportBase,
2776
2856
  imports,
2777
2857
  importIdRef,
2858
+ quiet,
2778
2859
  } = options
2779
2860
  const routes: WriterFunction[] = []
2780
2861
  const routePatterns: string[] = []
@@ -2811,6 +2892,7 @@ async function processPageFilesAst(options: {
2811
2892
  if (!sourceFile || !hasDefaultExport(sourceFile)) continue
2812
2893
 
2813
2894
  const metaPath = findExistingModuleFileByBaseNames(moduleBaseDir, ['page.meta', 'meta'])
2895
+ warnIfPageMetaMissingMetadataExport(metaPath, quiet)
2814
2896
  if (metaPath) {
2815
2897
  const metaImportName = `${metaPrefix}${importIdRef.value++}_${toVar(modId)}_${toVar(segs.join('_') || 'index')}`
2816
2898
  const metaImportPath = sanitizeGeneratedModuleSpecifier(
@@ -3374,6 +3456,7 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3374
3456
  runtimeImports,
3375
3457
  manifestImports: frontendRouteManifestImports,
3376
3458
  importIdRef,
3459
+ quiet,
3377
3460
  })
3378
3461
  frontendRoutes.push(...generatedFrontendRoutes.eagerRoutes)
3379
3462
  runtimeFrontendRoutes.push(...generatedFrontendRoutes.runtimeRoutes)
@@ -3497,6 +3580,7 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
3497
3580
  runtimeImports,
3498
3581
  manifestImports: backendRouteManifestImports,
3499
3582
  importIdRef,
3583
+ quiet,
3500
3584
  })
3501
3585
  backendRoutes.push(...generatedBackendRoutes.eagerRoutes)
3502
3586
  runtimeBackendRoutes.push(...generatedBackendRoutes.runtimeRoutes)
@@ -4026,6 +4110,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
4026
4110
  pkgImportBase: imps.pkgBase,
4027
4111
  imports,
4028
4112
  importIdRef,
4113
+ quiet,
4029
4114
  })
4030
4115
  frontendRoutes.push(...feAst.routes)
4031
4116
  hasRouteComponents = true
@@ -4047,6 +4132,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
4047
4132
  pkgImportBase: imps.pkgBase,
4048
4133
  imports,
4049
4134
  importIdRef,
4135
+ quiet,
4050
4136
  })
4051
4137
  backendRoutes.push(...beAst.routes)
4052
4138
  for (const pattern of beAst.routePatterns) {
@@ -4649,22 +4735,22 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
4649
4735
  }
4650
4736
 
4651
4737
  export async function generateModuleRegistry(options: ModuleRegistryOptions): Promise<GeneratorResult> {
4652
- const discovery = await createModuleRegistryDiscovery(options.resolver)
4738
+ const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false)
4653
4739
  return generateModuleRegistryFromDiscovery({ ...options, discovery })
4654
4740
  }
4655
4741
 
4656
4742
  export async function generateModuleRegistryApp(options: ModuleRegistryOptions): Promise<GeneratorResult> {
4657
- const discovery = await createModuleRegistryDiscovery(options.resolver)
4743
+ const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false)
4658
4744
  return generateModuleRegistryAppFromDiscovery({ ...options, discovery })
4659
4745
  }
4660
4746
 
4661
4747
  export async function generateModuleRegistryCli(options: ModuleRegistryOptions): Promise<GeneratorResult> {
4662
- const discovery = await createModuleRegistryDiscovery(options.resolver)
4748
+ const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false)
4663
4749
  return generateModuleRegistryCliFromDiscovery({ ...options, discovery })
4664
4750
  }
4665
4751
 
4666
4752
  export async function generateModuleRegistries(options: ModuleRegistryOptions): Promise<GeneratorResult[]> {
4667
- const discovery = await createModuleRegistryDiscovery(options.resolver)
4753
+ const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false)
4668
4754
  return [
4669
4755
  await generateModuleRegistryFromDiscovery({ ...options, discovery }),
4670
4756
  await generateModuleRegistryAppFromDiscovery({ ...options, discovery }),
@@ -709,7 +709,11 @@ export async function generateOpenApi(options: GenerateOpenApiOptions): Promise<
709
709
  // Fallback to static regex approach (extracts operationId/summary/tags but no schemas)
710
710
  if (!doc) {
711
711
  if (!quiet) {
712
- console.log('[OpenAPI] Falling back to static regex approach')
712
+ console.warn(
713
+ '[OpenAPI] ⚠ Bundling failed; falling back to static regex extraction — '
714
+ + 'request/response schemas are OMITTED from the generated document. '
715
+ + 'The usual cause is a route file importing a module specifier that does not resolve.',
716
+ )
713
717
  }
714
718
  const paths = buildOpenApiPaths(routes)
715
719
  doc = {