@open-mercato/cli 0.6.8-develop.6972.1.275e435508 → 0.6.8-develop.6973.1.17fe21ccd4
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/settings.experimental-hooks-validator.json +37 -0
- package/dist/agentic/claude-code/settings.json +0 -21
- package/dist/agentic/cursor/hooks.experimental-hooks-validator.json +20 -0
- package/dist/agentic/cursor/hooks.json +0 -10
- 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/lib/__integration__/TC-INT-008.spec.js +77 -4
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +4 -1
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +59 -12
- package/dist/lib/agentic-setup.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/__integration__/TC-INT-008.spec.ts +88 -6
- package/src/lib/__tests__/agentic-init.test.ts +53 -5
- package/src/lib/agentic-init.ts +4 -0
- 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
|
}
|
package/dist/lib/agentic-init.js
CHANGED
|
@@ -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;
|
|
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())
|
|
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"))
|
|
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
|
|
332
|
-
|
|
333
|
-
|
|
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(
|
|
492
|
-
|
|
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(
|
|
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,");
|