#!/usr/bin/env node
import { createRequire } from "node:module";
import { arg, defineCommand, runMain } from "politty";
import { z } from "zod";
import chalk from "chalk";
import fs, { existsSync, globSync, readFileSync, readdirSync } from "node:fs";
import path, { basename, dirname, join, relative, resolve } from "node:path";
import { execFile, execFileSync, execSync } from "node:child_process";
import fg from "fast-glob";
import { fromMarkdown } from "mdast-util-from-markdown";
import { toString } from "mdast-util-to-string";
import { createHash } from "node:crypto";
import { createServer, request } from "node:http";
import { createServer as createServer$1 } from "node:net";
import { readFile, readdir, stat } from "node:fs/promises";
//#region \0rolldown/runtime.js
var __defProp = Object.defineProperty;
var __exportAll = (all, no_symbols) => {
	let target = {};
	for (var name in all) __defProp(target, name, {
		get: all[name],
		enumerable: true
	});
	if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
	return target;
};
//#endregion
//#region src/util.ts
const PACKAGE_ROOT = path.resolve(import.meta.dirname, "..");
function readErpKitVersion() {
	return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf-8")).version;
}
//#endregion
//#region src/generator/scaffold.ts
const RENAME_MAP = {
	__dot__gitignore: ".gitignore",
	"__pnpm-workspace.yaml": "pnpm-workspace.yaml"
};
function copyTemplateDir(srcDir, destDir, replacements, placeholderFiles, excludeDirs = /* @__PURE__ */ new Set()) {
	for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
		const srcPath = path.join(srcDir, entry.name);
		const destName = RENAME_MAP[entry.name] ?? entry.name;
		const destPath = path.join(destDir, destName);
		if (entry.name === "node_modules") continue;
		if (excludeDirs.has(entry.name)) continue;
		if (entry.isDirectory()) {
			fs.mkdirSync(destPath, { recursive: true });
			copyTemplateDir(srcPath, destPath, replacements, placeholderFiles, excludeDirs);
		} else {
			if (fs.existsSync(destPath)) continue;
			fs.mkdirSync(path.dirname(destPath), { recursive: true });
			if (placeholderFiles.has(entry.name)) {
				let content = fs.readFileSync(srcPath, "utf-8");
				for (const [from, to] of Object.entries(replacements)) content = content.replaceAll(from, to);
				fs.writeFileSync(destPath, content);
			} else fs.copyFileSync(srcPath, destPath);
		}
	}
}
function scaffoldModuleBoilerplate(moduleDir, moduleName) {
	const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "module");
	const erpKitVersion = readErpKitVersion();
	copyTemplateDir(templateDir, moduleDir, {
		"template-module": moduleName,
		"\"workspace:*\"": `"${erpKitVersion}"`
	}, new Set([
		"package.json",
		"permissions.ts",
		"tailor.config.ts"
	]));
}
function scaffoldAppBoilerplate(appDir, appName) {
	const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "app");
	const erpKitVersion = readErpKitVersion();
	copyTemplateDir(templateDir, appDir, {
		"template-app-frontend": `${appName}-frontend`,
		"template-app-backend": appName,
		"template-app": appName,
		"\"workspace:*\"": `"${erpKitVersion}"`
	}, new Set([
		"package.json",
		"tailor.config.ts",
		"index.html"
	]), new Set(["docs"]));
}
function scaffoldProjectBoilerplate(projectDir, projectName) {
	const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "project");
	const erpKitVersion = readErpKitVersion();
	copyTemplateDir(templateDir, projectDir, {
		"template-project": projectName,
		"\"workspace:*\"": `"${erpKitVersion}"`
	}, new Set(["package.json"]));
}
//#endregion
//#region src/commands/lib/distribute.ts
const SKILLS_SRC = path.join(PACKAGE_ROOT, "skills");
const WORKFLOWS_SRC = path.join(PACKAGE_ROOT, "templates", "workflows");
function copyDirectoryRecursive(srcDir, destDir) {
	let copied = 0;
	for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
		const srcPath = path.join(srcDir, entry.name);
		const destPath = path.join(destDir, entry.name);
		if (entry.isDirectory()) copied += copyDirectoryRecursive(srcPath, destPath);
		else {
			fs.mkdirSync(destDir, { recursive: true });
			fs.copyFileSync(srcPath, destPath);
			copied++;
		}
	}
	return copied;
}
function discoverFrameworkSkills() {
	if (!fs.existsSync(SKILLS_SRC)) return [];
	return fs.readdirSync(SKILLS_SRC, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("erp-kit-")).map((entry) => entry.name);
}
function copySkills(cwd) {
	const skillsDest = path.join(cwd, ".agents", "skills");
	let removed = 0;
	if (fs.existsSync(skillsDest)) {
		for (const entry of fs.readdirSync(skillsDest)) if (entry.startsWith("erp-kit-")) {
			fs.rmSync(path.join(skillsDest, entry), {
				recursive: true,
				force: true
			});
			removed++;
		}
	}
	let copied = 0;
	for (const skill of discoverFrameworkSkills()) {
		const srcSkillDir = path.join(SKILLS_SRC, skill);
		if (!fs.existsSync(srcSkillDir)) continue;
		const destDir = path.join(skillsDest, skill);
		copied += copyDirectoryRecursive(srcSkillDir, destDir);
	}
	return {
		copied,
		removed
	};
}
function copyWorkflows(cwd) {
	const workflowsDest = path.join(cwd, ".github", "workflows");
	if (!fs.existsSync(WORKFLOWS_SRC)) return {
		copied: 0,
		removed: 0
	};
	const workflowFiles = fs.readdirSync(WORKFLOWS_SRC).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
	let copied = 0;
	for (const file of workflowFiles) {
		fs.mkdirSync(workflowsDest, { recursive: true });
		fs.copyFileSync(path.join(WORKFLOWS_SRC, file), path.join(workflowsDest, file));
		copied++;
	}
	return {
		copied,
		removed: 0
	};
}
function createSymlink(target, linkPath) {
	const type = process.platform === "win32" ? "junction" : void 0;
	const resolvedTarget = type === "junction" ? path.resolve(path.dirname(linkPath), target) : target;
	fs.symlinkSync(resolvedTarget, linkPath, type);
}
function copySkillsDirectory(src, dest) {
	if (!fs.existsSync(src)) return;
	fs.cpSync(src, dest, { recursive: true });
}
function setupSymlink(cwd) {
	const skillsDest = path.join(cwd, ".agents", "skills");
	const claudeSkills = path.join(cwd, ".claude", "skills");
	const relTarget = path.relative(path.dirname(claudeSkills), skillsDest);
	let exists = false;
	try {
		fs.lstatSync(claudeSkills);
		exists = true;
	} catch {}
	if (exists) {
		if (fs.lstatSync(claudeSkills).isSymbolicLink()) {
			if (fs.readlinkSync(claudeSkills) === relTarget) return "already_linked";
			fs.unlinkSync(claudeSkills);
			try {
				createSymlink(relTarget, claudeSkills);
				return "linked";
			} catch {
				copySkillsDirectory(skillsDest, claudeSkills);
				return "copied";
			}
		}
		return "skipped_directory";
	}
	fs.mkdirSync(path.dirname(claudeSkills), { recursive: true });
	try {
		createSymlink(relTarget, claudeSkills);
		return "linked";
	} catch {
		copySkillsDirectory(skillsDest, claudeSkills);
		return "copied";
	}
}
/**
* When .claude/skills is a real directory (copy fallback on Windows),
* re-sync it with .agents/skills after an update.
*/
function refreshCopiedSkills(cwd) {
	const claudeSkills = path.join(cwd, ".claude", "skills");
	try {
		const stat = fs.lstatSync(claudeSkills);
		if (stat.isSymbolicLink() || !stat.isDirectory()) return false;
	} catch {
		return false;
	}
	const skillsDest = path.join(cwd, ".agents", "skills");
	fs.rmSync(claudeSkills, {
		recursive: true,
		force: true
	});
	copySkillsDirectory(skillsDest, claudeSkills);
	return true;
}
function isAlreadyInitialized(cwd) {
	const skillsDest = path.join(cwd, ".agents", "skills");
	if (!fs.existsSync(skillsDest)) return false;
	return fs.readdirSync(skillsDest).some((entry) => entry.startsWith("erp-kit-"));
}
//#endregion
//#region src/commands/init.ts
function runInit(name, cwd) {
	console.log(chalk.bold("erp-kit init\n"));
	if (isAlreadyInitialized(cwd)) {
		console.log(chalk.yellow("Already initialized. Use `erp-kit update` to refresh framework resources."));
		return 1;
	}
	const skills = copySkills(cwd);
	console.log(chalk.green(`  Copied ${skills.copied} skill files to .agents/skills/`));
	const symlink = setupSymlink(cwd);
	if (symlink === "linked") console.log(chalk.green("  .claude/skills -> .agents/skills/ (linked)"));
	else if (symlink === "copied") console.log(chalk.yellow("  .claude/skills (copied — re-run `erp-kit update skills` after changes)"));
	else if (symlink === "skipped_directory") console.log(chalk.yellow("  Skipped .claude/skills (directory exists, not a symlink)"));
	const workflows = copyWorkflows(cwd);
	if (workflows.copied > 0) console.log(chalk.green(`  Copied ${workflows.copied} workflow(s) to .github/workflows/`));
	scaffoldProjectBoilerplate(cwd, name);
	console.log(chalk.green("  Scaffolded project structure"));
	console.log(chalk.bold.green("\nDone! Run `erp-kit check` to validate your docs."));
	return 0;
}
//#endregion
//#region src/commands/update.ts
const VALID_RESOURCES = ["skills", "workflows"];
function runUpdate(cwd, resources) {
	console.log(chalk.bold("erp-kit update\n"));
	const selected = resources.length === 0 ? new Set(VALID_RESOURCES) : new Set(resources.filter((r) => VALID_RESOURCES.includes(r)));
	if (selected.size === 0) {
		console.error(chalk.red(`Invalid resource. Valid: ${VALID_RESOURCES.join(", ")}`));
		return 1;
	}
	if (selected.has("skills")) {
		const result = copySkills(cwd);
		if (result.removed > 0) console.log(chalk.green(`  Removed ${result.removed} stale erp-kit-* skills`));
		console.log(chalk.green(`  Copied ${result.copied} skill files to .agents/skills/`));
		if (refreshCopiedSkills(cwd)) console.log(chalk.green(`  Refreshed .claude/skills/ (copy)`));
	}
	if (selected.has("workflows")) {
		const result = copyWorkflows(cwd);
		if (result.copied > 0) console.log(chalk.green(`  Copied ${result.copied} workflow(s) to .github/workflows/`));
	}
	console.log(chalk.bold.green("\nDone!"));
	return 0;
}
//#endregion
//#region src/commands/license.ts
const licenseGroups = {
	reciprocal: [
		"APSL-1.0",
		"APSL-1.1",
		"APSL-1.2",
		"APSL-2.0",
		"CDDL-1.0",
		"CDDL-1.1",
		"CPL-1.0",
		"EPL-1.0",
		"EPL-2.0",
		"FreeImage",
		"IPL-1.0",
		"MPL-1.0",
		"MPL-1.1",
		"MPL-2.0",
		"Ruby"
	],
	notice: [
		"AFL-1.1",
		"AFL-1.2",
		"AFL-2.0",
		"AFL-2.1",
		"AFL-3.0",
		"Apache-1.0",
		"Apache-1.1",
		"Apache-2.0",
		"Artistic-1.0-cl8",
		"Artistic-1.0-Perl",
		"Artistic-1.0",
		"Artistic-2.0",
		"BSL-1.0",
		"BSD-2-Clause-FreeBSD",
		"BSD-2-Clause-NetBSD",
		"BSD-2-Clause",
		"BSD-3-Clause-Attribution",
		"BSD-3-Clause-Clear",
		"BSD-3-Clause-LBNL",
		"BSD-3-Clause",
		"BSD-4-Clause",
		"BSD-4-Clause-UC",
		"BSD-Protection",
		"CC-BY-1.0",
		"CC-BY-2.0",
		"CC-BY-2.5",
		"CC-BY-3.0",
		"CC-BY-4.0",
		"FTL",
		"ISC",
		"ImageMagick",
		"Libpng",
		"Lil-1.0",
		"Linux-OpenIB",
		"LPL-1.02",
		"LPL-1.0",
		"MS-PL",
		"MIT",
		"NCSA",
		"OpenSSL",
		"PHP-3.01",
		"PHP-3.0",
		"PIL",
		"Python-2.0",
		"Python-2.0-complete",
		"PostgreSQL",
		"SGI-B-1.0",
		"SGI-B-1.1",
		"SGI-B-2.0",
		"Unicode-DFS-2015",
		"Unicode-DFS-2016",
		"Unicode-TOU",
		"UPL-1.0",
		"W3C-19980720",
		"W3C-20150513",
		"W3C",
		"X11",
		"Xnet",
		"Zend-2.0",
		"zlib-acknowledgement",
		"Zlib",
		"ZPL-1.1",
		"ZPL-2.0",
		"ZPL-2.1"
	],
	unencumbered: [
		"CC0-1.0",
		"Unlicense",
		"0BSD"
	]
};
function buildAllowSet(config) {
	const set = /* @__PURE__ */ new Set();
	for (const group of config.groups) for (const license of licenseGroups[group]) set.add(license);
	if (config.allow) for (const license of config.allow) set.add(license);
	if (config.deny) for (const license of config.deny) set.delete(license);
	return set;
}
function isLicenseAllowed(licenseString, allowSet) {
	if (/\s+(?:OR|AND)\s+/i.test(licenseString)) return licenseString.replace(/[()]/g, "").trim().split(/\s+(?:OR|AND)\s+/i).map((l) => l.trim()).filter((l) => l.length > 0).every((l) => allowSet.has(l));
	return allowSet.has(licenseString);
}
function runLicenseList() {
	for (const [group, licenses] of Object.entries(licenseGroups)) {
		console.log(`${group} (${licenses.length} licenses):`);
		for (const license of licenses) console.log(`  ${license}`);
		console.log();
	}
	return 0;
}
function runLicenseCheck(configPath) {
	const raw = fs.readFileSync(configPath, "utf-8");
	const config = JSON.parse(raw);
	const validGroups = Object.keys(licenseGroups);
	for (const group of config.groups) if (!validGroups.includes(group)) {
		console.error(`Unknown license group: "${group}". Valid groups: ${validGroups.join(", ")}`);
		return 2;
	}
	const allowSet = buildAllowSet(config);
	console.log("Checking licenses...\n");
	execSync("pnpm licenses list", { stdio: "inherit" });
	const output = execSync("pnpm licenses list --json");
	const licensesJson = JSON.parse(output.toString());
	const violations = [];
	for (const [license, packages] of Object.entries(licensesJson)) if (!isLicenseAllowed(license, allowSet)) for (const pkg of packages) violations.push({
		package: pkg.name,
		license
	});
	if (violations.length === 0) {
		console.log("All licenses are allowed.");
		return 0;
	}
	console.error("Found dependencies with disallowed licenses:\n");
	for (const violation of violations) {
		console.error(`  - ${violation.package}`);
		console.error(`    License: ${violation.license}\n`);
	}
	return 1;
}
//#endregion
//#region src/mdschema.ts
const require = createRequire(import.meta.url);
const PLATFORMS = {
	darwin: {
		arm64: "@jackchuka/mdschema-darwin-arm64",
		x64: "@jackchuka/mdschema-darwin-x64"
	},
	linux: {
		arm64: "@jackchuka/mdschema-linux-arm64",
		x64: "@jackchuka/mdschema-linux-x64"
	},
	win32: {
		arm64: "@jackchuka/mdschema-windows-arm64",
		x64: "@jackchuka/mdschema-windows-x64"
	}
};
function getMdschemaBin() {
	const pkgPath = require.resolve("@jackchuka/mdschema/package.json");
	const pkgDir = path.dirname(pkgPath);
	const mdschemaRequire = createRequire(pkgPath);
	const ext = process.platform === "win32" ? ".exe" : "";
	const pkg = PLATFORMS[process.platform]?.[process.arch];
	if (pkg) try {
		return mdschemaRequire.resolve(`${pkg}/bin/mdschema${ext}`);
	} catch {}
	const localBin = path.join(pkgDir, "bin", `mdschema${ext}`);
	if (fs.existsSync(localBin)) return localBin;
	const pkgJson = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
	const bin = typeof pkgJson.bin === "string" ? pkgJson.bin : pkgJson.bin?.mdschema;
	if (!bin) throw new Error("Could not resolve mdschema binary from package.json bin field");
	return path.join(pkgDir, bin);
}
function runMdschema(args, cwd) {
	return new Promise((resolve) => {
		execFile(getMdschemaBin(), args, {
			encoding: "utf-8",
			cwd,
			timeout: 3e4
		}, (error, stdout, stderr) => {
			if (error) {
				const execError = error;
				resolve({
					exitCode: execError.code === "ENOENT" ? 127 : execError.status ?? 1,
					stdout: stdout ?? "",
					stderr: stderr ?? ""
				});
			} else resolve({
				exitCode: 0,
				stdout: stdout ?? "",
				stderr: stderr ?? ""
			});
		});
	});
}
//#endregion
//#region src/schemas.ts
const SCHEMAS_ROOT = path.join(PACKAGE_ROOT, "schemas");
const MODULE_SCHEMAS = {
	module: path.join(SCHEMAS_ROOT, "module", "module.yml"),
	command: path.join(SCHEMAS_ROOT, "module", "command.yml"),
	model: path.join(SCHEMAS_ROOT, "module", "model.yml"),
	feature: path.join(SCHEMAS_ROOT, "module", "feature.yml"),
	query: path.join(SCHEMAS_ROOT, "module", "query.yml")
};
const APP_COMPOSE_SCHEMAS = {
	app: path.join(SCHEMAS_ROOT, "app", "requirements.yml"),
	actors: path.join(SCHEMAS_ROOT, "app", "actors.yml"),
	"business-flow": path.join(SCHEMAS_ROOT, "app", "business-flow.yml"),
	story: path.join(SCHEMAS_ROOT, "app", "story.yml"),
	screen: path.join(SCHEMAS_ROOT, "app", "screen.yml"),
	resolver: path.join(SCHEMAS_ROOT, "app", "resolver.yml")
};
const ALL_SCHEMAS = {
	...MODULE_SCHEMAS,
	...APP_COMPOSE_SCHEMAS
};
//#endregion
//#region src/commands/lib/paths.ts
const MODULE_PATHS = {
	commands: "command",
	db: "db",
	queries: "query",
	docs: {
		commands: "docs/commands",
		models: "docs/models",
		queries: "docs/queries",
		features: "docs/features"
	}
};
const APP_PATHS = {
	tests: { stories: "backend/src/tests/stories" },
	docs: {
		resolver: "docs/resolver",
		actors: "docs/actors",
		businessFlow: "docs/business-flow",
		story: "story",
		screen: "docs/screen"
	}
};
//#endregion
//#region src/commands/lib/discovery.ts
function moduleCategories(root) {
	return [
		{
			name: "command",
			sourcePattern: `${root}/*/${MODULE_PATHS.commands}/*.ts`,
			docPattern: `${root}/*/${MODULE_PATHS.docs.commands}/*.md`,
			exclusions: [/\.test\.ts$/, /\.generated\.ts$/]
		},
		{
			name: "model",
			sourcePattern: `${root}/*/${MODULE_PATHS.db}/*.ts`,
			docPattern: `${root}/*/${MODULE_PATHS.docs.models}/*.md`,
			exclusions: [/\.test\.ts$/, /^index\.ts$/]
		},
		{
			name: "query",
			sourcePattern: `${root}/*/${MODULE_PATHS.queries}/*.ts`,
			docPattern: `${root}/*/${MODULE_PATHS.docs.queries}/*.md`,
			exclusions: [/\.test\.ts$/]
		}
	];
}
function appComposeCategories(root) {
	return [{
		name: "resolver",
		sourcePattern: `${root}/backend/src/resolvers/*.ts`,
		docPattern: `${root}/${APP_PATHS.docs.resolver}/*.md`,
		exclusions: [/\.test\.ts$/, /^index\.ts$/]
	}];
}
function appTestCaseCategories(root) {
	return {
		name: "story-test-case",
		docPattern: `${root}/*/${APP_PATHS.docs.businessFlow}/*/${APP_PATHS.docs.story}/*.md`,
		testDir: APP_PATHS.tests.stories
	};
}
function moduleTestCaseCategories(root) {
	return [{
		name: "command-test-case",
		docPattern: `${root}/*/${MODULE_PATHS.docs.commands}/*.md`,
		testDir: MODULE_PATHS.commands
	}, {
		name: "query-test-case",
		docPattern: `${root}/*/${MODULE_PATHS.docs.queries}/*.md`,
		testDir: MODULE_PATHS.queries
	}];
}
function buildCheckTargets(config) {
	const targets = [];
	if (config.modulesRoot) {
		const m = config.modulesRoot;
		targets.push({
			glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.features}/*.md`,
			schemaKey: "feature"
		}, {
			glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.commands}/*.md`,
			schemaKey: "command"
		}, {
			glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.models}/*.md`,
			schemaKey: "model"
		}, {
			glob: `${m}/[a-zA-Z]*/${MODULE_PATHS.docs.queries}/*.md`,
			schemaKey: "query"
		}, {
			glob: `${m}/[a-zA-Z]*/README.md`,
			schemaKey: "module"
		});
	}
	if (config.appRoot) {
		const a = config.appRoot;
		targets.push({
			glob: `${a}/README.md`,
			schemaKey: "app"
		}, {
			glob: `${a}/${APP_PATHS.docs.actors}/*.md`,
			schemaKey: "actors"
		}, {
			glob: `${a}/${APP_PATHS.docs.businessFlow}/*/README.md`,
			schemaKey: "business-flow"
		}, {
			glob: `${a}/${APP_PATHS.docs.businessFlow}/*/${APP_PATHS.docs.story}/*.md`,
			schemaKey: "story"
		}, {
			glob: `${a}/${APP_PATHS.docs.screen}/*.md`,
			schemaKey: "screen"
		}, {
			glob: `${a}/${APP_PATHS.docs.resolver}/*.md`,
			schemaKey: "resolver"
		});
	}
	return targets;
}
//#endregion
//#region src/commands/check.ts
async function runCheck(config, cwd) {
	const targets = buildCheckTargets(config);
	const results = await Promise.all(targets.map(async (target) => {
		const schemaPath = ALL_SCHEMAS[target.schemaKey];
		if (!schemaPath) {
			console.error(`Unknown schema key: ${target.schemaKey}`);
			return 2;
		}
		const { exitCode, stdout, stderr } = await runMdschema([
			"check",
			target.glob,
			"--schema",
			schemaPath
		], cwd);
		if (stdout.trim()) console.log(stdout);
		if (stderr.trim()) console.error(stderr);
		return exitCode;
	}));
	if (results.includes(2)) return 2;
	return results.some((code) => code !== 0) ? 1 : 0;
}
//#endregion
//#region src/commands/init-module.ts
function runInitModule(name, dir) {
	const moduleDir = path.resolve(dir, name);
	fs.mkdirSync(moduleDir, { recursive: true });
	return 0;
}
async function runInitModuleWithReadme(name, dir, cwd) {
	const initResult = runInitModule(name, dir);
	if (initResult !== 0) return initResult;
	const moduleDir = path.resolve(cwd, dir, name);
	const readmePath = path.join(moduleDir, "README.md");
	const schemaPath = MODULE_SCHEMAS.module;
	const { exitCode, stdout, stderr } = await runMdschema([
		"generate",
		"--schema",
		schemaPath,
		"--output",
		readmePath
	], cwd);
	if (stdout.trim()) console.log(stdout);
	if (stderr.trim()) console.error(stderr);
	return exitCode;
}
function runInitApp(name, dir) {
	const appDir = path.resolve(dir, name);
	fs.mkdirSync(appDir, { recursive: true });
	return 0;
}
async function runInitAppWithReadme(name, dir, cwd) {
	const initResult = runInitApp(name, dir);
	if (initResult !== 0) return initResult;
	const appDir = path.resolve(cwd, dir, name);
	const readmePath = path.join(appDir, "README.md");
	const schemaPath = APP_COMPOSE_SCHEMAS.app;
	const { exitCode, stdout, stderr } = await runMdschema([
		"generate",
		"--schema",
		schemaPath,
		"--output",
		readmePath
	], cwd);
	if (stdout.trim()) console.log(stdout);
	if (stderr.trim()) console.error(stderr);
	return exitCode;
}
//#endregion
//#region src/commands/lib/command-result.ts
function success() {
	return { exitCode: 0 };
}
function failure(message, exitCode = 1) {
	return {
		exitCode,
		message
	};
}
function silentFailure(exitCode = 1) {
	return {
		exitCode,
		message: ""
	};
}
async function runCommand(fn) {
	const result = await fn();
	if (result.exitCode !== 0 && "message" in result && result.message) console.error(result.message);
	return result;
}
async function executeCommand(fn) {
	const result = await runCommand(fn);
	process.exit(result.exitCode);
}
//#endregion
//#region src/commands/lib/sync-check-source.ts
function shouldExclude(fileName, exclusions) {
	return exclusions.some((pattern) => pattern.test(fileName));
}
async function runSourceSyncCheck(config, cwd) {
	const errors = [];
	let totalSources = 0;
	let totalDocs = 0;
	const allCategories = [];
	if (config.modulesRoot) allCategories.push(...moduleCategories(config.modulesRoot));
	if (config.appRoot) allCategories.push(...appComposeCategories(config.appRoot));
	for (const category of allCategories) {
		const sources = await fg(category.sourcePattern, { cwd });
		const docs = await fg(category.docPattern, { cwd });
		const sourceBasenames = /* @__PURE__ */ new Map();
		const docBasenames = /* @__PURE__ */ new Map();
		for (const sourcePath of sources) {
			if (shouldExclude(path.basename(sourcePath), category.exclusions)) continue;
			let basename = path.basename(sourcePath, path.extname(sourcePath));
			if (basename.endsWith(".generated")) basename = basename.slice(0, -10);
			sourceBasenames.set(basename.toLowerCase(), sourcePath);
		}
		for (const docPath of docs) {
			const basename = path.basename(docPath, path.extname(docPath));
			docBasenames.set(basename.toLowerCase(), docPath);
		}
		for (const [basename, sourcePath] of sourceBasenames) if (!docBasenames.has(basename)) errors.push({
			type: "missing-doc",
			category: category.name,
			sourcePath,
			expectedBasename: basename
		});
		for (const [basename, docPath] of docBasenames) if (!sourceBasenames.has(basename)) errors.push({
			type: "orphaned-doc",
			category: category.name,
			docPath,
			expectedBasename: basename
		});
		totalSources += sourceBasenames.size;
		totalDocs += docBasenames.size;
	}
	return {
		exitCode: errors.length > 0 ? 1 : 0,
		errors,
		summary: {
			categoriesChecked: allCategories.length,
			totalSources,
			totalDocs
		}
	};
}
//#endregion
//#region src/commands/parse-doc-test-cases.ts
function isHeading$2(node) {
	return node.type === "heading";
}
function isList$1(node) {
	return node.type === "list";
}
/**
* Parse test case descriptions from the `## Test Cases` section of a Markdown doc.
* Uses mdast to traverse the AST instead of string matching.
*/
function parseTestCasesFromDoc(markdown) {
	const tree = fromMarkdown(markdown);
	const cases = [];
	let collecting = false;
	for (const node of tree.children) {
		if (isHeading$2(node)) {
			if (collecting) break;
			if (node.depth === 2 && toString(node) === "Test Cases") {
				collecting = true;
				continue;
			}
		}
		if (collecting && isList$1(node)) for (const item of node.children) {
			const text = toString(item).trim();
			if (text) cases.push(text);
		}
	}
	return cases;
}
/**
* Parse `it("...")` descriptions from a test file using regex.
* Test files are not Markdown, so regex is appropriate here.
* Uses separate patterns per quote type so that e.g. an apostrophe
* inside a double-quoted string does not end the match early.
*/
function parseItDescriptionsFromTest(content) {
	const descriptions = [];
	const regex = /\bit\(\s*"([^"]+)"/gs;
	let match;
	while ((match = regex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
	const singleQuoteRegex = /\bit\(\s*'([^']+)'/gs;
	while ((match = singleQuoteRegex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
	const backtickRegex = /\bit\(\s*`([^`]+)`/gs;
	while ((match = backtickRegex.exec(content)) !== null) descriptions.push(match[1].replace(/\s+/g, " ").trim());
	return descriptions;
}
//#endregion
//#region src/commands/lib/sync-check-tests.ts
function toCamelCase(pascalCase) {
	return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
}
async function runModuleTestCaseSyncCheck(root, cwd) {
	const errors = [];
	const categories = moduleTestCaseCategories(root);
	for (const category of categories) {
		const docPaths = await fg(category.docPattern, { cwd });
		for (const docPath of docPaths) {
			const docFullPath = path.join(cwd, docPath);
			const docTestCases = parseTestCasesFromDoc(fs.readFileSync(docFullPath, "utf-8"));
			if (docTestCases.length === 0) continue;
			const docBasename = path.basename(docPath, ".md");
			const docsIndex = docPath.indexOf("/docs/");
			if (docsIndex === -1) continue;
			const modulePath = docPath.substring(0, docsIndex);
			const testFileName = `${toCamelCase(docBasename)}.test.ts`;
			const testPath = path.join(modulePath, category.testDir, testFileName);
			const testFullPath = path.join(cwd, testPath);
			if (!fs.existsSync(testFullPath)) {
				errors.push({
					type: "missing-test-file",
					category: category.name,
					docPath,
					sourcePath: testPath,
					expectedBasename: testFileName
				});
				continue;
			}
			const itDescriptions = parseItDescriptionsFromTest(fs.readFileSync(testFullPath, "utf-8"));
			const docSet = new Set(docTestCases);
			const testSet = new Set(itDescriptions);
			for (const docCase of docSet) if (!testSet.has(docCase)) errors.push({
				type: "missing-test-case",
				category: category.name,
				docPath,
				sourcePath: testPath,
				expectedBasename: docCase
			});
			for (const testCase of testSet) if (!docSet.has(testCase)) errors.push({
				type: "extra-test-case",
				category: category.name,
				docPath,
				sourcePath: testPath,
				expectedBasename: testCase
			});
		}
	}
	return errors;
}
function resolveStoryTestPath(docPath, testDir) {
	const match = /^(.+)\/docs\/business-flow\/([^/]+)\/story\/([^/]+)\.md$/.exec(docPath);
	if (!match) return null;
	const [, appPath, flow, name] = match;
	return `${appPath}/${testDir}/${flow}/${name}.test.ts`;
}
async function runAppTestCaseSyncCheck(appRoot, cwd) {
	const errors = [];
	const config = appTestCaseCategories(appRoot);
	const docPaths = await fg(config.docPattern, { cwd });
	for (const docPath of docPaths) {
		const docFullPath = path.join(cwd, docPath);
		const docTestCases = parseTestCasesFromDoc(fs.readFileSync(docFullPath, "utf-8"));
		if (docTestCases.length === 0) continue;
		const testPath = resolveStoryTestPath(docPath, config.testDir);
		if (!testPath) continue;
		const testFullPath = path.join(cwd, testPath);
		if (!fs.existsSync(testFullPath)) {
			errors.push({
				type: "missing-test-file",
				category: config.name,
				docPath,
				sourcePath: testPath,
				expectedBasename: path.basename(testPath)
			});
			continue;
		}
		const itDescriptions = parseItDescriptionsFromTest(fs.readFileSync(testFullPath, "utf-8"));
		const docSet = new Set(docTestCases);
		const testSet = new Set(itDescriptions);
		for (const docCase of docSet) if (!testSet.has(docCase)) errors.push({
			type: "missing-test-case",
			category: config.name,
			docPath,
			sourcePath: testPath,
			expectedBasename: docCase
		});
		for (const testCase of testSet) if (!docSet.has(testCase)) errors.push({
			type: "extra-test-case",
			category: config.name,
			docPath,
			sourcePath: testPath,
			expectedBasename: testCase
		});
	}
	return errors;
}
//#endregion
//#region src/commands/sync-check.ts
async function runSyncCheck(config, cwd) {
	const sourceResult = await runSourceSyncCheck(config, cwd);
	if (config.modulesRoot) {
		const testCaseErrors = await runModuleTestCaseSyncCheck(config.modulesRoot, cwd);
		sourceResult.errors.push(...testCaseErrors);
	}
	if (config.appRoot) {
		const storyErrors = await runAppTestCaseSyncCheck(config.appRoot, cwd);
		sourceResult.errors.push(...storyErrors);
	}
	sourceResult.exitCode = sourceResult.errors.length > 0 ? 1 : 0;
	return sourceResult;
}
function formatSyncCheckReport(result) {
	const lines = [];
	lines.push(chalk.bold("docs-sync-check: Checking source-documentation correspondence...\n"));
	if (result.errors.length > 0) {
		lines.push(chalk.red.bold("Errors:\n"));
		const byCategory = /* @__PURE__ */ new Map();
		for (const error of result.errors) {
			const existing = byCategory.get(error.category) ?? [];
			existing.push(error);
			byCategory.set(error.category, existing);
		}
		for (const [category, categoryErrors] of byCategory) {
			lines.push(chalk.cyan(`  Category: ${category}\n`));
			for (const error of categoryErrors) {
				if (error.type === "missing-doc") {
					lines.push(`  ${chalk.red(error.sourcePath)}`);
					lines.push(`    ${chalk.yellow("Missing documentation for:")} ${error.expectedBasename}`);
				} else if (error.type === "orphaned-doc") {
					lines.push(`  ${chalk.red(error.docPath)}`);
					lines.push(`    ${chalk.yellow("Orphaned documentation:")} no source file for ${error.expectedBasename}`);
				} else if (error.type === "missing-test-case") {
					lines.push(`  ${chalk.red(error.sourcePath)}`);
					lines.push(`    ${chalk.yellow("Missing test case:")} "${error.expectedBasename}" is in doc but not in test`);
				} else if (error.type === "extra-test-case") {
					lines.push(`  ${chalk.red(error.sourcePath)}`);
					lines.push(`    ${chalk.yellow("Extra test case:")} "${error.expectedBasename}" is in test but not in doc`);
				} else if (error.type === "missing-test-file") {
					lines.push(`  ${chalk.red(error.docPath)}`);
					lines.push(`    ${chalk.yellow("Missing test file:")} ${error.expectedBasename}`);
				}
				lines.push("");
			}
		}
	} else lines.push(chalk.green("All source files have corresponding documentation.\n"));
	lines.push(chalk.bold("Summary:"));
	lines.push(`  Categories checked: ${result.summary.categoriesChecked}`);
	lines.push(`  Source files: ${result.summary.totalSources}, Doc files: ${result.summary.totalDocs}`);
	if (result.errors.length > 0) {
		lines.push(chalk.red(`  Errors: ${result.errors.length}`));
		lines.push("");
		lines.push(chalk.red.bold(`docs-sync-check failed with ${result.errors.length} error(s).`));
	} else {
		lines.push(chalk.green("  Errors: 0"));
		lines.push("");
		lines.push(chalk.green.bold("docs-sync-check passed."));
	}
	return lines.join("\n");
}
//#endregion
//#region src/generator/parse-command-doc.ts
function parseCommandDoc(fileName, markdown) {
	const commandName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
	const tree = fromMarkdown(markdown);
	return {
		commandName,
		errors: parseErrorScenarios(tree),
		externalDependencies: parseExternalDependencies(tree)
	};
}
function errorCodeToClassName(code) {
	return code.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("") + "Error";
}
function isHeading$1(node) {
	return node.type === "heading";
}
function isList(node) {
	return node.type === "list";
}
function getNodesUnderHeading$1(tree, headingText) {
	const nodes = [];
	let collecting = false;
	for (const node of tree.children) {
		if (isHeading$1(node)) {
			if (collecting) break;
			if (node.depth === 2 && toString(node) === headingText) {
				collecting = true;
				continue;
			}
		}
		if (collecting) nodes.push(node);
	}
	return nodes;
}
const ERROR_PATTERN = /^([A-Z_]+):\s*(.+)$/;
function parseErrorScenarios(tree) {
	const nodes = getNodesUnderHeading$1(tree, "Error Scenarios");
	const errors = [];
	for (const node of nodes) {
		if (!isList(node)) continue;
		for (const item of node.children) {
			const text = toString(item);
			const match = ERROR_PATTERN.exec(text);
			if (match) errors.push({
				code: match[1],
				description: match[2].trim()
			});
		}
	}
	return errors;
}
const DEPENDENCY_PATTERN = /^([^:]+)::(.+)$/;
function parseExternalDependencies(tree) {
	const nodes = getNodesUnderHeading$1(tree, "External Dependencies");
	const deps = [];
	for (const node of nodes) {
		if (!isList(node)) continue;
		for (const item of node.children) {
			const firstChild = item.children[0];
			if (firstChild?.type !== "paragraph") continue;
			for (const inline of firstChild.children) if (inline.type === "link" || inline.type === "linkReference") {
				const linkText = toString(inline);
				const match = DEPENDENCY_PATTERN.exec(linkText);
				if (match) deps.push({
					module: match[1],
					entity: match[2]
				});
			}
		}
	}
	return deps;
}
//#endregion
//#region src/generator/generate-errors.ts
function moduleNameToPrefix(moduleName) {
	return moduleName.toUpperCase().replace(/-/g, "_");
}
function generateErrors(moduleName, docs) {
	const seen = /* @__PURE__ */ new Set();
	const lines = [];
	const prefix = moduleNameToPrefix(moduleName);
	for (const doc of docs) for (const error of doc.errors) {
		if (seen.has(error.code)) continue;
		seen.add(error.code);
		const className = errorCodeToClassName(error.code);
		const prefixedCode = `${prefix}_${error.code}`;
		lines.push(`export const ${className} = createDomainError(`);
		lines.push(`  "${className}", "${prefixedCode}",`);
		const escapedDesc = error.description.replace(/`/g, "'");
		lines.push(`  (identifier: string) => \`${escapedDesc}: \${identifier}\`,`);
		lines.push(`);`);
		lines.push(``);
	}
	if (lines.length === 0) return "";
	return `// @generated — do not edit
import { createDomainError } from "@tailor-platform/erp-kit/module";

${lines.join("\n")}`;
}
//#endregion
//#region src/generator/generate-permissions.ts
function generatePermissions(moduleName, commandNames) {
	return `// @generated — do not edit
import { definePermissions } from "@tailor-platform/erp-kit/module";

export const { permissions, own, all } = definePermissions("${moduleName}", [
${[...commandNames].sort().map((name) => `  "${name}",`).join("\n")}
] as const);
`;
}
//#endregion
//#region src/generator/generate-shells.ts
function generateCommandShell(doc) {
	return [
		`// @generated — do not edit`,
		`import { permissions } from "../lib/permissions.generated";`,
		`import { run } from "./${doc.commandName}";`,
		`import { defineCommand } from "@tailor-platform/erp-kit/module";`,
		``,
		`export const ${doc.commandName} = defineCommand(permissions.${doc.commandName}, run);`,
		``
	].join("\n");
}
function generateQueryShell(doc) {
	return [
		`// @generated — do not edit`,
		`import { run } from "./${doc.commandName}";`,
		`import { defineQuery } from "@tailor-platform/erp-kit/module";`,
		``,
		`export const ${doc.commandName} = defineQuery(run);`,
		``
	].join("\n");
}
//#endregion
//#region src/generator/stub-templates.ts
function toPascal(name) {
	return name.charAt(0).toUpperCase() + name.slice(1);
}
const templates = {
	command: { render: (name) => {
		const inputType = `${toPascal(name)}Input`;
		return `import type { Transaction } from "../generated/kysely-tailordb";
import { ok, type CommandContext } from "@tailor-platform/erp-kit/module";

export interface ${inputType} {
  // TODO: define input fields
}

export async function run(db: Transaction, input: ${inputType}, ctx: CommandContext) {
  // TODO: implement
  return ok({});
}
`;
	} },
	commandTest: { render: (name) => {
		const pascal = toPascal(name);
		return `import { describe, expect, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { Transaction } from "../generated/kysely-tailordb";
import { run, ${pascal}Input } from "./${name}";
import type { CommandContext } from "@tailor-platform/erp-kit/module";

describe("${name} - test scenario", () => {
  const ctx: CommandContext = {
    actorId: "test-actor",
    permissions: ["TODO:${name}"],
  };

  it("should be implemented", async () => {
    const { db } = createMockDb<Transaction>();
    const result = await run(db, {} as ${pascal}Input, ctx);
    expect(result.ok).toBe(true);
  });
});
`;
	} },
	query: { render: (name) => {
		const inputType = `${toPascal(name)}Input`;
		return `import type { DB } from "../generated/kysely-tailordb";
import type { ReadonlyDB } from "@tailor-platform/erp-kit/module";

export interface ${inputType} {
  // TODO: define input fields
}

export async function run(db: ReadonlyDB<DB>, input: ${inputType}) {
  // TODO: implement
  return {};
}
`;
	} },
	queryTest: { render: (name) => {
		const inputType = `${toPascal(name)}Input`;
		return `import { describe, expect, it } from "vitest";
import { createMockDb } from "../../../testing/index";
import type { DB } from "../generated/kysely-tailordb";
import { run, type ${inputType} } from "./${name}";

describe("${name}", () => {
  it("should be implemented", async () => {
    const { db } = createMockDb<DB>();
    const result = await run(db, {} as ${inputType});
    expect(result).toBeDefined();
  });
});
`;
	} },
	db: { render: (name) => {
		return `import { db, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission } from "@tailor-platform/sdk";

export const ${name} = db
  .type("${toPascal(name)}", {
    // TODO: define fields
    ...db.fields.timestamps(),
  })
  .permission(unsafeAllowAllTypePermission)
  .gqlPermission(unsafeAllowAllGqlPermission);
`;
	} },
	resolver: { render: (name) => {
		return `import { createResolver, t } from "@tailor-platform/sdk";
import { createContext } from "@tailor-platform/erp-kit/app";
import { getDB } from "@/generated/kysely-tailordb";

export default createResolver({
  name: "${name}",
  operation: "mutation",
  input: {
    // TODO: define input fields
  },
  body: async (context) => {
    const db = getDB("main-db");
    return db.transaction().execute(async (trx) => {
      // TODO: implement
      return {};
    });
  },
  output: t
    .object({
      // TODO: define output fields
    })
    .description("${toPascal(name)} response"),
});
`;
	} },
	storyTest: { render: (name, testCases) => {
		return `import { describe, expect, inject, it } from "vitest";
import { createGraphQLClient } from "@/tests/utils/graphql-client";

describe("${name}", () => {
  const graphQLClient = createGraphQLClient(inject("url"), inject("token"));

${testCases.map((tc) => `  it("${tc}", async () => {\n    // TODO: implement\n  });`).join("\n\n")}
});
`;
	} }
};
function renderStub(type, name, testCases) {
	if (type === "storyTest") return templates.storyTest.render(name, testCases);
	return templates[type].render(name);
}
//#endregion
//#region src/generator/generate-code.ts
function runGenerateCode(modulePath, moduleName) {
	scaffoldModuleBoilerplate(modulePath, moduleName);
	const docsDir = path.join(modulePath, "docs", "commands");
	const libDir = path.join(modulePath, "lib");
	const commandDir = path.join(modulePath, "command");
	if (!fs.existsSync(docsDir)) {
		console.log(`No docs/commands/ directory found — skipping code generation`);
		console.log(`Generated boilerplate for ${moduleName}`);
		return 0;
	}
	const mdFiles = fs.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
	if (mdFiles.length === 0) {
		console.log(`No command docs found — skipping code generation`);
		console.log(`Generated boilerplate for ${moduleName}`);
		return 0;
	}
	const parsedDocs = [];
	for (const file of mdFiles) {
		const content = fs.readFileSync(path.join(docsDir, file), "utf-8");
		const name = path.basename(file, ".md");
		parsedDocs.push(parseCommandDoc(name, content));
	}
	const queryDocsDir = path.join(modulePath, "docs", "queries");
	const allDocsForErrors = [...parsedDocs];
	if (fs.existsSync(queryDocsDir)) {
		const queryFiles = fs.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
		for (const file of queryFiles) {
			const content = fs.readFileSync(path.join(queryDocsDir, file), "utf-8");
			const name = path.basename(file, ".md");
			allDocsForErrors.push(parseCommandDoc(name, content));
		}
	}
	let generated = 0;
	const errorsContent = generateErrors(moduleName, allDocsForErrors);
	if (errorsContent) {
		fs.mkdirSync(libDir, { recursive: true });
		const errorsFile = path.join(libDir, "errors.generated.ts");
		fs.writeFileSync(errorsFile, errorsContent);
		console.log(`  wrote ${path.relative(modulePath, errorsFile)}`);
		generated++;
	}
	const permissionsContent = generatePermissions(moduleName, parsedDocs.map((d) => d.commandName));
	const permissionsFile = path.join(libDir, "permissions.generated.ts");
	fs.writeFileSync(permissionsFile, permissionsContent);
	console.log(`  wrote ${path.relative(modulePath, permissionsFile)}`);
	generated++;
	fs.mkdirSync(commandDir, { recursive: true });
	for (const doc of parsedDocs) {
		const implFile = path.join(commandDir, `${doc.commandName}.ts`);
		const shellContent = generateCommandShell(doc);
		const shellFile = path.join(commandDir, `${doc.commandName}.generated.ts`);
		fs.writeFileSync(shellFile, shellContent);
		console.log(`  wrote ${path.relative(modulePath, shellFile)}`);
		generated++;
		if (!fs.existsSync(implFile)) {
			fs.writeFileSync(implFile, renderStub("command", doc.commandName));
			console.log(`  scaffolded ${path.relative(modulePath, implFile)}`);
		}
		const testFile = path.join(commandDir, `${doc.commandName}.test.ts`);
		if (!fs.existsSync(testFile)) {
			fs.writeFileSync(testFile, renderStub("commandTest", doc.commandName));
			console.log(`  scaffolded ${path.relative(modulePath, testFile)}`);
		}
	}
	if (fs.existsSync(queryDocsDir)) {
		const queryFiles = fs.readdirSync(queryDocsDir).filter((f) => f.endsWith(".md"));
		if (queryFiles.length > 0) {
			const queryDir = path.join(modulePath, "query");
			fs.mkdirSync(queryDir, { recursive: true });
			for (const file of queryFiles) {
				const content = fs.readFileSync(path.join(queryDocsDir, file), "utf-8");
				const doc = parseCommandDoc(path.basename(file, ".md"), content);
				const shellFile = path.join(queryDir, `${doc.commandName}.generated.ts`);
				fs.writeFileSync(shellFile, generateQueryShell(doc));
				console.log(`  wrote ${path.relative(modulePath, shellFile)}`);
				generated++;
				const implFile = path.join(queryDir, `${doc.commandName}.ts`);
				if (!fs.existsSync(implFile)) {
					fs.writeFileSync(implFile, renderStub("query", doc.commandName));
					console.log(`  scaffolded ${path.relative(modulePath, implFile)}`);
				}
				const testFile = path.join(queryDir, `${doc.commandName}.test.ts`);
				if (!fs.existsSync(testFile)) {
					fs.writeFileSync(testFile, renderStub("queryTest", doc.commandName));
					console.log(`  scaffolded ${path.relative(modulePath, testFile)}`);
				}
			}
		}
	}
	const modelDocsDir = path.join(modulePath, "docs", "models");
	if (fs.existsSync(modelDocsDir)) {
		const modelFiles = fs.readdirSync(modelDocsDir).filter((f) => f.endsWith(".md"));
		if (modelFiles.length > 0) {
			const dbDir = path.join(modulePath, "db");
			fs.mkdirSync(dbDir, { recursive: true });
			for (const file of modelFiles) {
				const modelName = path.basename(file, ".md");
				const camelName = modelName.charAt(0).toLowerCase() + modelName.slice(1);
				const dbFile = path.join(dbDir, `${camelName}.ts`);
				if (!fs.existsSync(dbFile)) {
					fs.writeFileSync(dbFile, renderStub("db", camelName));
					console.log(`  scaffolded ${path.relative(modulePath, dbFile)}`);
				}
			}
		}
	}
	console.log(`Generated ${generated} file(s) for ${moduleName}`);
	return 0;
}
//#endregion
//#region src/commands/generate-doc.ts
const MODULE_DOC_TYPES = [
	"feature",
	"command",
	"model",
	"query"
];
const APP_DOC_TYPES = [
	"actors",
	"business-flow",
	"story",
	"screen",
	"resolver"
];
[...MODULE_DOC_TYPES, ...APP_DOC_TYPES];
const MODULE_DIR_MAP = {
	feature: MODULE_PATHS.docs.features,
	command: MODULE_PATHS.docs.commands,
	model: MODULE_PATHS.docs.models,
	query: MODULE_PATHS.docs.queries
};
const APP_DIR_MAP = {
	actors: APP_PATHS.docs.actors,
	"business-flow": APP_PATHS.docs.businessFlow,
	screen: APP_PATHS.docs.screen,
	resolver: APP_PATHS.docs.resolver
};
function resolveDocPath(type, name, modulePath) {
	if (!name) throw new Error(`Name is required for doc type "${type}"`);
	if (type === "business-flow") return path.join(modulePath, APP_PATHS.docs.businessFlow, name, "README.md");
	if (type === "story") {
		const parts = name.split("/");
		if (parts.length !== 2) throw new Error(`Story name must be "<flow>/<story>" (e.g., "onboarding/admin--create-user")`);
		return path.join(modulePath, APP_PATHS.docs.businessFlow, parts[0], APP_PATHS.docs.story, `${parts[1]}.md`);
	}
	if (MODULE_DIR_MAP[type]) return path.join(modulePath, MODULE_DIR_MAP[type], `${name}.md`);
	if (APP_DIR_MAP[type]) return path.join(modulePath, APP_DIR_MAP[type], `${name}.md`);
	throw new Error(`Unknown doc type: ${type}`);
}
async function runGenerateDoc(type, name, modulePath, cwd) {
	const outputPath = resolveDocPath(type, name, modulePath);
	const absoluteOutput = path.resolve(cwd, outputPath);
	if (fs.existsSync(absoluteOutput)) {
		console.error(`File already exists: ${outputPath}`);
		return 1;
	}
	const schemaPath = ALL_SCHEMAS[type];
	if (!schemaPath) {
		console.error(`No schema found for type: ${type}`);
		return 2;
	}
	try {
		fs.mkdirSync(path.dirname(absoluteOutput), { recursive: true });
	} catch (err) {
		console.error(`Failed to create directory: ${err instanceof Error ? err.message : String(err)}`);
		return 1;
	}
	const { exitCode, stdout, stderr } = await runMdschema([
		"generate",
		"--schema",
		schemaPath,
		"--output",
		absoluteOutput
	], cwd);
	if (stdout.trim()) console.log(stdout);
	if (stderr.trim()) console.error(stderr);
	return exitCode;
}
//#endregion
//#region src/commands/module/generate.ts
const cwd$4 = process.cwd();
const pathArgs$2 = z.object({ path: arg(z.string(), {
	alias: "p",
	description: "Path to the module directory"
}) });
const generateCommand$1 = defineCommand({
	name: "generate",
	description: "Generate docs and code for a module",
	subCommands: {
		doc: defineCommand({
			name: "doc",
			description: "Create a documentation file from a schema template",
			args: pathArgs$2.extend({
				type: arg(z.enum(MODULE_DOC_TYPES), {
					positional: true,
					description: `Doc type (${MODULE_DOC_TYPES.join(", ")})`
				}),
				name: arg(z.string().optional(), {
					positional: true,
					description: "Item name (required for all types)"
				})
			}),
			run: (args) => {
				return executeCommand(async () => {
					const exitCode = await runGenerateDoc(args.type, args.name, args.path, cwd$4);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		code: defineCommand({
			name: "code",
			description: "Generate boilerplate, implementation stubs, and generated code from docs",
			args: pathArgs$2,
			run: (args) => {
				return executeCommand(() => {
					const modulePath = path.resolve(cwd$4, args.path);
					const moduleName = path.basename(modulePath);
					console.log(`Generating code for ${moduleName}...`);
					const exitCode = runGenerateCode(modulePath, moduleName);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		})
	}
});
//#endregion
//#region src/commands/module/index.ts
const cwd$3 = process.cwd();
const pathArgs$1 = z.object({ path: arg(z.string(), {
	alias: "p",
	description: "Path to modules directory"
}) });
const checkCommand$1 = defineCommand({
	name: "check",
	description: "Validate module docs against schemas",
	args: pathArgs$1,
	run: (args) => {
		return executeCommand(async () => {
			const exitCode = await runCheck({ modulesRoot: args.path }, cwd$3);
			return exitCode === 0 ? success() : silentFailure(exitCode);
		});
	}
});
const syncCheckCommand$1 = defineCommand({
	name: "sync-check",
	description: "Validate source <-> doc correspondence",
	args: pathArgs$1,
	run: (args) => {
		return executeCommand(async () => {
			const result = await runSyncCheck({ modulesRoot: args.path }, cwd$3);
			console.log(formatSyncCheckReport(result));
			return result.exitCode === 0 ? success() : silentFailure(result.exitCode);
		});
	}
});
const initCommand$2 = defineCommand({
	name: "init",
	description: "Bootstrap a new module with directory structure and README",
	args: z.object({
		name: arg(z.string(), {
			positional: true,
			description: "Module name"
		}),
		dir: arg(z.string(), {
			positional: true,
			description: "Parent directory where the module will be created"
		})
	}),
	run: (args) => {
		return executeCommand(async () => {
			const exitCode = await runInitModuleWithReadme(args.name, args.dir, cwd$3);
			return exitCode === 0 ? success() : silentFailure(exitCode);
		});
	}
});
const moduleCommand$1 = defineCommand({
	name: "module",
	description: "Module management",
	subCommands: {
		check: checkCommand$1,
		"sync-check": syncCheckCommand$1,
		init: initCommand$2,
		generate: generateCommand$1
	}
});
//#endregion
//#region src/generator/parse-resolver-doc.ts
const MODULE_COMMAND_PATTERN = /([a-z][\w-]*)\.(\w+)/;
const TABLE_ROW_PATTERN = /^\|(.+)\|(.+)\|$/;
function parseResolverDoc(fileName, markdown) {
	return {
		resolverName: fileName.charAt(0).toLowerCase() + fileName.slice(1),
		moduleCommands: parseModuleCommands(fromMarkdown(markdown)),
		errors: parseExceptionHandlingFromRaw(markdown)
	};
}
function isHeading(node) {
	return node.type === "heading";
}
function getNodesUnderHeading(tree, headingText) {
	const nodes = [];
	let collecting = false;
	for (const node of tree.children) {
		if (isHeading(node)) {
			if (collecting) break;
			if (node.depth === 2 && toString(node) === headingText) {
				collecting = true;
				continue;
			}
		}
		if (collecting) nodes.push(node);
	}
	return nodes;
}
function parseModuleCommands(tree) {
	const nodes = getNodesUnderHeading(tree, "Modules Commands Used");
	const commands = [];
	for (const node of nodes) {
		if (node.type !== "list") continue;
		for (const item of node.children) {
			const text = toString(item);
			const match = MODULE_COMMAND_PATTERN.exec(text);
			if (match) commands.push({
				module: match[1],
				command: match[2]
			});
		}
	}
	return commands;
}
function parseExceptionHandlingFromRaw(markdown) {
	const lines = markdown.split("\n");
	const errors = [];
	let inSection = false;
	let headerSkipped = false;
	let separatorSkipped = false;
	for (const line of lines) {
		const trimmed = line.trim();
		if (trimmed.startsWith("## Exception Handling")) {
			inSection = true;
			continue;
		}
		if (!inSection) continue;
		if (trimmed.startsWith("#")) break;
		if (!trimmed) continue;
		const match = TABLE_ROW_PATTERN.exec(trimmed);
		if (!match) continue;
		if (!headerSkipped) {
			headerSkipped = true;
			continue;
		}
		if (!separatorSkipped) {
			separatorSkipped = true;
			continue;
		}
		const code = match[1].trim();
		const description = match[2].trim();
		if (code) errors.push({
			code,
			description
		});
	}
	return errors;
}
//#endregion
//#region src/generator/generate-app-code.ts
function runGenerateAppCode(appPath) {
	const appName = path.basename(appPath);
	scaffoldAppBoilerplate(appPath, appName);
	generateResolverStubs(appPath, appName);
	generateStoryTestStubs(appPath, appName);
	return 0;
}
function generateResolverStubs(appPath, appName) {
	const docsDir = path.join(appPath, "docs", "resolver");
	if (!fs.existsSync(docsDir)) return;
	const mdFiles = fs.readdirSync(docsDir).filter((f) => f.endsWith(".md"));
	if (mdFiles.length === 0) return;
	const resolverDir = path.join(appPath, "backend", "src", "resolvers");
	fs.mkdirSync(resolverDir, { recursive: true });
	let generated = 0;
	for (const file of mdFiles) {
		const content = fs.readFileSync(path.join(docsDir, file), "utf-8");
		const doc = parseResolverDoc(path.basename(file, ".md"), content);
		const implFile = path.join(resolverDir, `${doc.resolverName}.ts`);
		if (!fs.existsSync(implFile)) {
			fs.writeFileSync(implFile, renderStub("resolver", doc.resolverName));
			console.log(`  scaffolded ${path.relative(appPath, implFile)}`);
			generated++;
		}
	}
	if (generated > 0) console.log(`Scaffolded ${generated} resolver(s) for ${appName}`);
}
function generateStoryTestStubs(appPath, appName) {
	const storyDocs = globSync(path.join(appPath, "docs/business-flow/*/story/*.md"));
	let generated = 0;
	for (const storyDocPath of storyDocs) {
		const testCases = parseTestCasesFromDoc(fs.readFileSync(storyDocPath, "utf-8"));
		if (testCases.length === 0) continue;
		const match = /\/docs\/business-flow\/([^/]+)\/story\/([^/]+)\.md$/.exec(storyDocPath);
		if (!match) continue;
		const [, flow, storyName] = match;
		const testDir = path.join(appPath, APP_PATHS.tests.stories, flow);
		const testFile = path.join(testDir, `${storyName}.test.ts`);
		if (fs.existsSync(testFile)) continue;
		fs.mkdirSync(testDir, { recursive: true });
		fs.writeFileSync(testFile, renderStub("storyTest", storyName, testCases));
		console.log(`  scaffolded ${path.relative(appPath, testFile)}`);
		generated++;
	}
	if (generated > 0) console.log(`Scaffolded ${generated} story test(s) for ${appName}`);
}
//#endregion
//#region src/shared/uuidv5.ts
/**
* Generates a deterministic UUID v5 from a namespace and name.
* Uses SHA-1 hashing per RFC 4122 §4.3.
*/
function uuidv5(namespace, name) {
	const hash = createHash("sha1").update(namespace).update(name).digest();
	hash[6] = hash[6] & 15 | 80;
	hash[8] = hash[8] & 63 | 128;
	const hex = hash.toString("hex");
	return [
		hex.slice(0, 8),
		hex.slice(8, 12),
		hex.slice(12, 16),
		hex.slice(16, 20),
		hex.slice(20, 32)
	].join("-");
}
//#endregion
//#region src/modules/primitives/seed/uomCategories.ts
const NS$3 = "erp-kit:primitives";
const uomCategoryIds = {
	Weight: uuidv5(NS$3, "uom-category:Weight"),
	Length: uuidv5(NS$3, "uom-category:Length"),
	Volume: uuidv5(NS$3, "uom-category:Volume"),
	Area: uuidv5(NS$3, "uom-category:Area"),
	Time: uuidv5(NS$3, "uom-category:Time"),
	Quantity: uuidv5(NS$3, "uom-category:Quantity")
};
const uomCategories = {
	[uomCategoryIds.Weight]: {
		name: "Weight",
		description: "Mass and weight measurement",
		isActive: true
	},
	[uomCategoryIds.Length]: {
		name: "Length",
		description: "Length and distance measurement",
		isActive: true
	},
	[uomCategoryIds.Volume]: {
		name: "Volume",
		description: "Volume and capacity measurement",
		isActive: true
	},
	[uomCategoryIds.Area]: {
		name: "Area",
		description: "Surface area measurement",
		isActive: true
	},
	[uomCategoryIds.Time]: {
		name: "Time",
		description: "Time duration measurement",
		isActive: true
	},
	[uomCategoryIds.Quantity]: {
		name: "Quantity",
		description: "Discrete count measurement",
		isActive: true
	}
};
//#endregion
//#region src/modules/primitives/seed/units.ts
const NS$2 = "erp-kit:primitives";
const unitIds = {
	kg: uuidv5(NS$2, "unit:kg"),
	g: uuidv5(NS$2, "unit:g"),
	lb: uuidv5(NS$2, "unit:lb"),
	oz: uuidv5(NS$2, "unit:oz"),
	m: uuidv5(NS$2, "unit:m"),
	cm: uuidv5(NS$2, "unit:cm"),
	ft: uuidv5(NS$2, "unit:ft"),
	in: uuidv5(NS$2, "unit:in"),
	L: uuidv5(NS$2, "unit:L"),
	mL: uuidv5(NS$2, "unit:mL"),
	gal: uuidv5(NS$2, "unit:gal"),
	sqm: uuidv5(NS$2, "unit:sqm"),
	sqft: uuidv5(NS$2, "unit:sqft"),
	hr: uuidv5(NS$2, "unit:hr"),
	min: uuidv5(NS$2, "unit:min"),
	s: uuidv5(NS$2, "unit:s"),
	ea: uuidv5(NS$2, "unit:ea"),
	dz: uuidv5(NS$2, "unit:dz"),
	pk: uuidv5(NS$2, "unit:pk")
};
const units = {
	[unitIds.kg]: {
		name: "Kilogram",
		symbol: "kg",
		categoryId: uomCategoryIds.Weight,
		conversionFactor: 1,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.g]: {
		name: "Gram",
		symbol: "g",
		categoryId: uomCategoryIds.Weight,
		conversionFactor: .001,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.lb]: {
		name: "Pound",
		symbol: "lb",
		categoryId: uomCategoryIds.Weight,
		conversionFactor: .453592,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.oz]: {
		name: "Ounce",
		symbol: "oz",
		categoryId: uomCategoryIds.Weight,
		conversionFactor: .0283495,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.m]: {
		name: "Meter",
		symbol: "m",
		categoryId: uomCategoryIds.Length,
		conversionFactor: 1,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.cm]: {
		name: "Centimeter",
		symbol: "cm",
		categoryId: uomCategoryIds.Length,
		conversionFactor: .01,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.ft]: {
		name: "Foot",
		symbol: "ft",
		categoryId: uomCategoryIds.Length,
		conversionFactor: .3048,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.in]: {
		name: "Inch",
		symbol: "in",
		categoryId: uomCategoryIds.Length,
		conversionFactor: .0254,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.L]: {
		name: "Liter",
		symbol: "L",
		categoryId: uomCategoryIds.Volume,
		conversionFactor: 1,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.mL]: {
		name: "Milliliter",
		symbol: "mL",
		categoryId: uomCategoryIds.Volume,
		conversionFactor: .001,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.gal]: {
		name: "Gallon",
		symbol: "gal",
		categoryId: uomCategoryIds.Volume,
		conversionFactor: 3.78541,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.sqm]: {
		name: "Square Meter",
		symbol: "m²",
		categoryId: uomCategoryIds.Area,
		conversionFactor: 1,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.sqft]: {
		name: "Square Foot",
		symbol: "ft²",
		categoryId: uomCategoryIds.Area,
		conversionFactor: .092903,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.hr]: {
		name: "Hour",
		symbol: "hr",
		categoryId: uomCategoryIds.Time,
		conversionFactor: 1,
		roundingPrecision: 2,
		isActive: true
	},
	[unitIds.min]: {
		name: "Minute",
		symbol: "min",
		categoryId: uomCategoryIds.Time,
		conversionFactor: 1 / 60,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.s]: {
		name: "Second",
		symbol: "s",
		categoryId: uomCategoryIds.Time,
		conversionFactor: 1 / 3600,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.ea]: {
		name: "Each",
		symbol: "ea",
		categoryId: uomCategoryIds.Quantity,
		conversionFactor: 1,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.dz]: {
		name: "Dozen",
		symbol: "dz",
		categoryId: uomCategoryIds.Quantity,
		conversionFactor: 12,
		roundingPrecision: 0,
		isActive: true
	},
	[unitIds.pk]: {
		name: "Pack",
		symbol: "pk",
		categoryId: uomCategoryIds.Quantity,
		conversionFactor: 1,
		roundingPrecision: 0,
		isActive: true
	}
};
//#endregion
//#region src/modules/primitives/seed/currencies.ts
const NS$1 = "erp-kit:primitives";
const currencyIds = {
	USD: uuidv5(NS$1, "currency:USD"),
	EUR: uuidv5(NS$1, "currency:EUR"),
	GBP: uuidv5(NS$1, "currency:GBP"),
	JPY: uuidv5(NS$1, "currency:JPY"),
	CNY: uuidv5(NS$1, "currency:CNY")
};
const currencies = {
	[currencyIds.USD]: {
		code: "USD",
		name: "US Dollar",
		symbol: "$",
		decimalPlaces: 2,
		isBaseCurrency: true,
		isActive: true
	},
	[currencyIds.EUR]: {
		code: "EUR",
		name: "Euro",
		symbol: "€",
		decimalPlaces: 2,
		isBaseCurrency: false,
		isActive: true
	},
	[currencyIds.GBP]: {
		code: "GBP",
		name: "British Pound",
		symbol: "£",
		decimalPlaces: 2,
		isBaseCurrency: false,
		isActive: true
	},
	[currencyIds.JPY]: {
		code: "JPY",
		name: "Japanese Yen",
		symbol: "¥",
		decimalPlaces: 0,
		isBaseCurrency: false,
		isActive: true
	},
	[currencyIds.CNY]: {
		code: "CNY",
		name: "Chinese Yuan",
		symbol: "¥",
		decimalPlaces: 2,
		isBaseCurrency: false,
		isActive: true
	}
};
//#endregion
//#region src/modules/primitives/seed/exchangeRates.ts
const NS = "erp-kit:primitives";
const exchangeRateIds = {
	"USD-EUR": uuidv5(NS, "rate:USD-EUR"),
	"USD-GBP": uuidv5(NS, "rate:USD-GBP"),
	"USD-JPY": uuidv5(NS, "rate:USD-JPY"),
	"USD-CNY": uuidv5(NS, "rate:USD-CNY")
};
const exchangeRates = {
	[exchangeRateIds["USD-EUR"]]: {
		sourceCurrencyId: currencyIds.USD,
		targetCurrencyId: currencyIds.EUR,
		rate: .92,
		effectiveDate: /* @__PURE__ */ new Date("2025-01-01")
	},
	[exchangeRateIds["USD-GBP"]]: {
		sourceCurrencyId: currencyIds.USD,
		targetCurrencyId: currencyIds.GBP,
		rate: .79,
		effectiveDate: /* @__PURE__ */ new Date("2025-01-01")
	},
	[exchangeRateIds["USD-JPY"]]: {
		sourceCurrencyId: currencyIds.USD,
		targetCurrencyId: currencyIds.JPY,
		rate: 148.5,
		effectiveDate: /* @__PURE__ */ new Date("2025-01-01")
	},
	[exchangeRateIds["USD-CNY"]]: {
		sourceCurrencyId: currencyIds.USD,
		targetCurrencyId: currencyIds.CNY,
		rate: 7.24,
		effectiveDate: /* @__PURE__ */ new Date("2025-01-01")
	}
};
//#endregion
//#region src/generator/generate-seed.ts
const INTERNAL_SEED = { primitives: /* @__PURE__ */ __exportAll({
	Currency: () => currencies,
	ExchangeRate: () => exchangeRates,
	Unit: () => units,
	UoMCategory: () => uomCategories,
	currencyIds: () => currencyIds,
	unitIds: () => unitIds,
	uomCategoryIds: () => uomCategoryIds
}) };
function mapToJsonl(data) {
	return Object.entries(data).map(([id, row]) => JSON.stringify({
		id,
		...row
	})).join("\n") + "\n";
}
function capitalize(s) {
	return s.charAt(0).toUpperCase() + s.slice(1);
}
/**
* Checks if a value is a seed data map: Record<string, Record<string, unknown>>.
* Distinguishes from ID maps (Record<string, string>) by checking nested values.
*/
function isSeedMap(value) {
	if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
	const entries = Object.entries(value);
	if (entries.length === 0) return false;
	return entries.every(([, v]) => typeof v === "object" && v !== null && !Array.isArray(v));
}
function runGenerateSeed(appPath) {
	const seedDir = path.join(appPath, "backend", "seed", "data");
	fs.mkdirSync(seedDir, { recursive: true });
	let written = 0;
	let skipped = 0;
	const modulesWithSeed = [];
	for (const [moduleName, mod] of Object.entries(INTERNAL_SEED)) {
		const entries = Object.entries(mod).filter(([, v]) => isSeedMap(v));
		if (entries.length === 0) continue;
		modulesWithSeed.push(moduleName);
		for (const [exportName, data] of entries) {
			const fileName = capitalize(exportName);
			const filePath = path.join(seedDir, `${fileName}.jsonl`);
			if (fs.existsSync(filePath)) {
				console.log(`  skipped ${fileName}.jsonl (already exists)`);
				skipped++;
				continue;
			}
			const rowCount = Object.keys(data).length;
			fs.writeFileSync(filePath, mapToJsonl(data));
			console.log(`  wrote ${fileName}.jsonl (${rowCount} rows)`);
			written++;
		}
	}
	console.log(`\nModules with seed data: ${modulesWithSeed.join(", ") || "none"}`);
	console.log(`Generated ${written} file(s), skipped ${skipped} existing`);
	return 0;
}
z.enum([
	"step.start",
	"step.complete",
	"decision",
	"agent.dispatch",
	"agent.result",
	"artifact.create",
	"validation",
	"error",
	"note"
]);
const StepStatus = z.enum([
	"pass",
	"fail",
	"blocked"
]);
const ArtifactType = z.enum([
	"doc",
	"code",
	"config",
	"report",
	"seed",
	"asset"
]);
const ArtifactOperation = z.enum([
	"create",
	"update",
	"delete"
]);
const ConversationMessage = z.object({
	role: z.enum(["user", "agent"]),
	message: z.string()
});
const GitContext = z.object({
	branch: z.string(),
	commit: z.string()
});
const StepStartData = z.object({
	skill: z.string(),
	context: z.record(z.string(), z.unknown())
});
const StepCompleteData = z.object({
	status: StepStatus,
	summary: z.string(),
	artifacts: z.array(z.string())
});
const DecisionData = z.object({
	question: z.string(),
	choice: z.string(),
	alternatives: z.array(z.string()),
	rationale: z.string()
});
const AgentDispatchData = z.object({
	agentName: z.string(),
	task: z.string(),
	inputs: z.record(z.string(), z.unknown())
});
const AgentResultData = z.object({
	agentName: z.string(),
	status: z.enum(["pass", "fail"]),
	outputs: z.record(z.string(), z.unknown()),
	duration_ms: z.number()
});
const ArtifactCreateData = z.object({
	path: z.string(),
	type: ArtifactType,
	operation: ArtifactOperation
});
const ValidationData = z.object({
	command: z.string(),
	status: z.enum(["pass", "fail"]),
	issues: z.array(z.string())
});
const ErrorData = z.object({
	message: z.string(),
	recoverable: z.boolean()
});
const NoteData = z.object({
	message: z.string(),
	tags: z.array(z.string())
});
const convField = () => z.array(ConversationMessage).default([]);
const StepStartEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("step.start"),
	data: StepStartData
});
const StepCompleteEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("step.complete"),
	data: StepCompleteData
});
const DecisionEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("decision"),
	data: DecisionData
});
const AgentDispatchEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("agent.dispatch"),
	data: AgentDispatchData
});
const AgentResultEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("agent.result"),
	data: AgentResultData
});
const ArtifactCreateEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("artifact.create"),
	data: ArtifactCreateData
});
const ValidationEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("validation"),
	data: ValidationData
});
const ErrorEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("error"),
	data: ErrorData
});
const NoteEntry = z.object({
	v: z.literal(1),
	timestamp: z.string().datetime(),
	sessionId: z.string(),
	prompt: z.string(),
	git: GitContext,
	conversation: convField(),
	event: z.literal("note"),
	data: NoteData
});
const ProgressEntry = z.union([
	StepStartEntry,
	StepCompleteEntry,
	DecisionEntry,
	AgentDispatchEntry,
	AgentResultEntry,
	ArtifactCreateEntry,
	ValidationEntry,
	ErrorEntry,
	NoteEntry
]);
const StepStartInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("step.start"),
	data: StepStartData
});
const StepCompleteInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("step.complete"),
	data: StepCompleteData
});
const DecisionInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("decision"),
	data: DecisionData
});
const AgentDispatchInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("agent.dispatch"),
	data: AgentDispatchData
});
const AgentResultInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("agent.result"),
	data: AgentResultData
});
const ArtifactCreateInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("artifact.create"),
	data: ArtifactCreateData
});
const ValidationInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("validation"),
	data: ValidationData
});
const ErrorInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("error"),
	data: ErrorData
});
const NoteInput = z.object({
	v: z.literal(1),
	sessionId: z.string(),
	prompt: z.string(),
	conversation: convField(),
	event: z.literal("note"),
	data: NoteData
});
const ProgressInput = z.union([
	StepStartInput,
	StepCompleteInput,
	DecisionInput,
	AgentDispatchInput,
	AgentResultInput,
	ArtifactCreateInput,
	ValidationInput,
	ErrorInput,
	NoteInput
]);
//#endregion
//#region src/commands/app/progress/git-context.ts
function getGitContext(cwd) {
	return {
		branch: execFileSync("git", [
			"rev-parse",
			"--abbrev-ref",
			"HEAD"
		], {
			cwd,
			encoding: "utf-8"
		}).trim(),
		commit: execFileSync("git", [
			"rev-parse",
			"--short",
			"HEAD"
		], {
			cwd,
			encoding: "utf-8"
		}).trim()
	};
}
//#endregion
//#region src/commands/app/progress/log.ts
function runProgressLog(jsonInput, dryRun, cwd) {
	let parsed;
	try {
		parsed = JSON.parse(jsonInput);
	} catch {
		return failure("Invalid JSON input");
	}
	const inputResult = ProgressInput.safeParse(parsed);
	if (!inputResult.success) return failure(`Invalid progress input: ${inputResult.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ")}`);
	const enriched = {
		...inputResult.data,
		timestamp: (/* @__PURE__ */ new Date()).toISOString(),
		git: getGitContext(cwd)
	};
	const entryResult = ProgressEntry.safeParse(enriched);
	if (!entryResult.success) return failure(`Invalid progress entry after enrichment: ${entryResult.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ")}`);
	const line = JSON.stringify(entryResult.data);
	console.log(line);
	if (dryRun) return success();
	const erpKitDir = path.join(cwd, ".erp-kit");
	fs.mkdirSync(erpKitDir, { recursive: true });
	fs.appendFileSync(path.join(erpKitDir, "progress.jsonl"), line + "\n", "utf-8");
	return success();
}
//#endregion
//#region src/commands/app/progress/schema-cmd.ts
function runProgressSchema() {
	const jsonSchema = z.toJSONSchema(ProgressInput);
	console.log(JSON.stringify(jsonSchema, null, 2));
	return success();
}
//#endregion
//#region src/commands/app/progress/index.ts
const cwd$2 = process.cwd();
const progressCommand = defineCommand({
	name: "progress",
	description: "Audit log for app skill sessions",
	subCommands: {
		log: defineCommand({
			name: "log",
			description: "Append a validated entry to the progress log",
			args: z.object({
				json: arg(z.string(), { description: "JSON payload (ProgressInput schema)" }),
				"dry-run": arg(z.boolean().default(false), { description: "Validate without writing" })
			}),
			run: (args) => {
				return executeCommand(() => {
					return runProgressLog(args.json, args["dry-run"], cwd$2);
				});
			}
		}),
		schema: defineCommand({
			name: "schema",
			description: "Output JSON Schema for progress log input",
			args: z.object({}),
			run: () => {
				return executeCommand(() => {
					return runProgressSchema();
				});
			}
		})
	}
});
//#endregion
//#region src/commands/app/index.ts
const cwd$1 = process.cwd();
const pathArgs = z.object({ path: arg(z.string(), {
	alias: "p",
	description: "Path to app directory"
}) });
const checkCommand = defineCommand({
	name: "check",
	description: "Validate app docs against schemas",
	args: pathArgs,
	run: (args) => {
		return executeCommand(async () => {
			const exitCode = await runCheck({ appRoot: args.path }, cwd$1);
			return exitCode === 0 ? success() : silentFailure(exitCode);
		});
	}
});
const syncCheckCommand = defineCommand({
	name: "sync-check",
	description: "Validate source <-> doc correspondence",
	args: pathArgs,
	run: (args) => {
		return executeCommand(async () => {
			const result = await runSyncCheck({ appRoot: args.path }, cwd$1);
			console.log(formatSyncCheckReport(result));
			return result.exitCode === 0 ? success() : silentFailure(result.exitCode);
		});
	}
});
const initCommand$1 = defineCommand({
	name: "init",
	description: "Bootstrap a new app with directory structure and README",
	args: z.object({
		name: arg(z.string(), {
			positional: true,
			description: "App name"
		}),
		dir: arg(z.string(), {
			positional: true,
			description: "Parent directory where the app will be created"
		})
	}),
	run: (args) => {
		return executeCommand(async () => {
			const exitCode = await runInitAppWithReadme(args.name, args.dir, cwd$1);
			return exitCode === 0 ? success() : silentFailure(exitCode);
		});
	}
});
const generateCommand = defineCommand({
	name: "generate",
	description: "Generate docs, code, and seed data for an app",
	subCommands: {
		doc: defineCommand({
			name: "doc",
			description: "Create a documentation file from a schema template",
			args: pathArgs.extend({
				type: arg(z.enum(APP_DOC_TYPES), {
					positional: true,
					description: `Doc type (${APP_DOC_TYPES.join(", ")})`
				}),
				name: arg(z.string().optional(), {
					positional: true,
					description: "Item name (required for most types)"
				})
			}),
			run: (args) => {
				return executeCommand(async () => {
					const exitCode = await runGenerateDoc(args.type, args.name, args.path, cwd$1);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		code: defineCommand({
			name: "code",
			description: "Generate boilerplate source files from docs",
			args: pathArgs,
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runGenerateAppCode(path.resolve(cwd$1, args.path));
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		seed: defineCommand({
			name: "seed",
			description: "Generate seed data from module defaults",
			args: pathArgs,
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runGenerateSeed(path.resolve(cwd$1, args.path));
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		})
	}
});
const appCommand = defineCommand({
	name: "app",
	description: "App management",
	subCommands: {
		check: checkCommand,
		"sync-check": syncCheckCommand,
		init: initCommand$1,
		generate: generateCommand,
		progress: progressCommand
	}
});
//#endregion
//#region src/mockServer.ts
/**
* Start a Mockoon mock server from a mock.json file.
* Returns a handle with the server URL and a stop function.
*/
async function createMockServer(mockJsonPath, port) {
	const { MockoonServer, createLoggerInstance, listenServerEvents } = await import("@mockoon/commons-server");
	const resolvedPath = resolve(mockJsonPath);
	const environment = JSON.parse(readFileSync(resolvedPath, "utf-8"));
	if (port !== void 0) environment.port = port;
	const actualPort = environment.port;
	const logger = createLoggerInstance(null);
	const server = new MockoonServer(environment, {
		environmentDirectory: dirname(resolvedPath),
		enableAdminApi: false,
		disableTls: true,
		enableRandomLatency: false,
		maxTransactionLogs: 100,
		envVarsPrefix: "MOCKOON_"
	});
	listenServerEvents(server, environment, logger, false);
	await new Promise((resolve, reject) => {
		server.on("started", resolve);
		server.on("error", (errorCode, originalError) => {
			reject(originalError ?? /* @__PURE__ */ new Error(`Mockoon error: ${errorCode}`));
		});
		server.start();
	});
	return {
		url: `http://127.0.0.1:${actualPort}`,
		port: actualPort,
		stop: () => new Promise((resolve) => {
			server.on("stopped", resolve);
			server.stop();
		})
	};
}
//#endregion
//#region src/commands/mock/start.ts
function readdirSafe(dir) {
	try {
		return readdirSync(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
	} catch {
		return [];
	}
}
function discoverMocks(mocksDir, filters) {
	const mocks = [];
	for (const provider of readdirSafe(mocksDir)) {
		const providerDir = join(mocksDir, provider);
		for (const scenario of readdirSafe(providerDir)) {
			const mockPath = join(providerDir, scenario, "mock.json");
			if (!existsSync(mockPath)) continue;
			mocks.push({
				provider,
				scenario,
				mockPath
			});
		}
	}
	if (filters.length === 0) return mocks;
	return mocks.filter(({ provider, scenario }) => filters.some((f) => f === provider || f === `${provider}/${scenario}`));
}
function findFreePort() {
	return new Promise((resolve, reject) => {
		const srv = createServer$1();
		srv.listen(0, "127.0.0.1", () => {
			const addr = srv.address();
			const port = typeof addr === "object" && addr ? addr.port : 0;
			srv.close(() => resolve(port));
		});
		srv.on("error", reject);
	});
}
async function startMock(mock) {
	const port = await findFreePort();
	return {
		server: await createMockServer(mock.mockPath, port),
		route: `/${mock.provider}/${mock.scenario}`,
		provider: mock.provider,
		scenario: mock.scenario
	};
}
function createProxy(routeTable) {
	return createServer((req, res) => {
		const match = req.url?.match(/^\/([^/?]+)\/([^/?]+)(\/[^?]*)?(\?.*)?$/);
		if (!match) {
			res.writeHead(404, { "Content-Type": "application/json" });
			res.end(JSON.stringify({ error: "Not found. Use /{provider}/{scenario}/..." }));
			return;
		}
		const [, provider, scenario] = match;
		const key = `/${provider}/${scenario}`;
		const target = routeTable.get(key);
		if (!target) {
			res.writeHead(404, { "Content-Type": "application/json" });
			res.end(JSON.stringify({
				error: `Unknown route: ${key}`,
				available: [...routeTable.keys()]
			}));
			return;
		}
		const downstream = (req.url ?? "/").slice(key.length) || "/";
		const proxyReq = request({
			hostname: "127.0.0.1",
			port: target.server.port,
			path: downstream,
			method: req.method,
			headers: {
				...req.headers,
				host: `127.0.0.1:${target.server.port}`
			}
		}, (proxyRes) => {
			res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
			proxyRes.pipe(res);
		});
		proxyReq.on("error", (err) => {
			if (!res.headersSent) res.writeHead(502, { "Content-Type": "application/json" });
			res.end(JSON.stringify({
				error: "Bad gateway",
				detail: err.message
			}));
		});
		req.pipe(proxyReq);
	});
}
async function runMockStart(mocksRoot, filters, port) {
	const mocksDir = resolve(mocksRoot);
	const mocks = discoverMocks(mocksDir, filters);
	if (mocks.length === 0) {
		console.error("No matching mocks found.");
		if (filters.length > 0) {
			console.error(`Filters: ${filters.join(", ")}`);
			console.error(`Available mocks are under: ${relative(process.cwd(), mocksDir)}/`);
		}
		return 1;
	}
	console.log(`Starting ${mocks.length} mock(s)...\n`);
	const running = [];
	for (const mock of mocks) {
		const info = await startMock(mock);
		running.push(info);
	}
	const routeTable = /* @__PURE__ */ new Map();
	for (const r of running) routeTable.set(r.route, r);
	console.log("Route table:");
	console.log("─".repeat(50));
	for (const [route, { server }] of routeTable) console.log(`  ${route}  \u2192  127.0.0.1:${server.port}`);
	console.log("─".repeat(50));
	const proxy = createProxy(routeTable);
	proxy.listen(port, () => {
		console.log(`\nReverse proxy listening on http://localhost:${port}`);
		console.log("Press Ctrl+C to stop all mocks.\n");
	});
	function shutdown() {
		console.log("\nShutting down...");
		proxy.close();
		for (const { server } of running) server.stop();
		process.exit(0);
	}
	process.on("SIGINT", shutdown);
	process.on("SIGTERM", shutdown);
	return new Promise(() => void 0);
}
//#endregion
//#region src/commands/mock/validate.ts
function pass(msg) {
	console.log(chalk.green(`\u2713 ${msg}`));
}
function fail(ctx, msg) {
	console.log(chalk.red(`\u2717 ${msg}`));
	ctx.failures++;
}
async function subdirs(dir) {
	const entries = await readdir(dir);
	const dirs = [];
	for (const entry of entries) if ((await stat(join(dir, entry))).isDirectory()) dirs.push(entry);
	return dirs.sort();
}
function checkStructure(ctx, entries, label) {
	if (entries.includes("README.md")) pass(`${label}: has README.md`);
	else fail(ctx, `${label}: missing README.md`);
	if (entries.includes("mock.json")) {
		pass(`${label}: has mock.json`);
		return true;
	}
	fail(ctx, `${label}: missing mock.json`);
	return false;
}
async function checkSchema(ctx, data, label) {
	const result = (await import("@mockoon/commons")).EnvironmentSchemaNoFix.validate(data, { abortEarly: false });
	if (!result.error) pass(`${label}: valid Mockoon schema`);
	else for (const detail of result.error.details) fail(ctx, `${label}: schema — ${detail.message}`);
}
function checkResponseQuality(ctx, data, label) {
	const routes = data.routes ?? [];
	for (const route of routes) for (const resp of route.responses ?? []) {
		const respLabel = `${label} \u2192 ${route.uuid}/${resp.uuid}`;
		if ((resp.headers ?? []).some((h) => h.key.toLowerCase() === "content-type")) pass(`${respLabel}: has Content-Type`);
		else fail(ctx, `${respLabel}: missing Content-Type header`);
		if (resp.label && resp.label.trim().length > 0) pass(`${respLabel}: has label "${resp.label}"`);
		else fail(ctx, `${respLabel}: missing or empty label`);
	}
}
function checkDatabucketRefs(ctx, data, label) {
	const bucketIds = new Set((data.data ?? []).map((d) => d.id));
	for (const route of data.routes ?? []) for (const resp of route.responses ?? []) if (resp.bodyType === "DATABUCKET") {
		const respLabel = `${label} \u2192 ${route.uuid}/${resp.uuid}`;
		if (resp.databucketID && bucketIds.has(resp.databucketID)) pass(`${respLabel}: databucket "${resp.databucketID}" exists`);
		else fail(ctx, `${respLabel}: databucketID "${resp.databucketID}" not found in data array`);
	}
}
async function discoverAllScenarios(mocksDir) {
	const scenarios = [];
	const providers = await subdirs(mocksDir);
	for (const provider of providers) {
		const providerDir = join(mocksDir, provider);
		for (const scenario of await subdirs(providerDir)) scenarios.push(`${provider}/${scenario}`);
	}
	return scenarios;
}
function resolveScenarioDir(arg) {
	const abs = resolve(arg);
	if (basename(abs) === "mock.json") return dirname(abs);
	return abs;
}
async function validateScenario(ctx, scenarioDir, mocksDir) {
	const label = relative(mocksDir, scenarioDir);
	console.log(chalk.bold(`\n\u2500\u2500 ${label} \u2500\u2500`));
	let entries;
	try {
		entries = await readdir(scenarioDir);
	} catch {
		fail(ctx, `${label}: directory not found`);
		return;
	}
	if (!checkStructure(ctx, entries, label)) return;
	const mockPath = join(scenarioDir, "mock.json");
	let data;
	try {
		data = JSON.parse(await readFile(mockPath, "utf-8"));
	} catch (err) {
		fail(ctx, `${label}: invalid JSON \u2014 ${err instanceof Error ? err.message : String(err)}`);
		return;
	}
	await checkSchema(ctx, data, label);
	checkResponseQuality(ctx, data, label);
	checkDatabucketRefs(ctx, data, label);
}
async function runMockValidate(mocksRoot, paths) {
	const ctx = { failures: 0 };
	const mocksDir = resolve(mocksRoot);
	const targets = paths.length > 0 ? paths.map(resolveScenarioDir) : (await discoverAllScenarios(mocksDir)).map((s) => join(mocksDir, s));
	if (targets.length === 0) {
		fail(ctx, "No scenarios found under mocks/");
		return 1;
	}
	console.log(chalk.bold("\nValidating mock configs...\n"));
	for (const target of targets) await validateScenario(ctx, target, mocksDir);
	console.log(chalk.bold("\n── summary ──"));
	if (ctx.failures === 0) console.log(chalk.green("✓ All checks passed"));
	else console.log(chalk.red(`\u2717 ${ctx.failures} check(s) failed`));
	return ctx.failures === 0 ? 0 : 1;
}
const mockCommand = defineCommand({
	name: "mock",
	description: "Mock API server management",
	subCommands: {
		start: defineCommand({
			name: "start",
			description: "Start mock API servers with reverse proxy",
			args: z.object({
				mocksRoot: arg(z.string().default("./mocks"), { description: "Path to mocks directory" }),
				port: arg(z.coerce.number().default(3e3), {
					alias: "p",
					description: "Reverse proxy port"
				}),
				filter: arg(z.array(z.string()).default([]), {
					positional: true,
					description: "Filter by provider or provider/scenario"
				})
			}),
			run: (args) => {
				return executeCommand(async () => {
					const exitCode = await runMockStart(args.mocksRoot, args.filter, args.port);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		validate: defineCommand({
			name: "validate",
			description: "Validate mock scenario configs",
			args: z.object({
				mocksRoot: arg(z.string().default("./mocks"), { description: "Path to mocks directory" }),
				paths: arg(z.array(z.string()).default([]), {
					positional: true,
					description: "Specific scenario paths to validate"
				})
			}),
			run: (args) => {
				return executeCommand(async () => {
					const exitCode = await runMockValidate(args.mocksRoot, args.paths);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		})
	}
});
//#endregion
//#region src/commands/doc/modules.ts
const MODULES_DIR$2 = join(PACKAGE_ROOT, "src", "modules");
function countDocs(dir) {
	if (!existsSync(dir)) return 0;
	return readdirSync(dir).filter((f) => f.endsWith(".md")).length;
}
function extractOverview(readmePath) {
	if (!existsSync(readmePath)) return "";
	const content = readFileSync(readmePath, "utf-8");
	const overviewMatch = /## Overview\n\n([\s\S]*?)(?=\n##\s|\n$)/.exec(content);
	if (!overviewMatch) return "";
	return overviewMatch[1].trim().split("\n\n")[0];
}
function extractDependencies(readmePath) {
	if (!existsSync(readmePath)) return [];
	const content = readFileSync(readmePath, "utf-8");
	const depsMatch = /## Module Dependencies\n\n([\s\S]*?)(?=\n##\s|$)/.exec(content);
	if (!depsMatch) return [];
	const deps = [];
	const linePattern = /^- \[([^\]]+)\]/;
	for (const line of depsMatch[1].trim().split("\n")) {
		const match = linePattern.exec(line);
		if (match) deps.push(match[1]);
	}
	return deps;
}
function getModuleOverviews() {
	if (!existsSync(MODULES_DIR$2)) return [];
	return readdirSync(MODULES_DIR$2, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
		const modDir = join(MODULES_DIR$2, d.name);
		const readmePath = join(modDir, "README.md");
		return {
			name: d.name,
			commandCount: countDocs(join(modDir, MODULE_PATHS.docs.commands)),
			queryCount: countDocs(join(modDir, MODULE_PATHS.docs.queries)),
			modelCount: countDocs(join(modDir, MODULE_PATHS.docs.models)),
			overview: extractOverview(readmePath),
			dependencies: extractDependencies(readmePath)
		};
	}).sort((a, b) => a.name.localeCompare(b.name));
}
function formatModuleOverviews(modules) {
	if (modules.length === 0) return "No modules found.";
	const lines = [];
	for (const mod of modules) {
		const counts = [
			`${mod.commandCount} commands`,
			`${mod.queryCount} queries`,
			`${mod.modelCount} models`
		].join(", ");
		lines.push(`# ${mod.name} (${counts})`);
		if (mod.overview) lines.push(mod.overview);
		if (mod.dependencies.length > 0) lines.push(`Dependencies: ${mod.dependencies.join(", ")}`);
		else lines.push("Dependencies: none");
		lines.push("");
	}
	lines.push(`${modules.length} modules`);
	return lines.join("\n");
}
function runDocModules(format = "text") {
	const modules = getModuleOverviews();
	if (format === "json") console.log(JSON.stringify(modules, null, 2));
	else console.log(formatModuleOverviews(modules));
	return 0;
}
//#endregion
//#region src/commands/doc/module.ts
const MODULES_DIR$1 = join(PACKAGE_ROOT, "src", "modules");
const DOC_TYPE_MAP$1 = {
	command: MODULE_PATHS.docs.commands,
	query: MODULE_PATHS.docs.queries,
	model: MODULE_PATHS.docs.models,
	feature: MODULE_PATHS.docs.features
};
function listDocNames(dir) {
	if (!existsSync(dir)) return [];
	return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => f.replace(/\.md$/, "")).sort();
}
function formatDocList(type, names) {
	if (names.length === 0) return "";
	return `${type}: ${names.join(", ")}`;
}
function runDocModule(moduleName, docType, docName, format = "text") {
	if (!existsSync(MODULES_DIR$1)) {
		console.error(`Module not found: ${moduleName}`);
		return 1;
	}
	const modDir = join(MODULES_DIR$1, moduleName);
	if (!existsSync(modDir)) {
		console.error(`Module not found: ${moduleName}`);
		const available = readdirSync(MODULES_DIR$1, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
		console.error(`Available modules: ${available.join(", ")}`);
		return 1;
	}
	if (docType && docName) {
		const docSubdir = DOC_TYPE_MAP$1[docType];
		if (!docSubdir) {
			console.error(`Unknown doc type: ${docType}`);
			console.error(`Available types: ${Object.keys(DOC_TYPE_MAP$1).join(", ")}`);
			return 1;
		}
		const docPath = join(modDir, docSubdir, `${docName}.md`);
		if (!existsSync(docPath)) {
			console.error(`Doc not found: ${moduleName}/${docType}/${docName}`);
			const available = listDocNames(join(modDir, docSubdir));
			if (available.length > 0) console.error(`Available ${docType}s: ${available.join(", ")}`);
			else console.error(`No ${docType} docs found for ${moduleName}`);
			return 1;
		}
		const content = readFileSync(docPath, "utf-8");
		if (format === "json") console.log(JSON.stringify({
			module: moduleName,
			type: docType,
			name: docName,
			content
		}, null, 2));
		else console.log(content);
		return 0;
	}
	const readmePath = join(modDir, "README.md");
	const readme = existsSync(readmePath) ? readFileSync(readmePath, "utf-8") : "";
	const docs = {};
	for (const [type, subdir] of Object.entries(DOC_TYPE_MAP$1)) {
		const names = listDocNames(join(modDir, subdir));
		if (names.length > 0) docs[type] = names;
	}
	if (format === "json") console.log(JSON.stringify({
		module: moduleName,
		readme,
		docs
	}, null, 2));
	else {
		if (readme) console.log(readme);
		else console.log(`# ${moduleName}\n\nNo README found.\n`);
		const sections = [];
		for (const [type, names] of Object.entries(docs)) sections.push(formatDocList(type, names));
		if (sections.length > 0) {
			console.log("\n## Available Documentation\n");
			console.log(sections.join("\n"));
		}
	}
	return 0;
}
//#endregion
//#region src/commands/doc/search.ts
const MODULES_DIR = join(PACKAGE_ROOT, "src", "modules");
const DOC_TYPE_MAP = {
	command: MODULE_PATHS.docs.commands,
	query: MODULE_PATHS.docs.queries,
	model: MODULE_PATHS.docs.models,
	feature: MODULE_PATHS.docs.features
};
function searchFile(filePath, query, module, type, name) {
	if (!existsSync(filePath)) return [];
	const content = readFileSync(filePath, "utf-8");
	const lowerQuery = query.toLowerCase();
	const results = [];
	const lines = content.split("\n");
	for (let i = 0; i < lines.length; i++) if (lines[i].toLowerCase().includes(lowerQuery)) results.push({
		module,
		type,
		name,
		line: i + 1,
		excerpt: lines[i].trim()
	});
	return results;
}
function searchModuleDocs(query, typeFilter) {
	if (!existsSync(MODULES_DIR)) return [];
	const results = [];
	const modules = readdirSync(MODULES_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).sort((a, b) => a.name.localeCompare(b.name));
	for (const mod of modules) {
		const modDir = join(MODULES_DIR, mod.name);
		if (!typeFilter || typeFilter === "readme") results.push(...searchFile(join(modDir, "README.md"), query, mod.name, "readme", "README"));
		for (const [type, subdir] of Object.entries(DOC_TYPE_MAP)) {
			if (typeFilter && typeFilter !== type) continue;
			const docsDir = join(modDir, subdir);
			if (!existsSync(docsDir)) continue;
			const files = readdirSync(docsDir).filter((f) => f.endsWith(".md"));
			for (const file of files) {
				const name = file.replace(/\.md$/, "");
				results.push(...searchFile(join(docsDir, file), query, mod.name, type, name));
			}
		}
	}
	return results;
}
function formatSearchResults(results) {
	if (results.length === 0) return "No results found.";
	const lines = [];
	for (const r of results) lines.push(`${r.module}/${r.type}/${r.name}:${r.line}: ${r.excerpt}`);
	lines.push("");
	lines.push(`${results.length} matches`);
	return lines.join("\n");
}
function runDocSearch(query, type, format = "text") {
	if (type && type !== "readme" && !(type in DOC_TYPE_MAP)) {
		console.error(`Unknown doc type: ${type}`);
		console.error(`Available types: readme, ${Object.keys(DOC_TYPE_MAP).join(", ")}`);
		return 1;
	}
	const results = searchModuleDocs(query, type);
	if (format === "json") console.log(JSON.stringify(results, null, 2));
	else console.log(formatSearchResults(results));
	return 0;
}
//#endregion
//#region src/commands/doc/index.ts
const formatArg = arg(z.enum(["text", "json"]).default("text"), {
	alias: "f",
	description: "Output format (text or json)"
});
const docCommand = defineCommand({
	name: "doc",
	description: "Browse module documentation",
	subCommands: {
		modules: defineCommand({
			name: "modules",
			description: "List all modules with capabilities overview",
			args: z.object({ format: formatArg }),
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runDocModules(args.format);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		module: defineCommand({
			name: "module",
			description: "Show documentation for a specific module",
			args: z.object({
				name: arg(z.string(), {
					positional: true,
					description: "Module name"
				}),
				type: arg(z.string().optional(), {
					positional: true,
					description: "Doc type (command, query, model, feature)"
				}),
				docName: arg(z.string().optional(), {
					positional: true,
					description: "Doc name"
				}),
				format: formatArg
			}),
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runDocModule(args.name, args.type, args.docName, args.format);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		search: defineCommand({
			name: "search",
			description: "Search across all module documentation",
			args: z.object({
				query: arg(z.string(), {
					positional: true,
					description: "Search query"
				}),
				type: arg(z.string().optional(), {
					alias: "t",
					description: "Filter by doc type (command, query, model, feature, readme)"
				}),
				format: formatArg
			}),
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runDocSearch(args.query, args.type, args.format);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		})
	}
});
//#endregion
//#region src/commands/index.ts
const cwd = process.cwd();
//#endregion
//#region src/cli.ts
runMain(defineCommand({
	name: "erp-kit",
	description: "ERP module framework CLI",
	subCommands: {
		module: moduleCommand$1,
		app: appCommand,
		mock: mockCommand,
		doc: docCommand,
		init: defineCommand({
			name: "init",
			description: "First-time setup for a consumer repo",
			args: z.object({ name: arg(z.string(), {
				positional: true,
				description: "Project name"
			}) }),
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runInit(args.name, cwd);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		update: defineCommand({
			name: "update",
			description: "Refresh framework-managed resources (skills, workflows)",
			args: z.object({ resources: arg(z.array(z.string()).default([]), {
				positional: true,
				description: "Resources to update (skills, workflows). Defaults to all."
			}) }),
			run: (args) => {
				return executeCommand(() => {
					const exitCode = runUpdate(cwd, args.resources);
					return exitCode === 0 ? success() : silentFailure(exitCode);
				});
			}
		}),
		license: defineCommand({
			name: "license",
			description: "License management",
			subCommands: {
				check: defineCommand({
					name: "check",
					description: "Check dependency licenses against allowlist",
					args: z.object({ config: arg(z.string(), {
						alias: "c",
						description: "Path to license config JSON file"
					}) }),
					run: (args) => {
						return executeCommand(() => {
							const exitCode = runLicenseCheck(args.config);
							return exitCode === 0 ? success() : silentFailure(exitCode);
						});
					}
				}),
				list: defineCommand({
					name: "list",
					description: "List available license groups",
					run: () => {
						return executeCommand(() => {
							const exitCode = runLicenseList();
							return exitCode === 0 ? success() : silentFailure(exitCode);
						});
					}
				})
			}
		})
	}
}));
//#endregion
export {};
