@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/agentic/claude-code/hooks/gate-evidence.ts +269 -0
- package/dist/agentic/claude-code/settings.json +21 -0
- package/dist/agentic/codex/hooks/gate-evidence.mjs +199 -0
- package/dist/agentic/codex/hooks.json +29 -0
- package/dist/agentic/cursor/hooks/gate-evidence.mjs +181 -0
- package/dist/agentic/cursor/hooks.json +10 -0
- package/dist/agentic/guides/module-facts.json +112 -112
- package/dist/agentic/guides/module-facts.v2.json +112 -112
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +13 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +22 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +20 -0
- package/dist/lib/agentic-setup.js +8 -2
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/module-di.js +25 -1
- package/dist/lib/generators/module-di.js.map +2 -2
- package/dist/lib/generators/module-registry.js +61 -15
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/openapi.js +3 -1
- package/dist/lib/generators/openapi.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/agentic-setup.ts +17 -2
- package/src/lib/generators/__tests__/silent-convention-warnings.test.ts +154 -0
- package/src/lib/generators/module-di.ts +35 -0
- package/src/lib/generators/module-registry.ts +93 -7
- package/src/lib/generators/openapi.ts +5 -1
|
@@ -122,6 +122,10 @@ function listFiles(root) {
|
|
|
122
122
|
}
|
|
123
123
|
return files;
|
|
124
124
|
}
|
|
125
|
+
function claudeHookFiles() {
|
|
126
|
+
const hooksDir = join(AGENTIC_DIR, "claude-code", "hooks");
|
|
127
|
+
return listFiles(hooksDir).map((file) => relative(hooksDir, file).replaceAll("\\", "/"));
|
|
128
|
+
}
|
|
125
129
|
function copyTree(sourceRoot, destinationRoot, config) {
|
|
126
130
|
for (const sourcePath of listFiles(sourceRoot)) {
|
|
127
131
|
const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath));
|
|
@@ -319,7 +323,7 @@ function finalizeHarnessManifest(config, selectedTools) {
|
|
|
319
323
|
if (selectedTools.includes("claude-code")) {
|
|
320
324
|
paths.add(join(targetDir, "CLAUDE.md"));
|
|
321
325
|
paths.add(join(targetDir, ".claude", "settings.json"));
|
|
322
|
-
paths.add(join(targetDir, ".claude", "hooks",
|
|
326
|
+
for (const hook of claudeHookFiles()) paths.add(join(targetDir, ".claude", "hooks", hook));
|
|
323
327
|
paths.add(join(targetDir, ".mcp.json.example"));
|
|
324
328
|
}
|
|
325
329
|
if (selectedTools.includes("codex")) paths.add(join(targetDir, ".codex", "mcp.json.example"));
|
|
@@ -485,7 +489,9 @@ function generateClaudeCode(config) {
|
|
|
485
489
|
const srcDir = join(AGENTIC_DIR, "claude-code");
|
|
486
490
|
writeTemplate(srcDir, "CLAUDE.md.template", join(targetDir, "CLAUDE.md"), config);
|
|
487
491
|
copyFile(srcDir, "settings.json", join(targetDir, ".claude", "settings.json"));
|
|
488
|
-
|
|
492
|
+
for (const hook of claudeHookFiles()) {
|
|
493
|
+
copyFile(srcDir, `hooks/${hook}`, join(targetDir, ".claude", "hooks", hook));
|
|
494
|
+
}
|
|
489
495
|
copyFile(srcDir, "mcp.json.example", join(targetDir, ".mcp.json.example"));
|
|
490
496
|
}
|
|
491
497
|
function generateCodex(config) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/agentic-setup.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n readdirSync,\n realpathSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { createHash } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { tmpdir } from 'node:os'\nimport { join, dirname, basename, relative, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Project, SyntaxKind } from 'ts-morph'\n\nconst moduleDir = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), moduleDir is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst bundledAgenticDir = join(moduleDir, '..', 'agentic')\nconst AGENTIC_DIR = existsSync(bundledAgenticDir)\n ? bundledAgenticDir\n : join(moduleDir, '..', '..', '..', 'create-app', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n updateHarness?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\ninterface HarnessManifestFile {\n path: string\n sha256: string\n source: string\n userEditable: boolean\n}\n\ninterface HarnessManifest {\n version: number\n generator: string\n files: HarnessManifestFile[]\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Module fact-sheet selection (mirrors packages/create-app/src/setup/tools/shared.ts) \u2500\u2500\n\n// AST-parse the static `enabledModules` array literal in the app's src/modules.ts\n// and collect each entry's `id`. Only the static literal is read (conditional\n// .push()/spread entries are intentionally not seen \u2014 see spec D6).\nfunction readEnabledModuleIds(modulesPath: string): { parsed: boolean; ids: string[] } {\n if (!existsSync(modulesPath)) return { parsed: false, ids: [] }\n try {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile('modules.ts', readFileSync(modulesPath, 'utf-8'))\n const declaration = sourceFile.getVariableDeclaration('enabledModules')\n const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) return { parsed: false, ids: [] }\n const ids: string[] = []\n for (const element of arrayLiteral.getElements()) {\n const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!objectLiteral) continue\n const idProperty = objectLiteral.getProperty('id')?.asKind(SyntaxKind.PropertyAssignment)\n const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue()\n if (idValue) ids.push(idValue)\n }\n return { parsed: true, ids }\n } catch {\n return { parsed: false, ids: [] }\n }\n}\n\n// Resolve which per-module fact-sheets to ship: the intersection of the bundled\n// fact-sheets (the D5 allowlist, materialized by build.mjs) with the app's enabled\n// modules. Falls back to the full bundled set when the enabled set cannot be read\n// (R5 \u2014 degraded, never empty).\nfunction selectModuleFactSheets(targetDir: string, modulesSubdir: string): string[] {\n const available = existsSync(modulesSubdir)\n ? readdirSync(modulesSubdir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && existsSync(join(modulesSubdir, entry.name, 'index.md')))\n .map((entry) => entry.name)\n : []\n if (available.length === 0) return []\n const parsed = readEnabledModuleIds(join(targetDir, 'src', 'modules.ts'))\n if (!parsed.parsed) return available\n const enabled = new Set(parsed.ids)\n const selected = available.filter((moduleId) => enabled.has(moduleId))\n return selected\n}\n\nconst MODULE_GUIDES_START = '<!-- om:module-guides:start -->'\nconst MODULE_GUIDES_END = '<!-- om:module-guides:end -->'\n\n// The generated standalone root must stay well under Codex's 32 KiB\n// project_doc_max_bytes so a routed chain (root + guide + skill) still fits.\nexport const STANDALONE_ROOT_TARGET_BYTES = 12 * 1024\n\nexport type ModuleGuidesRenderOptions = {\n // Emit the O(1) pointer form instead of enumerating every id. The inline index\n // is the better prompt, so callers only ask for this when the enumerated one\n // would push the root past its byte target.\n compact?: boolean\n}\n\nexport function renderModuleGuidesBlock(\n selected: string[],\n options: ModuleGuidesRenderOptions = {},\n): string {\n if (selected.length === 0) return '_No module fact-sheets are bundled for this app._'\n const index = options.compact\n ? `Enabled module facts: ${selected.length} sheets bundled, too many to index inline \u2014 list the module facts directory to see which modules have one.`\n : `Enabled module facts: ${selected.map((moduleId) => `\\`${moduleId}\\``).join(',')}.`\n return [\n index,\n '',\n 'Load `.ai/guides/modules/<id>/index.md` only for a targeted installed module/host; never preload all module facts.',\n ].join('\\n')\n}\n\n// Regenerate the marker-delimited Module-Specific Guides block in the written\n// AGENTS.md from the selected module set. Replaces strictly between the markers so\n// surrounding prose is untouched and repeat runs are idempotent.\nfunction injectModuleGuides(\n agentsMdPath: string,\n selected: string[],\n options: ModuleGuidesRenderOptions = {},\n): void {\n if (!existsSync(agentsMdPath)) return\n const content = readFileSync(agentsMdPath, 'utf-8')\n const startIndex = content.indexOf(MODULE_GUIDES_START)\n const endIndex = content.indexOf(MODULE_GUIDES_END)\n if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {\n console.warn(\n `[agentic] Module-Specific Guides markers (${MODULE_GUIDES_START} \u2026 ${MODULE_GUIDES_END}) not found in ${agentsMdPath}; the per-module guide list was not generated.`,\n )\n return\n }\n const before = content.slice(0, startIndex + MODULE_GUIDES_START.length)\n const after = content.slice(endIndex)\n const next = `${before}\\n${renderModuleGuidesBlock(selected, options)}\\n${after}`\n if (next !== content) writeFileSync(agentsMdPath, next)\n}\n\n// Last step of harness generation: every tool generator has finished patching\n// AGENTS.md, so this is the only point where the final root size is known. The\n// enumerated module index is the one block that grows with the app, so it is\n// also the one that sheds bytes when the root would otherwise blow its target.\nexport function enforceRootInstructionBudget(\n agentsMdPath: string,\n selected: string[],\n maxBytes: number = STANDALONE_ROOT_TARGET_BYTES,\n): boolean {\n if (!existsSync(agentsMdPath)) return false\n if (Buffer.byteLength(readFileSync(agentsMdPath)) <= maxBytes) return false\n injectModuleGuides(agentsMdPath, selected, { compact: true })\n return true\n}\n\nconst TEXT_EXTENSIONS = new Set(['.cjs', '.json', '.md', '.mdc', '.mjs', '.sh', '.ts', '.txt'])\n\nfunction isTextAsset(path: string): boolean {\n const dot = path.lastIndexOf('.')\n return dot === -1 || TEXT_EXTENSIONS.has(path.slice(dot))\n}\n\nfunction listFiles(root: string): string[] {\n if (!existsSync(root)) return []\n const files: string[] = []\n for (const entry of readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n const absolute = join(root, entry.name)\n if (entry.isDirectory()) files.push(...listFiles(absolute))\n else if (entry.isFile()) files.push(absolute)\n }\n return files\n}\n\nfunction copyTree(sourceRoot: string, destinationRoot: string, config: AgenticConfig): void {\n for (const sourcePath of listFiles(sourceRoot)) {\n const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath))\n ensureDir(destinationPath)\n if (isTextAsset(sourcePath)) {\n writeFileSync(destinationPath, resolvePlaceholders(readFileSync(sourcePath, 'utf8'), config))\n } else {\n copyFileSync(sourcePath, destinationPath)\n }\n if (process.platform !== 'win32') chmodSync(destinationPath, statSync(sourcePath).mode & 0o777)\n }\n}\n\nfunction hashFile(path: string): string {\n return createHash('sha256').update(readFileSync(path)).digest('hex')\n}\n\nfunction canonicalHarnessRoot(root: string): string {\n const resolved = resolve(root)\n if (!existsSync(resolved)) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n const canonical = realpathSync(resolved)\n const entry = lstatSync(canonical, { throwIfNoEntry: false })\n if (!entry || !entry.isDirectory()) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n return canonical\n}\n\n/**\n * Validate a managed path without following any link below the canonical app\n * root. A lexical containment check alone is insufficient: `app/.ai -> /tmp`\n * would otherwise make an apparently safe update write outside the app.\n */\nfunction assertManagedPath(root: string, path: string, options: { leaf?: 'file' | 'any' } = {}): void {\n const absolutePath = resolve(path)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n throw new Error(`Harness-managed path escapes its root: ${absolutePath}`)\n }\n if (normalizedRelative === '') return\n\n const components = normalizedRelative.split(sep).filter(Boolean)\n let current = root\n for (let index = 0; index < components.length; index += 1) {\n current = join(current, components[index])\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) return\n if (entry.isSymbolicLink()) {\n throw new Error(`Harness-managed path contains a symbolic-link component: ${current}`)\n }\n const isLeaf = index === components.length - 1\n if (!isLeaf && !entry.isDirectory()) {\n throw new Error(`Harness-managed path component is not a directory: ${current}`)\n }\n if (isLeaf && options.leaf === 'file' && !entry.isFile()) {\n throw new Error(`Harness-managed file is not a regular file: ${current}`)\n }\n }\n}\n\nfunction ensureManagedParent(root: string, filePath: string): void {\n const parent = dirname(filePath)\n const normalizedRelative = relative(root, parent)\n if (normalizedRelative === '..' || normalizedRelative.startsWith(`..${sep}`)) {\n throw new Error(`Harness-managed path escapes its root: ${filePath}`)\n }\n let current = root\n for (const component of normalizedRelative.split(sep).filter(Boolean)) {\n assertManagedPath(root, current)\n current = join(current, component)\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) mkdirSync(current)\n const created = lstatSync(current, { throwIfNoEntry: false })\n if (!created || created.isSymbolicLink() || !created.isDirectory()) {\n throw new Error(`Harness-managed path component is not a real directory: ${current}`)\n }\n }\n}\n\nfunction harnessGeneratorId(): string {\n try {\n const upstream = JSON.parse(readFileSync(join(GUIDES_DIR, 'upstream', 'manifest.json'), 'utf8')) as {\n generator?: unknown\n }\n const generator = typeof upstream.generator === 'string' ? upstream.generator : ''\n const version = generator.slice(generator.lastIndexOf('@') + 1)\n if (version && version !== generator) return `open-mercato-agentic@${version}`\n } catch {\n // Source-mode tests may not have built upstream snapshots yet.\n }\n return 'open-mercato-agentic@unknown'\n}\n\nfunction externalSkillNames(targetDir: string): Set<string> {\n try {\n const tiers = JSON.parse(readFileSync(join(targetDir, '.ai', 'skills', 'tiers.json'), 'utf8')) as {\n external?: { skills?: unknown }\n }\n return new Set(Array.isArray(tiers.external?.skills) ? tiers.external.skills.filter((name): name is string => typeof name === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nfunction atomicCopyFile(sourcePath: string, destinationPath: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n copyFileSync(sourcePath, temporaryPath)\n if (process.platform !== 'win32') chmodSync(temporaryPath, statSync(sourcePath).mode & 0o777)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction atomicWriteFile(destinationPath: string, content: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n writeFileSync(temporaryPath, content)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction resolveManifestPath(root: string, relativePath: string): string | null {\n if (!relativePath || relativePath.includes('\\0')) return null\n const absolutePath = resolve(root, relativePath)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '' ||\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n return null\n }\n return absolutePath\n}\n\nfunction normalizeManifestRelativePath(path: string): string {\n return path.replace(/\\\\/g, '/')\n}\n\nfunction readHarnessManifest(manifestPath: string): HarnessManifest | null {\n if (!existsSync(manifestPath)) return null\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as Partial<HarnessManifest>\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.generator !== 'string' ||\n !Array.isArray(parsed.files)\n ) {\n return null\n }\n const files: HarnessManifestFile[] = []\n for (const entry of parsed.files) {\n if (\n !entry ||\n typeof entry.path !== 'string' ||\n typeof entry.sha256 !== 'string' ||\n !/^[a-f0-9]{64}$/.test(entry.sha256) ||\n typeof entry.source !== 'string' ||\n typeof entry.userEditable !== 'boolean'\n ) {\n return null\n }\n files.push({ ...entry, path: normalizeManifestRelativePath(entry.path) })\n }\n return { version: parsed.version, generator: parsed.generator, files }\n } catch {\n return null\n }\n}\n\nfunction targetPathsForTree(sourceRoot: string, destinationRoot: string): string[] {\n return listFiles(sourceRoot).map((sourcePath) => join(destinationRoot, relative(sourceRoot, sourcePath)))\n}\n\nfunction finalizeHarnessManifest(config: AgenticConfig, selectedTools: string[]): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n const paths = new Set<string>([\n join(targetDir, 'AGENTS.md'),\n ...targetPathsForTree(join(srcDir, 'ai'), join(targetDir, '.ai')),\n ...targetPathsForTree(join(srcDir, 'scripts'), join(targetDir, 'scripts')),\n ])\n for (const file of readdirSync(GUIDES_DIR)) {\n if (\n file.endsWith('.md')\n || file === 'module-facts.json'\n || file === 'module-facts.v2.json'\n || file === 'reference-module-facts.json'\n ) {\n paths.add(join(targetDir, '.ai', 'guides', file))\n }\n }\n for (const file of listFiles(join(GUIDES_DIR, 'upstream'))) {\n paths.add(join(targetDir, '.ai', 'guides', 'upstream', relative(join(GUIDES_DIR, 'upstream'), file)))\n }\n for (const moduleId of selectedModules) {\n const sourceRoot = join(GUIDES_DIR, 'modules', moduleId)\n const destinationRoot = join(targetDir, '.ai', 'guides', 'modules', moduleId)\n for (const file of targetPathsForTree(sourceRoot, destinationRoot)) paths.add(file)\n }\n for (const file of listFiles(join(GUIDES_DIR, 'reference-modules'))) {\n paths.add(join(targetDir, '.ai', 'guides', 'reference-modules', relative(join(GUIDES_DIR, 'reference-modules'), file)))\n }\n if (selectedTools.includes('claude-code')) {\n paths.add(join(targetDir, 'CLAUDE.md'))\n paths.add(join(targetDir, '.claude', 'settings.json'))\n paths.add(join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n paths.add(join(targetDir, '.mcp.json.example'))\n }\n if (selectedTools.includes('codex')) paths.add(join(targetDir, '.codex', 'mcp.json.example'))\n if (selectedTools.includes('cursor')) {\n for (const file of listFiles(join(AGENTIC_DIR, 'cursor'))) {\n const rel = relative(join(AGENTIC_DIR, 'cursor'), file)\n paths.add(join(targetDir, '.cursor', rel))\n }\n }\n const manifestPath = join(targetDir, '.ai', 'harness', 'manifest.json')\n const externalSkills = externalSkillNames(targetDir)\n paths.delete(manifestPath)\n const files = [...paths]\n .filter((path) => existsSync(path))\n .sort((left, right) => left.localeCompare(right))\n .map((path) => {\n const relativePath = normalizeManifestRelativePath(relative(targetDir, path))\n const skillName = relativePath.match(/^\\.ai\\/skills\\/([^/]+)\\//)?.[1]\n return {\n path: relativePath,\n sha256: hashFile(path),\n source: skillName ? (externalSkills.has(skillName) ? 'external-override' : 'local-skill') : 'generated',\n userEditable:\n relativePath === 'AGENTS.md'\n || relativePath === '.ai/agentic.config.json'\n || relativePath === '.ai/lessons.md'\n || relativePath.startsWith('.ai/lessons/'),\n }\n })\n atomicWriteFile(\n manifestPath,\n `${JSON.stringify({ version: 1, generator: harnessGeneratorId(), files }, null, 2)}\\n`,\n )\n}\n\n/**\n * Publish a fully generated harness candidate using the previous ownership\n * manifest as the only source of ownership. Modified owned files and exact-path\n * collisions with unknown files stay untouched; their candidate is written next\n * to them as `<path>.incoming` for explicit review.\n */\nexport type HarnessUpdateConflict = { path: string; candidate: string | null }\n\nfunction preserveIncomingCandidate(\n targetRoot: string,\n destinationPath: string,\n sourcePath: string,\n relativePath: string,\n): string {\n for (let suffix = 1; ; suffix += 1) {\n const label = suffix === 1 ? '.incoming' : `.incoming.${suffix}`\n const candidatePath = `${destinationPath}${label}`\n assertManagedPath(targetRoot, candidatePath, { leaf: 'file' })\n if (!existsSync(candidatePath)) {\n atomicCopyFile(sourcePath, candidatePath, targetRoot)\n return `${relativePath}${label}`\n }\n if (hashFile(candidatePath) === hashFile(sourcePath)) return `${relativePath}${label}`\n }\n}\n\nexport function applyHarnessUpdate(\n targetDir: string,\n stagingDir: string,\n options: { force?: boolean } = {},\n): HarnessUpdateConflict[] {\n const targetRoot = canonicalHarnessRoot(targetDir)\n const stagingRoot = canonicalHarnessRoot(stagingDir)\n const targetManifestPath = join(targetRoot, '.ai', 'harness', 'manifest.json')\n const stagingManifestPath = join(stagingRoot, '.ai', 'harness', 'manifest.json')\n assertManagedPath(targetRoot, targetManifestPath, { leaf: 'file' })\n assertManagedPath(stagingRoot, stagingManifestPath, { leaf: 'file' })\n const candidateManifest = readHarnessManifest(stagingManifestPath)\n if (!candidateManifest) {\n throw new Error('Generated harness candidate has a missing or invalid ownership manifest.')\n }\n\n const previousManifest = readHarnessManifest(targetManifestPath)\n const previousFiles = new Map(previousManifest?.files.map((entry) => [entry.path, entry]) ?? [])\n const candidatePaths = new Set(candidateManifest.files.map((entry) => entry.path))\n const candidates: Array<{\n entry: HarnessManifestFile\n sourcePath: string\n destinationPath: string\n }> = []\n\n // Validate the complete candidate before writing anything into the app.\n for (const entry of candidateManifest.files) {\n const sourcePath = resolveManifestPath(stagingRoot, entry.path)\n const destinationPath = resolveManifestPath(targetRoot, entry.path)\n if (sourcePath) assertManagedPath(stagingRoot, sourcePath, { leaf: 'file' })\n if (destinationPath) assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n if (!sourcePath || !destinationPath || !existsSync(sourcePath) || hashFile(sourcePath) !== entry.sha256) {\n throw new Error(`Generated harness candidate is invalid for ${JSON.stringify(entry.path)}.`)\n }\n candidates.push({ entry, sourcePath, destinationPath })\n }\n\n const conflicts: HarnessUpdateConflict[] = []\n for (const { entry, sourcePath, destinationPath } of candidates) {\n if (options.force) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n if (!existsSync(destinationPath)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const currentHash = hashFile(destinationPath)\n const previousEntry = previousFiles.get(entry.path)\n if (currentHash === entry.sha256 || (previousEntry && currentHash === previousEntry.sha256)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const candidate = preserveIncomingCandidate(targetRoot, destinationPath, sourcePath, entry.path)\n conflicts.push({ path: entry.path, candidate })\n }\n\n const retainedRetiredEntries: HarnessManifestFile[] = []\n for (const previousEntry of previousManifest?.files ?? []) {\n if (candidatePaths.has(previousEntry.path)) continue\n const destinationPath = resolveManifestPath(targetRoot, previousEntry.path)\n if (!destinationPath || !existsSync(destinationPath)) continue\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n const isRetiredFlatModuleFact = !previousEntry.userEditable\n && /^\\.ai\\/guides\\/(?:modules|reference-modules)\\/[^/]+\\.md$/.test(previousEntry.path)\n if (isRetiredFlatModuleFact) {\n rmSync(destinationPath, { force: true })\n continue\n }\n let unchanged = false\n try {\n unchanged = hashFile(destinationPath) === previousEntry.sha256\n } catch {\n // A user may replace a generated file with another filesystem object.\n // Preserve it and retain the ownership tombstone for a later review.\n }\n if (unchanged) {\n assertManagedPath(targetRoot, dirname(destinationPath))\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n rmSync(destinationPath, { force: true })\n } else {\n retainedRetiredEntries.push(previousEntry)\n conflicts.push({ path: previousEntry.path, candidate: null })\n }\n }\n\n // The candidate hashes deliberately remain in the manifest for conflicts. If\n // the user accepts an .incoming file, a later update can recognize it as an\n // unmodified owned file. Until then the hash mismatch keeps preserving it.\n const finalManifest: HarnessManifest = {\n ...candidateManifest,\n files: [...candidateManifest.files, ...retainedRetiredEntries],\n }\n atomicWriteFile(targetManifestPath, `${JSON.stringify(finalManifest, null, 2)}\\n`, targetRoot)\n return conflicts\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // Resolve which per-module fact-sheets this app gets (enabled \u2229 bundled allowlist).\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n\n // One recursive mapping mirrors create-app's shared emitter.\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n copyTree(join(srcDir, 'ai'), join(targetDir, '.ai'), config)\n copyTree(join(srcDir, 'scripts'), join(targetDir, 'scripts'), config)\n\n // Routed conceptual guides are copied wholesale (framework-wide). Per-module\n // fact-sheets (.ai/guides/modules/<module>/) are filtered to the app's enabled\n // module set; the combined v1 and corrected v2 module-facts sidecars are copied as-is.\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n\n const moduleFactsPath = join(GUIDES_DIR, 'module-facts.json')\n if (existsSync(moduleFactsPath)) {\n const destPath = join(guidesDestDir, 'module-facts.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsPath, destPath)\n }\n\n const moduleFactsV2Path = join(GUIDES_DIR, 'module-facts.v2.json')\n if (existsSync(moduleFactsV2Path)) {\n const destPath = join(guidesDestDir, 'module-facts.v2.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsV2Path, destPath)\n }\n\n const referenceFactsPath = join(GUIDES_DIR, 'reference-module-facts.json')\n if (existsSync(referenceFactsPath)) {\n const destPath = join(guidesDestDir, 'reference-module-facts.json')\n ensureDir(destPath)\n copyFileSync(referenceFactsPath, destPath)\n }\n\n copyTree(join(GUIDES_DIR, 'upstream'), join(guidesDestDir, 'upstream'), config)\n copyTree(join(GUIDES_DIR, 'reference-modules'), join(guidesDestDir, 'reference-modules'), config)\n\n const modulesSubdir = join(GUIDES_DIR, 'modules')\n for (const moduleId of selectedModules) {\n copyTree(join(modulesSubdir, moduleId), join(guidesDestDir, 'modules', moduleId), config)\n }\n }\n\n injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules)\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // The installer exclusively owns Claude's per-skill compatibility links.\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // No .codex/skills directory: Codex reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // No .cursor/skills directory: Cursor reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nfunction persistedAgentSelection(targetDir: string): string[] | null {\n const selectableIds = SELECTABLE.map((tool) => tool.id)\n const tiersPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n try {\n const tiers = JSON.parse(readFileSync(tiersPath, 'utf8')) as { agents?: { ignore?: unknown } }\n if (Array.isArray(tiers.agents?.ignore)\n && tiers.agents.ignore.every((id): id is string => typeof id === 'string')) {\n const ignored = new Set(tiers.agents.ignore)\n return selectableIds.filter((id) => !ignored.has(id))\n }\n } catch {\n // Fall through to the ownership manifest and existing generated assets.\n }\n\n const manifest = readHarnessManifest(join(targetDir, '.ai', 'harness', 'manifest.json'))\n const owned = new Set(manifest?.files.map((entry) => entry.path) ?? [])\n const selected = SELECTABLE.filter((tool) => {\n if (tool.id === 'claude-code') {\n return owned.has('CLAUDE.md') || owned.has('.claude/settings.json')\n || existsSync(join(targetDir, 'CLAUDE.md')) || existsSync(join(targetDir, '.claude', 'settings.json'))\n }\n if (tool.id === 'codex') {\n return owned.has('.codex/mcp.json.example') || existsSync(join(targetDir, '.codex', 'mcp.json.example'))\n }\n return owned.has('.cursor/hooks.json') || existsSync(join(targetDir, '.cursor', 'hooks.json'))\n }).map((tool) => tool.id)\n return selected.length > 0 ? selected : null\n}\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else if (options?.updateHarness) {\n selectedIds = persistedAgentSelection(targetDir) ?? await promptSelection(ask)\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n const stagingDir = mkdtempSync(join(tmpdir(), 'open-mercato-harness-'))\n try {\n const modulesSourcePath = join(targetDir, 'src', 'modules.ts')\n const modulesCandidatePath = join(stagingDir, 'src', 'modules.ts')\n if (existsSync(modulesSourcePath)) {\n ensureDir(modulesCandidatePath)\n copyFileSync(modulesSourcePath, modulesCandidatePath)\n }\n\n const stagingConfig: AgenticConfig = {\n projectName: config.projectName,\n targetDir: stagingDir,\n }\n generateHarness(stagingConfig, selectedIds)\n const conflicts = applyHarnessUpdate(targetDir, stagingDir, {\n force: options?.force,\n })\n if (conflicts.length > 0) {\n console.warn('')\n console.warn(' \u26A0 Preserved locally modified harness files:')\n for (const conflict of conflicts) {\n const detail = conflict.candidate\n ? `candidate: ${conflict.candidate}`\n : 'retired asset kept because it has local changes'\n console.warn(` \u2022 ${conflict.path} (${detail})`)\n }\n }\n } finally {\n rmSync(stagingDir, { recursive: true, force: true })\n }\n\n installSkills(targetDir)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n console.log(' .ai/agentic.config.json ships preconfigured (GitHub tracker, labels off);')\n console.log(' run /om-setup-agent-pipeline in your agent CLI to tailor labels, QA gate,')\n console.log(' tracker, or validation commands. Re-run `yarn install-skills` anytime to')\n console.log(' refresh the external open-mercato/skills subset.')\n console.log('')\n}\n\nfunction generateHarness(config: AgenticConfig, selectedIds: string[]): void {\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n enforceGeneratedRootBudget(config)\n\n persistAgentSelection(config.targetDir, selectedIds)\n finalizeHarnessManifest(config, selectedIds)\n}\n\n/** Run after every tool generator has patched AGENTS.md, before the manifest is hashed. */\nfunction enforceGeneratedRootBudget(\n config: AgenticConfig,\n maxBytes: number = STANDALONE_ROOT_TARGET_BYTES,\n): boolean {\n const { targetDir } = config\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n return enforceRootInstructionBudget(join(targetDir, 'AGENTS.md'), selectedModules, maxBytes)\n}\n\n/**\n * Persist the agent selection so later `yarn install-skills` runs keep honoring\n * it: agents the user did not pick go into `agents.ignore` in tiers.json and\n * never get a skills directory of their own.\n */\nfunction persistAgentSelection(targetDir: string, selectedIds: string[]): void {\n const manifestPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n if (!existsSync(manifestPath)) return\n const ignore = SELECTABLE.map((tool) => tool.id).filter((id) => !selectedIds.includes(id))\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<string, unknown>\n if (ignore.length > 0) {\n manifest.agents = { ignore }\n } else {\n delete manifest.agents\n }\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n}\n\nfunction installSkills(targetDir: string): void {\n const installScript = join(targetDir, 'scripts', 'install-skills.mjs')\n if (!existsSync(installScript)) return\n console.log('')\n console.log(' Installing agent skills (local tiers + external open-mercato/skills subset)...')\n const result = spawnSync(process.execPath, [installScript], {\n cwd: targetDir,\n stdio: 'inherit',\n env: { ...process.env, OM_SKILLS_OUTPUT_INDENT: '3' },\n })\n if (result.error || result.status !== 0) {\n console.log(' \u26A0 Skill installation did not complete; run `yarn install-skills` inside the app when online.')\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n readdirSync,\n realpathSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { createHash } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { tmpdir } from 'node:os'\nimport { join, dirname, basename, relative, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { Project, SyntaxKind } from 'ts-morph'\n\nconst moduleDir = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), moduleDir is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst bundledAgenticDir = join(moduleDir, '..', 'agentic')\nconst AGENTIC_DIR = existsSync(bundledAgenticDir)\n ? bundledAgenticDir\n : join(moduleDir, '..', '..', '..', 'create-app', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n updateHarness?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\ninterface HarnessManifestFile {\n path: string\n sha256: string\n source: string\n userEditable: boolean\n}\n\ninterface HarnessManifest {\n version: number\n generator: string\n files: HarnessManifestFile[]\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Module fact-sheet selection (mirrors packages/create-app/src/setup/tools/shared.ts) \u2500\u2500\n\n// AST-parse the static `enabledModules` array literal in the app's src/modules.ts\n// and collect each entry's `id`. Only the static literal is read (conditional\n// .push()/spread entries are intentionally not seen \u2014 see spec D6).\nfunction readEnabledModuleIds(modulesPath: string): { parsed: boolean; ids: string[] } {\n if (!existsSync(modulesPath)) return { parsed: false, ids: [] }\n try {\n const project = new Project({ useInMemoryFileSystem: true })\n const sourceFile = project.createSourceFile('modules.ts', readFileSync(modulesPath, 'utf-8'))\n const declaration = sourceFile.getVariableDeclaration('enabledModules')\n const arrayLiteral = declaration?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) return { parsed: false, ids: [] }\n const ids: string[] = []\n for (const element of arrayLiteral.getElements()) {\n const objectLiteral = element.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!objectLiteral) continue\n const idProperty = objectLiteral.getProperty('id')?.asKind(SyntaxKind.PropertyAssignment)\n const idValue = idProperty?.getInitializerIfKind(SyntaxKind.StringLiteral)?.getLiteralValue()\n if (idValue) ids.push(idValue)\n }\n return { parsed: true, ids }\n } catch {\n return { parsed: false, ids: [] }\n }\n}\n\n// Resolve which per-module fact-sheets to ship: the intersection of the bundled\n// fact-sheets (the D5 allowlist, materialized by build.mjs) with the app's enabled\n// modules. Falls back to the full bundled set when the enabled set cannot be read\n// (R5 \u2014 degraded, never empty).\nfunction selectModuleFactSheets(targetDir: string, modulesSubdir: string): string[] {\n const available = existsSync(modulesSubdir)\n ? readdirSync(modulesSubdir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && existsSync(join(modulesSubdir, entry.name, 'index.md')))\n .map((entry) => entry.name)\n : []\n if (available.length === 0) return []\n const parsed = readEnabledModuleIds(join(targetDir, 'src', 'modules.ts'))\n if (!parsed.parsed) return available\n const enabled = new Set(parsed.ids)\n const selected = available.filter((moduleId) => enabled.has(moduleId))\n return selected\n}\n\nconst MODULE_GUIDES_START = '<!-- om:module-guides:start -->'\nconst MODULE_GUIDES_END = '<!-- om:module-guides:end -->'\n\n// The generated standalone root must stay well under Codex's 32 KiB\n// project_doc_max_bytes so a routed chain (root + guide + skill) still fits.\nexport const STANDALONE_ROOT_TARGET_BYTES = 12 * 1024\n\nexport type ModuleGuidesRenderOptions = {\n // Emit the O(1) pointer form instead of enumerating every id. The inline index\n // is the better prompt, so callers only ask for this when the enumerated one\n // would push the root past its byte target.\n compact?: boolean\n}\n\nexport function renderModuleGuidesBlock(\n selected: string[],\n options: ModuleGuidesRenderOptions = {},\n): string {\n if (selected.length === 0) return '_No module fact-sheets are bundled for this app._'\n const index = options.compact\n ? `Enabled module facts: ${selected.length} sheets bundled, too many to index inline \u2014 list the module facts directory to see which modules have one.`\n : `Enabled module facts: ${selected.map((moduleId) => `\\`${moduleId}\\``).join(',')}.`\n return [\n index,\n '',\n 'Load `.ai/guides/modules/<id>/index.md` only for a targeted installed module/host; never preload all module facts.',\n ].join('\\n')\n}\n\n// Regenerate the marker-delimited Module-Specific Guides block in the written\n// AGENTS.md from the selected module set. Replaces strictly between the markers so\n// surrounding prose is untouched and repeat runs are idempotent.\nfunction injectModuleGuides(\n agentsMdPath: string,\n selected: string[],\n options: ModuleGuidesRenderOptions = {},\n): void {\n if (!existsSync(agentsMdPath)) return\n const content = readFileSync(agentsMdPath, 'utf-8')\n const startIndex = content.indexOf(MODULE_GUIDES_START)\n const endIndex = content.indexOf(MODULE_GUIDES_END)\n if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {\n console.warn(\n `[agentic] Module-Specific Guides markers (${MODULE_GUIDES_START} \u2026 ${MODULE_GUIDES_END}) not found in ${agentsMdPath}; the per-module guide list was not generated.`,\n )\n return\n }\n const before = content.slice(0, startIndex + MODULE_GUIDES_START.length)\n const after = content.slice(endIndex)\n const next = `${before}\\n${renderModuleGuidesBlock(selected, options)}\\n${after}`\n if (next !== content) writeFileSync(agentsMdPath, next)\n}\n\n// Last step of harness generation: every tool generator has finished patching\n// AGENTS.md, so this is the only point where the final root size is known. The\n// enumerated module index is the one block that grows with the app, so it is\n// also the one that sheds bytes when the root would otherwise blow its target.\nexport function enforceRootInstructionBudget(\n agentsMdPath: string,\n selected: string[],\n maxBytes: number = STANDALONE_ROOT_TARGET_BYTES,\n): boolean {\n if (!existsSync(agentsMdPath)) return false\n if (Buffer.byteLength(readFileSync(agentsMdPath)) <= maxBytes) return false\n injectModuleGuides(agentsMdPath, selected, { compact: true })\n return true\n}\n\nconst TEXT_EXTENSIONS = new Set(['.cjs', '.json', '.md', '.mdc', '.mjs', '.sh', '.ts', '.txt'])\n\nfunction isTextAsset(path: string): boolean {\n const dot = path.lastIndexOf('.')\n return dot === -1 || TEXT_EXTENSIONS.has(path.slice(dot))\n}\n\nfunction listFiles(root: string): string[] {\n if (!existsSync(root)) return []\n const files: string[] = []\n for (const entry of readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n const absolute = join(root, entry.name)\n if (entry.isDirectory()) files.push(...listFiles(absolute))\n else if (entry.isFile()) files.push(absolute)\n }\n return files\n}\n\n/**\n * The Claude Code hook files a scaffold installs, read from the agentic source tree.\n *\n * Enumerating them by hand let `settings.json` register `gate-evidence.ts` while this\n * generator kept copying only `entity-migration-check.ts`, so `mercato agentic:init` wrote a\n * hook registration pointing at a file that was never created. Deriving the list from disk\n * keeps this path and the create-app wizard in step whenever a hook is added.\n */\nfunction claudeHookFiles(): string[] {\n const hooksDir = join(AGENTIC_DIR, 'claude-code', 'hooks')\n return listFiles(hooksDir).map((file) => relative(hooksDir, file).replaceAll('\\\\', '/'))\n}\n\nfunction copyTree(sourceRoot: string, destinationRoot: string, config: AgenticConfig): void {\n for (const sourcePath of listFiles(sourceRoot)) {\n const destinationPath = join(destinationRoot, relative(sourceRoot, sourcePath))\n ensureDir(destinationPath)\n if (isTextAsset(sourcePath)) {\n writeFileSync(destinationPath, resolvePlaceholders(readFileSync(sourcePath, 'utf8'), config))\n } else {\n copyFileSync(sourcePath, destinationPath)\n }\n if (process.platform !== 'win32') chmodSync(destinationPath, statSync(sourcePath).mode & 0o777)\n }\n}\n\nfunction hashFile(path: string): string {\n return createHash('sha256').update(readFileSync(path)).digest('hex')\n}\n\nfunction canonicalHarnessRoot(root: string): string {\n const resolved = resolve(root)\n if (!existsSync(resolved)) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n const canonical = realpathSync(resolved)\n const entry = lstatSync(canonical, { throwIfNoEntry: false })\n if (!entry || !entry.isDirectory()) {\n throw new Error(`Harness root must be an existing directory: ${resolved}`)\n }\n return canonical\n}\n\n/**\n * Validate a managed path without following any link below the canonical app\n * root. A lexical containment check alone is insufficient: `app/.ai -> /tmp`\n * would otherwise make an apparently safe update write outside the app.\n */\nfunction assertManagedPath(root: string, path: string, options: { leaf?: 'file' | 'any' } = {}): void {\n const absolutePath = resolve(path)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n throw new Error(`Harness-managed path escapes its root: ${absolutePath}`)\n }\n if (normalizedRelative === '') return\n\n const components = normalizedRelative.split(sep).filter(Boolean)\n let current = root\n for (let index = 0; index < components.length; index += 1) {\n current = join(current, components[index])\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) return\n if (entry.isSymbolicLink()) {\n throw new Error(`Harness-managed path contains a symbolic-link component: ${current}`)\n }\n const isLeaf = index === components.length - 1\n if (!isLeaf && !entry.isDirectory()) {\n throw new Error(`Harness-managed path component is not a directory: ${current}`)\n }\n if (isLeaf && options.leaf === 'file' && !entry.isFile()) {\n throw new Error(`Harness-managed file is not a regular file: ${current}`)\n }\n }\n}\n\nfunction ensureManagedParent(root: string, filePath: string): void {\n const parent = dirname(filePath)\n const normalizedRelative = relative(root, parent)\n if (normalizedRelative === '..' || normalizedRelative.startsWith(`..${sep}`)) {\n throw new Error(`Harness-managed path escapes its root: ${filePath}`)\n }\n let current = root\n for (const component of normalizedRelative.split(sep).filter(Boolean)) {\n assertManagedPath(root, current)\n current = join(current, component)\n const entry = lstatSync(current, { throwIfNoEntry: false })\n if (!entry) mkdirSync(current)\n const created = lstatSync(current, { throwIfNoEntry: false })\n if (!created || created.isSymbolicLink() || !created.isDirectory()) {\n throw new Error(`Harness-managed path component is not a real directory: ${current}`)\n }\n }\n}\n\nfunction harnessGeneratorId(): string {\n try {\n const upstream = JSON.parse(readFileSync(join(GUIDES_DIR, 'upstream', 'manifest.json'), 'utf8')) as {\n generator?: unknown\n }\n const generator = typeof upstream.generator === 'string' ? upstream.generator : ''\n const version = generator.slice(generator.lastIndexOf('@') + 1)\n if (version && version !== generator) return `open-mercato-agentic@${version}`\n } catch {\n // Source-mode tests may not have built upstream snapshots yet.\n }\n return 'open-mercato-agentic@unknown'\n}\n\nfunction externalSkillNames(targetDir: string): Set<string> {\n try {\n const tiers = JSON.parse(readFileSync(join(targetDir, '.ai', 'skills', 'tiers.json'), 'utf8')) as {\n external?: { skills?: unknown }\n }\n return new Set(Array.isArray(tiers.external?.skills) ? tiers.external.skills.filter((name): name is string => typeof name === 'string') : [])\n } catch {\n return new Set()\n }\n}\n\nfunction atomicCopyFile(sourcePath: string, destinationPath: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n copyFileSync(sourcePath, temporaryPath)\n if (process.platform !== 'win32') chmodSync(temporaryPath, statSync(sourcePath).mode & 0o777)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction atomicWriteFile(destinationPath: string, content: string, managedRoot?: string): void {\n if (managedRoot) {\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n ensureManagedParent(managedRoot, destinationPath)\n } else {\n ensureDir(destinationPath)\n }\n const temporaryPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`\n try {\n if (managedRoot) assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n writeFileSync(temporaryPath, content)\n if (managedRoot) {\n assertManagedPath(managedRoot, dirname(destinationPath))\n assertManagedPath(managedRoot, destinationPath, { leaf: 'file' })\n assertManagedPath(managedRoot, temporaryPath, { leaf: 'file' })\n }\n renameSync(temporaryPath, destinationPath)\n } finally {\n if (!managedRoot || !lstatSync(temporaryPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n rmSync(temporaryPath, { force: true })\n }\n }\n}\n\nfunction resolveManifestPath(root: string, relativePath: string): string | null {\n if (!relativePath || relativePath.includes('\\0')) return null\n const absolutePath = resolve(root, relativePath)\n const normalizedRelative = relative(root, absolutePath)\n if (\n normalizedRelative === '' ||\n normalizedRelative === '..' ||\n normalizedRelative.startsWith(`..${sep}`)\n ) {\n return null\n }\n return absolutePath\n}\n\nfunction normalizeManifestRelativePath(path: string): string {\n return path.replace(/\\\\/g, '/')\n}\n\nfunction readHarnessManifest(manifestPath: string): HarnessManifest | null {\n if (!existsSync(manifestPath)) return null\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as Partial<HarnessManifest>\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.generator !== 'string' ||\n !Array.isArray(parsed.files)\n ) {\n return null\n }\n const files: HarnessManifestFile[] = []\n for (const entry of parsed.files) {\n if (\n !entry ||\n typeof entry.path !== 'string' ||\n typeof entry.sha256 !== 'string' ||\n !/^[a-f0-9]{64}$/.test(entry.sha256) ||\n typeof entry.source !== 'string' ||\n typeof entry.userEditable !== 'boolean'\n ) {\n return null\n }\n files.push({ ...entry, path: normalizeManifestRelativePath(entry.path) })\n }\n return { version: parsed.version, generator: parsed.generator, files }\n } catch {\n return null\n }\n}\n\nfunction targetPathsForTree(sourceRoot: string, destinationRoot: string): string[] {\n return listFiles(sourceRoot).map((sourcePath) => join(destinationRoot, relative(sourceRoot, sourcePath)))\n}\n\nfunction finalizeHarnessManifest(config: AgenticConfig, selectedTools: string[]): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n const paths = new Set<string>([\n join(targetDir, 'AGENTS.md'),\n ...targetPathsForTree(join(srcDir, 'ai'), join(targetDir, '.ai')),\n ...targetPathsForTree(join(srcDir, 'scripts'), join(targetDir, 'scripts')),\n ])\n for (const file of readdirSync(GUIDES_DIR)) {\n if (\n file.endsWith('.md')\n || file === 'module-facts.json'\n || file === 'module-facts.v2.json'\n || file === 'reference-module-facts.json'\n ) {\n paths.add(join(targetDir, '.ai', 'guides', file))\n }\n }\n for (const file of listFiles(join(GUIDES_DIR, 'upstream'))) {\n paths.add(join(targetDir, '.ai', 'guides', 'upstream', relative(join(GUIDES_DIR, 'upstream'), file)))\n }\n for (const moduleId of selectedModules) {\n const sourceRoot = join(GUIDES_DIR, 'modules', moduleId)\n const destinationRoot = join(targetDir, '.ai', 'guides', 'modules', moduleId)\n for (const file of targetPathsForTree(sourceRoot, destinationRoot)) paths.add(file)\n }\n for (const file of listFiles(join(GUIDES_DIR, 'reference-modules'))) {\n paths.add(join(targetDir, '.ai', 'guides', 'reference-modules', relative(join(GUIDES_DIR, 'reference-modules'), file)))\n }\n if (selectedTools.includes('claude-code')) {\n paths.add(join(targetDir, 'CLAUDE.md'))\n paths.add(join(targetDir, '.claude', 'settings.json'))\n for (const hook of claudeHookFiles()) paths.add(join(targetDir, '.claude', 'hooks', hook))\n paths.add(join(targetDir, '.mcp.json.example'))\n }\n if (selectedTools.includes('codex')) paths.add(join(targetDir, '.codex', 'mcp.json.example'))\n if (selectedTools.includes('cursor')) {\n for (const file of listFiles(join(AGENTIC_DIR, 'cursor'))) {\n const rel = relative(join(AGENTIC_DIR, 'cursor'), file)\n paths.add(join(targetDir, '.cursor', rel))\n }\n }\n const manifestPath = join(targetDir, '.ai', 'harness', 'manifest.json')\n const externalSkills = externalSkillNames(targetDir)\n paths.delete(manifestPath)\n const files = [...paths]\n .filter((path) => existsSync(path))\n .sort((left, right) => left.localeCompare(right))\n .map((path) => {\n const relativePath = normalizeManifestRelativePath(relative(targetDir, path))\n const skillName = relativePath.match(/^\\.ai\\/skills\\/([^/]+)\\//)?.[1]\n return {\n path: relativePath,\n sha256: hashFile(path),\n source: skillName ? (externalSkills.has(skillName) ? 'external-override' : 'local-skill') : 'generated',\n userEditable:\n relativePath === 'AGENTS.md'\n || relativePath === '.ai/agentic.config.json'\n || relativePath === '.ai/lessons.md'\n || relativePath.startsWith('.ai/lessons/'),\n }\n })\n atomicWriteFile(\n manifestPath,\n `${JSON.stringify({ version: 1, generator: harnessGeneratorId(), files }, null, 2)}\\n`,\n )\n}\n\n/**\n * Publish a fully generated harness candidate using the previous ownership\n * manifest as the only source of ownership. Modified owned files and exact-path\n * collisions with unknown files stay untouched; their candidate is written next\n * to them as `<path>.incoming` for explicit review.\n */\nexport type HarnessUpdateConflict = { path: string; candidate: string | null }\n\nfunction preserveIncomingCandidate(\n targetRoot: string,\n destinationPath: string,\n sourcePath: string,\n relativePath: string,\n): string {\n for (let suffix = 1; ; suffix += 1) {\n const label = suffix === 1 ? '.incoming' : `.incoming.${suffix}`\n const candidatePath = `${destinationPath}${label}`\n assertManagedPath(targetRoot, candidatePath, { leaf: 'file' })\n if (!existsSync(candidatePath)) {\n atomicCopyFile(sourcePath, candidatePath, targetRoot)\n return `${relativePath}${label}`\n }\n if (hashFile(candidatePath) === hashFile(sourcePath)) return `${relativePath}${label}`\n }\n}\n\nexport function applyHarnessUpdate(\n targetDir: string,\n stagingDir: string,\n options: { force?: boolean } = {},\n): HarnessUpdateConflict[] {\n const targetRoot = canonicalHarnessRoot(targetDir)\n const stagingRoot = canonicalHarnessRoot(stagingDir)\n const targetManifestPath = join(targetRoot, '.ai', 'harness', 'manifest.json')\n const stagingManifestPath = join(stagingRoot, '.ai', 'harness', 'manifest.json')\n assertManagedPath(targetRoot, targetManifestPath, { leaf: 'file' })\n assertManagedPath(stagingRoot, stagingManifestPath, { leaf: 'file' })\n const candidateManifest = readHarnessManifest(stagingManifestPath)\n if (!candidateManifest) {\n throw new Error('Generated harness candidate has a missing or invalid ownership manifest.')\n }\n\n const previousManifest = readHarnessManifest(targetManifestPath)\n const previousFiles = new Map(previousManifest?.files.map((entry) => [entry.path, entry]) ?? [])\n const candidatePaths = new Set(candidateManifest.files.map((entry) => entry.path))\n const candidates: Array<{\n entry: HarnessManifestFile\n sourcePath: string\n destinationPath: string\n }> = []\n\n // Validate the complete candidate before writing anything into the app.\n for (const entry of candidateManifest.files) {\n const sourcePath = resolveManifestPath(stagingRoot, entry.path)\n const destinationPath = resolveManifestPath(targetRoot, entry.path)\n if (sourcePath) assertManagedPath(stagingRoot, sourcePath, { leaf: 'file' })\n if (destinationPath) assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n if (!sourcePath || !destinationPath || !existsSync(sourcePath) || hashFile(sourcePath) !== entry.sha256) {\n throw new Error(`Generated harness candidate is invalid for ${JSON.stringify(entry.path)}.`)\n }\n candidates.push({ entry, sourcePath, destinationPath })\n }\n\n const conflicts: HarnessUpdateConflict[] = []\n for (const { entry, sourcePath, destinationPath } of candidates) {\n if (options.force) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n if (!existsSync(destinationPath)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const currentHash = hashFile(destinationPath)\n const previousEntry = previousFiles.get(entry.path)\n if (currentHash === entry.sha256 || (previousEntry && currentHash === previousEntry.sha256)) {\n atomicCopyFile(sourcePath, destinationPath, targetRoot)\n continue\n }\n\n const candidate = preserveIncomingCandidate(targetRoot, destinationPath, sourcePath, entry.path)\n conflicts.push({ path: entry.path, candidate })\n }\n\n const retainedRetiredEntries: HarnessManifestFile[] = []\n for (const previousEntry of previousManifest?.files ?? []) {\n if (candidatePaths.has(previousEntry.path)) continue\n const destinationPath = resolveManifestPath(targetRoot, previousEntry.path)\n if (!destinationPath || !existsSync(destinationPath)) continue\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n const isRetiredFlatModuleFact = !previousEntry.userEditable\n && /^\\.ai\\/guides\\/(?:modules|reference-modules)\\/[^/]+\\.md$/.test(previousEntry.path)\n if (isRetiredFlatModuleFact) {\n rmSync(destinationPath, { force: true })\n continue\n }\n let unchanged = false\n try {\n unchanged = hashFile(destinationPath) === previousEntry.sha256\n } catch {\n // A user may replace a generated file with another filesystem object.\n // Preserve it and retain the ownership tombstone for a later review.\n }\n if (unchanged) {\n assertManagedPath(targetRoot, dirname(destinationPath))\n assertManagedPath(targetRoot, destinationPath, { leaf: 'file' })\n rmSync(destinationPath, { force: true })\n } else {\n retainedRetiredEntries.push(previousEntry)\n conflicts.push({ path: previousEntry.path, candidate: null })\n }\n }\n\n // The candidate hashes deliberately remain in the manifest for conflicts. If\n // the user accepts an .incoming file, a later update can recognize it as an\n // unmodified owned file. Until then the hash mismatch keeps preserving it.\n const finalManifest: HarnessManifest = {\n ...candidateManifest,\n files: [...candidateManifest.files, ...retainedRetiredEntries],\n }\n atomicWriteFile(targetManifestPath, `${JSON.stringify(finalManifest, null, 2)}\\n`, targetRoot)\n return conflicts\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // Resolve which per-module fact-sheets this app gets (enabled \u2229 bundled allowlist).\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n\n // One recursive mapping mirrors create-app's shared emitter.\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n copyTree(join(srcDir, 'ai'), join(targetDir, '.ai'), config)\n copyTree(join(srcDir, 'scripts'), join(targetDir, 'scripts'), config)\n\n // Routed conceptual guides are copied wholesale (framework-wide). Per-module\n // fact-sheets (.ai/guides/modules/<module>/) are filtered to the app's enabled\n // module set; the combined v1 and corrected v2 module-facts sidecars are copied as-is.\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n\n const moduleFactsPath = join(GUIDES_DIR, 'module-facts.json')\n if (existsSync(moduleFactsPath)) {\n const destPath = join(guidesDestDir, 'module-facts.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsPath, destPath)\n }\n\n const moduleFactsV2Path = join(GUIDES_DIR, 'module-facts.v2.json')\n if (existsSync(moduleFactsV2Path)) {\n const destPath = join(guidesDestDir, 'module-facts.v2.json')\n ensureDir(destPath)\n copyFileSync(moduleFactsV2Path, destPath)\n }\n\n const referenceFactsPath = join(GUIDES_DIR, 'reference-module-facts.json')\n if (existsSync(referenceFactsPath)) {\n const destPath = join(guidesDestDir, 'reference-module-facts.json')\n ensureDir(destPath)\n copyFileSync(referenceFactsPath, destPath)\n }\n\n copyTree(join(GUIDES_DIR, 'upstream'), join(guidesDestDir, 'upstream'), config)\n copyTree(join(GUIDES_DIR, 'reference-modules'), join(guidesDestDir, 'reference-modules'), config)\n\n const modulesSubdir = join(GUIDES_DIR, 'modules')\n for (const moduleId of selectedModules) {\n copyTree(join(modulesSubdir, moduleId), join(guidesDestDir, 'modules', moduleId), config)\n }\n }\n\n injectModuleGuides(join(targetDir, 'AGENTS.md'), selectedModules)\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n for (const hook of claudeHookFiles()) {\n copyFile(srcDir, `hooks/${hook}`, join(targetDir, '.claude', 'hooks', hook))\n }\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // The installer exclusively owns Claude's per-skill compatibility links.\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // No .codex/skills directory: Codex reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // No .cursor/skills directory: Cursor reads the canonical .agents/skills/,\n // which scripts/install-skills.sh populates.\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nfunction persistedAgentSelection(targetDir: string): string[] | null {\n const selectableIds = SELECTABLE.map((tool) => tool.id)\n const tiersPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n try {\n const tiers = JSON.parse(readFileSync(tiersPath, 'utf8')) as { agents?: { ignore?: unknown } }\n if (Array.isArray(tiers.agents?.ignore)\n && tiers.agents.ignore.every((id): id is string => typeof id === 'string')) {\n const ignored = new Set(tiers.agents.ignore)\n return selectableIds.filter((id) => !ignored.has(id))\n }\n } catch {\n // Fall through to the ownership manifest and existing generated assets.\n }\n\n const manifest = readHarnessManifest(join(targetDir, '.ai', 'harness', 'manifest.json'))\n const owned = new Set(manifest?.files.map((entry) => entry.path) ?? [])\n const selected = SELECTABLE.filter((tool) => {\n if (tool.id === 'claude-code') {\n return owned.has('CLAUDE.md') || owned.has('.claude/settings.json')\n || existsSync(join(targetDir, 'CLAUDE.md')) || existsSync(join(targetDir, '.claude', 'settings.json'))\n }\n if (tool.id === 'codex') {\n return owned.has('.codex/mcp.json.example') || existsSync(join(targetDir, '.codex', 'mcp.json.example'))\n }\n return owned.has('.cursor/hooks.json') || existsSync(join(targetDir, '.cursor', 'hooks.json'))\n }).map((tool) => tool.id)\n return selected.length > 0 ? selected : null\n}\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else if (options?.updateHarness) {\n selectedIds = persistedAgentSelection(targetDir) ?? await promptSelection(ask)\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n const stagingDir = mkdtempSync(join(tmpdir(), 'open-mercato-harness-'))\n try {\n const modulesSourcePath = join(targetDir, 'src', 'modules.ts')\n const modulesCandidatePath = join(stagingDir, 'src', 'modules.ts')\n if (existsSync(modulesSourcePath)) {\n ensureDir(modulesCandidatePath)\n copyFileSync(modulesSourcePath, modulesCandidatePath)\n }\n\n const stagingConfig: AgenticConfig = {\n projectName: config.projectName,\n targetDir: stagingDir,\n }\n generateHarness(stagingConfig, selectedIds)\n const conflicts = applyHarnessUpdate(targetDir, stagingDir, {\n force: options?.force,\n })\n if (conflicts.length > 0) {\n console.warn('')\n console.warn(' \u26A0 Preserved locally modified harness files:')\n for (const conflict of conflicts) {\n const detail = conflict.candidate\n ? `candidate: ${conflict.candidate}`\n : 'retired asset kept because it has local changes'\n console.warn(` \u2022 ${conflict.path} (${detail})`)\n }\n }\n } finally {\n rmSync(stagingDir, { recursive: true, force: true })\n }\n\n installSkills(targetDir)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n console.log(' .ai/agentic.config.json ships preconfigured (GitHub tracker, labels off);')\n console.log(' run /om-setup-agent-pipeline in your agent CLI to tailor labels, QA gate,')\n console.log(' tracker, or validation commands. Re-run `yarn install-skills` anytime to')\n console.log(' refresh the external open-mercato/skills subset.')\n console.log('')\n}\n\nfunction generateHarness(config: AgenticConfig, selectedIds: string[]): void {\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n enforceGeneratedRootBudget(config)\n\n persistAgentSelection(config.targetDir, selectedIds)\n finalizeHarnessManifest(config, selectedIds)\n}\n\n/** Run after every tool generator has patched AGENTS.md, before the manifest is hashed. */\nfunction enforceGeneratedRootBudget(\n config: AgenticConfig,\n maxBytes: number = STANDALONE_ROOT_TARGET_BYTES,\n): boolean {\n const { targetDir } = config\n const selectedModules = selectModuleFactSheets(targetDir, join(GUIDES_DIR, 'modules'))\n return enforceRootInstructionBudget(join(targetDir, 'AGENTS.md'), selectedModules, maxBytes)\n}\n\n/**\n * Persist the agent selection so later `yarn install-skills` runs keep honoring\n * it: agents the user did not pick go into `agents.ignore` in tiers.json and\n * never get a skills directory of their own.\n */\nfunction persistAgentSelection(targetDir: string, selectedIds: string[]): void {\n const manifestPath = join(targetDir, '.ai', 'skills', 'tiers.json')\n if (!existsSync(manifestPath)) return\n const ignore = SELECTABLE.map((tool) => tool.id).filter((id) => !selectedIds.includes(id))\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<string, unknown>\n if (ignore.length > 0) {\n manifest.agents = { ignore }\n } else {\n delete manifest.agents\n }\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`)\n}\n\nfunction installSkills(targetDir: string): void {\n const installScript = join(targetDir, 'scripts', 'install-skills.mjs')\n if (!existsSync(installScript)) return\n console.log('')\n console.log(' Installing agent skills (local tiers + external open-mercato/skills subset)...')\n const result = spawnSync(process.execPath, [installScript], {\n cwd: targetDir,\n stdio: 'inherit',\n env: { ...process.env, OM_SKILLS_OUTPUT_INDENT: '3' },\n })\n if (result.error || result.status !== 0) {\n console.log(' \u26A0 Skill installation did not complete; run `yarn install-skills` inside the app when online.')\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -36,10 +36,12 @@ async function generateModuleDi(options) {
|
|
|
36
36
|
const usePkg = resolveModuleConventionFile(roots.pkgBase, "di");
|
|
37
37
|
const importName = `D_${toVar(modId)}_${i++}`;
|
|
38
38
|
if (useApp) {
|
|
39
|
+
warnIfDiMissingRegisterExport(findModuleConventionFilePath(roots.appBase, "di"), quiet);
|
|
39
40
|
const importPath = isAppModule ? `../../src/modules/${modId}/di` : `${imp.appBase}/di`;
|
|
40
41
|
imports.push({ name: importName, moduleSpecifier: importPath });
|
|
41
42
|
registrars.push(`${importName}.register`);
|
|
42
43
|
} else if (usePkg) {
|
|
44
|
+
warnIfDiMissingRegisterExport(findModuleConventionFilePath(roots.pkgBase, "di"), quiet);
|
|
43
45
|
imports.push({ name: importName, moduleSpecifier: `${imp.pkgBase}/di` });
|
|
44
46
|
registrars.push(`${importName}.register`);
|
|
45
47
|
}
|
|
@@ -88,7 +90,29 @@ async function generateModuleDi(options) {
|
|
|
88
90
|
function resolveModuleConventionFile(baseDir, basename) {
|
|
89
91
|
return MODULE_CODE_EXTENSIONS.some((extension) => fs.existsSync(path.join(baseDir, `${basename}${extension}`)));
|
|
90
92
|
}
|
|
93
|
+
function findModuleConventionFilePath(baseDir, basename) {
|
|
94
|
+
for (const extension of MODULE_CODE_EXTENSIONS) {
|
|
95
|
+
const candidate = path.join(baseDir, `${basename}${extension}`);
|
|
96
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
function warnIfDiMissingRegisterExport(diPath, quiet = false) {
|
|
101
|
+
if (!diPath || quiet) return;
|
|
102
|
+
let source = "";
|
|
103
|
+
try {
|
|
104
|
+
source = fs.readFileSync(diPath, "utf8");
|
|
105
|
+
} catch {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const exportsRegister = /export\s+(async\s+)?function\s+register\b/.test(source) || /export\s+(const|let|var)\s+register\b/.test(source) || /export\s*\{[^}]*\bregister\b[^}]*\}/.test(source);
|
|
109
|
+
if (exportsRegister) return;
|
|
110
|
+
console.warn(
|
|
111
|
+
`[generate] \u26A0 di.ts exports no 'register' \u2014 this module's DI registrations will never run: ${diPath}`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
91
114
|
export {
|
|
92
|
-
generateModuleDi
|
|
115
|
+
generateModuleDi,
|
|
116
|
+
warnIfDiMissingRegisterExport
|
|
93
117
|
};
|
|
94
118
|
//# sourceMappingURL=module-di.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/generators/module-di.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n toVar,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n} from '../utils'\nimport {\n addAutoGeneratedComment,\n addImportSpec,\n arrayLiteral,\n createGeneratedSourceFile,\n getSourceText,\n identifier,\n methodCall,\n parenthesized,\n} from './ast'\n\nexport interface ModuleDiOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\nexport async function generateModuleDi(options: ModuleDiOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'di.generated.ts')\n const checksumFile = path.join(outputDir, 'di.generated.checksum')\n\n const mods = resolver.loadEnabledModules()\n const imports: Array<{ name: string; moduleSpecifier: string }> = []\n const registrars: string[] = []\n let i = 0\n\n for (const entry of mods) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imp = resolver.getModuleImportBase(entry)\n const isAppModule = entry.from === '@app'\n\n const useApp = resolveModuleConventionFile(roots.appBase, 'di')\n const usePkg = resolveModuleConventionFile(roots.pkgBase, 'di')\n const importName = `D_${toVar(modId)}_${i++}`\n\n if (useApp) {\n // For @app modules, use relative path to work in both Next.js and Node.js CLI context\n // From .mercato/generated/, go up two levels (../..) to reach the app root, then into src/modules/\n const importPath = isAppModule ? `../../src/modules/${modId}/di` : `${imp.appBase}/di`\n imports.push({ name: importName, moduleSpecifier: importPath })\n registrars.push(`${importName}.register`)\n } else if (usePkg) {\n imports.push({ name: importName, moduleSpecifier: `${imp.pkgBase}/di` })\n registrars.push(`${importName}.register`)\n }\n }\n\n const sourceFile = createGeneratedSourceFile('di.generated.ts')\n addAutoGeneratedComment(sourceFile, 'di')\n imports.forEach((entry) => {\n addImportSpec(sourceFile, {\n kind: StructureKind.ImportDeclaration,\n namespaceImport: entry.name,\n moduleSpecifier: entry.moduleSpecifier,\n })\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'diRegistrars',\n type: '(((c: any) => void) | undefined)[]',\n initializer: methodCall(\n parenthesized(arrayLiteral(registrars, (currentWriter, registrar) => identifier(registrar)(currentWriter))),\n 'filter',\n [identifier('Boolean')],\n ),\n },\n ],\n })\n sourceFile.addExportDeclaration({\n namedExports: ['diRegistrars'],\n })\n sourceFile.addExportAssignment({\n isExportEquals: false,\n expression: 'diRegistrars',\n })\n const output = getSourceText(sourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: output,\n structureChecksum: '',\n result,\n quiet,\n })\n\n return result\n}\n\nfunction resolveModuleConventionFile(baseDir: string, basename: string): boolean {\n return MODULE_CODE_EXTENSIONS.some((extension) => fs.existsSync(path.join(baseDir, `${basename}${extension}`)))\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,eAAe,+BAA+B;AAEvD,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOP,eAAsB,iBAAiB,SAAoD;AACzF,QAAM,EAAE,UAAU,QAAQ,MAAM,IAAI;AACpC,QAAM,SAAS,sBAAsB;AAErC,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,UAAU,KAAK,KAAK,WAAW,iBAAiB;AACtD,QAAM,eAAe,KAAK,KAAK,WAAW,uBAAuB;AAEjE,QAAM,OAAO,SAAS,mBAAmB;AACzC,QAAM,UAA4D,CAAC;AACnE,QAAM,aAAuB,CAAC;AAC9B,MAAI,IAAI;AAER,aAAW,SAAS,MAAM;AACxB,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,SAAS,eAAe,KAAK;AAC3C,UAAM,MAAM,SAAS,oBAAoB,KAAK;AAC9C,UAAM,cAAc,MAAM,SAAS;AAEnC,UAAM,SAAS,4BAA4B,MAAM,SAAS,IAAI;AAC9D,UAAM,SAAS,4BAA4B,MAAM,SAAS,IAAI;AAC9D,UAAM,aAAa,KAAK,MAAM,KAAK,CAAC,IAAI,GAAG;AAE3C,QAAI,QAAQ;
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport { StructureKind, VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n toVar,\n type GeneratorResult,\n createGeneratorResult,\n writeGeneratedFile,\n} from '../utils'\nimport {\n addAutoGeneratedComment,\n addImportSpec,\n arrayLiteral,\n createGeneratedSourceFile,\n getSourceText,\n identifier,\n methodCall,\n parenthesized,\n} from './ast'\n\nexport interface ModuleDiOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\nexport async function generateModuleDi(options: ModuleDiOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'di.generated.ts')\n const checksumFile = path.join(outputDir, 'di.generated.checksum')\n\n const mods = resolver.loadEnabledModules()\n const imports: Array<{ name: string; moduleSpecifier: string }> = []\n const registrars: string[] = []\n let i = 0\n\n for (const entry of mods) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imp = resolver.getModuleImportBase(entry)\n const isAppModule = entry.from === '@app'\n\n const useApp = resolveModuleConventionFile(roots.appBase, 'di')\n const usePkg = resolveModuleConventionFile(roots.pkgBase, 'di')\n const importName = `D_${toVar(modId)}_${i++}`\n\n if (useApp) {\n warnIfDiMissingRegisterExport(findModuleConventionFilePath(roots.appBase, 'di'), quiet)\n // For @app modules, use relative path to work in both Next.js and Node.js CLI context\n // From .mercato/generated/, go up two levels (../..) to reach the app root, then into src/modules/\n const importPath = isAppModule ? `../../src/modules/${modId}/di` : `${imp.appBase}/di`\n imports.push({ name: importName, moduleSpecifier: importPath })\n registrars.push(`${importName}.register`)\n } else if (usePkg) {\n warnIfDiMissingRegisterExport(findModuleConventionFilePath(roots.pkgBase, 'di'), quiet)\n imports.push({ name: importName, moduleSpecifier: `${imp.pkgBase}/di` })\n registrars.push(`${importName}.register`)\n }\n }\n\n const sourceFile = createGeneratedSourceFile('di.generated.ts')\n addAutoGeneratedComment(sourceFile, 'di')\n imports.forEach((entry) => {\n addImportSpec(sourceFile, {\n kind: StructureKind.ImportDeclaration,\n namespaceImport: entry.name,\n moduleSpecifier: entry.moduleSpecifier,\n })\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'diRegistrars',\n type: '(((c: any) => void) | undefined)[]',\n initializer: methodCall(\n parenthesized(arrayLiteral(registrars, (currentWriter, registrar) => identifier(registrar)(currentWriter))),\n 'filter',\n [identifier('Boolean')],\n ),\n },\n ],\n })\n sourceFile.addExportDeclaration({\n namedExports: ['diRegistrars'],\n })\n sourceFile.addExportAssignment({\n isExportEquals: false,\n expression: 'diRegistrars',\n })\n const output = getSourceText(sourceFile)\n\n writeGeneratedFile({\n outFile,\n checksumFile,\n content: output,\n structureChecksum: '',\n result,\n quiet,\n })\n\n return result\n}\n\nfunction resolveModuleConventionFile(baseDir: string, basename: string): boolean {\n return MODULE_CODE_EXTENSIONS.some((extension) => fs.existsSync(path.join(baseDir, `${basename}${extension}`)))\n}\n\nfunction findModuleConventionFilePath(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\n/**\n * Warns when a discovered `di.ts` exports no `register`.\n *\n * The generated registrar list is built from `<import>.register` for every module that has a\n * `di` file. A differently named export makes that entry `undefined`, so the module's DI\n * registrations silently never run and its services surface as missing at request time\n * instead of at generation time.\n */\nexport function warnIfDiMissingRegisterExport(diPath: string | null, quiet = false): void {\n if (!diPath || quiet) return\n let source = ''\n try {\n source = fs.readFileSync(diPath, 'utf8')\n } catch {\n return\n }\n const exportsRegister = /export\\s+(async\\s+)?function\\s+register\\b/.test(source)\n || /export\\s+(const|let|var)\\s+register\\b/.test(source)\n || /export\\s*\\{[^}]*\\bregister\\b[^}]*\\}/.test(source)\n if (exportsRegister) return\n console.warn(\n `[generate] \u26A0 di.ts exports no 'register' \u2014 this module's DI registrations will never run: ${diPath}`,\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -909,7 +909,7 @@ function extractCommandIdsFromSource(sourcePath) {
|
|
|
909
909
|
collectRegistrations(sourceFile);
|
|
910
910
|
return Array.from(ids).sort((a, b) => a.localeCompare(b));
|
|
911
911
|
}
|
|
912
|
-
function collectCommandLoaderEntries(roots, imps, modId) {
|
|
912
|
+
function collectCommandLoaderEntries(roots, imps, modId, quiet = false) {
|
|
913
913
|
const files = scanModuleDir(roots, COMMAND_SCAN_CONFIG);
|
|
914
914
|
const entries = [];
|
|
915
915
|
for (const file of files) {
|
|
@@ -919,11 +919,13 @@ function collectCommandLoaderEntries(roots, imps, modId) {
|
|
|
919
919
|
const logicalKey = stripModuleCodeExtension(file.relPath);
|
|
920
920
|
const basename = path.basename(logicalKey);
|
|
921
921
|
if (basename === "shared" || basename === "factory") continue;
|
|
922
|
+
const ids = extractCommandIdsFromSource(resolved.absolutePath);
|
|
923
|
+
if (ids.length > 0) warnIfRegisterCommandNotAtImportTime(resolved.absolutePath, quiet);
|
|
922
924
|
entries.push({
|
|
923
925
|
moduleId: modId,
|
|
924
926
|
key: `${modId}:commands:${logicalKey}`,
|
|
925
927
|
importPath: resolved.importPath,
|
|
926
|
-
ids
|
|
928
|
+
ids
|
|
927
929
|
});
|
|
928
930
|
}
|
|
929
931
|
return entries;
|
|
@@ -999,6 +1001,39 @@ function findExistingModuleFileByBaseNames(baseDir, relativeBaseNames) {
|
|
|
999
1001
|
}
|
|
1000
1002
|
return null;
|
|
1001
1003
|
}
|
|
1004
|
+
const warnedConventionPaths = /* @__PURE__ */ new Set();
|
|
1005
|
+
function resetConventionWarnings() {
|
|
1006
|
+
warnedConventionPaths.clear();
|
|
1007
|
+
}
|
|
1008
|
+
function alreadyWarned(sourcePath) {
|
|
1009
|
+
if (warnedConventionPaths.has(sourcePath)) return true;
|
|
1010
|
+
warnedConventionPaths.add(sourcePath);
|
|
1011
|
+
return false;
|
|
1012
|
+
}
|
|
1013
|
+
function warnIfPageMetaMissingMetadataExport(metaPath, quiet = false) {
|
|
1014
|
+
if (!metaPath || quiet) return;
|
|
1015
|
+
if (hasNamedExport(metaPath, "metadata")) return;
|
|
1016
|
+
if (alreadyWarned(metaPath)) return;
|
|
1017
|
+
console.warn(
|
|
1018
|
+
`[generate] \u26A0 Page metadata file exports no 'metadata' \u2014 page metadata is dropped, including requireAuth/requireFeatures, so the page renders with NO authorization gate: ${metaPath}`
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
function warnIfRegisterCommandNotAtImportTime(sourcePath, quiet = false) {
|
|
1022
|
+
if (quiet) return;
|
|
1023
|
+
let source = "";
|
|
1024
|
+
try {
|
|
1025
|
+
source = fs.readFileSync(sourcePath, "utf8");
|
|
1026
|
+
} catch {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
if (!/\bregisterCommand\s*\(/.test(source)) return;
|
|
1030
|
+
const hasTopLevelCall = /^registerCommand\s*\(/m.test(source);
|
|
1031
|
+
if (hasTopLevelCall) return;
|
|
1032
|
+
if (alreadyWarned(sourcePath)) return;
|
|
1033
|
+
console.warn(
|
|
1034
|
+
`[generate] \u26A0 registerCommand(...) is never called at import time \u2014 these command ids will appear in the manifest but the handlers will not register at runtime: ${sourcePath}`
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1002
1037
|
function toModuleImportSubpath(filePath, baseDir) {
|
|
1003
1038
|
const relativePath = path.relative(baseDir, filePath).replace(/\\/g, "/");
|
|
1004
1039
|
return stripModuleCodeExtension(relativePath);
|
|
@@ -1280,7 +1315,8 @@ function discoverTranslations(roots) {
|
|
|
1280
1315
|
appHas: fs.existsSync(path.join(i18nApp, `${locale}.json`))
|
|
1281
1316
|
}));
|
|
1282
1317
|
}
|
|
1283
|
-
async function createModuleRegistryDiscovery(resolver) {
|
|
1318
|
+
async function createModuleRegistryDiscovery(resolver, quiet = false) {
|
|
1319
|
+
resetConventionWarnings();
|
|
1284
1320
|
const enabled = resolver.loadEnabledModules();
|
|
1285
1321
|
const modules = [];
|
|
1286
1322
|
const trackedRoots = /* @__PURE__ */ new Set();
|
|
@@ -1310,7 +1346,7 @@ async function createModuleRegistryDiscovery(resolver) {
|
|
|
1310
1346
|
resolve,
|
|
1311
1347
|
frontendFiles: scanModuleDir(roots, SCAN_CONFIGS.frontendPages),
|
|
1312
1348
|
backendFiles: scanModuleDir(roots, SCAN_CONFIGS.backendPages),
|
|
1313
|
-
commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId),
|
|
1349
|
+
commandLoaderEntries: collectCommandLoaderEntries(roots, imps, modId, quiet),
|
|
1314
1350
|
getSubscribers: () => subscribers ??= discoverSubscribers(roots, imps, modId),
|
|
1315
1351
|
getWorkers: () => workers ??= discoverWorkers(roots, imps, modId),
|
|
1316
1352
|
translations: discoverTranslations(roots),
|
|
@@ -1346,7 +1382,7 @@ async function loadPageMetadataForManifest(options) {
|
|
|
1346
1382
|
};
|
|
1347
1383
|
}
|
|
1348
1384
|
async function processPageFiles(options) {
|
|
1349
|
-
const { files, type, modId, appDir, pkgDir, appImportBase, pkgImportBase, eagerImports, runtimeImports, manifestImports, importIdRef } = options;
|
|
1385
|
+
const { files, type, modId, appDir, pkgDir, appImportBase, pkgImportBase, eagerImports, runtimeImports, manifestImports, importIdRef, quiet } = options;
|
|
1350
1386
|
const metaPrefix = type === "frontend" ? "M" : "BM";
|
|
1351
1387
|
const eagerRoutes = [];
|
|
1352
1388
|
const runtimeRoutes = [];
|
|
@@ -1368,6 +1404,7 @@ async function processPageFiles(options) {
|
|
|
1368
1404
|
const sourceFile = findExistingModuleFile(moduleBaseDir, pageFile);
|
|
1369
1405
|
if (!sourceFile || !hasDefaultExport(sourceFile)) continue;
|
|
1370
1406
|
const metaPath = findExistingModuleFileByBaseNames(moduleBaseDir, ["page.meta", "meta"]);
|
|
1407
|
+
warnIfPageMetaMissingMetadataExport(metaPath, quiet);
|
|
1371
1408
|
let metaExpr = "undefined";
|
|
1372
1409
|
let runtimeMetaExpr = "undefined";
|
|
1373
1410
|
let manifestMetaExpr = "undefined";
|
|
@@ -2105,7 +2142,8 @@ async function processPageFilesAst(options) {
|
|
|
2105
2142
|
appImportBase,
|
|
2106
2143
|
pkgImportBase,
|
|
2107
2144
|
imports,
|
|
2108
|
-
importIdRef
|
|
2145
|
+
importIdRef,
|
|
2146
|
+
quiet
|
|
2109
2147
|
} = options;
|
|
2110
2148
|
const routes = [];
|
|
2111
2149
|
const routePatterns = [];
|
|
@@ -2133,6 +2171,7 @@ async function processPageFilesAst(options) {
|
|
|
2133
2171
|
const sourceFile = findExistingModuleFile(moduleBaseDir, pageFile);
|
|
2134
2172
|
if (!sourceFile || !hasDefaultExport(sourceFile)) continue;
|
|
2135
2173
|
const metaPath = findExistingModuleFileByBaseNames(moduleBaseDir, ["page.meta", "meta"]);
|
|
2174
|
+
warnIfPageMetaMissingMetadataExport(metaPath, quiet);
|
|
2136
2175
|
if (metaPath) {
|
|
2137
2176
|
const metaImportName = `${metaPrefix}${importIdRef.value++}_${toVar(modId)}_${toVar(segs.join("_") || "index")}`;
|
|
2138
2177
|
const metaImportPath = sanitizeGeneratedModuleSpecifier(
|
|
@@ -2603,7 +2642,8 @@ async function generateModuleRegistryFromDiscovery(options) {
|
|
|
2603
2642
|
eagerImports: imports,
|
|
2604
2643
|
runtimeImports,
|
|
2605
2644
|
manifestImports: frontendRouteManifestImports,
|
|
2606
|
-
importIdRef
|
|
2645
|
+
importIdRef,
|
|
2646
|
+
quiet
|
|
2607
2647
|
});
|
|
2608
2648
|
frontendRoutes.push(...generatedFrontendRoutes.eagerRoutes);
|
|
2609
2649
|
runtimeFrontendRoutes.push(...generatedFrontendRoutes.runtimeRoutes);
|
|
@@ -2705,7 +2745,8 @@ async function generateModuleRegistryFromDiscovery(options) {
|
|
|
2705
2745
|
eagerImports: imports,
|
|
2706
2746
|
runtimeImports,
|
|
2707
2747
|
manifestImports: backendRouteManifestImports,
|
|
2708
|
-
importIdRef
|
|
2748
|
+
importIdRef,
|
|
2749
|
+
quiet
|
|
2709
2750
|
});
|
|
2710
2751
|
backendRoutes.push(...generatedBackendRoutes.eagerRoutes);
|
|
2711
2752
|
runtimeBackendRoutes.push(...generatedBackendRoutes.runtimeRoutes);
|
|
@@ -3183,7 +3224,8 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3183
3224
|
appImportBase,
|
|
3184
3225
|
pkgImportBase: imps.pkgBase,
|
|
3185
3226
|
imports,
|
|
3186
|
-
importIdRef
|
|
3227
|
+
importIdRef,
|
|
3228
|
+
quiet
|
|
3187
3229
|
});
|
|
3188
3230
|
frontendRoutes.push(...feAst.routes);
|
|
3189
3231
|
hasRouteComponents = true;
|
|
@@ -3203,7 +3245,8 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3203
3245
|
appImportBase,
|
|
3204
3246
|
pkgImportBase: imps.pkgBase,
|
|
3205
3247
|
imports,
|
|
3206
|
-
importIdRef
|
|
3248
|
+
importIdRef,
|
|
3249
|
+
quiet
|
|
3207
3250
|
});
|
|
3208
3251
|
backendRoutes.push(...beAst.routes);
|
|
3209
3252
|
for (const pattern of beAst.routePatterns) {
|
|
@@ -3736,19 +3779,19 @@ async function generateModuleRegistryCliFromDiscovery(options) {
|
|
|
3736
3779
|
return result;
|
|
3737
3780
|
}
|
|
3738
3781
|
async function generateModuleRegistry(options) {
|
|
3739
|
-
const discovery = await createModuleRegistryDiscovery(options.resolver);
|
|
3782
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false);
|
|
3740
3783
|
return generateModuleRegistryFromDiscovery({ ...options, discovery });
|
|
3741
3784
|
}
|
|
3742
3785
|
async function generateModuleRegistryApp(options) {
|
|
3743
|
-
const discovery = await createModuleRegistryDiscovery(options.resolver);
|
|
3786
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false);
|
|
3744
3787
|
return generateModuleRegistryAppFromDiscovery({ ...options, discovery });
|
|
3745
3788
|
}
|
|
3746
3789
|
async function generateModuleRegistryCli(options) {
|
|
3747
|
-
const discovery = await createModuleRegistryDiscovery(options.resolver);
|
|
3790
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false);
|
|
3748
3791
|
return generateModuleRegistryCliFromDiscovery({ ...options, discovery });
|
|
3749
3792
|
}
|
|
3750
3793
|
async function generateModuleRegistries(options) {
|
|
3751
|
-
const discovery = await createModuleRegistryDiscovery(options.resolver);
|
|
3794
|
+
const discovery = await createModuleRegistryDiscovery(options.resolver, options.quiet ?? false);
|
|
3752
3795
|
return [
|
|
3753
3796
|
await generateModuleRegistryFromDiscovery({ ...options, discovery }),
|
|
3754
3797
|
await generateModuleRegistryAppFromDiscovery({ ...options, discovery }),
|
|
@@ -3763,6 +3806,9 @@ export {
|
|
|
3763
3806
|
generateModuleRegistryApp,
|
|
3764
3807
|
generateModuleRegistryCli,
|
|
3765
3808
|
hasNamedExport,
|
|
3766
|
-
|
|
3809
|
+
resetConventionWarnings,
|
|
3810
|
+
resolveNamedObjectExport,
|
|
3811
|
+
warnIfPageMetaMissingMetadataExport,
|
|
3812
|
+
warnIfRegisterCommandNotAtImportTime
|
|
3767
3813
|
};
|
|
3768
3814
|
//# sourceMappingURL=module-registry.js.map
|