@open-mercato/cli 0.6.8-develop.6972.1.275e435508 → 0.6.8-develop.6974.1.43440f247a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/agentic/claude-code/settings.experimental-hooks-validator.json +37 -0
  3. package/dist/agentic/claude-code/settings.json +0 -21
  4. package/dist/agentic/cursor/hooks.experimental-hooks-validator.json +20 -0
  5. package/dist/agentic/cursor/hooks.json +0 -10
  6. package/dist/agentic/guides/module-facts.json +112 -112
  7. package/dist/agentic/guides/module-facts.v2.json +112 -112
  8. package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
  9. package/dist/agentic/guides/modules/api_docs/index.md +1 -1
  10. package/dist/agentic/guides/modules/api_keys/index.md +1 -1
  11. package/dist/agentic/guides/modules/attachments/index.md +1 -1
  12. package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
  13. package/dist/agentic/guides/modules/auth/index.md +1 -1
  14. package/dist/agentic/guides/modules/business_rules/index.md +1 -1
  15. package/dist/agentic/guides/modules/catalog/index.md +1 -1
  16. package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
  17. package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
  18. package/dist/agentic/guides/modules/checkout/index.md +1 -1
  19. package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
  20. package/dist/agentic/guides/modules/configs/index.md +1 -1
  21. package/dist/agentic/guides/modules/content/index.md +1 -1
  22. package/dist/agentic/guides/modules/currencies/index.md +1 -1
  23. package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
  24. package/dist/agentic/guides/modules/customers/index.md +1 -1
  25. package/dist/agentic/guides/modules/dashboards/index.md +1 -1
  26. package/dist/agentic/guides/modules/data_sync/index.md +1 -1
  27. package/dist/agentic/guides/modules/design_system/index.md +1 -1
  28. package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
  29. package/dist/agentic/guides/modules/directory/index.md +1 -1
  30. package/dist/agentic/guides/modules/entities/index.md +1 -1
  31. package/dist/agentic/guides/modules/eudr/index.md +1 -1
  32. package/dist/agentic/guides/modules/events/index.md +1 -1
  33. package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
  34. package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
  35. package/dist/agentic/guides/modules/generators/index.md +1 -1
  36. package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
  37. package/dist/agentic/guides/modules/integrations/index.md +1 -1
  38. package/dist/agentic/guides/modules/messages/index.md +1 -1
  39. package/dist/agentic/guides/modules/notifications/index.md +1 -1
  40. package/dist/agentic/guides/modules/onboarding/index.md +1 -1
  41. package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
  42. package/dist/agentic/guides/modules/perspectives/index.md +1 -1
  43. package/dist/agentic/guides/modules/planner/index.md +1 -1
  44. package/dist/agentic/guides/modules/portal/index.md +1 -1
  45. package/dist/agentic/guides/modules/progress/index.md +1 -1
  46. package/dist/agentic/guides/modules/query_index/index.md +1 -1
  47. package/dist/agentic/guides/modules/record_locks/index.md +1 -1
  48. package/dist/agentic/guides/modules/resources/index.md +1 -1
  49. package/dist/agentic/guides/modules/sales/index.md +1 -1
  50. package/dist/agentic/guides/modules/scheduler/index.md +1 -1
  51. package/dist/agentic/guides/modules/search/index.md +1 -1
  52. package/dist/agentic/guides/modules/security/index.md +1 -1
  53. package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
  54. package/dist/agentic/guides/modules/sso/index.md +1 -1
  55. package/dist/agentic/guides/modules/staff/index.md +1 -1
  56. package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
  57. package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
  58. package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
  59. package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
  60. package/dist/agentic/guides/modules/translations/index.md +1 -1
  61. package/dist/agentic/guides/modules/webhooks/index.md +1 -1
  62. package/dist/agentic/guides/modules/wms/index.md +1 -1
  63. package/dist/agentic/guides/modules/workflows/index.md +1 -1
  64. package/dist/agentic/guides/reference-module-facts.json +1 -1
  65. package/dist/agentic/guides/upstream/manifest.json +1 -1
  66. package/dist/lib/__integration__/TC-INT-008.spec.js +77 -4
  67. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  68. package/dist/lib/agentic-init.js +4 -1
  69. package/dist/lib/agentic-init.js.map +2 -2
  70. package/dist/lib/agentic-setup.js +59 -12
  71. package/dist/lib/agentic-setup.js.map +2 -2
  72. package/package.json +6 -6
  73. package/src/lib/__integration__/TC-INT-008.spec.ts +88 -6
  74. package/src/lib/__tests__/agentic-init.test.ts +53 -5
  75. package/src/lib/agentic-init.ts +4 -0
  76. package/src/lib/agentic-setup.ts +67 -10
@@ -35,8 +35,8 @@ function runCommand(command, args, cwd, env = {}) {
35
35
  }
36
36
  });
37
37
  }
38
- function runMercato(args, cwd) {
39
- return runCommand(process.execPath, [cliBin, ...args], cwd);
38
+ function runMercato(args, cwd, env = {}) {
39
+ return runCommand(process.execPath, [cliBin, ...args], cwd, env);
40
40
  }
41
41
  function writeFile(filePath, content) {
42
42
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
@@ -133,10 +133,14 @@ function mapClaudeSourceToOutput(relativePath) {
133
133
  if (relativePath === "settings.json") {
134
134
  return ".claude/settings.json";
135
135
  }
136
+ if (relativePath === "settings.experimental-hooks-validator.json") {
137
+ return null;
138
+ }
136
139
  if (relativePath === "mcp.json.example") {
137
140
  return ".mcp.json.example";
138
141
  }
139
142
  if (relativePath.startsWith("hooks/")) {
143
+ if (relativePath.includes("gate-evidence.")) return null;
140
144
  return normalizePath(path.join(".claude", relativePath));
141
145
  }
142
146
  throw new Error(`Unexpected Claude source path: ${relativePath}`);
@@ -145,10 +149,14 @@ function mapCursorSourceToOutput(relativePath) {
145
149
  if (relativePath === "hooks.json") {
146
150
  return ".cursor/hooks.json";
147
151
  }
152
+ if (relativePath === "hooks.experimental-hooks-validator.json") {
153
+ return null;
154
+ }
148
155
  if (relativePath === "mcp.json.example") {
149
156
  return ".cursor/mcp.json.example";
150
157
  }
151
158
  if (relativePath.startsWith("hooks/") || relativePath.startsWith("rules/")) {
159
+ if (relativePath.includes("gate-evidence.")) return null;
152
160
  return normalizePath(path.join(".cursor", relativePath));
153
161
  }
154
162
  throw new Error(`Unexpected Cursor source path: ${relativePath}`);
@@ -160,6 +168,9 @@ function mapCodexSourceToOutput(relativePath) {
160
168
  if (relativePath === "enforcement-rules.md") {
161
169
  return null;
162
170
  }
171
+ if (relativePath === "hooks.json" || relativePath === "hooks/gate-evidence.mjs") {
172
+ return null;
173
+ }
163
174
  throw new Error(`Unexpected Codex source path: ${relativePath}`);
164
175
  }
165
176
  function readPlaywrightConfigPathFromTemplate() {
@@ -246,11 +257,25 @@ test.describe("TC-INT-008: CLI agentic init mirrors standalone scaffolding asset
246
257
  expect(commandOutput).toContain("Agentic setup complete:");
247
258
  expect(fs.existsSync(path.join(appDir, ".mercato", "generated"))).toBe(false);
248
259
  const sharedOutputs = listRelativeFiles(path.join(agenticRoot, "shared")).map(mapSharedSourceToOutput);
249
- const claudeOutputs = listRelativeFiles(path.join(agenticRoot, "claude-code")).map(mapClaudeSourceToOutput);
250
- const cursorOutputs = listRelativeFiles(path.join(agenticRoot, "cursor")).map(mapCursorSourceToOutput);
260
+ const claudeOutputs = listRelativeFiles(path.join(agenticRoot, "claude-code")).map(mapClaudeSourceToOutput).filter((relativePath) => relativePath !== null);
261
+ const cursorOutputs = listRelativeFiles(path.join(agenticRoot, "cursor")).map(mapCursorSourceToOutput).filter((relativePath) => relativePath !== null);
251
262
  const codexOutputs = listRelativeFiles(path.join(agenticRoot, "codex")).map(mapCodexSourceToOutput).filter((relativePath) => relativePath !== null);
252
263
  expect(sharedOutputs).toContain(standalonePlaywrightConfigPath);
253
264
  assertPathsExist(appDir, [...sharedOutputs, ...claudeOutputs, ...cursorOutputs, ...codexOutputs]);
265
+ for (const relativePath of [
266
+ ".claude/hooks/gate-evidence.ts",
267
+ ".codex/hooks.json",
268
+ ".codex/hooks/gate-evidence.mjs",
269
+ ".cursor/hooks/gate-evidence.mjs"
270
+ ]) {
271
+ expect(fs.existsSync(path.join(appDir, relativePath))).toBe(false);
272
+ }
273
+ expect(fs.readFileSync(path.join(appDir, ".claude", "settings.json"), "utf8")).not.toContain("gate-evidence");
274
+ expect(fs.readFileSync(path.join(appDir, ".cursor", "hooks.json"), "utf8")).not.toContain("gate-evidence");
275
+ const defaultManifest = JSON.parse(
276
+ fs.readFileSync(path.join(appDir, ".ai", "harness", "manifest.json"), "utf8")
277
+ );
278
+ expect(defaultManifest.files.some((entry) => entry.path.includes("gate-evidence"))).toBe(false);
254
279
  expect(fs.existsSync(path.join(appDir, standalonePlaywrightConfigPath))).toBe(true);
255
280
  const generatedGuideNames = listRelativeFiles(path.join(appDir, ".ai", "guides"));
256
281
  expect(generatedGuideNames).toEqual(expectedGuideOutputNames());
@@ -289,6 +314,54 @@ test.describe("TC-INT-008: CLI agentic init mirrors standalone scaffolding asset
289
314
  fs.rmSync(tempRoot, { recursive: true, force: true });
290
315
  }
291
316
  });
317
+ test("installs gate-evidence hooks only through the explicit flag or environment opt-in", () => {
318
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-cli-agentic-hooks-"));
319
+ try {
320
+ const flagAppDir = createStandaloneFixture(path.join(tempRoot, "flag"));
321
+ runMercato([
322
+ "agentic:init",
323
+ "--tool=claude-code,codex,cursor",
324
+ "--experimental-hooks-validator"
325
+ ], flagAppDir);
326
+ assertPathsExist(flagAppDir, [
327
+ ".claude/hooks/gate-evidence.ts",
328
+ ".codex/hooks.json",
329
+ ".codex/hooks/gate-evidence.mjs",
330
+ ".cursor/hooks/gate-evidence.mjs"
331
+ ]);
332
+ expect(fs.readFileSync(path.join(flagAppDir, ".claude", "settings.json"), "utf8")).toContain("gate-evidence");
333
+ expect(fs.readFileSync(path.join(flagAppDir, ".cursor", "hooks.json"), "utf8")).toContain("gate-evidence");
334
+ const enabledManifest = JSON.parse(
335
+ fs.readFileSync(path.join(flagAppDir, ".ai", "harness", "manifest.json"), "utf8")
336
+ );
337
+ expect(enabledManifest.files.filter((entry) => entry.path.includes("gate-evidence"))).toHaveLength(3);
338
+ runMercato([
339
+ "agentic:init",
340
+ "--tool=claude-code,codex,cursor",
341
+ "--update-harness"
342
+ ], flagAppDir);
343
+ for (const relativePath of [
344
+ ".claude/hooks/gate-evidence.ts",
345
+ ".codex/hooks.json",
346
+ ".codex/hooks/gate-evidence.mjs",
347
+ ".cursor/hooks/gate-evidence.mjs"
348
+ ]) {
349
+ expect(fs.existsSync(path.join(flagAppDir, relativePath))).toBe(false);
350
+ }
351
+ expect(fs.readFileSync(path.join(flagAppDir, ".claude", "settings.json"), "utf8")).not.toContain("gate-evidence");
352
+ expect(fs.readFileSync(path.join(flagAppDir, ".cursor", "hooks.json"), "utf8")).not.toContain("gate-evidence");
353
+ const envAppDir = createStandaloneFixture(path.join(tempRoot, "environment"));
354
+ runMercato(["agentic:init", "--tool=codex"], envAppDir, {
355
+ OM_HARNESS_EXPERIMENTAL_HOOKS_VALIDATOR: "1"
356
+ });
357
+ assertPathsExist(envAppDir, [
358
+ ".codex/hooks.json",
359
+ ".codex/hooks/gate-evidence.mjs"
360
+ ]);
361
+ } finally {
362
+ fs.rmSync(tempRoot, { recursive: true, force: true });
363
+ }
364
+ });
292
365
  test("emits a runnable exact-version framework context escape hatch for an installed package", () => {
293
366
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-cli-framework-context-"));
294
367
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/__integration__/TC-INT-008.spec.ts"],
4
- "sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliDir = path.join(repoRoot, 'packages', 'cli')\nconst cliBin = path.join(cliDir, 'dist', 'bin.js')\nconst cliBuildScript = path.join(cliDir, 'build.mjs')\nconst cliIntegrationRunnerPath = path.join(cliDir, 'src', 'lib', 'testing', 'integration.ts')\nconst standaloneTemplatePackageJsonPath = path.join(repoRoot, 'packages', 'create-app', 'template', 'package.json.template')\nconst agenticRoot = path.join(repoRoot, 'packages', 'create-app', 'agentic')\nconst packagesRoot = path.join(repoRoot, 'packages')\nconst coreVersion = JSON.parse(fs.readFileSync(path.join(packagesRoot, 'core', 'package.json'), 'utf8')).version as string\nconst UNROUTED_PACKAGE_GUIDES = new Set(['cache', 'core', 'events', 'queue', 'search', 'shared', 'ui'])\n\n// Modules the standalone fixture enables in src/modules.ts. Both are on the\n// fact-sheet allowlist, so agentic:init must ship exactly their fact-sheets\n// (enabled \u2229 allowlist \u2014 spec D6) and list them in the AGENTS.md marker block.\nconst FIXTURE_ENABLED_MODULES = ['customers', 'sales']\n\nfunction normalizePath(value: string): string {\n return value.split(path.sep).join('/')\n}\n\nfunction runCommand(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv = {}): string {\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n // Keep the test hermetic: agentic:init runs scripts/install-skills.sh,\n // whose external step (`npx skills add`) needs the network. Local tier\n // symlinks are still installed.\n OM_SKIP_EXTERNAL_SKILLS: '1',\n ...env,\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction ensureCliBuilt(): void {\n runCommand(process.execPath, [cliBuildScript], cliDir)\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n const appDir = path.join(rootDir, 'sample-store')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: 'sample-store',\n private: true,\n dependencies: { '@open-mercato/core': coreVersion },\n },\n null,\n 2,\n ),\n )\n const moduleEntries = FIXTURE_ENABLED_MODULES\n .map((moduleId) => ` { id: '${moduleId}', from: '@open-mercato/core' },`)\n .join('\\n')\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [\\n${moduleEntries}\\n]\\n`)\n return appDir\n}\n\nfunction installFakeFrameworkPackage(appDir: string): string {\n const packageRoot = path.join(appDir, 'node_modules', '@open-mercato', 'core')\n writeFile(path.join(packageRoot, 'package.json'), JSON.stringify({\n name: '@open-mercato/core',\n version: coreVersion,\n type: 'module',\n exports: { '.': './dist/index.js' },\n }))\n writeFile(path.join(packageRoot, 'dist', 'index.js'), 'export {}\\n')\n writeFile(path.join(packageRoot, 'AGENTS.md'), '# Installed core instructions\\n')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n writeFile(path.join(packageRoot, 'src', 'modules', moduleId, 'AGENTS.md'), `# Installed ${moduleId} instructions\\n`)\n writeFile(\n path.join(packageRoot, 'src', 'modules', moduleId, 'data', 'entities.ts'),\n `export class ${moduleId === 'customers' ? 'Person' : 'Sale'} {}\\n`,\n )\n }\n return packageRoot\n}\n\nfunction snapshotTextFiles(rootDir: string): Record<string, string> {\n return Object.fromEntries(\n listRelativeFiles(rootDir).map((relativePath) => [\n relativePath,\n fs.readFileSync(path.join(rootDir, relativePath), 'utf8'),\n ]),\n )\n}\n\nfunction listRelativeFiles(rootDir: string): string[] {\n if (!fs.existsSync(rootDir)) {\n return []\n }\n\n const collected: string[] = []\n for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {\n const absolutePath = path.join(rootDir, entry.name)\n if (entry.isDirectory()) {\n for (const nestedPath of listRelativeFiles(absolutePath)) {\n collected.push(path.join(entry.name, nestedPath))\n }\n continue\n }\n if (entry.isFile()) {\n collected.push(entry.name)\n }\n }\n\n return collected.map(normalizePath).sort()\n}\n\nfunction mapSharedSourceToOutput(relativePath: string): string {\n if (relativePath === 'AGENTS.md.template') {\n return 'AGENTS.md'\n }\n\n if (relativePath.startsWith('scripts/')) {\n return relativePath\n }\n\n if (!relativePath.startsWith('ai/')) {\n throw new Error(`Unexpected shared source path: ${relativePath}`)\n }\n\n return normalizePath(path.join('.ai', relativePath.slice('ai/'.length)))\n}\n\nfunction mapClaudeSourceToOutput(relativePath: string): string {\n if (relativePath === 'CLAUDE.md.template') {\n return 'CLAUDE.md'\n }\n if (relativePath === 'settings.json') {\n return '.claude/settings.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.mcp.json.example'\n }\n if (relativePath.startsWith('hooks/')) {\n return normalizePath(path.join('.claude', relativePath))\n }\n\n throw new Error(`Unexpected Claude source path: ${relativePath}`)\n}\n\nfunction mapCursorSourceToOutput(relativePath: string): string {\n if (relativePath === 'hooks.json') {\n return '.cursor/hooks.json'\n }\n if (relativePath === 'mcp.json.example') {\n return '.cursor/mcp.json.example'\n }\n if (relativePath.startsWith('hooks/') || relativePath.startsWith('rules/')) {\n return normalizePath(path.join('.cursor', relativePath))\n }\n\n throw new Error(`Unexpected Cursor source path: ${relativePath}`)\n}\n\nfunction mapCodexSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'mcp.json.example') {\n return '.codex/mcp.json.example'\n }\n if (relativePath === 'enforcement-rules.md') {\n return null\n }\n\n throw new Error(`Unexpected Codex source path: ${relativePath}`)\n}\n\nfunction readPlaywrightConfigPathFromTemplate(): string {\n const packageTemplate = JSON.parse(fs.readFileSync(standaloneTemplatePackageJsonPath, 'utf8')) as {\n scripts?: Record<string, string>\n }\n const integrationScript = packageTemplate.scripts?.['test:integration']\n if (!integrationScript) {\n throw new Error('Standalone template is missing the test:integration script')\n }\n\n const configPathMatch = integrationScript.match(/--config\\s+([^\\s]+)/)\n if (!configPathMatch?.[1]) {\n throw new Error('Standalone template test:integration script is missing --config')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction readPlaywrightConfigPathFromCliRunner(): string {\n const integrationRunnerSource = fs.readFileSync(cliIntegrationRunnerPath, 'utf8')\n const configPathMatch = integrationRunnerSource.match(/const PLAYWRIGHT_INTEGRATION_CONFIG_PATH = '([^']+)'/)\n if (!configPathMatch?.[1]) {\n throw new Error('CLI integration runner is missing PLAYWRIGHT_INTEGRATION_CONFIG_PATH')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction expectedGuideOutputNames(): string[] {\n const collected = new Set<string>()\n\n // Static conceptual guides checked into create-app (e.g. module-system.md) are\n // bundled into dist/agentic/guides by the CLI build and copied wholesale.\n const staticGuidesRoot = path.join(agenticRoot, 'guides')\n if (fs.existsSync(staticGuidesRoot)) {\n for (const entry of fs.readdirSync(staticGuidesRoot, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith('.md')) {\n collected.add(entry.name)\n }\n }\n }\n\n for (const packageName of fs.readdirSync(packagesRoot)) {\n const packageGuide = path.join(packagesRoot, packageName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(packageGuide) && !UNROUTED_PACKAGE_GUIDES.has(packageName)) {\n collected.add(`${packageName}.md`)\n }\n\n const modulesRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n if (!fs.existsSync(modulesRoot)) {\n continue\n }\n\n for (const moduleName of fs.readdirSync(modulesRoot)) {\n const moduleGuide = path.join(modulesRoot, moduleName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(moduleGuide)) {\n collected.add(`${packageName}.${moduleName}.md`)\n }\n }\n }\n\n // Generated fact-sheet artifacts (spec 2026-06-27-ts-morph-module-fact-sheets):\n // the v1/v2 sidecars and disabled local-reference projection are copied as-is,\n // while installed fact-sheets are filtered to the fixture's enabled modules. The legacy\n // core.<module>.md redirect stubs are no longer\n // emitted (#3754). framework-extension-points.md is likewise generated into\n // dist/agentic/guides by both build.mjs pipelines (#4810) rather than checked in\n // alongside the static conceptual guides, so it needs an explicit entry here.\n collected.add('module-facts.json')\n collected.add('module-facts.v2.json')\n collected.add('reference-module-facts.json')\n collected.add('framework-extension-points.md')\n collected.add('upstream/AGENTS.md')\n collected.add('upstream/BACKWARD_COMPATIBILITY.md')\n collected.add('upstream/manifest.json')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n const moduleFactsRoot = path.join(cliDir, 'dist', 'agentic', 'guides', 'modules', moduleId)\n for (const file of fs.readdirSync(moduleFactsRoot)) {\n if (file.endsWith('.md')) collected.add(normalizePath(path.join('modules', moduleId, file)))\n }\n }\n const referenceFactsRoot = path.join(cliDir, 'dist', 'agentic', 'guides', 'reference-modules')\n for (const file of listRelativeFiles(referenceFactsRoot)) {\n collected.add(normalizePath(path.join('reference-modules', file)))\n }\n\n return Array.from(collected).sort()\n}\n\nfunction assertPathsExist(appDir: string, relativePaths: string[]): void {\n const missingPaths = relativePaths.filter((relativePath) => !fs.existsSync(path.join(appDir, relativePath)))\n expect(missingPaths).toEqual([])\n}\n\ntest.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding assets', () => {\n test.beforeAll(() => {\n ensureCliBuilt()\n })\n\n test('should run bootstrap-free and generate the shared, guide, and tool-specific agentic files', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-agentic-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const standalonePlaywrightConfigPath = readPlaywrightConfigPathFromTemplate()\n const cliPlaywrightConfigPath = readPlaywrightConfigPathFromCliRunner()\n const commandOutput = runMercato(['agentic:init', '--tool=claude-code,codex,cursor'], appDir)\n\n expect(cliPlaywrightConfigPath).toBe(standalonePlaywrightConfigPath)\n expect(commandOutput).toContain('Agentic setup complete:')\n expect(fs.existsSync(path.join(appDir, '.mercato', 'generated'))).toBe(false)\n\n const sharedOutputs = listRelativeFiles(path.join(agenticRoot, 'shared')).map(mapSharedSourceToOutput)\n const claudeOutputs = listRelativeFiles(path.join(agenticRoot, 'claude-code')).map(mapClaudeSourceToOutput)\n const cursorOutputs = listRelativeFiles(path.join(agenticRoot, 'cursor')).map(mapCursorSourceToOutput)\n const codexOutputs = listRelativeFiles(path.join(agenticRoot, 'codex'))\n .map(mapCodexSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n\n expect(sharedOutputs).toContain(standalonePlaywrightConfigPath)\n assertPathsExist(appDir, [...sharedOutputs, ...claudeOutputs, ...cursorOutputs, ...codexOutputs])\n expect(fs.existsSync(path.join(appDir, standalonePlaywrightConfigPath))).toBe(true)\n\n const generatedGuideNames = listRelativeFiles(path.join(appDir, '.ai', 'guides'))\n expect(generatedGuideNames).toEqual(expectedGuideOutputNames())\n\n const agentsSource = fs.readFileSync(path.join(appDir, 'AGENTS.md'), 'utf8')\n expect(agentsSource).toContain('<!-- CODEX_ENFORCEMENT_RULES_START -->')\n expect(agentsSource).toContain('.ai/guides/upstream/BACKWARD_COMPATIBILITY.md')\n\n // The Module-Specific Guides marker block is a compact enabled-module ID\n // index (enabled \u2229 bundled) plus one progressively loaded path pattern.\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n expect(agentsSource).toContain(`\\`${moduleId}\\``)\n }\n expect(agentsSource).toContain('`.ai/guides/modules/<id>/index.md`')\n expect(agentsSource.match(/\\.ai\\/guides\\/modules\\//g)).toHaveLength(1)\n expect(agentsSource).not.toContain('`auth`')\n expect(agentsSource).not.toContain('Core CRM capabilities')\n\n const specsReadmeSource = fs.readFileSync(path.join(appDir, '.ai', 'specs', 'README.md'), 'utf8')\n expect(specsReadmeSource).toContain('sample-store')\n\n const cursorRulesSource = fs.readFileSync(path.join(appDir, '.cursor', 'rules', 'open-mercato.mdc'), 'utf8')\n expect(cursorRulesSource).toContain('sample-store')\n\n // om-spec-writing moved to the external open-mercato/skills collection\n // (installed via `yarn install-skills`), so agentic:init must not ship a copy.\n expect(fs.existsSync(path.join(appDir, '.ai', 'skills', 'om-spec-writing'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, 'scripts', 'install-skills.sh'))).toBe(true)\n\n // install-skills.sh (run by agentic:init) installs every local tier skill once,\n // into the canonical .agents/skills/. Codex and Cursor read that directory\n // natively, so they get no skills directory of their own; Claude Code cannot,\n // so it keeps a link layer pointing back at the canonical copy.\n const tiersManifest = JSON.parse(\n fs.readFileSync(path.join(agenticRoot, 'shared', 'ai', 'skills', 'tiers.json'), 'utf8'),\n ) as { default: string[]; tiers: Record<string, { skills: string[] }> }\n const defaultTierSkills = tiersManifest.default.flatMap((tierName) => tiersManifest.tiers[tierName].skills)\n expect(defaultTierSkills.length).toBeGreaterThan(0)\n\n for (const skillName of defaultTierSkills) {\n const canonicalLinkPath = path.join(appDir, '.agents', 'skills', skillName)\n expect(fs.lstatSync(canonicalLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(canonicalLinkPath))).toBe(`../../.ai/skills/${skillName}`)\n\n const claudeLinkPath = path.join(appDir, '.claude', 'skills', skillName)\n expect(fs.lstatSync(claudeLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(claudeLinkPath))).toBe(`../../.agents/skills/${skillName}`)\n }\n\n expect(fs.existsSync(path.join(appDir, '.codex', 'skills'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, '.cursor', 'skills'))).toBe(false)\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n\n test('emits a runnable exact-version framework context escape hatch for an installed package', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-framework-context-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const packageRoot = installFakeFrameworkPackage(appDir)\n const resolvedPackageRoot = fs.realpathSync(packageRoot)\n const packageBefore = snapshotTextFiles(packageRoot)\n\n runMercato(['agentic:init', '--tool=codex'], appDir)\n const generatedScript = path.join(appDir, 'scripts', 'framework-context.mjs')\n expect(fs.existsSync(generatedScript)).toBe(true)\n\n const output = runCommand(\n process.execPath,\n [generatedScript, '--module', 'customers', '--query', 'Person', '--json'],\n appDir,\n // The generated standalone helper must not depend on a globally\n // installed ripgrep binary; process.execPath is already absolute.\n { PATH: '', Path: '' },\n )\n const context = JSON.parse(output) as {\n module: string\n package: { name: string; version: string; root: string }\n sourceKind: string\n sourceRoot: string\n materializedSource: string\n instructions: Array<{ kind: string; path: string | null; materializedPath?: string }>\n boundedSearch: { status: string; matches: number; maxMatches: number; result: string }\n warnings: string[]\n }\n\n expect(context.module).toBe('customers')\n expect(context.package).toEqual({ name: '@open-mercato/core', version: coreVersion, root: resolvedPackageRoot })\n expect(context.sourceKind).toBe('source')\n expect(normalizePath(context.sourceRoot)).toBe(normalizePath(path.join(resolvedPackageRoot, 'src', 'modules', 'customers')))\n expect(context.instructions.filter((entry) => entry.path).map((entry) => entry.kind)).toEqual([\n 'standalone-root',\n 'upstream-bc',\n 'package',\n 'module-1',\n 'upstream-root',\n ])\n expect(context.instructions.filter((entry) => entry.path).every((entry) => entry.materializedPath)).toBe(true)\n expect(context.boundedSearch).toMatchObject({ status: 'matched', matches: 1, maxMatches: 200 })\n expect(fs.existsSync(path.join(appDir, context.materializedSource))).toBe(true)\n expect(fs.existsSync(path.join(appDir, context.boundedSearch.result))).toBe(true)\n expect(context.warnings.some((warning) => warning.includes('Generated facts for customers are stale'))).toBe(false)\n expect(snapshotTextFiles(packageRoot)).toEqual(packageBefore)\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliDir = path.join(repoRoot, 'packages', 'cli')\nconst cliBin = path.join(cliDir, 'dist', 'bin.js')\nconst cliBuildScript = path.join(cliDir, 'build.mjs')\nconst cliIntegrationRunnerPath = path.join(cliDir, 'src', 'lib', 'testing', 'integration.ts')\nconst standaloneTemplatePackageJsonPath = path.join(repoRoot, 'packages', 'create-app', 'template', 'package.json.template')\nconst agenticRoot = path.join(repoRoot, 'packages', 'create-app', 'agentic')\nconst packagesRoot = path.join(repoRoot, 'packages')\nconst coreVersion = JSON.parse(fs.readFileSync(path.join(packagesRoot, 'core', 'package.json'), 'utf8')).version as string\nconst UNROUTED_PACKAGE_GUIDES = new Set(['cache', 'core', 'events', 'queue', 'search', 'shared', 'ui'])\n\n// Modules the standalone fixture enables in src/modules.ts. Both are on the\n// fact-sheet allowlist, so agentic:init must ship exactly their fact-sheets\n// (enabled \u2229 allowlist \u2014 spec D6) and list them in the AGENTS.md marker block.\nconst FIXTURE_ENABLED_MODULES = ['customers', 'sales']\n\nfunction normalizePath(value: string): string {\n return value.split(path.sep).join('/')\n}\n\nfunction runCommand(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv = {}): string {\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n // Keep the test hermetic: agentic:init runs scripts/install-skills.sh,\n // whose external step (`npx skills add`) needs the network. Local tier\n // symlinks are still installed.\n OM_SKIP_EXTERNAL_SKILLS: '1',\n ...env,\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string, env: NodeJS.ProcessEnv = {}): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd, env)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction ensureCliBuilt(): void {\n runCommand(process.execPath, [cliBuildScript], cliDir)\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n const appDir = path.join(rootDir, 'sample-store')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: 'sample-store',\n private: true,\n dependencies: { '@open-mercato/core': coreVersion },\n },\n null,\n 2,\n ),\n )\n const moduleEntries = FIXTURE_ENABLED_MODULES\n .map((moduleId) => ` { id: '${moduleId}', from: '@open-mercato/core' },`)\n .join('\\n')\n writeFile(path.join(appDir, 'src', 'modules.ts'), `export const enabledModules = [\\n${moduleEntries}\\n]\\n`)\n return appDir\n}\n\nfunction installFakeFrameworkPackage(appDir: string): string {\n const packageRoot = path.join(appDir, 'node_modules', '@open-mercato', 'core')\n writeFile(path.join(packageRoot, 'package.json'), JSON.stringify({\n name: '@open-mercato/core',\n version: coreVersion,\n type: 'module',\n exports: { '.': './dist/index.js' },\n }))\n writeFile(path.join(packageRoot, 'dist', 'index.js'), 'export {}\\n')\n writeFile(path.join(packageRoot, 'AGENTS.md'), '# Installed core instructions\\n')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n writeFile(path.join(packageRoot, 'src', 'modules', moduleId, 'AGENTS.md'), `# Installed ${moduleId} instructions\\n`)\n writeFile(\n path.join(packageRoot, 'src', 'modules', moduleId, 'data', 'entities.ts'),\n `export class ${moduleId === 'customers' ? 'Person' : 'Sale'} {}\\n`,\n )\n }\n return packageRoot\n}\n\nfunction snapshotTextFiles(rootDir: string): Record<string, string> {\n return Object.fromEntries(\n listRelativeFiles(rootDir).map((relativePath) => [\n relativePath,\n fs.readFileSync(path.join(rootDir, relativePath), 'utf8'),\n ]),\n )\n}\n\nfunction listRelativeFiles(rootDir: string): string[] {\n if (!fs.existsSync(rootDir)) {\n return []\n }\n\n const collected: string[] = []\n for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {\n const absolutePath = path.join(rootDir, entry.name)\n if (entry.isDirectory()) {\n for (const nestedPath of listRelativeFiles(absolutePath)) {\n collected.push(path.join(entry.name, nestedPath))\n }\n continue\n }\n if (entry.isFile()) {\n collected.push(entry.name)\n }\n }\n\n return collected.map(normalizePath).sort()\n}\n\nfunction mapSharedSourceToOutput(relativePath: string): string {\n if (relativePath === 'AGENTS.md.template') {\n return 'AGENTS.md'\n }\n\n if (relativePath.startsWith('scripts/')) {\n return relativePath\n }\n\n if (!relativePath.startsWith('ai/')) {\n throw new Error(`Unexpected shared source path: ${relativePath}`)\n }\n\n return normalizePath(path.join('.ai', relativePath.slice('ai/'.length)))\n}\n\nfunction mapClaudeSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'CLAUDE.md.template') {\n return 'CLAUDE.md'\n }\n if (relativePath === 'settings.json') {\n return '.claude/settings.json'\n }\n if (relativePath === 'settings.experimental-hooks-validator.json') {\n return null\n }\n if (relativePath === 'mcp.json.example') {\n return '.mcp.json.example'\n }\n if (relativePath.startsWith('hooks/')) {\n if (relativePath.includes('gate-evidence.')) return null\n return normalizePath(path.join('.claude', relativePath))\n }\n\n throw new Error(`Unexpected Claude source path: ${relativePath}`)\n}\n\nfunction mapCursorSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'hooks.json') {\n return '.cursor/hooks.json'\n }\n if (relativePath === 'hooks.experimental-hooks-validator.json') {\n return null\n }\n if (relativePath === 'mcp.json.example') {\n return '.cursor/mcp.json.example'\n }\n if (relativePath.startsWith('hooks/') || relativePath.startsWith('rules/')) {\n if (relativePath.includes('gate-evidence.')) return null\n return normalizePath(path.join('.cursor', relativePath))\n }\n\n throw new Error(`Unexpected Cursor source path: ${relativePath}`)\n}\n\nfunction mapCodexSourceToOutput(relativePath: string): string | null {\n if (relativePath === 'mcp.json.example') {\n return '.codex/mcp.json.example'\n }\n if (relativePath === 'enforcement-rules.md') {\n return null\n }\n if (relativePath === 'hooks.json' || relativePath === 'hooks/gate-evidence.mjs') {\n return null\n }\n\n throw new Error(`Unexpected Codex source path: ${relativePath}`)\n}\n\nfunction readPlaywrightConfigPathFromTemplate(): string {\n const packageTemplate = JSON.parse(fs.readFileSync(standaloneTemplatePackageJsonPath, 'utf8')) as {\n scripts?: Record<string, string>\n }\n const integrationScript = packageTemplate.scripts?.['test:integration']\n if (!integrationScript) {\n throw new Error('Standalone template is missing the test:integration script')\n }\n\n const configPathMatch = integrationScript.match(/--config\\s+([^\\s]+)/)\n if (!configPathMatch?.[1]) {\n throw new Error('Standalone template test:integration script is missing --config')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction readPlaywrightConfigPathFromCliRunner(): string {\n const integrationRunnerSource = fs.readFileSync(cliIntegrationRunnerPath, 'utf8')\n const configPathMatch = integrationRunnerSource.match(/const PLAYWRIGHT_INTEGRATION_CONFIG_PATH = '([^']+)'/)\n if (!configPathMatch?.[1]) {\n throw new Error('CLI integration runner is missing PLAYWRIGHT_INTEGRATION_CONFIG_PATH')\n }\n\n return normalizePath(configPathMatch[1])\n}\n\nfunction expectedGuideOutputNames(): string[] {\n const collected = new Set<string>()\n\n // Static conceptual guides checked into create-app (e.g. module-system.md) are\n // bundled into dist/agentic/guides by the CLI build and copied wholesale.\n const staticGuidesRoot = path.join(agenticRoot, 'guides')\n if (fs.existsSync(staticGuidesRoot)) {\n for (const entry of fs.readdirSync(staticGuidesRoot, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith('.md')) {\n collected.add(entry.name)\n }\n }\n }\n\n for (const packageName of fs.readdirSync(packagesRoot)) {\n const packageGuide = path.join(packagesRoot, packageName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(packageGuide) && !UNROUTED_PACKAGE_GUIDES.has(packageName)) {\n collected.add(`${packageName}.md`)\n }\n\n const modulesRoot = path.join(packagesRoot, packageName, 'src', 'modules')\n if (!fs.existsSync(modulesRoot)) {\n continue\n }\n\n for (const moduleName of fs.readdirSync(modulesRoot)) {\n const moduleGuide = path.join(modulesRoot, moduleName, 'agentic', 'standalone-guide.md')\n if (fs.existsSync(moduleGuide)) {\n collected.add(`${packageName}.${moduleName}.md`)\n }\n }\n }\n\n // Generated fact-sheet artifacts (spec 2026-06-27-ts-morph-module-fact-sheets):\n // the v1/v2 sidecars and disabled local-reference projection are copied as-is,\n // while installed fact-sheets are filtered to the fixture's enabled modules. The legacy\n // core.<module>.md redirect stubs are no longer\n // emitted (#3754). framework-extension-points.md is likewise generated into\n // dist/agentic/guides by both build.mjs pipelines (#4810) rather than checked in\n // alongside the static conceptual guides, so it needs an explicit entry here.\n collected.add('module-facts.json')\n collected.add('module-facts.v2.json')\n collected.add('reference-module-facts.json')\n collected.add('framework-extension-points.md')\n collected.add('upstream/AGENTS.md')\n collected.add('upstream/BACKWARD_COMPATIBILITY.md')\n collected.add('upstream/manifest.json')\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n const moduleFactsRoot = path.join(cliDir, 'dist', 'agentic', 'guides', 'modules', moduleId)\n for (const file of fs.readdirSync(moduleFactsRoot)) {\n if (file.endsWith('.md')) collected.add(normalizePath(path.join('modules', moduleId, file)))\n }\n }\n const referenceFactsRoot = path.join(cliDir, 'dist', 'agentic', 'guides', 'reference-modules')\n for (const file of listRelativeFiles(referenceFactsRoot)) {\n collected.add(normalizePath(path.join('reference-modules', file)))\n }\n\n return Array.from(collected).sort()\n}\n\nfunction assertPathsExist(appDir: string, relativePaths: string[]): void {\n const missingPaths = relativePaths.filter((relativePath) => !fs.existsSync(path.join(appDir, relativePath)))\n expect(missingPaths).toEqual([])\n}\n\ntest.describe('TC-INT-008: CLI agentic init mirrors standalone scaffolding assets', () => {\n test.beforeAll(() => {\n ensureCliBuilt()\n })\n\n test('should run bootstrap-free and generate the shared, guide, and tool-specific agentic files', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-agentic-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const standalonePlaywrightConfigPath = readPlaywrightConfigPathFromTemplate()\n const cliPlaywrightConfigPath = readPlaywrightConfigPathFromCliRunner()\n const commandOutput = runMercato(['agentic:init', '--tool=claude-code,codex,cursor'], appDir)\n\n expect(cliPlaywrightConfigPath).toBe(standalonePlaywrightConfigPath)\n expect(commandOutput).toContain('Agentic setup complete:')\n expect(fs.existsSync(path.join(appDir, '.mercato', 'generated'))).toBe(false)\n\n const sharedOutputs = listRelativeFiles(path.join(agenticRoot, 'shared')).map(mapSharedSourceToOutput)\n const claudeOutputs = listRelativeFiles(path.join(agenticRoot, 'claude-code'))\n .map(mapClaudeSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n const cursorOutputs = listRelativeFiles(path.join(agenticRoot, 'cursor'))\n .map(mapCursorSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n const codexOutputs = listRelativeFiles(path.join(agenticRoot, 'codex'))\n .map(mapCodexSourceToOutput)\n .filter((relativePath): relativePath is string => relativePath !== null)\n\n expect(sharedOutputs).toContain(standalonePlaywrightConfigPath)\n assertPathsExist(appDir, [...sharedOutputs, ...claudeOutputs, ...cursorOutputs, ...codexOutputs])\n for (const relativePath of [\n '.claude/hooks/gate-evidence.ts',\n '.codex/hooks.json',\n '.codex/hooks/gate-evidence.mjs',\n '.cursor/hooks/gate-evidence.mjs',\n ]) {\n expect(fs.existsSync(path.join(appDir, relativePath))).toBe(false)\n }\n expect(fs.readFileSync(path.join(appDir, '.claude', 'settings.json'), 'utf8')).not.toContain('gate-evidence')\n expect(fs.readFileSync(path.join(appDir, '.cursor', 'hooks.json'), 'utf8')).not.toContain('gate-evidence')\n const defaultManifest = JSON.parse(\n fs.readFileSync(path.join(appDir, '.ai', 'harness', 'manifest.json'), 'utf8'),\n ) as { files: Array<{ path: string }> }\n expect(defaultManifest.files.some((entry) => entry.path.includes('gate-evidence'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, standalonePlaywrightConfigPath))).toBe(true)\n\n const generatedGuideNames = listRelativeFiles(path.join(appDir, '.ai', 'guides'))\n expect(generatedGuideNames).toEqual(expectedGuideOutputNames())\n\n const agentsSource = fs.readFileSync(path.join(appDir, 'AGENTS.md'), 'utf8')\n expect(agentsSource).toContain('<!-- CODEX_ENFORCEMENT_RULES_START -->')\n expect(agentsSource).toContain('.ai/guides/upstream/BACKWARD_COMPATIBILITY.md')\n\n // The Module-Specific Guides marker block is a compact enabled-module ID\n // index (enabled \u2229 bundled) plus one progressively loaded path pattern.\n for (const moduleId of FIXTURE_ENABLED_MODULES) {\n expect(agentsSource).toContain(`\\`${moduleId}\\``)\n }\n expect(agentsSource).toContain('`.ai/guides/modules/<id>/index.md`')\n expect(agentsSource.match(/\\.ai\\/guides\\/modules\\//g)).toHaveLength(1)\n expect(agentsSource).not.toContain('`auth`')\n expect(agentsSource).not.toContain('Core CRM capabilities')\n\n const specsReadmeSource = fs.readFileSync(path.join(appDir, '.ai', 'specs', 'README.md'), 'utf8')\n expect(specsReadmeSource).toContain('sample-store')\n\n const cursorRulesSource = fs.readFileSync(path.join(appDir, '.cursor', 'rules', 'open-mercato.mdc'), 'utf8')\n expect(cursorRulesSource).toContain('sample-store')\n\n // om-spec-writing moved to the external open-mercato/skills collection\n // (installed via `yarn install-skills`), so agentic:init must not ship a copy.\n expect(fs.existsSync(path.join(appDir, '.ai', 'skills', 'om-spec-writing'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, 'scripts', 'install-skills.sh'))).toBe(true)\n\n // install-skills.sh (run by agentic:init) installs every local tier skill once,\n // into the canonical .agents/skills/. Codex and Cursor read that directory\n // natively, so they get no skills directory of their own; Claude Code cannot,\n // so it keeps a link layer pointing back at the canonical copy.\n const tiersManifest = JSON.parse(\n fs.readFileSync(path.join(agenticRoot, 'shared', 'ai', 'skills', 'tiers.json'), 'utf8'),\n ) as { default: string[]; tiers: Record<string, { skills: string[] }> }\n const defaultTierSkills = tiersManifest.default.flatMap((tierName) => tiersManifest.tiers[tierName].skills)\n expect(defaultTierSkills.length).toBeGreaterThan(0)\n\n for (const skillName of defaultTierSkills) {\n const canonicalLinkPath = path.join(appDir, '.agents', 'skills', skillName)\n expect(fs.lstatSync(canonicalLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(canonicalLinkPath))).toBe(`../../.ai/skills/${skillName}`)\n\n const claudeLinkPath = path.join(appDir, '.claude', 'skills', skillName)\n expect(fs.lstatSync(claudeLinkPath).isSymbolicLink()).toBe(true)\n expect(normalizePath(fs.readlinkSync(claudeLinkPath))).toBe(`../../.agents/skills/${skillName}`)\n }\n\n expect(fs.existsSync(path.join(appDir, '.codex', 'skills'))).toBe(false)\n expect(fs.existsSync(path.join(appDir, '.cursor', 'skills'))).toBe(false)\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n\n test('installs gate-evidence hooks only through the explicit flag or environment opt-in', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-agentic-hooks-'))\n\n try {\n const flagAppDir = createStandaloneFixture(path.join(tempRoot, 'flag'))\n runMercato([\n 'agentic:init',\n '--tool=claude-code,codex,cursor',\n '--experimental-hooks-validator',\n ], flagAppDir)\n\n assertPathsExist(flagAppDir, [\n '.claude/hooks/gate-evidence.ts',\n '.codex/hooks.json',\n '.codex/hooks/gate-evidence.mjs',\n '.cursor/hooks/gate-evidence.mjs',\n ])\n expect(fs.readFileSync(path.join(flagAppDir, '.claude', 'settings.json'), 'utf8')).toContain('gate-evidence')\n expect(fs.readFileSync(path.join(flagAppDir, '.cursor', 'hooks.json'), 'utf8')).toContain('gate-evidence')\n const enabledManifest = JSON.parse(\n fs.readFileSync(path.join(flagAppDir, '.ai', 'harness', 'manifest.json'), 'utf8'),\n ) as { files: Array<{ path: string }> }\n expect(enabledManifest.files.filter((entry) => entry.path.includes('gate-evidence'))).toHaveLength(3)\n\n runMercato([\n 'agentic:init',\n '--tool=claude-code,codex,cursor',\n '--update-harness',\n ], flagAppDir)\n for (const relativePath of [\n '.claude/hooks/gate-evidence.ts',\n '.codex/hooks.json',\n '.codex/hooks/gate-evidence.mjs',\n '.cursor/hooks/gate-evidence.mjs',\n ]) {\n expect(fs.existsSync(path.join(flagAppDir, relativePath))).toBe(false)\n }\n expect(fs.readFileSync(path.join(flagAppDir, '.claude', 'settings.json'), 'utf8')).not.toContain('gate-evidence')\n expect(fs.readFileSync(path.join(flagAppDir, '.cursor', 'hooks.json'), 'utf8')).not.toContain('gate-evidence')\n\n const envAppDir = createStandaloneFixture(path.join(tempRoot, 'environment'))\n runMercato(['agentic:init', '--tool=codex'], envAppDir, {\n OM_HARNESS_EXPERIMENTAL_HOOKS_VALIDATOR: '1',\n })\n assertPathsExist(envAppDir, [\n '.codex/hooks.json',\n '.codex/hooks/gate-evidence.mjs',\n ])\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n\n test('emits a runnable exact-version framework context escape hatch for an installed package', () => {\n const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-framework-context-'))\n\n try {\n const appDir = createStandaloneFixture(tempRoot)\n const packageRoot = installFakeFrameworkPackage(appDir)\n const resolvedPackageRoot = fs.realpathSync(packageRoot)\n const packageBefore = snapshotTextFiles(packageRoot)\n\n runMercato(['agentic:init', '--tool=codex'], appDir)\n const generatedScript = path.join(appDir, 'scripts', 'framework-context.mjs')\n expect(fs.existsSync(generatedScript)).toBe(true)\n\n const output = runCommand(\n process.execPath,\n [generatedScript, '--module', 'customers', '--query', 'Person', '--json'],\n appDir,\n // The generated standalone helper must not depend on a globally\n // installed ripgrep binary; process.execPath is already absolute.\n { PATH: '', Path: '' },\n )\n const context = JSON.parse(output) as {\n module: string\n package: { name: string; version: string; root: string }\n sourceKind: string\n sourceRoot: string\n materializedSource: string\n instructions: Array<{ kind: string; path: string | null; materializedPath?: string }>\n boundedSearch: { status: string; matches: number; maxMatches: number; result: string }\n warnings: string[]\n }\n\n expect(context.module).toBe('customers')\n expect(context.package).toEqual({ name: '@open-mercato/core', version: coreVersion, root: resolvedPackageRoot })\n expect(context.sourceKind).toBe('source')\n expect(normalizePath(context.sourceRoot)).toBe(normalizePath(path.join(resolvedPackageRoot, 'src', 'modules', 'customers')))\n expect(context.instructions.filter((entry) => entry.path).map((entry) => entry.kind)).toEqual([\n 'standalone-root',\n 'upstream-bc',\n 'package',\n 'module-1',\n 'upstream-root',\n ])\n expect(context.instructions.filter((entry) => entry.path).every((entry) => entry.materializedPath)).toBe(true)\n expect(context.boundedSearch).toMatchObject({ status: 'matched', matches: 1, maxMatches: 200 })\n expect(fs.existsSync(path.join(appDir, context.materializedSource))).toBe(true)\n expect(fs.existsSync(path.join(appDir, context.boundedSearch.result))).toBe(true)\n expect(context.warnings.some((warning) => warning.includes('Generated facts for customers are stale'))).toBe(false)\n expect(snapshotTextFiles(packageRoot)).toEqual(packageBefore)\n } finally {\n fs.rmSync(tempRoot, { recursive: true, force: true })\n }\n })\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -22,6 +22,8 @@ function parseArgs(args) {
22
22
  options.force = true;
23
23
  } else if (arg === "--update-harness") {
24
24
  options.updateHarness = true;
25
+ } else if (arg === "--experimental-hooks-validator") {
26
+ options.experimentalHooksValidator = true;
25
27
  } else if (arg.startsWith("--tool=")) {
26
28
  options.tool = arg.slice("--tool=".length);
27
29
  } else if (arg === "--tool") {
@@ -77,7 +79,8 @@ async function runAgenticInit(args) {
77
79
  await runAgenticSetup(targetDir, ask, {
78
80
  tool: options.tool,
79
81
  force: options.force,
80
- updateHarness: options.updateHarness
82
+ updateHarness: options.updateHarness,
83
+ experimentalHooksValidator: options.experimentalHooksValidator
81
84
  });
82
85
  } finally {
83
86
  rl.close();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/agentic-init.ts"],
4
- "sourcesContent": ["import { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { createInterface } from 'node:readline'\n\ninterface AgenticInitOptions {\n tool?: string\n force?: boolean\n updateHarness?: boolean\n}\n\nconst TOOL_EXISTING_FILES: Record<string, string[]> = {\n 'claude-code': [\n 'CLAUDE.md',\n '.claude/settings.json',\n '.mcp.json.example',\n ],\n 'codex': [\n '.codex/mcp.json.example',\n ],\n 'cursor': [\n '.cursor/hooks.json',\n ],\n}\n\nfunction parseArgs(args: string[]): AgenticInitOptions {\n const options: AgenticInitOptions = {}\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--force' || arg === '-f') {\n options.force = true\n } else if (arg === '--update-harness') {\n options.updateHarness = true\n } else if (arg.startsWith('--tool=')) {\n options.tool = arg.slice('--tool='.length)\n } else if (arg === '--tool') {\n options.tool = args[++i]\n }\n }\n return options\n}\n\nexport function resolveRelevantAgenticFiles(toolOption?: string): string[] {\n if (typeof toolOption !== 'string' || toolOption.trim().length === 0) {\n return Object.values(TOOL_EXISTING_FILES).flat()\n }\n\n const toolIds = toolOption.split(',').map((toolId) => toolId.trim()).filter(Boolean)\n const relevantFiles = new Set<string>()\n\n for (const toolId of toolIds) {\n const toolFiles = TOOL_EXISTING_FILES[toolId]\n if (!toolFiles) continue\n for (const relativePath of toolFiles) {\n relevantFiles.add(relativePath)\n }\n }\n\n return relevantFiles.size > 0 ? Array.from(relevantFiles) : Object.values(TOOL_EXISTING_FILES).flat()\n}\n\nexport async function runAgenticInit(args: string[]): Promise<number> {\n const targetDir = resolve('.')\n const options = parseArgs(args)\n\n if (options.force && options.updateHarness) {\n console.error('\u274C --force and --update-harness are mutually exclusive')\n return 1\n }\n\n // Validate this is an Open Mercato app directory\n if (!existsSync(join(targetDir, 'src', 'modules.ts'))) {\n console.error('\u274C Not an Open Mercato app directory (src/modules.ts not found)')\n return 1\n }\n\n // Check if agentic files already exist and warn unless --force\n if (!options.force && !options.updateHarness) {\n const existingFiles = resolveRelevantAgenticFiles(options.tool)\n .filter((relativePath) => existsSync(join(targetDir, relativePath)))\n\n if (existingFiles.length > 0) {\n console.log('')\n console.log('\u26A0\uFE0F Agentic files already exist:')\n for (const f of existingFiles) {\n console.log(` \u2022 ${f}`)\n }\n console.log('')\n console.log('Run with --update-harness to preserve local edits, or --force to replace generated files.')\n console.log('')\n return 0\n }\n }\n\n // Dynamic import of the setup wizard from create-app's agentic source\n // Since we can't import from create-app at runtime in standalone apps,\n // we inline the generator logic here using the same source files approach.\n const { runAgenticSetup } = await import('./agentic-setup.js')\n\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n const ask = (q: string) => new Promise<string>((res) => rl.question(q, (a) => res(a.trim())))\n\n try {\n await runAgenticSetup(targetDir, ask, {\n tool: options.tool,\n force: options.force,\n updateHarness: options.updateHarness,\n })\n } finally {\n rl.close()\n }\n\n return 0\n}\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,MAAM,eAAe;AAC9B,SAAS,uBAAuB;AAQhC,MAAM,sBAAgD;AAAA,EACpD,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,UAAU,MAAoC;AACrD,QAAM,UAA8B,CAAC;AACrC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,QAAQ,aAAa,QAAQ,MAAM;AACrC,cAAQ,QAAQ;AAAA,IAClB,WAAW,QAAQ,oBAAoB;AACrC,cAAQ,gBAAgB;AAAA,IAC1B,WAAW,IAAI,WAAW,SAAS,GAAG;AACpC,cAAQ,OAAO,IAAI,MAAM,UAAU,MAAM;AAAA,IAC3C,WAAW,QAAQ,UAAU;AAC3B,cAAQ,OAAO,KAAK,EAAE,CAAC;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,4BAA4B,YAA+B;AACzE,MAAI,OAAO,eAAe,YAAY,WAAW,KAAK,EAAE,WAAW,GAAG;AACpE,WAAO,OAAO,OAAO,mBAAmB,EAAE,KAAK;AAAA,EACjD;AAEA,QAAM,UAAU,WAAW,MAAM,GAAG,EAAE,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,EAAE,OAAO,OAAO;AACnF,QAAM,gBAAgB,oBAAI,IAAY;AAEtC,aAAW,UAAU,SAAS;AAC5B,UAAM,YAAY,oBAAoB,MAAM;AAC5C,QAAI,CAAC,UAAW;AAChB,eAAW,gBAAgB,WAAW;AACpC,oBAAc,IAAI,YAAY;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,cAAc,OAAO,IAAI,MAAM,KAAK,aAAa,IAAI,OAAO,OAAO,mBAAmB,EAAE,KAAK;AACtG;AAEA,eAAsB,eAAe,MAAiC;AACpE,QAAM,YAAY,QAAQ,GAAG;AAC7B,QAAM,UAAU,UAAU,IAAI;AAE9B,MAAI,QAAQ,SAAS,QAAQ,eAAe;AAC1C,YAAQ,MAAM,6DAAwD;AACtE,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,WAAW,KAAK,WAAW,OAAO,YAAY,CAAC,GAAG;AACrD,YAAQ,MAAM,sEAAiE;AAC/E,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,eAAe;AAC5C,UAAM,gBAAgB,4BAA4B,QAAQ,IAAI,EAC3D,OAAO,CAAC,iBAAiB,WAAW,KAAK,WAAW,YAAY,CAAC,CAAC;AAErE,QAAI,cAAc,SAAS,GAAG;AAC5B,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,4CAAkC;AAC9C,iBAAW,KAAK,eAAe;AAC7B,gBAAQ,IAAI,aAAQ,CAAC,EAAE;AAAA,MACzB;AACA,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,2FAA2F;AACvG,cAAQ,IAAI,EAAE;AACd,aAAO;AAAA,IACT;AAAA,EACF;AAKA,QAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,oBAAoB;AAE7D,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,QAAM,MAAM,CAAC,MAAc,IAAI,QAAgB,CAAC,QAAQ,GAAG,SAAS,GAAG,CAAC,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AAE5F,MAAI;AACF,UAAM,gBAAgB,WAAW,KAAK;AAAA,MACpC,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,eAAe,QAAQ;AAAA,IACzB,CAAC;AAAA,EACH,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["import { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { createInterface } from 'node:readline'\n\ninterface AgenticInitOptions {\n tool?: string\n force?: boolean\n updateHarness?: boolean\n experimentalHooksValidator?: boolean\n}\n\nconst TOOL_EXISTING_FILES: Record<string, string[]> = {\n 'claude-code': [\n 'CLAUDE.md',\n '.claude/settings.json',\n '.mcp.json.example',\n ],\n 'codex': [\n '.codex/mcp.json.example',\n ],\n 'cursor': [\n '.cursor/hooks.json',\n ],\n}\n\nfunction parseArgs(args: string[]): AgenticInitOptions {\n const options: AgenticInitOptions = {}\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--force' || arg === '-f') {\n options.force = true\n } else if (arg === '--update-harness') {\n options.updateHarness = true\n } else if (arg === '--experimental-hooks-validator') {\n options.experimentalHooksValidator = true\n } else if (arg.startsWith('--tool=')) {\n options.tool = arg.slice('--tool='.length)\n } else if (arg === '--tool') {\n options.tool = args[++i]\n }\n }\n return options\n}\n\nexport function resolveRelevantAgenticFiles(toolOption?: string): string[] {\n if (typeof toolOption !== 'string' || toolOption.trim().length === 0) {\n return Object.values(TOOL_EXISTING_FILES).flat()\n }\n\n const toolIds = toolOption.split(',').map((toolId) => toolId.trim()).filter(Boolean)\n const relevantFiles = new Set<string>()\n\n for (const toolId of toolIds) {\n const toolFiles = TOOL_EXISTING_FILES[toolId]\n if (!toolFiles) continue\n for (const relativePath of toolFiles) {\n relevantFiles.add(relativePath)\n }\n }\n\n return relevantFiles.size > 0 ? Array.from(relevantFiles) : Object.values(TOOL_EXISTING_FILES).flat()\n}\n\nexport async function runAgenticInit(args: string[]): Promise<number> {\n const targetDir = resolve('.')\n const options = parseArgs(args)\n\n if (options.force && options.updateHarness) {\n console.error('\u274C --force and --update-harness are mutually exclusive')\n return 1\n }\n\n // Validate this is an Open Mercato app directory\n if (!existsSync(join(targetDir, 'src', 'modules.ts'))) {\n console.error('\u274C Not an Open Mercato app directory (src/modules.ts not found)')\n return 1\n }\n\n // Check if agentic files already exist and warn unless --force\n if (!options.force && !options.updateHarness) {\n const existingFiles = resolveRelevantAgenticFiles(options.tool)\n .filter((relativePath) => existsSync(join(targetDir, relativePath)))\n\n if (existingFiles.length > 0) {\n console.log('')\n console.log('\u26A0\uFE0F Agentic files already exist:')\n for (const f of existingFiles) {\n console.log(` \u2022 ${f}`)\n }\n console.log('')\n console.log('Run with --update-harness to preserve local edits, or --force to replace generated files.')\n console.log('')\n return 0\n }\n }\n\n // Dynamic import of the setup wizard from create-app's agentic source\n // Since we can't import from create-app at runtime in standalone apps,\n // we inline the generator logic here using the same source files approach.\n const { runAgenticSetup } = await import('./agentic-setup.js')\n\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n const ask = (q: string) => new Promise<string>((res) => rl.question(q, (a) => res(a.trim())))\n\n try {\n await runAgenticSetup(targetDir, ask, {\n tool: options.tool,\n force: options.force,\n updateHarness: options.updateHarness,\n experimentalHooksValidator: options.experimentalHooksValidator,\n })\n } finally {\n rl.close()\n }\n\n return 0\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -122,9 +122,19 @@ function listFiles(root) {
122
122
  }
123
123
  return files;
124
124
  }
125
- function claudeHookFiles() {
125
+ function claudeHookFiles(experimentalHooksValidator) {
126
126
  const hooksDir = join(AGENTIC_DIR, "claude-code", "hooks");
127
- return listFiles(hooksDir).map((file) => relative(hooksDir, file).replaceAll("\\", "/"));
127
+ return listFiles(hooksDir).map((file) => relative(hooksDir, file).replaceAll("\\", "/")).filter((file) => experimentalHooksValidator || file !== "gate-evidence.ts");
128
+ }
129
+ function resolveExperimentalHooksValidator(explicitValue, environment = process.env) {
130
+ if (explicitValue !== void 0) return explicitValue;
131
+ const token = environment.OM_HARNESS_EXPERIMENTAL_HOOKS_VALIDATOR?.trim().toLowerCase();
132
+ if (!token) return false;
133
+ if (["1", "true", "yes", "on"].includes(token)) return true;
134
+ if (["0", "false", "no", "off"].includes(token)) return false;
135
+ throw new Error(
136
+ "OM_HARNESS_EXPERIMENTAL_HOOKS_VALIDATOR must be one of: 1, true, yes, on, 0, false, no, off"
137
+ );
128
138
  }
129
139
  function copyTree(sourceRoot, destinationRoot, config) {
130
140
  for (const sourcePath of listFiles(sourceRoot)) {
@@ -323,14 +333,31 @@ function finalizeHarnessManifest(config, selectedTools) {
323
333
  if (selectedTools.includes("claude-code")) {
324
334
  paths.add(join(targetDir, "CLAUDE.md"));
325
335
  paths.add(join(targetDir, ".claude", "settings.json"));
326
- for (const hook of claudeHookFiles()) paths.add(join(targetDir, ".claude", "hooks", hook));
336
+ for (const hook of claudeHookFiles(config.experimentalHooksValidator)) {
337
+ paths.add(join(targetDir, ".claude", "hooks", hook));
338
+ }
327
339
  paths.add(join(targetDir, ".mcp.json.example"));
328
340
  }
329
- if (selectedTools.includes("codex")) paths.add(join(targetDir, ".codex", "mcp.json.example"));
341
+ if (selectedTools.includes("codex")) {
342
+ paths.add(join(targetDir, ".codex", "mcp.json.example"));
343
+ if (config.experimentalHooksValidator) {
344
+ paths.add(join(targetDir, ".codex", "hooks.json"));
345
+ paths.add(join(targetDir, ".codex", "hooks", "gate-evidence.mjs"));
346
+ }
347
+ }
330
348
  if (selectedTools.includes("cursor")) {
331
- for (const file of listFiles(join(AGENTIC_DIR, "cursor"))) {
332
- const rel = relative(join(AGENTIC_DIR, "cursor"), file);
333
- paths.add(join(targetDir, ".cursor", rel));
349
+ for (const relativePath of [
350
+ "hooks.json",
351
+ "hooks/entity-migration-check.mjs",
352
+ "mcp.json.example",
353
+ "rules/open-mercato.mdc",
354
+ "rules/entity-guard.mdc",
355
+ "rules/generated-guard.mdc"
356
+ ]) {
357
+ paths.add(join(targetDir, ".cursor", relativePath));
358
+ }
359
+ if (config.experimentalHooksValidator) {
360
+ paths.add(join(targetDir, ".cursor", "hooks", "gate-evidence.mjs"));
334
361
  }
335
362
  }
336
363
  const manifestPath = join(targetDir, ".ai", "harness", "manifest.json");
@@ -488,8 +515,12 @@ function generateClaudeCode(config) {
488
515
  const { targetDir } = config;
489
516
  const srcDir = join(AGENTIC_DIR, "claude-code");
490
517
  writeTemplate(srcDir, "CLAUDE.md.template", join(targetDir, "CLAUDE.md"), config);
491
- copyFile(srcDir, "settings.json", join(targetDir, ".claude", "settings.json"));
492
- for (const hook of claudeHookFiles()) {
518
+ copyFile(
519
+ srcDir,
520
+ config.experimentalHooksValidator ? "settings.experimental-hooks-validator.json" : "settings.json",
521
+ join(targetDir, ".claude", "settings.json")
522
+ );
523
+ for (const hook of claudeHookFiles(config.experimentalHooksValidator)) {
493
524
  copyFile(srcDir, `hooks/${hook}`, join(targetDir, ".claude", "hooks", hook));
494
525
  }
495
526
  copyFile(srcDir, "mcp.json.example", join(targetDir, ".mcp.json.example"));
@@ -519,6 +550,10 @@ function generateCodex(config) {
519
550
  }
520
551
  writeFileSync(agentsPath, agents);
521
552
  }
553
+ if (config.experimentalHooksValidator) {
554
+ copyFile(srcDir, "hooks.json", join(targetDir, ".codex", "hooks.json"));
555
+ copyFile(srcDir, "hooks/gate-evidence.mjs", join(targetDir, ".codex", "hooks", "gate-evidence.mjs"));
556
+ }
522
557
  copyFile(srcDir, "mcp.json.example", join(targetDir, ".codex", "mcp.json.example"));
523
558
  }
524
559
  function generateCursor(config) {
@@ -527,8 +562,15 @@ function generateCursor(config) {
527
562
  writeTemplate(srcDir, "rules/open-mercato.mdc", join(targetDir, ".cursor", "rules", "open-mercato.mdc"), config);
528
563
  copyFile(srcDir, "rules/entity-guard.mdc", join(targetDir, ".cursor", "rules", "entity-guard.mdc"));
529
564
  copyFile(srcDir, "rules/generated-guard.mdc", join(targetDir, ".cursor", "rules", "generated-guard.mdc"));
530
- copyFile(srcDir, "hooks.json", join(targetDir, ".cursor", "hooks.json"));
565
+ copyFile(
566
+ srcDir,
567
+ config.experimentalHooksValidator ? "hooks.experimental-hooks-validator.json" : "hooks.json",
568
+ join(targetDir, ".cursor", "hooks.json")
569
+ );
531
570
  copyFile(srcDir, "hooks/entity-migration-check.mjs", join(targetDir, ".cursor", "hooks", "entity-migration-check.mjs"));
571
+ if (config.experimentalHooksValidator) {
572
+ copyFile(srcDir, "hooks/gate-evidence.mjs", join(targetDir, ".cursor", "hooks", "gate-evidence.mjs"));
573
+ }
532
574
  copyFile(srcDir, "mcp.json.example", join(targetDir, ".cursor", "mcp.json.example"));
533
575
  }
534
576
  const TOOLS = [
@@ -612,7 +654,8 @@ async function runAgenticSetup(targetDir, ask, options) {
612
654
  }
613
655
  const config = {
614
656
  projectName: basename(targetDir),
615
- targetDir
657
+ targetDir,
658
+ experimentalHooksValidator: resolveExperimentalHooksValidator(options?.experimentalHooksValidator)
616
659
  };
617
660
  const stagingDir = mkdtempSync(join(tmpdir(), "open-mercato-harness-"));
618
661
  try {
@@ -624,7 +667,8 @@ async function runAgenticSetup(targetDir, ask, options) {
624
667
  }
625
668
  const stagingConfig = {
626
669
  projectName: config.projectName,
627
- targetDir: stagingDir
670
+ targetDir: stagingDir,
671
+ experimentalHooksValidator: config.experimentalHooksValidator
628
672
  };
629
673
  generateHarness(stagingConfig, selectedIds);
630
674
  const conflicts = applyHarnessUpdate(targetDir, stagingDir, {
@@ -653,6 +697,9 @@ async function runAgenticSetup(targetDir, ask, options) {
653
697
  if (selectedIds.includes("cursor")) {
654
698
  console.log(" \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example");
655
699
  }
700
+ if (config.experimentalHooksValidator) {
701
+ console.log(" \u2713 Experimental gate-evidence/typecheck validator hooks");
702
+ }
656
703
  console.log("");
657
704
  console.log(" .ai/agentic.config.json ships preconfigured (GitHub tracker, labels off);");
658
705
  console.log(" run /om-setup-agent-pipeline in your agent CLI to tailor labels, QA gate,");