@sdt-tools/cli 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +13 -8
- package/dist/cli.js.map +1 -1
- package/dist/{connection-SYTH4V53.js → connection-GNTZDHXF.js} +24 -1
- package/dist/connection-GNTZDHXF.js.map +1 -0
- package/dist/{errorReporting-ZRNJ3VW7.js → errorReporting-AQXKKGZH.js} +2 -2
- package/dist/{errorReporting-ZRNJ3VW7.js.map → errorReporting-AQXKKGZH.js.map} +1 -1
- package/dist/import-script-2OF5BI6A.js +83 -0
- package/dist/import-script-2OF5BI6A.js.map +1 -0
- package/dist/index.cjs +35 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +35 -6
- package/dist/index.js.map +1 -1
- package/dist/{mcp-3QI4TH4N.js → mcp-SARDMCDV.js} +2 -2
- package/dist/{mcp-3QI4TH4N.js.map → mcp-SARDMCDV.js.map} +1 -1
- package/dist/{publish-Y2J56K4Y.js → publish-UMVIWH6H.js} +13 -7
- package/dist/publish-UMVIWH6H.js.map +1 -0
- package/package.json +2 -2
- package/dist/connection-SYTH4V53.js.map +0 -1
- package/dist/publish-Y2J56K4Y.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/init.ts","../src/util/logger.ts","../src/commands/build.ts","../src/commands/extract.ts","../src/commands/compare.ts","../src/util/help-catalog.ts","../src/util/color.ts","../src/util/mapping.ts","../src/commands/publish.ts","../src/commands/drift.ts","../src/commands/validate.ts","../src/commands/connection.ts","../src/commands/scaffold.ts","../src/commands/graph.ts","../src/util/ai-explain.ts","../src/commands/history.ts","../src/commands/verify.ts","../src/commands/install-hooks.ts","../src/commands/script.ts","../src/commands/revert.ts","../src/commands/seed.ts","../src/commands/lineage.ts","../src/commands/diagnose.ts","../src/commands/review.ts","../src/commands/impact.ts","../src/commands/cost-estimate.ts","../src/commands/pr-comment.ts","../src/commands/template.ts","../src/commands/anonymize.ts","../src/commands/safety.ts","../src/commands/safer-alternative.ts","../src/commands/sketch.ts","../src/commands/compare-profiles.ts","../src/commands/explorer.ts","../src/commands/catalog.ts","../src/commands/exec.ts","../src/commands/search.ts","../src/commands/query-log.ts"],"sourcesContent":["import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { newProjectTemplate, saveProject } from '@sdt-tools/core/project';\nimport type { ProjectScope } from '@sdt-tools/core/project';\nimport { logger } from '../util/logger.js';\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n cmd\n .description('Initialize a new SDT project in the current directory.')\n .option('--name <name>', 'Project name', 'NewSnowflakeProject')\n .option('--scope <scope>', 'Project scope: account | database | schema', 'database')\n .option('--db <database>', 'Database name (required for database/schema scope)')\n .option('--schema <schema>', 'Schema name (required for schema scope)')\n .option('--dir <dir>', 'Target directory (default: cwd)', process.cwd())\n .option(\n '--force',\n 'Overwrite an existing <name>.sdtproj in the target directory. Without ' +\n 'this flag, init refuses to clobber an existing project file so a ' +\n 're-run never silently discards your project configuration.',\n )\n .action(async (opts) => {\n const scopeType = String(opts.scope) as ProjectScope['type'];\n if (!['account', 'database', 'schema'].includes(scopeType)) {\n throw new Error(`Invalid --scope: ${opts.scope}. Use account | database | schema.`);\n }\n const scope: ProjectScope = { type: scopeType };\n if (scopeType !== 'account') {\n if (!opts.db) throw new Error(`--db is required for scope=${scopeType}`);\n scope.database = String(opts.db);\n }\n if (scopeType === 'schema') {\n if (!opts.schema) throw new Error('--schema is required for scope=schema');\n scope.schema = String(opts.schema);\n }\n const root = path.resolve(String(opts.dir));\n await fs.mkdir(root, { recursive: true });\n const project = newProjectTemplate(String(opts.name), scope);\n const projectPath = path.join(root, `${project.name}.sdtproj`);\n // Refuse to clobber an existing project file unless --force. Mirrors\n // the `sdt standards init --force` pattern: a silent overwrite can\n // discard hand-edited project configuration on an accidental re-run.\n if (!opts.force) {\n try {\n await fs.access(projectPath);\n logger.error(`${projectPath} already exists; pass --force to overwrite.`);\n process.exitCode = 1;\n return;\n } catch {\n // File doesn't exist — proceed.\n }\n }\n await saveProject(projectPath, project);\n // Seed conventional folders so the user sees the layout SDT expects.\n const seedFolders = ['databases', 'scripts/pre', 'scripts/post'];\n for (const f of seedFolders) await fs.mkdir(path.join(root, f), { recursive: true });\n logger.success(`Created ${projectPath}`);\n logger.dim(\n ` Scope: ${scopeType}${scope.database ? ' / ' + scope.database : ''}${scope.schema ? ' / ' + scope.schema : ''}`,\n );\n logger.dim(` Next: sdt extract --connection <profile> --output ${root}`);\n });\n return cmd;\n}\n","/**\n * Minimal logger used by the CLI. Wraps chalk/ora so a future move to a\n * non-tty mode is centralised.\n */\nimport chalk from 'chalk';\n\nexport const logger = {\n info: (msg: string) => console.log(msg),\n success: (msg: string) => console.log(chalk.green('✔'), msg),\n warn: (msg: string) => console.warn(chalk.yellow('!'), msg),\n error: (msg: string) => console.error(chalk.red('✖'), msg),\n step: (msg: string) => console.log(chalk.cyan('→'), msg),\n dim: (msg: string) => console.log(chalk.gray(msg)),\n};\n","import { Command } from 'commander';\nimport { buildProject } from '@sdt-tools/core/pac';\nimport { logger } from '../util/logger.js';\n\nexport function buildCommand(): Command {\n const cmd = new Command('build');\n cmd\n .description('Build a .sdtpac from a .sdtproj project.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file')\n .option('-o, --out <path>', 'Output .sdtpac path (default: <projectRoot>/bin/<name>.sdtpac)')\n .action(async (opts) => {\n const result = await buildProject(String(opts.project), {\n outputPath: opts.out ? String(opts.out) : undefined,\n });\n logger.success(`Built ${result.outputPath}`);\n logger.dim(` ${result.fileCount} source file(s), ${result.objectCount} object(s) in model`);\n });\n return cmd;\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog } from '@sdt-tools/core';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { AccountExtractor, defaultExtractors } from '@sdt-tools/core/extract';\nimport { writeProjectTree } from '@sdt-tools/core/project';\nimport { logger } from '../util/logger.js';\n\nexport function extractCommand(): Command {\n const cmd = new Command('extract');\n cmd\n .description('Extract a Snowflake account/database/schema into a project layout.')\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .requiredOption(\n '-o, --output <path>',\n 'Target project directory (must contain a .sdtproj or pass --init)',\n )\n .option('--db <database>', 'Limit to a single database')\n .option('--schema <schema>', 'Limit to a single schema (requires --db)')\n .option('--types <list>', 'Comma-separated object types to include (default: all implemented)')\n .option(\n '--write-catalog-cache',\n 'Also write the extracted model to the EE1 catalog cache (.sdt/cache/<connection>/catalog.msgpack) so subsequent editor sessions have a populated cache without an extra `catalog refresh` round-trip.',\n false,\n )\n .option(\n '--use-catalog-cache',\n 'Read object metadata from the on-disk EE1 catalog cache instead of querying Snowflake. Fast / offline — no live connection required. Writes a catalog-snapshot.json to the output dir. Requires a prior `sdt catalog refresh` or `sdt extract --write-catalog-cache` run.',\n false,\n )\n .action(async (opts) => {\n if (opts.useCatalogCache) {\n const out = path.resolve(String(opts.output));\n await fs.mkdir(out, { recursive: true });\n const cache = new catalog.CatalogCache({ root: out, connection: String(opts.connection) });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0 && snapshot.fingerprint === null) {\n logger.error(\n `No catalog cache found at ${cache.path}. Run \"sdt catalog refresh -c ${String(opts.connection)}\" or \"sdt extract --write-catalog-cache\" first.`,\n );\n process.exitCode = 1;\n return;\n }\n const outPath = path.join(out, '.sdt-cache', 'catalog-snapshot.json');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, JSON.stringify(snapshot, null, 2));\n const objCount = snapshot.databases.flatMap((d) =>\n d.schemas.flatMap((s) => s.objects),\n ).length;\n logger.success(\n `Loaded ${objCount} object(s) from catalog cache (${snapshot.databases.length} database(s)) → ${outPath}`,\n );\n logger.dim(\n `Cache was snapshotted at ${snapshot.snapshotAt}. Use \"sdt catalog refresh\" to update it.`,\n );\n return;\n }\n\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const include = opts.types\n ? new Set(\n String(opts.types)\n .split(',')\n .map((s) => s.trim().toUpperCase()),\n )\n : undefined;\n logger.step(`Connecting to ${profile.account} as ${profile.auth.username}…`);\n await conn.connect();\n try {\n const account = new AccountExtractor(defaultExtractors());\n const objects = await account.extract(\n conn,\n {\n database: opts.db ? String(opts.db) : undefined,\n schema: opts.schema ? String(opts.schema) : undefined,\n },\n { include },\n );\n const out = path.resolve(String(opts.output));\n await fs.mkdir(out, { recursive: true });\n const dumpPath = path.join(out, '.sdt-cache', 'extracted.json');\n await fs.mkdir(path.dirname(dumpPath), { recursive: true });\n await fs.writeFile(dumpPath, JSON.stringify(objects, null, 2));\n const filesCreated = await writeProjectTree(out, objects);\n logger.success(\n `Extracted ${objects.length} object(s) → ${filesCreated} .sql file(s) under ${out} (cache: ${dumpPath}).`,\n );\n\n if (opts.writeCatalogCache) {\n const snapshot = catalog.snapshotFromObjects(objects, {\n connection: String(opts.connection),\n });\n const cache = new catalog.CatalogCache({\n root: out,\n connection: String(opts.connection),\n });\n await cache.set(snapshot);\n logger.success(\n `Wrote catalog cache → ${cache.path} (${snapshot.databases.length} database(s), ${objects.length} object(s)).`,\n );\n }\n } finally {\n await conn.disconnect();\n }\n });\n return cmd;\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n LiveSource,\n PacSource,\n ProjectSource,\n writeCompareHistory,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { compileSlice, loadProject } from '@sdt-tools/core/project';\nimport { ai, safety, typecheck } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\nimport { makeColorizer, resolveColorMode } from '../util/color.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\n/**\n * Auto-load a slice from a `.sdtproj` argument. Returns `undefined` when\n * the argument is not a `.sdtproj` or the project doesn't declare a slice.\n * Suite-level invocations bypass this and pass a slice directly.\n */\nasync function maybeLoadSliceFromArg(\n arg: string,\n): Promise<ReturnType<typeof compileSlice> | undefined> {\n if (!arg.toLowerCase().endsWith('.sdtproj')) return undefined;\n const loaded = await loadProject(arg);\n if (!loaded.project.slice) return undefined;\n return compileSlice(loaded.project.slice);\n}\n\n/**\n * Resolve a polymorphic source/target argument. Supported forms:\n * - path/to/foo.sdtproj\n * - path/to/foo.sdtpac\n * - snowflake://<profile>[/db[/schema]]\n */\nasync function resolveSource(arg: string): Promise<CompareSource> {\n if (arg.startsWith('snowflake://')) {\n const rest = arg.slice('snowflake://'.length);\n const [profileName, db, schema] = rest.split('/');\n if (!profileName) throw new Error(`Invalid snowflake URI: ${arg}`);\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n return new LiveSource(conn, { database: db, schema });\n }\n const lower = arg.toLowerCase();\n if (lower.endsWith('.sdtproj')) return new ProjectSource(arg);\n if (lower.endsWith('.sdtpac')) return new PacSource(arg);\n throw new Error(\n `Unrecognized source: ${arg}. Use *.sdtproj, *.sdtpac, or snowflake://<profile>[/db[/schema]].`,\n );\n}\n\nexport function compareCommand(): Command {\n const cmd = new Command('compare');\n cmd\n .description(\n 'Compare two schemas. Sources may be .sdtproj, .sdtpac, or snowflake://<profile>[/db[/schema]].',\n )\n .argument('[source]', 'Left side of the comparison (or use --source)')\n .argument('[target]', 'Right side of the comparison (or use --target)')\n .option(\n '--source <path>',\n 'Left side of the comparison (flag form of the positional source arg)',\n )\n .option(\n '--target <path>',\n 'Right side of the comparison (flag form of the positional target arg)',\n )\n .option('-o, --output <path>', 'Write JSON result to this path')\n .option('--format <format>', 'Output format: json | summary | markdown', 'summary')\n .option('--ignore-case', 'Treat unquoted identifiers case-insensitively', false)\n .option(\n '--no-slice',\n \"Disable the source project's Slice (if it has one). Default: a project's slice is applied automatically.\",\n )\n .option(\n '--explain',\n 'After the diff, call the configured AI provider to narrate each change in plain English with reasoning. Requires `sdt ai` to be configured.',\n false,\n )\n .option(\n '--color <mode>',\n 'Colorize severity output: always | never | auto. Default auto (color on TTY).',\n 'auto',\n )\n .option(\n '--type-safe',\n 'After the compare, run the TYPECHECK.1 impact analyzer. Exits with code 2 if the configured --break-on threshold is reached (default `error`). CI-friendly gate — pair with `--format json` for machine-readable output.',\n false,\n )\n .option(\n '--break-on <severity>',\n 'TYPECHECK.2 threshold for --type-safe: `error` (exit 2 on any error ripple, default) | `warning` (exit 2 on any error OR warning ripple, strict CI mode).',\n 'error',\n )\n .option(\n '--write-impact [path]',\n 'Write the TYPECHECK.1 impact analysis to a JSON file the VS Code extension can surface as squiggle-underlines. Default path: `.sdt/impact.json` resolved relative to the source `.sdtproj` directory (or CWD if the source is not a project). Composes with `--type-safe` — the file is written before the gate decides exit code.',\n )\n .option(\n '--no-history',\n 'Skip writing the compare-history audit record (AUDITCMP.1). Default: every compare run writes a record to `.sdt/history/compare/`, exportable via `sdt audit-log emit`.',\n )\n .action(async (sourceArgPos, targetArgPos, opts) => {\n // Accept the source/target either positionally (`sdt compare X Y`) or via\n // flags (`--source X --target Y`). The flag form mirrors `ddt compare`\n // and `sdt script`, and is what GETTING_STARTED documents; the positional\n // form is kept for back-compat. Flags win when both are given.\n const sourceArg = opts.source\n ? String(opts.source)\n : sourceArgPos\n ? String(sourceArgPos)\n : '';\n const targetArg = opts.target\n ? String(opts.target)\n : targetArgPos\n ? String(targetArgPos)\n : '';\n if (!sourceArg || !targetArg) {\n throw new Error(\n 'compare needs a source and a target — pass them positionally (`sdt compare <source> <target>`) or via `--source`/`--target`.',\n );\n }\n\n // Logical-name mapping (`--map`, `--map-file`) — rewrites source-side\n // FQNs so two schemas whose database / schema names differ can compare\n // semantically. See docs/LOGICAL_NAME_MAPPING.md. Mirrors `ddt compare`.\n const nameMapping = await buildMappingFromOptions(opts);\n const source = await resolveSource(String(sourceArg));\n const target = await resolveSource(String(targetArg));\n\n // Auto-load slice from the source `.sdtproj` unless --no-slice was set.\n // The target side (live or pac) doesn't carry a slice; it's the\n // project's slice that defines the scope.\n const slice =\n opts.slice === false ? undefined : await maybeLoadSliceFromArg(String(sourceArg));\n\n const engine = new CompareEngine();\n const startedAt = new Date().toISOString();\n const result = await engine.compare(source, target, {\n ignoreCase: Boolean(opts.ignoreCase),\n ...(nameMapping ? { nameMapping } : {}),\n ...(slice ? { sliceFilter: slice } : {}),\n });\n\n // AUDITCMP.1 — compare operations leave the same audit trail deploys\n // do. Written before the format-specific early returns so every\n // output mode is covered. Best-effort: a failed write never breaks\n // the compare itself.\n if (opts.history !== false) {\n const finishedAt = new Date().toISOString();\n try {\n const histAssessment = safety.assess(result);\n const changed = result.summary.added + result.summary.removed + result.summary.modified;\n await writeCompareHistory(compareHistoryRoot(String(sourceArg)), {\n startedAt,\n finishedAt,\n durationMs: Date.parse(finishedAt) - Date.parse(startedAt),\n outcome: histAssessment.blocked\n ? 'BLOCKED'\n : changed === 0\n ? 'NO_CHANGES'\n : 'CHANGES_FOUND',\n source: { kind: result.source.kind, label: result.source.label },\n target: { kind: result.target.kind, label: result.target.label },\n summary: result.summary,\n sliceApplied: Boolean(slice),\n ...(histAssessment.blocked && histAssessment.blockReason\n ? { blockReason: histAssessment.blockReason }\n : {}),\n });\n } catch {\n /* audit trail is best-effort; never fail the compare over it */\n }\n }\n\n if (opts.output) {\n const out = path.resolve(String(opts.output));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, JSON.stringify(result, null, 2));\n logger.success(`Wrote ${out}`);\n }\n\n if (opts.format === 'json') {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n if (opts.format === 'markdown') {\n const assessment = safety.assess(result);\n process.stdout.write(renderCompareMarkdown(result, assessment) + '\\n');\n return;\n }\n logger.info(\n `Compare ${result.source.kind}:${result.source.label} → ${result.target.kind}:${result.target.label}`,\n );\n if (slice) {\n const outside = result.outsideScope?.length ?? 0;\n const refs = result.referenced?.length ?? 0;\n logger.info(\n ` Slice active: ${result.objects.length} owned · ${outside} outside scope (untouched) · ${refs} referenced`,\n );\n }\n logger.info(\n ` +${result.summary.added} added, -${result.summary.removed} removed, ~${result.summary.modified} modified, =${result.summary.unchanged} unchanged`,\n );\n for (const o of result.objects) {\n if (o.kind === 'unchanged') continue;\n logger.info(` ${o.kind.padEnd(8)} ${o.identity.objectType.padEnd(20)} ${o.identity.fqn}`);\n }\n\n // Reversibility-grouped safety findings. Three buckets — Unrecoverable\n // first (highest urgency), then Data-impacting, then Reversible.\n // Empty diff is silent; assessment.blocked is surfaced once findings\n // exist.\n const assessment = safety.assess(result);\n const buckets = safety.groupByReversibility(assessment);\n const total =\n buckets.unrecoverable.length + buckets.dataImpacting.length + buckets.reversible.length;\n if (total > 0) {\n const colorize = makeColorizer(resolveColorMode(opts.color));\n logger.info('');\n logger.info('Safety findings (grouped by reversibility):');\n const block = safety.formatReversibilityBuckets(buckets);\n const colored = colorize.applyToBlock(block);\n for (const line of colored.split('\\n')) logger.info(' ' + line);\n if (assessment.blocked && assessment.blockReason) {\n logger.error(' ' + colorize.unrecoverable('BLOCKED: ' + assessment.blockReason));\n }\n }\n\n // AI-narrated diff (--explain). Calls the configured provider with a\n // structured prompt containing the diff summary + per-object changes\n // + safety findings. Output is the assistant's plain-English narration.\n if (opts.explain) {\n logger.info('');\n logger.info('AI explanation:');\n try {\n const userPrompt = buildExplainPrompt(result, assessment);\n const reply = await ai.complete(\n [\n { role: 'system', content: SYSTEM_PROMPT },\n { role: 'user', content: userPrompt },\n ],\n { feature: 'compare.explain' },\n );\n for (const line of reply.text.split('\\n')) logger.info(' ' + line);\n } catch (err) {\n logger.error(' --explain failed: ' + (err instanceof Error ? err.message : String(err)));\n logger.error(\n ' Run `sdt ai status` to verify your AI provider is configured (`sdt ai test` to send a probe).',\n );\n }\n }\n\n // --write-impact: TYPECHECK.4 — write the impact analysis to a\n // JSON file the VS Code provider reads. Always runs the analyzer\n // (even when --type-safe is off) so the editor surface is\n // independent of the CI-gate flag. Composes with --type-safe.\n if (opts.writeImpact !== undefined) {\n await writeImpactJson(\n result,\n opts.writeImpact === true ? undefined : String(opts.writeImpact),\n String(sourceArg),\n );\n }\n\n // --type-safe: TYPECHECK.2 CI gate. Runs the TYPECHECK.1 impact\n // analyzer and exits with code 2 if any error-severity ripple\n // (column-drop or table-drop reaching a dependent object) is\n // detected. Stays silent on a clean diff so this composes well\n // with --format json (which already returned above).\n if (opts.typeSafe) {\n const breakOnRaw = String(opts.breakOn ?? 'error').toLowerCase();\n if (breakOnRaw !== 'error' && breakOnRaw !== 'warning') {\n throw new Error(\n `--break-on must be 'error' or 'warning' (got '${opts.breakOn}'). 'error' fails on any error-severity ripple (default); 'warning' fails on any warning or error ripple (strict CI).`,\n );\n }\n const breakOn = breakOnRaw as 'error' | 'warning';\n const impactFindings = typecheck.analyzeImpact(result);\n const impactSummary = typecheck.summarizeImpact(impactFindings);\n if (impactSummary.findingsCount > 0) {\n logger.info('');\n logger.info(\n `Type-safety gate (--break-on ${breakOn}) — ${impactSummary.findingsCount} breaking change(s); ${impactSummary.errors} error ripple(s), ${impactSummary.warnings} warning ripple(s); ${impactSummary.affectedObjects.length} dependent object(s).`,\n );\n for (const f of impactFindings) {\n for (const r of f.ripples) {\n const tag = r.severity === 'error' ? 'ERROR' : 'WARN ';\n logger.info(\n ` ${tag} ${r.fqn} ← ${f.breakingChangeOn.fqn} (${f.breakingChangeOn.kind})`,\n );\n }\n }\n const failOnError = impactSummary.errors > 0;\n const failOnWarning = breakOn === 'warning' && impactSummary.warnings > 0;\n if (failOnError) {\n logger.error(\n `Type-safety gate FAILED — ${impactSummary.errors} error ripple(s). Fix the dependents (drop / update / re-bind) before re-running compare, OR rerun with the change scoped out of the diff.`,\n );\n process.exitCode = 2;\n } else if (failOnWarning) {\n logger.error(\n `Type-safety gate FAILED (strict --break-on warning) — ${impactSummary.warnings} warning ripple(s). Tighten the dependent SQL to accept the new type, or drop --break-on warning to allow.`,\n );\n process.exitCode = 2;\n }\n } else {\n logger.info('Type-safety gate PASSED — no breaking-change ripples detected.');\n }\n }\n });\n addMappingFlags(cmd);\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n 'compare.excludeObjectPatterns',\n 'compare.includeObjectPatterns',\n ]);\n return cmd;\n}\n\n/**\n * TYPECHECK.4 — write the impact analysis JSON to disk so the VS Code\n * provider can surface it as squiggle-underlines. Defaults to\n * `<project-dir>/.sdt/impact.json` when the source is a `.sdtproj`,\n * otherwise `<cwd>/.sdt/impact.json`.\n */\nasync function writeImpactJson(\n result: Parameters<typeof typecheck.analyzeImpact>[0],\n explicitPath: string | undefined,\n sourceArg: string,\n): Promise<void> {\n const findings = typecheck.analyzeImpact(result);\n const summary = typecheck.summarizeImpact(findings);\n const file: typecheck.ImpactFile = {\n version: typecheck.IMPACT_FILE_VERSION,\n generatedAt: new Date().toISOString(),\n source: `${result.source.kind}:${result.source.label}`,\n target: `${result.target.kind}:${result.target.label}`,\n findings,\n summary,\n };\n const outPath = explicitPath ? path.resolve(explicitPath) : defaultImpactPath(sourceArg);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, typecheck.serializeImpactFile(file));\n logger.success(\n `Wrote ${outPath} — ${summary.findingsCount} finding(s), ${summary.errors} error / ${summary.warnings} warning ripple(s).`,\n );\n}\n\nfunction defaultImpactPath(sourceArg: string): string {\n if (sourceArg.toLowerCase().endsWith('.sdtproj')) {\n return path.resolve(path.dirname(sourceArg), '.sdt', 'impact.json');\n }\n return path.resolve('.sdt', 'impact.json');\n}\n\n/**\n * AUDITCMP.1 — workspace root for the compare-history record. Project /\n * pac sources anchor the audit trail next to the artifact being compared;\n * live (snowflake://) sources fall back to CWD.\n */\nfunction compareHistoryRoot(sourceArg: string): string {\n const lower = sourceArg.toLowerCase();\n if (lower.endsWith('.sdtproj') || lower.endsWith('.sdtpac')) {\n return path.dirname(path.resolve(sourceArg));\n }\n return process.cwd();\n}\n\nexport const SYSTEM_PROMPT = `You are a senior Snowflake DBA reviewing a schema diff. Your job is to narrate the changes in plain English to a teammate who hasn't seen the underlying SQL. For each change, briefly say:\n - what it is (e.g. \"a new fact table is added\")\n - why a reasonable engineer might do this (the intent)\n - what to watch out for (the risk, if any)\n\nBe concrete; use the FQNs you're given. Keep it to 3-6 sentences per object. Don't repeat the raw diff back — explain it.`;\n\nfunction renderCompareMarkdown(\n result: {\n source: { kind: string; label: string };\n target: { kind: string; label: string };\n objects: Array<{ kind: string; identity: { fqn: string; objectType: string } }>;\n summary: { added: number; removed: number; modified: number; unchanged: number };\n },\n assessment: {\n unrecoverable: unknown[];\n destructive: unknown[];\n expensive: unknown[];\n warnings: unknown[];\n blocked?: boolean;\n blockReason?: string;\n },\n): string {\n const lines: string[] = [];\n lines.push(\n `# Compare: ${result.source.kind}:${result.source.label} → ${result.target.kind}:${result.target.label}`,\n );\n lines.push('');\n lines.push(\n `**Summary**: +${result.summary.added} added · -${result.summary.removed} removed · ~${result.summary.modified} modified · =${result.summary.unchanged} unchanged.`,\n );\n lines.push('');\n lines.push('**Safety**:');\n lines.push(`- 🛑 Unrecoverable: ${assessment.unrecoverable.length}`);\n lines.push(`- 🔥 Destructive: ${assessment.destructive.length}`);\n lines.push(`- ⏱ Expensive: ${assessment.expensive.length}`);\n lines.push(`- ⚠ Warnings: ${assessment.warnings.length}`);\n if (assessment.blocked) {\n lines.push('');\n lines.push(\n `> **BLOCKED**: ${assessment.blockReason ?? 'safety classifier refuses to proceed'}`,\n );\n }\n lines.push('');\n const changed = result.objects.filter((o) => o.kind !== 'unchanged');\n if (changed.length === 0) {\n lines.push('_No object-level changes._');\n return lines.join('\\n');\n }\n lines.push('| Kind | Type | FQN |');\n lines.push('| --- | --- | --- |');\n for (const o of changed) {\n lines.push(`| ${o.kind} | \\`${o.identity.objectType}\\` | \\`${o.identity.fqn}\\` |`);\n }\n return lines.join('\\n');\n}\n\nexport function buildExplainPrompt(\n result: {\n source: { label: string };\n target: { label: string };\n objects: Array<{\n kind: string;\n identity: { fqn: string; objectType: string };\n changes?: unknown[];\n }>;\n summary: { added: number; removed: number; modified: number; unchanged: number };\n },\n assessment: {\n unrecoverable: unknown[];\n destructive: unknown[];\n expensive: unknown[];\n warnings: unknown[];\n },\n): string {\n const lines: string[] = [];\n lines.push(`Source: ${result.source.label}`);\n lines.push(`Target: ${result.target.label}`);\n lines.push(\n `Summary: +${result.summary.added} added, -${result.summary.removed} removed, ~${result.summary.modified} modified.`,\n );\n lines.push(\n `Safety: ${assessment.unrecoverable.length} unrecoverable, ${assessment.destructive.length} destructive, ${assessment.expensive.length} expensive, ${assessment.warnings.length} warnings.`,\n );\n lines.push('');\n lines.push('Changes (up to 40):');\n const changed = result.objects.filter((o) => o.kind !== 'unchanged').slice(0, 40);\n for (const o of changed) {\n lines.push(`- ${o.kind} ${o.identity.objectType} ${o.identity.fqn}`);\n }\n if (result.objects.filter((o) => o.kind !== 'unchanged').length > 40) {\n lines.push(\n ` (… ${result.objects.filter((o) => o.kind !== 'unchanged').length - 40} more truncated)`,\n );\n }\n lines.push('');\n lines.push(\n 'Please narrate this diff in plain English. Group related changes together when it helps.',\n );\n return lines.join('\\n');\n}\n","/**\n * Per-command --help enrichments — show 3-5 related catalog entries\n * under each command's help screen, with a one-line summary and a\n * pointer to `sdt explain <name>` for the full entry.\n *\n * Free-tier discoverability: a user who opens `sdt publish --help`\n * lands on a clear list of the deployment options that govern the\n * command's safety behaviour, without needing to know they exist or\n * read the project format reference first.\n *\n * Mirrors `Databricks/packages/cli/src/util/help-catalog.ts`.\n */\nimport type { Command } from 'commander';\nimport { DEPLOY_OPTIONS_CATALOG, type OptionEntry } from '@sdt-tools/core/options';\n\nconst CATALOG_BY_NAME: Map<string, OptionEntry> = new Map(\n DEPLOY_OPTIONS_CATALOG.map((entry) => [entry.name, entry]),\n);\n\n/**\n * Attach an \"After\" help block listing the named catalog entries with\n * one-line summaries. Unknown keys are silently skipped so a stale\n * mapping never breaks --help.\n */\nexport function attachRelatedOptions(cmd: Command, names: readonly string[]): void {\n const entries: OptionEntry[] = [];\n for (const n of names) {\n const e = CATALOG_BY_NAME.get(n);\n if (e) entries.push(e);\n }\n if (entries.length === 0) return;\n const maxName = entries.reduce((m, e) => Math.max(m, e.name.length), 0);\n const lines = [\n '',\n 'Related options (run `sdt explain <name>` for safety tier, default, and example):',\n ...entries.map((e) => ` ${e.name.padEnd(maxName)} ${e.summary}`),\n ];\n cmd.addHelpText('after', lines.join('\\n'));\n}\n","/**\n * ANSI severity coloring for CLI output. Resolves the `--color` flag\n * against the current TTY state and returns a `colorize` function\n * that wraps text in the right ANSI code (or returns it unchanged\n * when color is disabled).\n *\n * Conventions used across SDT/DDT CLI surfaces:\n * - UNRECOVERABLE → bold red\n * - DESTRUCTIVE → red\n * - EXPENSIVE → yellow\n * - WARNING → cyan\n * - SAFE / OK → green\n *\n * Paired with `Databricks/packages/cli/src/util/color.ts`.\n */\nexport type ColorMode = 'always' | 'never' | 'auto';\n\nconst ANSI = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n};\n\nexport function resolveColorMode(flag: string | undefined): boolean {\n const mode = (flag ?? 'auto').toLowerCase() as ColorMode;\n if (mode === 'always') return true;\n if (mode === 'never') return false;\n // auto — only color when stdout is a TTY AND NO_COLOR env isn't set.\n if (process.env.NO_COLOR) return false;\n return Boolean(process.stdout.isTTY);\n}\n\nexport interface Colorizer {\n unrecoverable(s: string): string;\n destructive(s: string): string;\n expensive(s: string): string;\n warning(s: string): string;\n safe(s: string): string;\n dim(s: string): string;\n /** Apply ANSI coloring to a multi-line block based on per-line severity tokens (🛑, ⚠, ✓, etc). */\n applyToBlock(block: string): string;\n}\n\nexport function makeColorizer(enabled: boolean): Colorizer {\n if (!enabled) {\n const identity = (s: string): string => s;\n return {\n unrecoverable: identity,\n destructive: identity,\n expensive: identity,\n warning: identity,\n safe: identity,\n dim: identity,\n applyToBlock: identity,\n };\n }\n const wrap =\n (codes: string) =>\n (s: string): string =>\n `${codes}${s}${ANSI.reset}`;\n return {\n unrecoverable: wrap(ANSI.bold + ANSI.red),\n destructive: wrap(ANSI.red),\n expensive: wrap(ANSI.yellow),\n warning: wrap(ANSI.cyan),\n safe: wrap(ANSI.green),\n dim: wrap(ANSI.gray),\n applyToBlock(block: string): string {\n // Walk each line; apply the strongest matching severity color.\n // The marker tokens (🛑/⚠/✓/info-prefixes) are stable across\n // `safety.formatReversibilityBuckets` and the diagnostics output.\n return block\n .split('\\n')\n .map((line) => {\n if (/UNRECOVERABLE/.test(line) || line.includes('🛑'))\n return ANSI.bold + ANSI.red + line + ANSI.reset;\n if (/DESTRUCTIVE/.test(line)) return ANSI.red + line + ANSI.reset;\n if (/EXPENSIVE/.test(line)) return ANSI.yellow + line + ANSI.reset;\n if (/WARNING/.test(line) || line.includes('⚠')) return ANSI.cyan + line + ANSI.reset;\n if (/\\bSAFE\\b|\\bOK\\b/.test(line) || line.includes('✓'))\n return ANSI.green + line + ANSI.reset;\n return line;\n })\n .join('\\n');\n },\n };\n}\n","import { promises as fs } from 'node:fs';\nimport { Option, type Command } from 'commander';\nimport { compare } from '@sdt-tools/core';\n\ntype NameMapping = compare.NameMapping;\n\nexport interface MappingOptions {\n map?: string[];\n mapFile?: string;\n mapCaseSensitive?: boolean;\n mapRewriteStandalone?: boolean;\n mapRewriteStrings?: boolean;\n}\n\n/** Attach `--map`, `--map-file`, `--map-case-sensitive`, `--map-rewrite-standalone`, `--map-rewrite-strings` to a command. */\nexport function addMappingFlags(cmd: Command): Command {\n return cmd\n .option(\n '--map <src=tgt>',\n 'Logical-name mapping (repeatable). Examples: DB_A=DB_B, DB_A.STAGING=DB_B.RAW. Rewrites source-side FQNs and DDL body refs.',\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option('--map-file <path>', 'JSON file of mappings.')\n .addOption(\n new Option(\n '--map-case-sensitive',\n 'Match identifiers case-sensitively. Default: insensitive.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--map-rewrite-standalone',\n 'Rewrite standalone one-part refs (e.g. USE DATABASE DB_A). Default: off (safer).',\n ).default(false),\n )\n .addOption(\n new Option(\n '--map-rewrite-strings',\n 'Phase 3: also rewrite FQN-shaped tokens inside string literals (best-effort, may produce false positives in legitimate string content). Default: off.',\n ).default(false),\n );\n}\n\n/** Build a `NameMapping` from `--map`/`--map-file` flag values. Returns undefined when no mappings supplied. */\nexport async function buildMappingFromOptions(\n opts: MappingOptions,\n): Promise<NameMapping | undefined> {\n const flagMappings = Array.isArray(opts.map) ? opts.map : [];\n let mapping: NameMapping = { entries: [] };\n if (opts.mapFile) {\n const raw = await fs.readFile(String(opts.mapFile), 'utf8');\n mapping = compare.mappingFromFile(JSON.parse(raw));\n }\n if (flagMappings.length > 0) {\n const fromArgs = compare.mappingFromArgs(flagMappings);\n mapping = { entries: [...mapping.entries, ...fromArgs.entries] };\n }\n if (mapping.entries.length === 0) return undefined;\n if (opts.mapCaseSensitive) mapping.caseSensitive = true;\n if (opts.mapRewriteStandalone) mapping.rewriteStandaloneRefs = true;\n if (opts.mapRewriteStrings) mapping.rewriteInsideStrings = true;\n return mapping;\n}\n\n/** Render a one-line summary of a NameMapping for the operator's log output. */\nexport function describeMapping(mapping: NameMapping | undefined): string {\n if (!mapping || mapping.entries.length === 0) return '';\n return mapping.entries.map((e) => `${e.source}→${e.target}`).join(', ');\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { readPac } from '@sdt-tools/core/pac';\nimport {\n CompareEngine,\n LiveSource,\n buildExecutionPlan,\n defaultSafePlan,\n validatePlan,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport {\n ScriptGenerator,\n SnowflakeExecutor,\n buildDeployManifest,\n executePlan,\n resolveDeployScripts,\n formatDeployScript,\n colorizeMigrationScript,\n splitStatements as coreSplitStatements,\n type DeployScript,\n type DeploymentReport,\n type StepResult,\n} from '@sdt-tools/core/deploy';\nimport { compileSlice, mergeDeployOptions, type SdtDeployOptions } from '@sdt-tools/core/project';\nimport {\n ai,\n aiPreflight,\n approval,\n pacFreshness,\n protectedObjects,\n safety,\n license,\n testFramework,\n} from '@sdt-tools/core';\nimport { executeDcmProjectDeploy, mapDcmResultToDeploymentReport } from '@sdt-tools/core/exporters';\nimport { assessDcmCompatibility, formatDcmCompatibilityReport } from '@sdt-tools/core/safety';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\nclass ModelSource implements CompareSource {\n readonly kind = 'pac' as const;\n readonly platform = 'Snowflake' as const;\n readonly label: string;\n private readonly model: Awaited<ReturnType<typeof readPac>>['model'];\n constructor(label: string, model: Awaited<ReturnType<typeof readPac>>['model']) {\n this.label = label;\n this.model = model;\n }\n async load() {\n return this.model;\n }\n}\n\n/**\n * Split a multi-statement SQL block into individual statements. Thin\n * wrapper around `@sdt-tools/core/deploy.splitStatements` so callsites here\n * keep their `string[]` shape.\n */\nfunction splitStatements(sql: string): string[] {\n return coreSplitStatements(sql).map((s) => s.sql);\n}\n\nexport function publishCommand(): Command {\n const cmd = new Command('publish');\n cmd\n .description(\n 'Compare a .sdtpac to a live Snowflake target and apply (or dry-run) the migration.',\n )\n .option(\n '--pac <path>',\n 'Path to a built .sdtpac. Required for a normal publish; omit only with --restore-from-snapshot.',\n )\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .option(\n '--restore-from-snapshot <batchId>',\n 'Recovery mode: skip the compare step and emit ALTER TABLE … SWAP WITH against the snapshot batch <batchId> from the registry. ' +\n 'Dry-run by default; pass --apply --yes to execute. ' +\n \"This is the command printed by TRUST.4's post-deploy-smoke + TRUST.8's restore-hint when a deploy fails — they tell the operator to run `sdt publish --restore-from-snapshot <id>`.\",\n )\n .option(\n '--snapshot-dir <path>',\n 'Snapshot registry directory used with --restore-from-snapshot.',\n '.sdt/snapshots',\n )\n .option('--db <database>', 'Target database (defaults to pac scope.database)')\n .option('--schema <schema>', 'Target schema (defaults to pac scope.schema)')\n .option('--dry-run', 'Print the migration script without executing it', false)\n .option('--apply', 'Execute the migration against the live target (gated by safety)', false)\n .option('--out <path>', 'Write the generated migration script to this path')\n .option(\n '--color <mode>',\n 'Color stdout: auto | always | never. Honors NO_COLOR / SDT_NO_COLOR env vars in auto mode.',\n 'auto',\n )\n .option('--no-pre-scripts', 'Skip pre-deploy scripts even if the pac configures them')\n .option('--no-post-scripts', 'Skip post-deploy scripts even if the pac configures them')\n .option(\n '--no-slice',\n \"Disable the pac's Project Slice (if it has one). Default: the slice baked into the pac is applied automatically and target objects outside the slice are left untouched.\",\n )\n .option('--yes', 'Confirm REQUIRE_YES_FLAG safety gate (required for --apply)', false)\n .option(\n '--confirm-production',\n 'Confirm REQUIRE_CONFIRM_PRODUCTION gate (required for prod-named profiles with destructive changes)',\n false,\n )\n .option(\n '--query-tag <tag>',\n \"Set Snowflake QUERY_TAG for this deploy (audit / observability). The CLI runs ALTER SESSION SET QUERY_TAG='<tag>' before any migration statement so QUERY_HISTORY can attribute the deploy. Defaults to 'sdt:<projectName>@<projectVersion>:<unix-ms>'.\",\n )\n .option(\n '--manifest <path>',\n 'After --apply, write a JSON deploy manifest (every step + status + duration + reverse SQL) to <path>. Replayable via `sdt revert --manifest <path>`.',\n )\n .option(\n '--ai-preflight',\n \"Before --apply, ask AI to grade the operator's plain-language deploy description against the actual diff + safety findings. Blocks on 'mismatch' unless --confirm-after-preflight-mismatch is also passed.\",\n false,\n )\n .option(\n '--ai-preflight-text <narrative>',\n 'Non-interactive form of --ai-preflight. Supplies the narrative directly instead of reading from stdin.',\n )\n .option(\n '--strict-ai-preflight',\n \"Also block on 'partial' (not just 'mismatch'). Useful for production deploys.\",\n false,\n )\n .option(\n '--confirm-after-preflight-mismatch',\n 'Proceed even when --ai-preflight returns a mismatch verdict. Acknowledges that the AI grader flagged a discrepancy.',\n false,\n )\n .option(\n '--require-approvals <n>',\n 'Multi-approver gate: refuse --apply until <n> distinct approvers have signed off via `sdt approval add <deploy-id> --as <user>`. Team-tier.',\n )\n .option(\n '--approver <ids>',\n 'Comma-separated allow-list of approver IDs honoured by --require-approvals. Empty = any approver counts.',\n )\n .option(\n '--deploy-id <id>',\n 'Stable deploy identifier paired with --require-approvals (default: <connection>:<db>.<schema>).',\n )\n .option(\n '--approvals-root <path>',\n 'Approvals directory (default: .sdt/approvals).',\n path.join('.sdt', 'approvals'),\n )\n .option(\n '--allow-protected <fqns>',\n 'Comma-separated FQNs to allow despite .sdt-protection.json protection. Repeatable.',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[],\n )\n .option(\n '--allow-all-protected',\n 'Override all protection config entries (caution: disables DSR.4 guardrails).',\n false,\n )\n .option(\n '--freshness <mode>',\n 'Pac age check: warn (log if stale, continue), strict (block if stale), skip (no check). Default warn.',\n 'warn',\n )\n .option(\n '--post-deploy-tests <project>',\n 'After a successful --apply, discover YAML tests under <project>/tests/ and run them against the same connection. Exits 2 on any blocking (error-severity) DQ failure. Emits POST_DEPLOY_DQ_FAILED hint with --restore-from-snapshot recipe when tests fail.',\n )\n .option(\n '--via-dcm <stage>',\n 'Enterprise: delegate execution to Snowflake DCM Projects. <stage> is the DCM project FQN (e.g. @MY_DB.PUBLIC.MY_STAGE/my_project). SDT runs its safety pre-flight and DCM compatibility check, then executes EXECUTE DCM PROJECT DEPLOY. DCM must have been populated via `sdt export --dcm` first.',\n )\n .option(\n '--profile <name>',\n 'VARSYNTAX.2 — look up `deploymentProfiles[<name>].variables` from the pac manifest and substitute `$(VAR)` references in the generated migration script. Errors if the named profile is absent from the pac (e.g. pac built before VARSYNTAX.2, or profile not declared in .sdtproj). Distinct from `--connection`, which selects the Snowflake credential profile.',\n )\n .option(\n '--variables <kv>',\n 'VARSYNTAX.2 — comma-separated KEY=VALUE pairs for `$(VAR)` substitution. Merged on top of `--profile <name>` variables (CLI values win on key collision).',\n )\n .action(async (opts) => {\n if (opts.apply && opts.dryRun) {\n logger.error('--apply and --dry-run are mutually exclusive.');\n process.exitCode = 1;\n return;\n }\n\n // Recovery mode — branch out of the normal compare/apply flow and\n // emit ALTER TABLE … SWAP WITH from a recorded snapshot batch.\n if (opts.restoreFromSnapshot) {\n await runRestoreFromSnapshot(opts);\n return;\n }\n\n if (!opts.pac) {\n logger.error('--pac <path> is required (unless --restore-from-snapshot is given).');\n process.exitCode = 1;\n return;\n }\n const pacPath = path.resolve(String(opts.pac));\n const pac = await readPac(pacPath);\n\n // Freshness gate — runs before any network call so stale artifacts\n // are caught fast, before an expensive live-extract round trip.\n const freshnessMode = (opts.freshness as pacFreshness.FreshnessMode | undefined) ?? 'warn';\n if (freshnessMode !== 'skip') {\n const fr = pacFreshness.checkPacFreshness(pac.manifest.builtAt);\n if (fr.status !== 'fresh') {\n const msg = pacFreshness.formatFreshnessWarning(fr, pacPath);\n if (freshnessMode === 'strict') {\n logger.error(msg);\n process.exitCode = 1;\n return;\n } else {\n logger.warn(msg);\n }\n }\n }\n\n const profileName = String(opts.connection);\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n const db = opts.db ? String(opts.db) : pac.manifest.scope.database;\n const schema = opts.schema ? String(opts.schema) : pac.manifest.scope.schema;\n const live = new LiveSource(conn, { database: db, schema });\n const source = new ModelSource(pacPath, pac.model);\n\n const baseline: SdtDeployOptions | undefined = pac.manifest.deployOptions;\n const merged = mergeDeployOptions(baseline);\n // Apply the production safety floor: if the profile name looks like\n // production, force preDeployClone=true regardless of what the user\n // authored. Documented in docs/UX_PLAYBOOK.md §\"Per-profile safety\n // floor\". Compose by mutating the `deployment` block in place.\n const isProd = safety.looksLikeProduction(profileName);\n const resolved = {\n ...merged,\n deployment: safety.applyProductionSafetyFloor(merged.deployment, isProd),\n };\n if (isProd && merged.deployment.preDeployClone !== true) {\n logger.info(\n ' Profile \"' +\n profileName +\n '\" looks like production — forcing deployOptions.deployment.preDeployClone=true (safety floor).',\n );\n }\n const preScripts: DeployScript[] =\n opts.preScripts === false\n ? []\n : resolveDeployScripts(pac.source, resolved.deployment.preDeployScriptPatterns);\n const postScripts: DeployScript[] =\n opts.postScripts === false\n ? []\n : resolveDeployScripts(pac.source, resolved.deployment.postDeployScriptPatterns);\n\n // Logical-name mapping (`--map`, `--map-file`) — rewrites pac-side FQNs\n // so a pac built against DB_A can publish into DB_B. See\n // docs/LOGICAL_NAME_MAPPING.md. Mirrors `ddt publish`.\n const nameMapping = await buildMappingFromOptions(opts);\n const engine = new CompareEngine();\n logger.step('Comparing pac to live...');\n\n // Apply the pac's Slice (if any) so target objects outside the slice\n // are partitioned into `outsideScope` rather than treated as removals.\n // --no-slice on the publish command bypasses this.\n const sliceConfig = opts.slice === false ? undefined : pac.manifest.slice;\n const slice = sliceConfig ? compileSlice(sliceConfig) : undefined;\n\n const result = await engine.compare(source, live, {\n ...(nameMapping ? { nameMapping } : {}),\n ...(slice ? { sliceFilter: slice } : {}),\n });\n if (slice) {\n const outside = result.outsideScope?.length ?? 0;\n const refs = result.referenced?.length ?? 0;\n logger.info(\n ' Slice active: ' +\n result.objects.length +\n ' owned · ' +\n outside +\n ' outside scope (untouched) · ' +\n refs +\n ' referenced',\n );\n }\n logger.info(\n ' +' +\n result.summary.added +\n ' -' +\n result.summary.removed +\n ' ~' +\n result.summary.modified +\n ' =' +\n result.summary.unchanged,\n );\n\n // Protection check — refuse to touch protected objects unless overridden.\n const protConfig = await protectedObjects.loadProtectionConfig(path.dirname(pacPath));\n if (protConfig) {\n const ops = result.objects\n .filter((o) => o.kind !== 'unchanged' && o.kind !== 'added')\n .map((o) => ({\n fqn: o.identity.fqn,\n objectType: String(o.identity.objectType),\n kind: o.kind,\n }));\n const allowedFqns = ((opts.allowProtected as string[]) ?? []).flatMap((s) =>\n s.split(',').map((f) => f.trim()),\n );\n const violations = protectedObjects.checkProtectedObjects(ops, protConfig, {\n allowedFqns,\n allowAll: Boolean(opts.allowAllProtected),\n });\n if (violations.length > 0) {\n logger.error(protectedObjects.formatProtectionViolations(violations));\n process.exitCode = 1;\n await conn.disconnect();\n return;\n }\n }\n\n // VARSYNTAX.2 — resolve `$(VAR)` variables from the pac's\n // deployment-profile snapshot (when `--profile <name>` is given)\n // merged with `--variables KEY=VALUE` (CLI wins on key collision).\n // Absent / empty leaves `$(VAR)` references literal so the prior\n // behavior is preserved when no flag is passed.\n const deploymentProfileName = opts.profile ? String(opts.profile) : undefined;\n let publishVariables: Record<string, string> | undefined;\n if (deploymentProfileName) {\n const profileBlock = pac.manifest.deploymentProfiles?.[deploymentProfileName];\n if (!profileBlock) {\n const available = Object.keys(pac.manifest.deploymentProfiles ?? {});\n logger.error(\n `--profile ${deploymentProfileName}: no deploymentProfile by that name in the pac manifest. ` +\n (available.length === 0\n ? 'The pac carries no deploymentProfiles (was it built before VARSYNTAX.2, or does the .sdtproj declare any?).'\n : `Available: ${available.join(', ')}.`),\n );\n process.exitCode = 1;\n await conn.disconnect();\n return;\n }\n if (profileBlock.variables) publishVariables = { ...profileBlock.variables };\n }\n const cliVariables = parsePublishVariables(opts.variables);\n if (cliVariables) {\n publishVariables = { ...(publishVariables ?? {}), ...cliVariables };\n }\n\n const gen = new ScriptGenerator();\n // VARSYNTAX.3 — supply the deploy context so `$(SDT_PROFILE)`,\n // `$(SDT_PROJECT_NAME)`, `$(SDT_PROJECT_VERSION)`, `$(SDT_PLATFORM)`,\n // `$(SDT_TIMESTAMP)`, `$(SDT_USER)` substitute without the operator\n // having to pass them via `--variables`.\n const generateContext: {\n profile?: string;\n projectName?: string;\n projectVersion?: string;\n user?: string;\n } = {\n projectName: pac.manifest.projectName,\n projectVersion: pac.manifest.projectVersion,\n ...(deploymentProfileName ? { profile: deploymentProfileName } : {}),\n ...(profile.auth?.username ? { user: profile.auth.username } : {}),\n };\n const body = gen.generate(result, {\n banner: 'SDT publish: ' + pac.manifest.projectName + ' v' + pac.manifest.projectVersion,\n deployment: resolved.deployment,\n ...(publishVariables ? { variables: publishVariables } : {}),\n context: generateContext,\n });\n\n const sections: string[] = [];\n if (preScripts.length > 0) {\n sections.push('-- ' + '='.repeat(68));\n sections.push('-- PRE-DEPLOY (' + preScripts.length + ' script(s))');\n sections.push('-- ' + '='.repeat(68));\n for (const s of preScripts) sections.push(formatDeployScript(s, 'pre'));\n }\n sections.push(body.sql);\n if (postScripts.length > 0) {\n sections.push('');\n sections.push('-- ' + '='.repeat(68));\n sections.push('-- POST-DEPLOY (' + postScripts.length + ' script(s))');\n sections.push('-- ' + '='.repeat(68));\n for (const s of postScripts) sections.push(formatDeployScript(s, 'post'));\n }\n const fullScript = sections.join('\\n');\n\n logger.info(\n ' pre-deploy: ' +\n preScripts.length +\n ' script(s); post-deploy: ' +\n postScripts.length +\n ' script(s)',\n );\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, fullScript);\n logger.success('Wrote migration script to ' + out);\n }\n\n if (opts.dryRun || !opts.apply) {\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n process.stdout.write(colorizeMigrationScript(fullScript, { mode: colorMode }) + '\\n');\n await conn.disconnect();\n return;\n }\n\n // --apply path: run safety classifier and check gates.\n const assessment = safety.assess(result, { deployment: resolved.deployment });\n logger.info(\n ' safety: ' +\n assessment.unrecoverable.length +\n ' unrecoverable, ' +\n assessment.destructive.length +\n ' destructive, ' +\n assessment.expensive.length +\n ' expensive, ' +\n assessment.warnings.length +\n ' warnings',\n );\n if (assessment.blocked) {\n logger.error('Deploy refused: ' + assessment.blockReason);\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n\n const satisfied = safety.satisfiedGates({\n yes: Boolean(opts.yes),\n confirmProduction:\n Boolean(opts.confirmProduction) || !safety.looksLikeProduction(profileName),\n allowDropTable: resolved.deployment.allowDropTable,\n allowDropColumn: resolved.deployment.allowDropColumn,\n allowNarrowing: resolved.deployment.allowNarrowingTypes,\n allowTableRebuild: resolved.deployment.allowTableRebuild,\n allowUnrecoverableDrop: resolved.deployment.allowUnrecoverableDrop,\n });\n const outstanding = safety.outstandingGates(assessment, satisfied);\n if (outstanding.length > 0) {\n logger.error(\n 'Outstanding safety gate(s): ' +\n outstanding.join(', ') +\n '. Pass --yes / --confirm-production or set the matching deployOptions.deployment.* flag in the profile.',\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n\n // Approval gate (Team-tier): refuse to apply until N distinct\n // approvers have recorded approval tokens for this deploy id.\n if (opts.requireApprovals !== undefined && opts.requireApprovals !== false) {\n const required = Number(opts.requireApprovals) || 0;\n const allowed = opts.approver\n ? String(opts.approver)\n .split(',')\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n const deployId = String(opts.deployId ?? `${profileName}:${db}.${schema}`);\n const approvalsRoot = String(opts.approvalsRoot);\n const file = await approval.readApprovalFile(approvalsRoot, deployId);\n const outcome = approval.evaluateApprovalGate(\n { deployId, required, allowedApprovers: allowed },\n file.approvals,\n );\n if (!outcome.satisfied) {\n logger.error(\n 'Approval gate blocked deploy: ' +\n (outcome.blockReason ?? 'gate not satisfied') +\n `. Record approvals with \\`sdt approval add ${deployId} --as <user>\\`.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n logger.info(\n ` approvals: ${outcome.satisfiedBy.length}/${required} ` +\n `(${outcome.satisfiedBy.join(', ')})`,\n );\n }\n\n // AI preflight grader: ask the operator to type what they expect\n // this deploy to do, then let an AI compare that narrative to the\n // actual SQL + safety findings. Blocks deploy on `mismatch`.\n if (opts.aiPreflight) {\n const narrative = await readPreflightNarrative(opts.aiPreflightText);\n if (!narrative) {\n logger.error(\n '--ai-preflight needs a narrative. Provide it inline via --ai-preflight-text or via stdin.',\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n logger.step('Grading deploy narrative with AI...');\n try {\n const findings = [\n ...assessment.unrecoverable.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ...assessment.destructive.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ...assessment.expensive.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ];\n const compareSummary = `added ${result.summary.added}, modified ${result.summary.modified}, removed ${result.summary.removed}, unchanged ${result.summary.unchanged}`;\n const verdict = await aiPreflight.gradePreflight(\n {\n narrative,\n compareSummary,\n safetyFindings: findings,\n diffSampleDdl: fullScript,\n target: `${db}.${schema}@${profileName}`,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'ai-preflight',\n });\n return r.text;\n },\n },\n );\n logger.info(' preflight verdict: ' + verdict.verdict);\n if (verdict.reasoning) logger.info(' preflight reasoning: ' + verdict.reasoning);\n for (const d of verdict.discrepancies) logger.info(' • ' + d);\n\n const isBlocking =\n verdict.verdict === 'mismatch' ||\n (opts.strictAiPreflight && verdict.verdict === 'partial');\n if (isBlocking && !opts.confirmAfterPreflightMismatch) {\n logger.error(\n `Deploy refused: AI preflight returned \"${verdict.verdict}\". Re-run with --confirm-after-preflight-mismatch to override, or revise the narrative.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n if (verdict.parseFailed) {\n logger.warn(\n ' preflight verdict could not be parsed — continuing without a clean alignment signal.',\n );\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\n `--ai-preflight failed: ${msg}. Configure an AI provider via \\`sdt ai status\\` or omit --ai-preflight.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n }\n\n // ── DCM path — replaces the standard executor when --via-dcm is set ──\n if (opts.viaDcm) {\n const dcmStage = String(opts.viaDcm);\n\n // Enterprise license check (warn mode for v0.1 — feature is allowed with warning if no license).\n const lic = await license.loadLicense();\n const licCheck = license.checkProFeature(lic, 'dcm-deploy');\n if (licCheck.warning) logger.warn('[Enterprise] ' + licCheck.warning);\n\n // DCM compatibility pre-flight — always runs, even for --dry-run.\n const dcmCompatReport = assessDcmCompatibility(result);\n if (dcmCompatReport.blocked) {\n logger.error('--via-dcm blocked:\\n' + formatDcmCompatibilityReport(dcmCompatReport));\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n if (dcmCompatReport.findings.length > 0) {\n logger.warn(\n 'DCM compatibility warnings:\\n' + formatDcmCompatibilityReport(dcmCompatReport),\n );\n }\n\n if (opts.dryRun || !opts.apply) {\n logger.info(\n 'DCM compatibility check passed (' +\n dcmCompatReport.findings.length +\n ' warning(s)). Use --apply to execute via DCM.',\n );\n await conn.disconnect();\n return;\n }\n\n // Execute via DCM.\n logger.step('Executing via DCM: EXECUTE DCM PROJECT ' + dcmStage + ' DEPLOY');\n const dcmResult = await executeDcmProjectDeploy(conn, dcmStage);\n const bodyReport = mapDcmResultToDeploymentReport(dcmResult);\n\n if (dcmResult.overallStatus === 'SUCCESS') {\n logger.success(\n 'DCM deploy complete. ' + dcmResult.objects.length + ' object(s) processed.',\n );\n } else {\n logger.error(\n 'DCM deploy finished with failures: ' +\n dcmResult.failures.length +\n ' failed, ' +\n dcmResult.objects.length +\n ' total.',\n );\n process.exitCode = 1;\n }\n\n if (opts.manifest) {\n const m = buildDeployManifest(bodyReport, profile.account);\n const mPath = path.resolve(String(opts.manifest));\n await fs.mkdir(path.dirname(mPath), { recursive: true });\n await fs.writeFile(mPath, JSON.stringify(m, null, 2) + '\\n', 'utf8');\n logger.success('Wrote deploy manifest → ' + mPath);\n }\n\n await conn.disconnect();\n return;\n }\n // ── End DCM path ────────────────────────────────────────────────────────\n\n // Set the Snowflake QUERY_TAG before executing any migration\n // statement. Threading the tag into QUERY_HISTORY is what makes a\n // deploy auditable after the fact (\"which statements ran as part of\n // sdt-vX.Y.Z published at 13:42?\"). Default tag encodes the project\n // identity + a millisecond timestamp so two back-to-back applies are\n // distinguishable.\n const queryTag =\n typeof opts.queryTag === 'string' && opts.queryTag.length > 0\n ? String(opts.queryTag)\n : `sdt:${pac.manifest.projectName}@${pac.manifest.projectVersion}:${Date.now()}`;\n try {\n await conn.query(`ALTER SESSION SET QUERY_TAG = '${queryTag.replace(/'/g, \"''\")}'`);\n logger.info(' query_tag: ' + queryTag);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\n 'Failed to set QUERY_TAG: ' +\n msg +\n '. Continuing without tag — audit attribution will be missing.',\n );\n }\n\n // Execute. Statements run sequentially. Snowflake DDL auto-commits per\n // statement, so partial deploys do not roll back automatically; if\n // preDeployClone was enabled, use UNDROP DATABASE or clone-swap to\n // recover. The main body runs through executePlan + SnowflakeExecutor\n // so every step's reverseSql is captured for `sdt revert`. Pre/post\n // scripts are file-based (no emitter, no reverseSql) so they keep the\n // simpler sequential-query path.\n logger.step('Applying migration...');\n let executed = 0;\n let failed = 0;\n const runOne = async (sql: string, label: string): Promise<boolean> => {\n const stmts = splitStatements(sql);\n for (const stmt of stmts) {\n try {\n await conn.query(stmt);\n executed += 1;\n } catch (err) {\n failed += 1;\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(' [' + label + '] failed: ' + msg + '\\n ' + stmt);\n return false;\n }\n }\n return true;\n };\n\n let ok = true;\n for (const s of preScripts) {\n logger.info(' pre: ' + s.path);\n ok = await runOne(s.sql, 'pre/' + s.path);\n if (!ok) break;\n }\n\n let bodyReport: DeploymentReport | undefined;\n if (ok) {\n const plan = defaultSafePlan(result);\n const validated = validatePlan(result, plan);\n const steps = buildExecutionPlan(result, validated, {\n deployment: resolved.deployment,\n });\n if (steps.length > 0) {\n const executor = new SnowflakeExecutor(conn, {\n onStatement: (sql) => {\n executed += 1;\n const head = sql.split('\\n')[0]?.slice(0, 100) ?? '';\n logger.info(' → ' + head + (sql.length > 100 ? ' …' : ''));\n },\n });\n bodyReport = await executePlan(steps, executor, {\n rollbackOnFailure: false,\n onStepEnd: (r: StepResult) => {\n if (r.status === 'FAILED') {\n failed += 1;\n logger.error(\n ' [' +\n r.step.fqn +\n '] failed: ' +\n (r.error ?? 'unknown') +\n '\\n ' +\n r.step.forwardSql,\n );\n }\n },\n });\n if (bodyReport.finalState !== 'CLEAN_SUCCESS') ok = false;\n }\n }\n\n if (ok) {\n for (const s of postScripts) {\n logger.info(' post: ' + s.path);\n ok = await runOne(s.sql, 'post/' + s.path);\n if (!ok) break;\n }\n }\n\n // Write deploy manifest if requested. The manifest captures every\n // body step (forwardSql + reverseSql + status + duration) and is\n // replayable via `sdt revert --manifest <path>`. Pre/post scripts are\n // not in the manifest (they have no inverse).\n if (opts.manifest && bodyReport) {\n const m = buildDeployManifest(bodyReport, profile.account);\n const mPath = path.resolve(String(opts.manifest));\n await fs.mkdir(path.dirname(mPath), { recursive: true });\n await fs.writeFile(mPath, JSON.stringify(m, null, 2) + '\\n', 'utf8');\n logger.success('Wrote deploy manifest → ' + mPath);\n }\n\n if (ok) {\n logger.success('Deploy complete. ' + executed + ' statement(s) executed.');\n\n // Post-deploy DQ tests (DQ.6).\n if (opts.postDeployTests) {\n const projectRoot = path.resolve(String(opts.postDeployTests));\n logger.step('Running post-deploy DQ tests from ' + projectRoot + '...');\n const testFiles = await testFramework.discoverTests(projectRoot);\n if (testFiles.length === 0) {\n logger.warn(\n ' POST_DEPLOY_DQ: no tests found under ' + projectRoot + '/tests/ — skipping.',\n );\n } else {\n const report = await testFramework.runTestFiles(testFiles, conn);\n process.stdout.write(testFramework.renderTextReport(report));\n if (report.summary.blocking) {\n logger.error(\n 'POST_DEPLOY_DQ_FAILED: ' +\n report.summary.fail +\n ' fail / ' +\n report.summary.error +\n ' error.' +\n (opts.manifest\n ? ' Recover: `sdt revert --manifest ' + String(opts.manifest) + '`'\n : ' Consider re-deploying prior version or using `sdt revert --manifest` if --manifest was used.'),\n );\n process.exitCode = 2;\n } else {\n logger.success(\n ' POST_DEPLOY_DQ: ' + report.summary.pass + '/' + report.summary.total + ' pass.',\n );\n }\n }\n }\n } else {\n logger.error(\n 'Deploy aborted after ' +\n executed +\n ' statement(s); ' +\n failed +\n ' failure(s). Recover via UNDROP / clone-swap if preDeployClone was set.',\n );\n process.exitCode = 1;\n }\n await conn.disconnect();\n });\n addMappingFlags(cmd);\n attachRelatedOptions(cmd, [\n 'deployment.allowDropTable',\n 'deployment.allowDropColumn',\n 'deployment.allowUnrecoverableDrop',\n 'deployment.allowNarrowingTypes',\n 'deployment.preDeployClone',\n 'deployment.blockOnPossibleDataLoss',\n 'deployment.preserveTargetOnlyObjects',\n ]);\n return cmd;\n}\n\n/**\n * `sdt publish --restore-from-snapshot <batchId>` recovery path.\n *\n * Loads the batch from the registry, emits the restore SQL (one\n * `ALTER TABLE … SWAP WITH` per source object, or a MANUAL hint row for\n * materialised objects), and either prints it (dry-run / no --apply) or\n * executes it against the live target (--apply --yes, --confirm-production\n * for prod-named profiles).\n *\n * Skips: pac freshness, compare, safety classifier, AI preflight, approval\n * gate, DCM path, manifest writing. Recovery is an emergency lever — the\n * gates that protect the forward path don't apply when we're restoring a\n * known-good snapshot the safety classifier itself authored.\n */\nasync function runRestoreFromSnapshot(opts: Record<string, unknown>): Promise<void> {\n const batchId = String(opts.restoreFromSnapshot);\n const registryDir = path.resolve(String(opts.snapshotDir ?? '.sdt/snapshots'));\n const profileName = String(opts.connection);\n\n let batch: safety.SnapshotBatch;\n try {\n batch = await safety.readSnapshotBatch(registryDir, batchId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Snapshot batch \"${batchId}\" not found in ${registryDir}: ${msg}`);\n process.exitCode = 1;\n return;\n }\n\n const sqlLines = safety.emitRestoreFromSnapshotSql(batch);\n const sql = sqlLines.join('\\n');\n\n logger.info(`Restoring from batch ${batch.batchId} (createdAt=${batch.createdAt})`);\n logger.info(\n ` ${batch.entries.length} object(s) recorded; ${sqlLines.filter((l) => !l.startsWith('--')).length} statement(s) will run.`,\n );\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, sql + '\\n', 'utf8');\n logger.success(`Wrote restore SQL → ${out}`);\n }\n\n if (opts.dryRun || !opts.apply) {\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n process.stdout.write(colorizeMigrationScript(sql, { mode: colorMode }) + '\\n');\n return;\n }\n\n if (!opts.yes) {\n logger.error('--apply requires --yes (restore replaces production tables via SWAP WITH).');\n process.exitCode = 1;\n return;\n }\n if (safety.looksLikeProduction(profileName) && !opts.confirmProduction) {\n logger.error(\n `Profile \"${profileName}\" looks like production — also pass --confirm-production to restore.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n let executed = 0;\n let failed = 0;\n try {\n for (const stmt of coreSplitStatements(sql).map((s) => s.sql)) {\n try {\n await conn.query(stmt);\n executed += 1;\n const head = stmt.split('\\n')[0]?.slice(0, 100) ?? '';\n logger.info(' → ' + head + (stmt.length > 100 ? ' …' : ''));\n } catch (err) {\n failed += 1;\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(` [restore ${batch.batchId}] ${msg}\\n ${stmt}`);\n }\n }\n } finally {\n await conn.disconnect();\n }\n\n if (failed === 0) {\n logger.success(`Restore complete. ${executed} statement(s) executed.`);\n } else {\n logger.error(\n `Restore finished with failures: ${executed} ok, ${failed} failed. ` +\n `Inspect the snapshot tables under ${registryDir} and recover by hand.`,\n );\n process.exitCode = 1;\n }\n}\n\n/**\n * Read the AI-preflight narrative from --ai-preflight-text (preferred for CI)\n * or from stdin (interactive). Returns trimmed text, or undefined when no\n * narrative was supplied.\n */\nasync function readPreflightNarrative(inlineText: unknown): Promise<string | undefined> {\n if (typeof inlineText === 'string' && inlineText.trim().length > 0) {\n return inlineText.trim();\n }\n if (process.stdin.isTTY) {\n process.stdout.write(\n '\\n--ai-preflight is active. In one paragraph, describe what you expect this deploy to do.\\nEnd with an empty line (or Ctrl-D):\\n> ',\n );\n }\n process.stdin.setEncoding('utf8');\n let buffer = '';\n await new Promise<void>((resolve) => {\n const onData = (chunk: string): void => {\n buffer += chunk;\n if (/\\n\\s*\\n/.test(buffer)) {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n resolve();\n }\n };\n const onEnd = (): void => {\n process.stdin.removeListener('data', onData);\n resolve();\n };\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n });\n const trimmed = buffer.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\n/**\n * VARSYNTAX.2 — parse the `--variables KEY=VALUE,KEY=VALUE,...` flag.\n * Returns undefined when nothing is parsed (no KV pairs, missing values,\n * empty string) so callers can `...(parsed ? { variables: parsed } : {})`\n * without leaking an empty object.\n */\nexport function parsePublishVariables(raw: unknown): Record<string, string> | undefined {\n if (!raw) return undefined;\n const out: Record<string, string> = {};\n for (const pair of String(raw).split(',')) {\n const eq = pair.indexOf('=');\n if (eq <= 0) continue;\n const k = pair.slice(0, eq).trim();\n const v = pair.slice(eq + 1).trim();\n if (k.length > 0) out[k] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n","import { Command } from 'commander';\nimport path from 'node:path';\nimport { readPac } from '@sdt-tools/core/pac';\nimport {\n CompareEngine,\n DbtManifestSource,\n LiveSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { loadProject } from '@sdt-tools/core/project';\nimport { driftAnomaly } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\nclass ModelSource implements CompareSource {\n readonly kind = 'pac' as const;\n readonly platform = 'Snowflake' as const;\n readonly label: string;\n private readonly model: Awaited<ReturnType<typeof readPac>>['model'];\n constructor(label: string, model: Awaited<ReturnType<typeof readPac>>['model']) {\n this.label = label;\n this.model = model;\n }\n async load() {\n return this.model;\n }\n}\n\nfunction driftWatchSubcommand(): Command {\n const sub = new Command('watch');\n sub\n .description(\n 'Poll a project against the live Snowflake account on a fixed interval. Prints DRIFT_DETECTED events to stdout (or POSTs to --webhook) when the catalog diverges from the project pac.',\n )\n .requiredOption('-p, --project <path>', 'Path to .sdtproj')\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .option('--interval <seconds>', 'Poll interval in seconds (min 5).', '60')\n .option(\n '--webhook <url>',\n 'POST drift events as JSON to this URL (Slack/Teams/generic receiver).',\n )\n .option('--format <fmt>', 'Output format: text | json.', 'text')\n .option(\n '--quiet',\n 'Suppress CLEAN status lines; emit only DRIFT_DETECTED and error events.',\n false,\n )\n .action(async (opts) => {\n const intervalSecs = Math.max(5, parseInt(String(opts.interval), 10) || 60);\n const format = String(opts.format) === 'json' ? 'json' : 'text';\n const webhookUrl = opts.webhook ? String(opts.webhook) : undefined;\n const quiet = !!opts.quiet;\n\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const loaded = await loadProject(String(opts.project));\n const pacPath = path.join(loaded.rootDir, 'bin', `${loaded.project.name}.sdtpac`);\n const scope = {\n database: loaded.project.scope.database,\n schema: loaded.project.scope.schema,\n };\n\n if (!quiet && format === 'text') {\n logger.info(\n `drift watch: polling every ${intervalSecs}s — ${loaded.project.name} → ${profile.account}`,\n );\n logger.info('Press Ctrl+C to stop.');\n }\n\n const postToWebhook = async (event: Record<string, unknown>): Promise<void> => {\n if (!webhookUrl) return;\n try {\n const res = await fetch(webhookUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(event),\n });\n if (!res.ok && format === 'text') logger.warn(`Webhook POST failed: HTTP ${res.status}`);\n } catch (err) {\n if (format === 'text')\n logger.warn(`Webhook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n\n const pollOnce = async (): Promise<void> => {\n const ts = new Date().toISOString();\n try {\n const pac = await readPac(pacPath);\n const declared = new ModelSource(pacPath, pac.model);\n const live = new LiveSource(conn, scope);\n const engine = new CompareEngine();\n const result = await engine.compare(declared, live);\n const s = result.summary;\n const drifted = s.added + s.removed + s.modified;\n if (drifted > 0) {\n const event = {\n type: 'DRIFT_DETECTED',\n timestamp: ts,\n project: loaded.project.name,\n added: s.added,\n removed: s.removed,\n modified: s.modified,\n };\n if (format === 'json') process.stdout.write(JSON.stringify(event) + '\\n');\n else logger.warn(`[${ts}] DRIFT_DETECTED +${s.added} -${s.removed} ~${s.modified}`);\n await postToWebhook(event);\n } else if (!quiet) {\n if (format === 'json')\n process.stdout.write(\n JSON.stringify({ type: 'CLEAN', timestamp: ts, project: loaded.project.name }) +\n '\\n',\n );\n else logger.info(`[${ts}] clean`);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (format === 'json')\n process.stdout.write(\n JSON.stringify({ type: 'POLL_ERROR', timestamp: ts, error: message }) + '\\n',\n );\n else logger.error(`[${ts}] poll error: ${message}`);\n }\n };\n\n await pollOnce();\n const timer = setInterval(() => {\n void pollOnce();\n }, intervalSecs * 1000);\n process.once('SIGINT', () => {\n clearInterval(timer);\n void conn.disconnect().then(() => process.exit(0));\n });\n await new Promise<void>(() => {});\n });\n return sub;\n}\n\nexport function driftCommand(): Command {\n const cmd = new Command('drift');\n cmd\n .description(\n 'Check whether a live Snowflake target has drifted from the project pac or a dbt manifest.',\n )\n .option('-p, --project <path>', 'Path to .sdtproj (required unless --vs-dbt-project is used)')\n .option(\n '--vs-dbt-project <path>',\n 'Compare a compiled dbt project (or target/manifest.json) against the live target. ' +\n 'Run `dbt compile` first. When set, --project is not required.',\n )\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .option(\n '--anomalies',\n 'Also classify drift via the anomaly detector (new grants to PUBLIC, bypass-role grants, owner changes, audit-column drops, mask removals, new bypass-named roles).',\n false,\n )\n .option(\n '--anomalies-only',\n 'Skip the simple drift summary and emit only the anomaly report. Implies --anomalies.',\n false,\n )\n .option(\n '--fail-on-anomaly <severity>',\n 'Exit non-zero when any anomaly at or above this severity fires. Values: critical | high | medium | low. Default: drift presence alone determines exit code.',\n );\n // Logical-name mapping (`--map`, `--map-file`) — rewrites declared-side\n // FQNs so a project authored against DEV names can be drift-checked\n // against a PROD target. See docs/LOGICAL_NAME_MAPPING.md. Mirrors\n // `ddt drift` (RH3.2 parity).\n addMappingFlags(cmd);\n cmd.action(async (opts) => {\n if (!opts.project && !opts.vsDBtProject) {\n logger.error('Provide either --project <path> or --vs-dbt-project <path>.');\n process.exitCode = 1;\n return;\n }\n\n const nameMapping = await buildMappingFromOptions(opts);\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n\n let declared: CompareSource;\n let scope: { database?: string; schema?: string };\n\n if (opts.vsDBtProject) {\n declared = new DbtManifestSource(String(opts.vsDBtProject), `dbt:${opts.vsDBtProject}`);\n scope = {};\n } else {\n const loaded = await loadProject(String(opts.project));\n const pacPath = path.join(loaded.rootDir, 'bin', `${loaded.project.name}.sdtpac`);\n const pac = await readPac(pacPath);\n declared = new ModelSource(pacPath, pac.model);\n scope = {\n database: loaded.project.scope.database,\n schema: loaded.project.scope.schema,\n };\n }\n\n const live = new LiveSource(conn, scope);\n const engine = new CompareEngine();\n const result = await engine.compare(declared, live, {\n ...(nameMapping ? { nameMapping } : {}),\n });\n const drifted = result.summary.added + result.summary.removed + result.summary.modified;\n if (!opts.anomaliesOnly) {\n if (drifted === 0) {\n logger.success('No drift detected.');\n } else {\n logger.warn(\n `Drift: +${result.summary.added} -${result.summary.removed} ~${result.summary.modified}`,\n );\n process.exitCode = 1;\n }\n }\n\n if (opts.anomalies || opts.anomaliesOnly) {\n const report = driftAnomaly.detectAnomalies(result);\n if (report.totalAnomalies === 0) {\n logger.info('Anomaly scan: 0 findings.');\n } else {\n logger.warn(`Anomaly scan: ${report.totalAnomalies} finding(s):`);\n for (const a of report.anomalies) {\n logger.info(` [${a.severity}] ${a.category}: ${a.fqn} — ${a.reason}`);\n }\n const failOn = (opts.failOnAnomaly as string | undefined)?.toLowerCase();\n if (failOn && ['critical', 'high', 'medium', 'low'].includes(failOn)) {\n const failRank = driftAnomaly.anomalySeverityRank(failOn as driftAnomaly.AnomalySeverity);\n const triggered = report.anomalies.some(\n (a) => driftAnomaly.anomalySeverityRank(a.severity) <= failRank,\n );\n if (triggered) process.exitCode = 1;\n }\n }\n }\n await conn.disconnect();\n });\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n ]);\n cmd.addCommand(driftWatchSubcommand());\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n catalog,\n project,\n validate as validateNs,\n variables as variablesNs,\n} from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\n/**\n * `sdt validate` — schema-shape sanity check on a `.sdtproj`. Default\n * mode confirms the project file parses, scope resolves, and object\n * files discover successfully. The `--references` flag adds the\n * Microsoft-SSDT-style build-time semantic resolution: every object reference in every\n * project body is classified as resolved / dangling / external /\n * temporary / dynamic, with warnings for unresolved references.\n *\n * Column-level resolution is Phase 2 (BACKLOG-tracked).\n */\nexport function validateCommand(): Command {\n const cmd = new Command('validate');\n cmd\n .description(\n 'Validate a .sdtproj — schema check; optionally resolve every object reference (--references).',\n )\n .requiredOption('-p, --project <path>', 'Path to .sdtproj')\n .option(\n '--references',\n 'Run the build-time semantic resolver — flag dangling/external/temp/dynamic references.',\n )\n .option(\n '--columns',\n '[--references] Also resolve every column reference. ERROR on missing column on a known table. Phase 2 of the SSDT-build-equivalent resolver.',\n )\n .option(\n '--min-severity <s>',\n '[--references] Filter findings: error | warning | info. Default info.',\n 'info',\n )\n .option('--format <fmt>', '[--references] table | json. Default table.', 'table')\n .option('-o, --out <path>', '[--references] Write report to file instead of stdout.')\n .option(\n '--check-variables',\n 'VARSYNTAX.4 — refuse if any `$(VAR)` reference in a tracked `.sql` file is not declared in built-ins / deploymentProfiles[*].variables. Exits 1 when undeclared references are found.',\n )\n .action(async (opts) => {\n const loaded = await project.loadProject(String(opts.project));\n const files = await project.discoverObjectFiles(loaded);\n logger.success(`Project ${loaded.project.name} v${loaded.project.version} is valid.`);\n logger.dim(\n ` Scope: ${loaded.project.scope.type}${loaded.project.scope.database ? '/' + loaded.project.scope.database : ''}`,\n );\n logger.dim(` Files: ${files.length}`);\n logger.dim(` Profiles: ${Object.keys(loaded.project.deploymentProfiles ?? {}).length}`);\n\n if (opts.checkVariables) {\n const projRoot = path.dirname(path.resolve(String(opts.project)));\n // RH4.3 — bounded-concurrency reads (cap FDs on large projects).\n // stopOnError preserves the prior Promise.all reject-on-first-error\n // semantics; results stay dense + in input order.\n const { results } = await catalog.mapPool(\n files,\n async (f) => {\n const relPath = path.relative(projRoot, f).split(path.sep).join('/');\n const content = await fs.readFile(f, 'utf8');\n return { path: relPath, content };\n },\n { concurrency: 16, stopOnError: true },\n );\n const fileContents = results.filter(\n (r): r is { path: string; content: string } => r !== undefined,\n );\n const profilesBlock = loaded.project.deploymentProfiles ?? {};\n const profileVariableKeys = Object.values(profilesBlock).map((p) =>\n Object.keys(p.variables ?? {}),\n );\n const report = variablesNs.checkVariableReferences({\n files: fileContents,\n deploymentProfileVariables: profileVariableKeys,\n });\n if (report.undeclared.length > 0) {\n const msg = variablesNs.formatCheckVariablesReport(report);\n process.stdout.write(msg + '\\n');\n process.exitCode = 1;\n return;\n }\n logger.dim(` Variables: ${report.references.length} reference(s), all declared.`);\n }\n\n if (!opts.references) return;\n\n logger.dim('');\n logger.dim('Resolving references…');\n const model = await project.parseProjectModel(loaded);\n const report = validateNs.validateProject(model, {\n source: String(opts.project),\n minSeverity: opts.minSeverity as validateNs.BuildSeverity,\n columns: Boolean(opts.columns),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n const payload =\n fmt === 'json' ? JSON.stringify(report, null, 2) : validateNs.formatBuildReport(report);\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n logger.dim(`Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n // Non-zero exit when at least one ERROR-severity finding fires so\n // `sdt validate --references` can gate a CI step.\n if (report.totals.error > 0) process.exitCode = 1;\n });\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n ]);\n return cmd;\n}\n","import { Command } from 'commander';\nimport {\n getProfile,\n loadProfiles,\n removeProfile,\n SnowflakeConnection,\n upsertProfile,\n type ConnectionProfile,\n} from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\n\nexport function connectionCommand(): Command {\n const cmd = new Command('connection');\n cmd.description('Manage Snowflake connection profiles.');\n\n cmd\n .command('list')\n .description('List configured connection profiles.')\n .action(async () => {\n const profiles = await loadProfiles();\n if (!profiles.length) {\n logger.dim('(no profiles configured — run `sdt connection add` to add one)');\n return;\n }\n for (const p of profiles) {\n logger.info(\n ` ${p.name.padEnd(20)} ${p.account.padEnd(28)} ${p.auth.method} as ${p.auth.username}`,\n );\n }\n });\n\n cmd\n .command('add')\n .description('Add or replace a connection profile.')\n .requiredOption('--name <name>', 'Profile name')\n .requiredOption('--account <account>', 'Snowflake account locator (e.g. xy12345.us-east-1)')\n .requiredOption('--user <user>', 'Snowflake username')\n .option(\n '--auth <method>',\n 'Auth method: PASSWORD | KEY_PAIR | OAUTH | EXTERNAL_BROWSER | MFA',\n 'PASSWORD',\n )\n .option('--password <value>', 'Password or env:VAR_NAME placeholder')\n .option('--key <path>', 'Path to RSA private key (for KEY_PAIR auth)')\n .option('--key-passphrase <value>', 'Passphrase or env:VAR_NAME placeholder')\n .option('--role <role>', 'Default role')\n .option('--warehouse <wh>', 'Default warehouse')\n .option('--database <db>', 'Default database')\n .option('--schema <schema>', 'Default schema')\n .action(async (opts) => {\n const auth = String(opts.auth).toUpperCase() as ConnectionProfile['auth']['method'];\n let authBlock: ConnectionProfile['auth'];\n switch (auth) {\n case 'PASSWORD':\n if (!opts.password) throw new Error('--password is required for PASSWORD auth');\n authBlock = {\n method: 'PASSWORD',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n case 'KEY_PAIR':\n if (!opts.key) throw new Error('--key is required for KEY_PAIR auth');\n authBlock = {\n method: 'KEY_PAIR',\n username: String(opts.user),\n privateKeyPath: String(opts.key),\n privateKeyPassphrase: opts.keyPassphrase ? String(opts.keyPassphrase) : undefined,\n };\n break;\n case 'OAUTH':\n if (!opts.password)\n throw new Error('--password (token, or env:VAR) is required for OAUTH auth');\n authBlock = {\n method: 'OAUTH',\n username: String(opts.user),\n token: String(opts.password),\n };\n break;\n case 'EXTERNAL_BROWSER':\n authBlock = { method: 'EXTERNAL_BROWSER', username: String(opts.user) };\n break;\n case 'MFA':\n if (!opts.password) throw new Error('--password is required for MFA auth');\n authBlock = {\n method: 'MFA',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n default:\n throw new Error(`Unsupported auth method: ${auth}`);\n }\n const profile: ConnectionProfile = {\n name: String(opts.name),\n account: String(opts.account),\n auth: authBlock,\n role: opts.role ? String(opts.role) : undefined,\n warehouse: opts.warehouse ? String(opts.warehouse) : undefined,\n database: opts.database ? String(opts.database) : undefined,\n schema: opts.schema ? String(opts.schema) : undefined,\n };\n await upsertProfile(profile);\n logger.success(`Saved profile \"${profile.name}\".`);\n });\n\n cmd\n .command('remove')\n .description('Remove a connection profile.')\n .argument('<name>')\n .action(async (name) => {\n const ok = await removeProfile(String(name));\n if (ok) logger.success(`Removed profile \"${name}\".`);\n else logger.warn(`No profile named \"${name}\".`);\n });\n\n cmd\n .command('test')\n .description('Test connectivity for a profile.')\n .argument('<name>')\n .action(async (name) => {\n const profile = await getProfile(String(name));\n const conn = new SnowflakeConnection(profile);\n try {\n const result = await conn.test();\n logger.success(`OK — Snowflake ${result.version}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\n\n/**\n * Placeholder factory for commands whose backing engine is a later\n * deliverable. Prints a clear \"not yet implemented\" message and exits\n * non-zero so CI notices.\n *\n * Mirrors `ddt scaffold` — exported for embedders, not wired into the\n * SDT CLI itself.\n */\nexport function scaffoldCommand(name: string): Command {\n return new Command(name)\n .description(`${name} — Snowflake (scaffold; later-release deliverable).`)\n .action(() => {\n console.error(\n `sdt ${name}: scaffold — the Snowflake engine for this command is a later deliverable.\\n` +\n `Track progress at Snowflake/docs/ROADMAP.md.`,\n );\n process.exitCode = 2;\n });\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { compare, pac, project } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt graph` — emit an object-dependency DAG (Mermaid or DOT) from a\n * `.sdtproj` or `.sdtpac`. Lets reviewers see blast radius before a\n * drop. Inspired by DBeaver's \"Object References\" panel — but at the\n * cross-object level rather than column level.\n *\n * With `--compare-to <other-source>`, diffs the two graphs and (when\n * `--explain` is on) narrates the DAG changes in plain English — the\n * AI Phase 6 \"lineage explanation\" surface.\n *\n * Mirrors `ddt graph`.\n */\nexport function graphCommand(): Command {\n const cmd = new Command('graph');\n cmd\n .description('Build an object-dependency DAG and emit it as Mermaid or DOT.')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--format <fmt>',\n 'mermaid | dot | md (Mermaid wrapped in a markdown fenced block)',\n 'mermaid',\n )\n .option('--json', 'Emit the raw { nodes, edges } JSON instead of a renderer.', false)\n .option(\n '--compare-to <path>',\n 'A second .sdtproj or .sdtpac. When set, emit added / removed / changed nodes + edges (the DAG delta) instead of the static graph.',\n )\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const graph = compare.buildDependencyGraph(model);\n\n let diff: compare.DependencyGraphDiff | undefined;\n if (opts.compareTo) {\n const otherModel = await loadModel(String(opts.compareTo));\n const otherGraph = compare.buildDependencyGraph(otherModel);\n // Source = \"after\", compareTo = \"before\" → the user is asking\n // \"what did the source side add vs the reference snapshot?\"\n diff = compare.diffDependencyGraphs(otherGraph, graph);\n }\n\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n let payload: string;\n if (opts.json) {\n payload = JSON.stringify(diff ?? graph, null, 2);\n } else if (diff) {\n payload = renderDiffMarkdown(diff);\n } else if (fmt === 'mermaid') {\n payload = compare.renderGraphMermaid(graph);\n } else if (fmt === 'dot') {\n payload = compare.renderGraphDot(graph);\n } else if (fmt === 'md') {\n payload = `# Schema dependency graph\\n\\n${graph.nodes.length} node(s), ${graph.edges.length} edge(s).\\n\\n\\`\\`\\`mermaid\\n${compare.renderGraphMermaid(graph)}\\n\\`\\`\\`\\n`;\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use mermaid | dot | md.`);\n }\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${graph.nodes.length} nodes, ${graph.edges.length} edges).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n await runExplain(\n {\n feature: 'graph.explain',\n systemPrompt: diff\n ? 'You are a data-platform architect narrating a dependency-graph DELTA between two snapshots. Walk through added / removed / changed nodes and edges in plain English. Call out structural shifts (new sources, dropped consumers, type changes) and likely-but-not-yet-broken downstream consequences.'\n : 'You are a data-platform architect explaining a dependency graph. Describe the dominant data-flow shape, point out hot or fragile nodes, and recommend any decomposition the graph suggests.',\n },\n opts as { explain?: boolean },\n () => (diff ? buildDiffPrompt(diff) : buildGraphPrompt(graph)),\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction renderDiffMarkdown(d: compare.DependencyGraphDiff): string {\n const lines: string[] = ['# Dependency-graph delta', ''];\n lines.push(\n `**Summary**: ${d.summary.nodeDelta >= 0 ? '+' : ''}${d.summary.nodeDelta} nodes, ` +\n `${d.summary.edgeDelta >= 0 ? '+' : ''}${d.summary.edgeDelta} edges. ` +\n `${d.addedNodes.length} added node(s), ${d.removedNodes.length} removed node(s), ` +\n `${d.changedNodes.length} changed node(s).`,\n );\n lines.push('');\n if (d.addedNodes.length > 0) {\n lines.push('## Added nodes');\n for (const n of d.addedNodes) lines.push(`- \\`${n.fqn}\\` (${n.objectType})`);\n lines.push('');\n }\n if (d.removedNodes.length > 0) {\n lines.push('## Removed nodes');\n for (const n of d.removedNodes) lines.push(`- \\`${n.fqn}\\` (${n.objectType})`);\n lines.push('');\n }\n if (d.changedNodes.length > 0) {\n lines.push('## Changed nodes (objectType)');\n for (const c of d.changedNodes) lines.push(`- \\`${c.fqn}\\`: ${c.before} → ${c.after}`);\n lines.push('');\n }\n if (d.addedEdges.length > 0) {\n lines.push('## Added edges');\n for (const e of d.addedEdges) lines.push(`- \\`${e.from}\\` → \\`${e.to}\\` (${e.kind})`);\n lines.push('');\n }\n if (d.removedEdges.length > 0) {\n lines.push('## Removed edges');\n for (const e of d.removedEdges) lines.push(`- \\`${e.from}\\` → \\`${e.to}\\` (${e.kind})`);\n }\n return lines.join('\\n');\n}\n\nfunction buildGraphPrompt(g: compare.DependencyGraph): string {\n const sample = g.edges.slice(0, 40).map((e) => ` - ${e.from} -> ${e.to}`);\n return [\n `Dependency graph: ${g.nodes.length} nodes, ${g.edges.length} edges.`,\n '',\n 'Edges (up to 40):',\n ...sample,\n '',\n 'Narrate this graph in plain English.',\n ].join('\\n');\n}\n\nfunction buildDiffPrompt(d: compare.DependencyGraphDiff): string {\n const lines: string[] = [];\n lines.push(\n `Graph delta: ${d.summary.nodeDelta >= 0 ? '+' : ''}${d.summary.nodeDelta} nodes, ` +\n `${d.summary.edgeDelta >= 0 ? '+' : ''}${d.summary.edgeDelta} edges.`,\n );\n if (d.addedNodes.length > 0) {\n lines.push('', `Added nodes (${d.addedNodes.length}, up to 20):`);\n for (const n of d.addedNodes.slice(0, 20)) lines.push(` + ${n.fqn} (${n.objectType})`);\n }\n if (d.removedNodes.length > 0) {\n lines.push('', `Removed nodes (${d.removedNodes.length}, up to 20):`);\n for (const n of d.removedNodes.slice(0, 20)) lines.push(` - ${n.fqn} (${n.objectType})`);\n }\n if (d.changedNodes.length > 0) {\n lines.push('', `Changed nodes (${d.changedNodes.length}):`);\n for (const c of d.changedNodes.slice(0, 20))\n lines.push(` ~ ${c.fqn}: ${c.before} -> ${c.after}`);\n }\n if (d.addedEdges.length > 0) {\n lines.push('', `Added edges (${d.addedEdges.length}, up to 20):`);\n for (const e of d.addedEdges.slice(0, 20)) lines.push(` + ${e.from} -> ${e.to}`);\n }\n if (d.removedEdges.length > 0) {\n lines.push('', `Removed edges (${d.removedEdges.length}, up to 20):`);\n for (const e of d.removedEdges.slice(0, 20)) lines.push(` - ${e.from} -> ${e.to}`);\n }\n lines.push(\n '',\n 'Narrate this delta in plain English. Highlight structural shifts and likely downstream consequences.',\n );\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","/**\n * `--explain` flag helper — shared across every command that produces a\n * structured report (compare, diagnose, review, impact, cost-estimate,\n * lineage, lint, pr-comment, test, …).\n *\n * Each consumer calls `attachExplainFlag(cmd, { feature, systemPrompt })`\n * during command construction, then awaits `runExplain(buildPrompt, opts)`\n * after the structured output has been printed. The helper:\n *\n * - declares the `--explain` (alias `--ai-explain`) flag,\n * - reads the configured AI provider via `@sdt-tools/core/ai`,\n * - calls `complete()` with a stable system prompt + the consumer's\n * prompt body,\n * - prints the narration to stdout under an \"AI explanation:\" header,\n * - gracefully degrades when no provider is configured (a friendly\n * hint pointing at `sdt ai status` is printed; non-zero exit code is\n * NOT set — `--explain` is best-effort decoration on top of the\n * structured output).\n *\n * Mirrors `Databricks/packages/cli/src/util/ai-explain.ts`.\n */\nimport type { Command } from 'commander';\nimport { ai } from '@sdt-tools/core';\nimport { logger } from './logger.js';\n\nexport interface ExplainContext {\n /**\n * Stable feature identifier surfaced to the AI usage telemetry so we\n * can analyze which command surfaces actually drive AI traffic.\n * Convention: `<command>.explain` (e.g. `diagnose.explain`).\n */\n feature: string;\n /**\n * System prompt setting the assistant's persona. Each command picks\n * the wording that matches its role (senior DBA / senior data eng /\n * release-manager / etc.). The default is a generic Snowflake-savvy\n * narrator suitable for most commands.\n */\n systemPrompt?: string;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are a senior Snowflake DBA reviewing structured output from the SDT CLI. Narrate it for a teammate who has not seen the underlying SQL. Be concrete and specific — reference identifiers by name. Group related items together. Skip information that is already obvious from the structured output; add the missing intent, risks, and follow-up actions. 4-10 sentences total unless the data warrants more.`;\n\n/**\n * Attach the `--explain` flag to a command. Idempotent — safe to call on\n * any command, including ones that already define `--explain`\n * (commander will throw, so we guard against double-attach).\n */\nexport function attachExplainFlag(cmd: Command, description?: string): Command {\n const hasExplain = cmd.options.some((o) => o.long === '--explain' || o.long === '--ai-explain');\n if (hasExplain) return cmd;\n cmd.option(\n '--explain',\n description ??\n 'After the structured output, call the configured AI provider to narrate the result in plain English. Requires `sdt ai` to be configured.',\n false,\n );\n return cmd;\n}\n\n/**\n * Run the AI narration step. Call this AFTER the structured output is\n * printed so the user sees the deterministic result first and the AI\n * commentary second.\n *\n * `opts.explain` is the parsed value of the `--explain` flag — when\n * falsy, this is a no-op. The consumer passes a `buildPrompt` callback\n * that returns the user message body; the callback is only invoked when\n * `--explain` is on, so consumers don't pay the prompt-construction cost\n * when AI is off.\n */\nexport async function runExplain(\n ctx: ExplainContext,\n opts: { explain?: boolean },\n buildPrompt: () => string,\n): Promise<void> {\n if (!opts.explain) return;\n const system = ctx.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n logger.info('');\n logger.info('AI explanation:');\n try {\n const reply = await ai.complete(\n [\n { role: 'system', content: system },\n { role: 'user', content: buildPrompt() },\n ],\n { feature: ctx.feature },\n );\n for (const line of reply.text.split('\\n')) logger.info(' ' + line);\n } catch (err) {\n logger.error(' --explain failed: ' + (err instanceof Error ? err.message : String(err)));\n logger.error(\n ' Run `sdt ai status` to verify your AI provider is configured (`sdt ai test` to send a probe).',\n );\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { SnowflakeQueryHistoryReader } from '@sdt-tools/core/queryHistory';\nimport { logger } from '../util/logger.js';\nimport type { QueryHistoryEntry } from '@sdt-tools/core/queryHistory';\n\n/**\n * `sdt history` — two modes.\n *\n * 1. **Manifest mode** (default) — read deploy manifests from a\n * directory (written by `sdt publish --apply --manifest <path>`)\n * and show a chronological summary.\n *\n * 2. **Live mode** (triggered by `--last`, `--query`, or `--verify`)\n * — query the Snowflake account's QUERY_HISTORY views via the\n * SnowflakeQueryHistoryReader. Requires `--connection <profile>`.\n */\ninterface Manifest {\n version: 1;\n deployedAt?: string;\n account?: string;\n warehouse?: string;\n finalState?: string;\n failedStepId?: string | null;\n steps?: Array<{\n status?: string;\n objectType?: string;\n fqn?: string;\n forwardSql?: string;\n reverseSql?: string;\n }>;\n}\n\nexport function historyCommand(): Command {\n const cmd = new Command('history');\n cmd\n .description(\n 'List deploy manifests (default) or query the live Snowflake QUERY_HISTORY views via --last/--query/--verify.',\n )\n // Manifest mode\n .option(\n '--dir <path>',\n 'Directory containing *.json manifests (manifest mode).',\n './.sdt/history',\n )\n .option(\n '--limit <n>',\n 'Manifest mode: most-recent N entries. Live mode: max rows returned.',\n '20',\n )\n .option('--json', 'Emit JSON instead of human-readable table.', false)\n .option(\n '--full-sql',\n 'Include full SQL text in the output (default: truncated to 120 chars).',\n false,\n )\n // Live mode\n .option(\n '--connection <profile>',\n 'Connection profile (required for --last / --query / --verify).',\n )\n .option('--last [n]', 'Live mode: show the N most-recent queries. Default 20.')\n .option('--query <id>', 'Live mode: look up a single query by its QUERY_ID.')\n .option(\n '--verify <tag>',\n 'Live mode: read all queries tagged with this string. Use the auto-generated tag from `sdt publish --apply` for deploy verification.',\n )\n .option('--since <iso>', 'Live mode: only include entries after this ISO 8601 timestamp.')\n .option(\n '--view <kind>',\n \"Live mode: which view to query — 'session' | 'user' | 'account'. Default 'session'.\",\n 'session',\n )\n .action(\n async (opts: {\n dir?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n connection?: string;\n last?: boolean | string;\n query?: string;\n verify?: string;\n since?: string;\n view?: string;\n }) => {\n const isLive =\n opts.last !== undefined || opts.query !== undefined || opts.verify !== undefined;\n if (isLive) {\n await runLive(opts);\n } else {\n await runManifests(opts);\n }\n },\n );\n return cmd;\n}\n\nasync function runManifests(opts: {\n dir?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n}): Promise<void> {\n const dir = path.resolve(String(opts.dir ?? './.sdt/history'));\n let files: string[];\n try {\n const entries = await fs.readdir(dir);\n files = entries.filter((f) => f.endsWith('.json')).map((f) => path.join(dir, f));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(\n `No history directory at ${dir}. Pass --dir <path> or pipe deploys to write manifests there.`,\n );\n process.exitCode = 1;\n return;\n }\n throw err;\n }\n\n const entries: Array<{ path: string; mtime: Date; manifest: Manifest }> = [];\n for (const f of files) {\n try {\n const raw = await fs.readFile(f, 'utf8');\n const m = JSON.parse(raw) as Manifest;\n const stat = await fs.stat(f);\n entries.push({ path: f, mtime: stat.mtime, manifest: m });\n } catch {\n // skip files that don't parse\n }\n }\n entries.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n const limit = parseInt(String(opts.limit ?? 20), 10);\n const visible = entries.slice(0, limit > 0 ? limit : entries.length);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n visible.map((e) => ({ path: e.path, mtime: e.mtime.toISOString(), ...e.manifest })),\n null,\n 2,\n ),\n );\n return;\n }\n\n if (visible.length === 0) {\n console.log(`No manifests found in ${dir}.`);\n return;\n }\n console.log(`History: ${visible.length} of ${entries.length} deploys at ${dir}`);\n console.log('');\n console.log(\n ' DEPLOYED AT ACCOUNT FINAL STATE STEPS',\n );\n console.log(\n ' ─────────────────── ────────────────────────────────── ────────────────── ─────',\n );\n for (const e of visible) {\n const m = e.manifest;\n const when = m.deployedAt\n ? new Date(m.deployedAt).toISOString().slice(0, 19).replace('T', ' ')\n : e.mtime.toISOString().slice(0, 19).replace('T', ' ');\n const host = (m.account ?? '?').padEnd(34).slice(0, 34);\n const state = (m.finalState ?? '?').padEnd(18).slice(0, 18);\n const succ = m.steps?.filter((s) => s.status === 'SUCCESS').length ?? 0;\n const tot = m.steps?.length ?? 0;\n console.log(` ${when} ${host} ${state} ${succ}/${tot}`);\n if (opts.fullSql) {\n for (const s of m.steps ?? []) {\n if (s.forwardSql) console.log(` [forward] ${s.fqn ?? ''}\\n${indent(s.forwardSql, 8)}`);\n }\n }\n }\n console.log('');\n console.log(\n `Pass --json for machine-readable output, --limit <n> to control depth, --full-sql to expand each step.`,\n );\n}\n\nasync function runLive(opts: {\n connection?: string;\n last?: boolean | string;\n query?: string;\n verify?: string;\n since?: string;\n view?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n}): Promise<void> {\n if (!opts.connection) {\n logger.error('Live history mode requires --connection <profile>.');\n process.exitCode = 1;\n return;\n }\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n await conn.connect();\n try {\n const view = String(opts.view ?? 'session').toLowerCase() as 'session' | 'user' | 'account';\n const reader = new SnowflakeQueryHistoryReader(conn, { defaultView: view });\n const limit = Math.max(1, parseInt(String(opts.limit ?? '20'), 10) || 20);\n const since = opts.since ? new Date(opts.since) : undefined;\n\n let entries: QueryHistoryEntry[] = [];\n if (opts.query) {\n const e = await reader.readById(String(opts.query));\n entries = e ? [e] : [];\n } else if (opts.verify) {\n entries = await reader.readByTag(String(opts.verify), {\n ...(since ? { since } : {}),\n limit,\n });\n } else {\n // --last [n]\n const n = typeof opts.last === 'string' ? parseInt(opts.last, 10) || limit : limit;\n // Reuse readByUser with the current user; if that's not set on the\n // reader, the underlying view still respects the current session's\n // user via INFORMATION_SCHEMA semantics.\n entries = await reader.readByUser(profile.auth.username ?? '', {\n ...(since ? { since } : {}),\n limit: n,\n });\n }\n\n if (opts.json) {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n renderEntries(entries, Boolean(opts.fullSql));\n } finally {\n await conn.disconnect();\n }\n}\n\nfunction renderEntries(entries: readonly QueryHistoryEntry[], fullSql: boolean): void {\n if (entries.length === 0) {\n console.log('No matching queries found.');\n return;\n }\n console.log(`${entries.length} quer${entries.length === 1 ? 'y' : 'ies'}:`);\n console.log('');\n console.log(' STARTED STATUS DURATION USER QUERY_ID');\n console.log(\n ' ─────────────────── ──────── ──────── ───────────────────── ────────────────────────────',\n );\n for (const e of entries) {\n const when = e.startedAt.slice(0, 19).replace('T', ' ');\n const status = e.status.toUpperCase().padEnd(8);\n const dur = `${e.durationMs}ms`.padEnd(8);\n const user = (e.user ?? '?').padEnd(20).slice(0, 20);\n console.log(` ${when} ${status} ${dur} ${user} ${e.queryId}`);\n const sql = fullSql ? e.sqlText : truncate(e.sqlText, 120);\n if (sql)\n console.log(\n ` ${sql\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)\n .join(' ')}`,\n );\n if (e.queryTag) console.log(` tag: ${e.queryTag}`);\n if (e.errorMessage) console.log(` ERROR: ${e.errorMessage}`);\n }\n}\n\nfunction indent(text: string, n: number): string {\n const pad = ' '.repeat(n);\n return text\n .split('\\n')\n .map((l) => pad + l)\n .join('\\n');\n}\n\nfunction truncate(s: string, max: number): string {\n if (!s) return '';\n const collapsed = s.replace(/\\s+/g, ' ').trim();\n if (collapsed.length <= max) return collapsed;\n return collapsed.slice(0, max - 1) + '…';\n}\n","import { Command } from 'commander';\nimport { pac } from '@sdt-tools/core';\n\n/**\n * `sdt verify <pac>` — recompute checksums and confirm the .sdtpac is\n * intact. Catches tampering / corruption / partial-extraction\n * accidents. Sets up the Enterprise-tier signing chain — a signed pac\n * is `verify` + `signature-check` together.\n */\nexport function verifyCommand(): Command {\n const cmd = new Command('verify');\n cmd\n .description('Recompute checksums on a .sdtpac and confirm every object matches the manifest.')\n .requiredOption('--pac <path>', 'Path to the .sdtpac to verify.')\n .option('--json', 'Emit JSON instead of human-readable output.', false)\n .action(async (opts) => {\n const contents = await pac.readPac(String(opts.pac));\n const expected = contents.checksums;\n const actual = pac.computeChecksums(contents.model);\n\n const missing: string[] = [];\n const mismatched: Array<{ id: string; expected: string; actual: string }> = [];\n const orphaned: string[] = [];\n\n const expectedIds = new Set(Object.keys(expected));\n const actualIds = new Set(Object.keys(actual));\n for (const id of expectedIds) {\n if (!actualIds.has(id)) {\n missing.push(id);\n continue;\n }\n if (expected[id] !== actual[id]) {\n mismatched.push({ id, expected: expected[id]!, actual: actual[id]! });\n }\n }\n for (const id of actualIds) {\n if (!expectedIds.has(id)) orphaned.push(id);\n }\n\n const ok = missing.length === 0 && mismatched.length === 0 && orphaned.length === 0;\n if (opts.json) {\n console.log(\n JSON.stringify(\n { ok, missing, mismatched, orphaned, objectCount: contents.model.length },\n null,\n 2,\n ),\n );\n } else {\n console.log(`Pac: ${opts.pac}`);\n console.log(\n `Project: ${contents.manifest.projectName} v${contents.manifest.projectVersion}`,\n );\n console.log(\n `Built: ${contents.manifest.builtAt} by ${contents.manifest.builtBy.name} ${contents.manifest.builtBy.version}`,\n );\n console.log(`Objects: ${contents.model.length}`);\n console.log('');\n if (ok) {\n console.log('✓ verify OK — every checksum matches.');\n } else {\n console.log('✗ verify FAILED');\n if (missing.length > 0) {\n console.log(` missing checksums (${missing.length}):`);\n for (const id of missing) console.log(` ${id}`);\n }\n if (mismatched.length > 0) {\n console.log(` mismatched (${mismatched.length}):`);\n for (const m of mismatched)\n console.log(\n ` ${m.id} expected=${m.expected.slice(0, 12)}… actual=${m.actual.slice(0, 12)}…`,\n );\n }\n if (orphaned.length > 0) {\n console.log(` orphaned (in model but not in checksums) (${orphaned.length}):`);\n for (const id of orphaned) console.log(` ${id}`);\n }\n }\n }\n if (!ok) process.exitCode = 1;\n });\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\n/**\n * `sdt install-hooks` — install a git pre-commit hook that runs\n * `sdt format --check` + `sdt validate` before allowing a commit.\n *\n * Husky-style: writes a single shell script to `.git/hooks/pre-commit`\n * that delegates to the CLI. Refuses to overwrite an existing hook\n * unless --force.\n */\nconst HOOK_MARKER = '# sdt-managed-hook';\n\nconst HOOK_BODY = `#!/bin/sh\n${HOOK_MARKER} — installed by \\`sdt install-hooks\\`. Remove this hook or re-install with --force to update.\n\n# Find the project file relative to the repo root.\nproject=$(find . -maxdepth 3 -name '*.sdtproj' -not -path '*/node_modules/*' -not -path '*/dist/*' | head -1)\nif [ -z \"$project\" ]; then\n echo \"sdt pre-commit hook: no .sdtproj found (skipping).\"\n exit 0\nfi\n\necho \"sdt pre-commit: validate + format-check on $project\"\n\nif ! command -v sdt >/dev/null 2>&1; then\n echo \"sdt CLI not on PATH. Install with \\`npm i -g @sdt-tools/cli\\`, or remove the hook at .git/hooks/pre-commit.\"\n exit 1\nfi\n\nif ! sdt validate -p \"$project\"; then\n echo \"\"\n echo \"Refusing commit: \\`sdt validate\\` failed.\"\n exit 1\nfi\n\nif ! sdt format -p \"$project\" --check; then\n echo \"\"\n echo \"Refusing commit: some .sql files are not formatted. Run \\`sdt format -p $project\\` and re-stage.\"\n exit 1\nfi\n`;\n\nexport function installHooksCommand(): Command {\n const cmd = new Command('install-hooks');\n cmd\n .description(\n 'Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit.',\n )\n .option('--force', 'Overwrite an existing hook (refuses by default if the file exists).', false)\n .option('--uninstall', 'Remove the sdt-managed pre-commit hook instead of installing.', false)\n .action(async (opts) => {\n const cwd = process.cwd();\n const gitDir = await findGitDir(cwd);\n if (!gitDir) {\n throw new Error(`No .git directory found at or above ${cwd}.`);\n }\n const hookPath = path.join(gitDir, 'hooks', 'pre-commit');\n\n if (opts.uninstall) {\n if (!existsSync(hookPath)) {\n console.log('No pre-commit hook installed.');\n return;\n }\n const existing = await fs.readFile(hookPath, 'utf8');\n if (!existing.includes(HOOK_MARKER)) {\n console.error(\n `Refusing to remove: ${hookPath} is not a sdt-managed hook (missing marker).`,\n );\n process.exitCode = 1;\n return;\n }\n await fs.unlink(hookPath);\n console.log(`Removed ${hookPath}.`);\n return;\n }\n\n if (existsSync(hookPath) && !opts.force) {\n const existing = await fs.readFile(hookPath, 'utf8');\n if (existing.includes(HOOK_MARKER)) {\n console.log(`Hook already installed at ${hookPath}. Re-run with --force to overwrite.`);\n } else {\n console.error(`Refusing to overwrite: ${hookPath} exists and is NOT a sdt-managed hook.`);\n console.error('Inspect it, then re-run with --force if you want to replace it.');\n process.exitCode = 1;\n }\n return;\n }\n\n await fs.mkdir(path.dirname(hookPath), { recursive: true });\n await fs.writeFile(hookPath, HOOK_BODY, { mode: 0o755 });\n console.log(`Installed pre-commit hook at ${hookPath}.`);\n console.log(' Runs `sdt validate` + `sdt format --check` on every commit.');\n console.log(\n ' Bypass once with `git commit --no-verify`. Remove with `sdt install-hooks --uninstall`.',\n );\n });\n return cmd;\n}\n\nasync function findGitDir(start: string): Promise<string | undefined> {\n let dir = path.resolve(start);\n while (true) {\n const candidate = path.join(dir, '.git');\n if (existsSync(candidate)) {\n const stat = await fs.stat(candidate);\n if (stat.isDirectory()) return candidate;\n const ptr = await fs.readFile(candidate, 'utf8');\n const m = ptr.match(/^gitdir:\\s*(.+)$/m);\n if (m && m[1]) {\n const resolved = path.isAbsolute(m[1]) ? m[1] : path.resolve(dir, m[1]);\n return resolved;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n PacSource,\n ProjectSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { ScriptGenerator, colorizeMigrationScript } from '@sdt-tools/core/deploy';\nimport { mergeDeployOptions, loadProject } from '@sdt-tools/core/project';\nimport { readPac } from '@sdt-tools/core/pac';\nimport { safety } from '@sdt-tools/core';\nimport type { DeploymentProfile } from '@sdt-tools/core/project';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\n/**\n * `sdt script` — generate a deploy SQL script for source → target. Mirrors\n * SqlPackage `/Action:Script` / SSDT's \"Generate Script\" affordance. Always\n * offline — does not touch a live Snowflake account.\n *\n * Output formats:\n * - sql (default): human-readable migration script with banner comments\n * - json: raw CompareResult + safety assessment + per-statement\n * metadata, suitable for CI gates or UI rendering\n *\n * Mirrors `ddt script`. To compare against a live account, use\n * `sdt compare` or `sdt publish`.\n */\nexport function scriptCommand(): Command {\n const cmd = new Command('script');\n cmd\n .description(\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the account.',\n )\n .requiredOption('--source <path>', 'Source: .sdtproj or .sdtpac (the desired state).')\n .requiredOption('--target <path>', 'Target: .sdtproj or .sdtpac (the current state).')\n .option('-o, --out <path>', 'Write the script to <path>. Defaults to stdout.')\n .option('--format <fmt>', 'sql | json', 'sql')\n .option('--variables <kv>', 'Comma-separated KEY=VALUE pairs for $(VAR) substitution.')\n .option(\n '--profile <name>',\n 'VARSYNTAX.5 — look up `deploymentProfiles[<name>].variables` from the --source artifact (`.sdtproj` reads `project.deploymentProfiles`; `.sdtpac` reads `manifest.deploymentProfiles`) and substitute `$(VAR)` references at script-emission time. `--variables` overrides on key collision.',\n )\n .option('--ignore-case', 'Compare object FQNs case-insensitively.', false)\n .option('--banner <text>', 'Banner line prepended to the script.')\n .option(\n '--color <mode>',\n 'Color stdout: auto | always | never. Honors NO_COLOR / SDT_NO_COLOR env vars in auto mode. Files written via -o are never colorized.',\n 'auto',\n );\n addMappingFlags(cmd);\n cmd.action(async (opts) => {\n const format = String(opts.format ?? 'sql').toLowerCase();\n if (format !== 'sql' && format !== 'json') {\n throw new Error(`Unknown --format: ${opts.format}. Use sql or json.`);\n }\n const nameMapping = await buildMappingFromOptions(opts);\n const source = await sourceFor(String(opts.source), 'source');\n const target = await sourceFor(String(opts.target), 'target');\n const engine = new CompareEngine();\n const result = await engine.compare(source, target, {\n ignoreCase: !!opts.ignoreCase,\n ...(nameMapping ? { nameMapping } : {}),\n });\n\n const deployment = mergeDeployOptions().deployment;\n const cliVariables = parseVariables(opts.variables);\n\n // VARSYNTAX.5 — resolve --profile <name> from the --source artifact's\n // deploymentProfiles bag (if present), merge with --variables CLI\n // override (CLI wins on key collision). Also gather the project context\n // (name / version) so VARSYNTAX.3 built-ins (`$(SDT_PROFILE)`,\n // `$(SDT_PROJECT_NAME)`, `$(SDT_PROJECT_VERSION)`, …) auto-populate.\n let profileVariables: Record<string, string> | undefined;\n let ctxProjectName: string | undefined;\n let ctxProjectVersion: string | undefined;\n const sourcePath = String(opts.source);\n if (opts.profile || sourcePath.endsWith('.sdtproj') || sourcePath.endsWith('.sdtpac')) {\n try {\n if (sourcePath.endsWith('.sdtpac')) {\n const srcPac = await readPac(sourcePath);\n ctxProjectName = srcPac.manifest.projectName;\n ctxProjectVersion = srcPac.manifest.projectVersion;\n if (opts.profile) {\n const block: DeploymentProfile | undefined =\n srcPac.manifest.deploymentProfiles?.[String(opts.profile)];\n if (!block) {\n const available = Object.keys(srcPac.manifest.deploymentProfiles ?? {});\n throw new Error(\n `--profile ${String(opts.profile)}: no deploymentProfile by that name in the --source pac manifest. ` +\n (available.length === 0\n ? 'The pac carries no deploymentProfiles (was it built before VARSYNTAX.2, or does the .sdtproj declare any?).'\n : `Available: ${available.join(', ')}.`),\n );\n }\n if (block.variables) profileVariables = { ...block.variables };\n }\n } else if (sourcePath.endsWith('.sdtproj')) {\n const loaded = await loadProject(sourcePath);\n ctxProjectName = loaded.project.name;\n ctxProjectVersion = loaded.project.version;\n if (opts.profile) {\n const block: DeploymentProfile | undefined =\n loaded.project.deploymentProfiles?.[String(opts.profile)];\n if (!block) {\n const available = Object.keys(loaded.project.deploymentProfiles ?? {});\n throw new Error(\n `--profile ${String(opts.profile)}: no deploymentProfile by that name in the --source .sdtproj. ` +\n (available.length === 0\n ? 'The project declares no deploymentProfiles.'\n : `Available: ${available.join(', ')}.`),\n );\n }\n if (block.variables) profileVariables = { ...block.variables };\n }\n }\n } catch (e) {\n // If the user passed --profile, hard-fail. Otherwise best-effort:\n // built-ins stay defaulted on a partial / unreadable source.\n if (opts.profile) throw e;\n }\n }\n const variables =\n profileVariables || cliVariables\n ? { ...(profileVariables ?? {}), ...(cliVariables ?? {}) }\n : undefined;\n\n const generator = new ScriptGenerator();\n const script = generator.generate(result, {\n deployment,\n ...(variables ? { variables } : {}),\n ...(opts.banner ? { banner: String(opts.banner) } : {}),\n context: {\n ...(opts.profile ? { profile: String(opts.profile) } : {}),\n ...(ctxProjectName ? { projectName: ctxProjectName } : {}),\n ...(ctxProjectVersion ? { projectVersion: ctxProjectVersion } : {}),\n },\n });\n const assessment = safety.assess(result);\n\n let payload: string;\n if (format === 'json') {\n payload = JSON.stringify(\n {\n source: result.source,\n target: result.target,\n summary: { ...result.summary, ...script.summary },\n safety: assessment,\n statements: script.statements,\n },\n null,\n 2,\n );\n } else {\n const header = [\n `-- ${assessment.blocked ? 'BLOCKED: ' + assessment.blockReason : 'Generated by sdt script'}`,\n `-- unrecoverable=${assessment.unrecoverable.length} destructive=${assessment.destructive.length} expensive=${assessment.expensive.length} warnings=${assessment.warnings.length}`,\n '',\n ].join('\\n');\n payload = header + script.sql;\n }\n\n if (opts.out) {\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${outPath} (${payload.length} bytes).`);\n } else {\n // Colorize stdout for SQL only — JSON stays raw so downstream tools can\n // parse it. ANSI escapes are stripped when stdout is not a TTY (auto mode).\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n const rendered =\n format === 'sql' ? colorizeMigrationScript(payload, { mode: colorMode }) : payload;\n process.stdout.write(rendered);\n if (!rendered.endsWith('\\n')) process.stdout.write('\\n');\n }\n if (assessment.blocked) {\n process.exitCode = 2;\n }\n });\n return cmd;\n}\n\nasync function sourceFor(filePath: string, label: string): Promise<CompareSource> {\n return filePath.endsWith('.sdtpac')\n ? new PacSource(filePath, label)\n : new ProjectSource(filePath, label);\n}\n\nfunction parseVariables(raw: unknown): Record<string, string> | undefined {\n if (!raw) return undefined;\n const out: Record<string, string> = {};\n for (const pair of String(raw).split(',')) {\n const [k, v] = pair.split('=');\n if (k && v !== undefined) out[k.trim()] = v.trim();\n }\n return out;\n}\n","import { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport {\n SnowflakeExecutor,\n revertStepsFromManifest,\n type DeployManifest,\n} from '@sdt-tools/core/deploy';\n\n/**\n * `sdt revert --manifest <path>` — undo a previous deploy by executing\n * each step's `reverseSql` in reverse order. Manifests come from\n * `sdt publish --apply --manifest <path>` (the JSON deploy manifest\n * captured after `--apply`).\n *\n * Steps without `reverseSql` are inherently irreversible (DROP, etc.)\n * and skipped with a clear warning. The command exits non-zero if any\n * reverse fails or if any step was irreversible (the user must inspect\n * by hand).\n *\n * Mirrors `Databricks/packages/cli/src/commands/revert.ts`. Use case: a\n * deploy succeeded but something downstream broke; revert it. Use case:\n * drift is detected and you need to roll back to the last-known-good\n * state.\n */\nexport function revertCommand(): Command {\n const cmd = new Command('revert');\n cmd\n .description(\n 'Replay a previous deploy manifest in reverse, executing reverseSql for each successful step.',\n )\n .requiredOption(\n '--manifest <path>',\n 'Path to a JSON deploy manifest from `sdt publish --apply --manifest`.',\n )\n .requiredOption(\n '--connection <name>',\n 'Connection profile to revert against. Should match the original deploy.',\n )\n .requiredOption('--yes', 'Explicit confirmation. Required because revert is destructive.')\n .option(\n '--continue-on-error',\n 'Continue past failed reverse statements. Default: stop on first failure.',\n false,\n )\n .option('--dry-run', 'Print what would be reverted without executing.', false)\n .action(async (opts) => {\n const raw = await fs.readFile(String(opts.manifest), 'utf8');\n const manifest = JSON.parse(raw) as DeployManifest;\n if (manifest.version !== 1) {\n throw new Error(\n `Unsupported manifest version: ${manifest.version}. This CLI understands v1.`,\n );\n }\n\n const profile = await getProfile(String(opts.connection));\n if (profile.account !== manifest.account) {\n console.error('');\n console.error(\n `WARNING: manifest's account (${manifest.account}) doesn't match the profile's account (${profile.account}).`,\n );\n console.error(\n 'Reverting against a different account than the original deploy may have unintended effects.',\n );\n console.error('Re-run with the correct --connection, or proceed carefully.');\n console.error('');\n }\n\n // Reverse-iterate; only successful steps need undoing.\n const reverseSteps = revertStepsFromManifest(manifest);\n\n console.log(`Reverting ${reverseSteps.length} step(s) from ${opts.manifest}`);\n console.log(`Original deploy: ${manifest.deployedAt} → ${manifest.account}`);\n console.log('');\n\n if (opts.dryRun) {\n for (const s of reverseSteps) {\n const tag = s.reverseSql ? '↩' : '⚠';\n console.log(`${tag} ${s.objectType} ${s.fqn}`);\n if (s.reverseSql) {\n console.log(` ${s.reverseSql.split('\\n')[0]?.slice(0, 100) ?? ''}`);\n } else {\n console.log(` (no reverseSql — IRREVERSIBLE; would be skipped)`);\n }\n }\n const skippable = reverseSteps.filter((s) => !s.reverseSql).length;\n console.log('');\n console.log(\n `Dry-run summary: ${reverseSteps.length - skippable} reversible, ${skippable} irreversible.`,\n );\n return;\n }\n\n const conn = new SnowflakeConnection(profile);\n let succeeded = 0;\n let failed = 0;\n let irreversible = 0;\n try {\n await conn.connect();\n const executor = new SnowflakeExecutor(conn);\n for (const s of reverseSteps) {\n if (!s.reverseSql) {\n console.log(`⚠ skip ${s.objectType} ${s.fqn} — irreversible (no reverseSql captured)`);\n irreversible++;\n continue;\n }\n process.stdout.write(`↩ ${s.objectType} ${s.fqn} …`);\n const t0 = Date.now();\n try {\n await executor.execute(s.reverseSql);\n console.log(` ✓ (${Date.now() - t0}ms)`);\n succeeded++;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.log(` ✗ ${msg}`);\n failed++;\n if (!opts.continueOnError) {\n console.error('');\n console.error('Stopping on first failure. Use --continue-on-error to push through.');\n break;\n }\n }\n }\n } finally {\n await conn.disconnect();\n }\n\n console.log('');\n console.log(\n `Summary: ${succeeded} reverted, ${failed} failed, ${irreversible} irreversible.`,\n );\n if (failed > 0 || irreversible > 0) process.exitCode = 1;\n });\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { SnowflakeExecutor } from '@sdt-tools/core/deploy';\nimport { discoverSeeds, loadProject, renderSeedMerge } from '@sdt-tools/core/project';\n\n/**\n * `sdt seed` — declare static reference rows next to DDL; engine\n * generates MERGE statements to keep them in sync.\n *\n * Mirrors `Databricks/packages/cli/src/commands/seed.ts`. Subcommands:\n * list enumerate seed files + row counts\n * render -p <project> emit MERGEs to stdout (offline)\n * apply -p <project> -c <conn> execute the MERGEs against an account\n */\nexport function seedCommand(): Command {\n const cmd = new Command('seed').description(\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n );\n\n cmd\n .command('list')\n .description('Enumerate seed files under <project>/seeds/.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n if (seeds.length === 0) {\n console.log(\n 'No seeds found. Add files under <project>/seeds/<database>/<schema>/<table>.{json,csv}.',\n );\n return;\n }\n for (const s of seeds) {\n console.log(\n ` ${s.database}.${s.schema}.${s.table.padEnd(28)} ${String(s.rows.length).padStart(5)} rows keys=[${s.keys.join(', ')}]`,\n );\n }\n console.log('');\n console.log(`${seeds.length} seed(s).`);\n });\n\n cmd\n .command('render')\n .description('Emit MERGE statements for every seed file. Offline; no account contact.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .option('-o, --out <path>', 'Write to file. Defaults to stdout.')\n .option(\n '--delete-not-in-source',\n 'Prepend a DELETE so target-only rows are removed (Snowflake equivalent of WHEN NOT MATCHED BY SOURCE). Default off (safer).',\n false,\n )\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n const renderOpts = { deleteNotInSource: !!opts.deleteNotInSource };\n const sql = seeds.map((s) => renderSeedMerge(s, renderOpts)).join('\\n\\n') + '\\n';\n if (opts.out) {\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, sql, 'utf8');\n console.error(`Wrote ${outPath} (${sql.length} bytes, ${seeds.length} seed(s)).`);\n } else {\n process.stdout.write(sql);\n }\n });\n\n cmd\n .command('apply')\n .description('Execute every seed MERGE against a connection profile.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .requiredOption('--connection <name>', 'Connection profile to apply against.')\n .requiredOption('--yes', 'Explicit confirmation. Required because apply writes data.')\n .option('--dry-run', 'Print the MERGEs without executing.', false)\n .option(\n '--delete-not-in-source',\n 'Prepend a DELETE so target-only rows are removed (Snowflake equivalent of WHEN NOT MATCHED BY SOURCE). Default off (safer).',\n false,\n )\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n if (seeds.length === 0) {\n console.log('No seeds found. Nothing to apply.');\n return;\n }\n const renderOpts = { deleteNotInSource: !!opts.deleteNotInSource };\n if (opts.dryRun) {\n for (const s of seeds) console.log(renderSeedMerge(s, renderOpts) + '\\n');\n return;\n }\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n let succeeded = 0;\n let failed = 0;\n try {\n await conn.connect();\n const exec = new SnowflakeExecutor(conn);\n for (const s of seeds) {\n process.stdout.write(`▶ ${s.database}.${s.schema}.${s.table} (${s.rows.length} rows) …`);\n const t0 = Date.now();\n try {\n await exec.execute(renderSeedMerge(s, renderOpts));\n console.log(` ✓ (${Date.now() - t0}ms)`);\n succeeded++;\n } catch (err) {\n console.log(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n failed++;\n }\n }\n } finally {\n await conn.disconnect();\n }\n console.log('');\n console.log(`Summary: ${succeeded} succeeded, ${failed} failed.`);\n if (failed > 0) process.exitCode = 1;\n });\n\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport { randomUUID } from 'node:crypto';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { lineage, pac, project, columnLineage } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * CLL.7-followup runtime: thread CLI flags + `.sdt/lineage.json` config\n * through the OpenLineage substrate. Exported so vitest can drive it\n * directly with a stub fetchImpl + readFile (no real network / disk).\n */\nexport interface EmitOpenLineageCliInputs {\n dag: columnLineage.ColumnLineageDag;\n endpointFlag?: string;\n configPath?: string;\n namespace?: string;\n jobNamespace?: string;\n job?: string;\n /**\n * OpenLineage emit mode. `auto` resolves to `per-event` when the\n * built events array has ≤ AUTO_MODE_THRESHOLD entries, `batch`\n * otherwise. Resolution happens at the CLI layer; the substrate\n * only ever sees the concrete `per-event` or `batch`.\n */\n mode?: 'per-event' | 'batch' | 'auto';\n /** OpenLineage event type (subset of the spec enum). Default `COMPLETE`. */\n eventType?: 'START' | 'RUNNING' | 'COMPLETE' | 'ABORT' | 'FAIL' | 'OTHER';\n /**\n * Override the event timestamp (ISO 8601). Default: now() at emit time.\n * Useful for backfill — historical pipeline runs replayed into Marquez/\n * OpenMetadata keep their original eventTime instead of being collapsed\n * onto \"now\".\n */\n eventTime?: string;\n /** Per-request timeout in ms (positive integer; 0/negative/NaN are ignored). */\n timeoutMs?: number;\n token?: string;\n /** Override OpenLineage producer URL identifying the emitting tool. */\n producer?: string;\n /** Repeatable `name=value` strings from `--emit-openlineage-header`. */\n headerArgs?: readonly string[];\n runId?: string;\n dryRun?: boolean;\n /** Persist built events JSON to this path on disk (audit / replay). */\n eventsOutPath?: string;\n /**\n * Output format for the events-out file. `json` (default) writes the\n * familiar `{events: [...]}` wrapper with pretty-printed indentation;\n * `jsonl` writes one event per line (newline-delimited JSON) for\n * streaming-ingest pipelines (Vector / Fluent Bit / OpenTelemetry\n * collectors / Snowflake VARIANT loaders).\n */\n eventsOutFormat?: 'json' | 'jsonl';\n /** Skip the POST when the events array is empty (no DAG produced 0 events). */\n skipEmpty?: boolean;\n /**\n * Refuse to emit when the built events count is below this threshold.\n * Returns `ok: false` with `MIN_EVENTS_NOT_MET`. CI-friendly guard\n * against silent lineage gaps — a refactor that accidentally bypasses\n * column-lineage extraction would otherwise quietly emit zero events\n * and pass the build.\n */\n minEvents?: number;\n sourceHint?: string;\n}\n\nconst VALID_OL_EVENT_TYPES = new Set<EmitOpenLineageCliInputs['eventType']>([\n 'START',\n 'RUNNING',\n 'COMPLETE',\n 'ABORT',\n 'FAIL',\n 'OTHER',\n]);\n\n/**\n * Validate `--emit-openlineage-event-type <value>` against the OL enum.\n * Returns the upper-cased value when valid. Throws with operator-facing\n * message when unknown — the action handler surfaces the throw as exit\n * code 1 (uncaught throw from commander action) which is the same\n * convention used by other input-validation throws in this CLI.\n */\nexport function validateEventType(raw: string): EmitOpenLineageCliInputs['eventType'] {\n const upper = raw.toUpperCase() as EmitOpenLineageCliInputs['eventType'];\n if (!VALID_OL_EVENT_TYPES.has(upper)) {\n throw new Error(\n `--emit-openlineage-event-type ${JSON.stringify(raw)} is not a valid OpenLineage event type. ` +\n `Use one of: ${[...VALID_OL_EVENT_TYPES].join(', ')}.`,\n );\n }\n return upper;\n}\n\n/**\n * Threshold at which `--emit-openlineage-mode auto` flips from\n * `per-event` (one HTTP POST per event, easier to debug in the\n * collector UI) to `batch` (single POST with `{events: [...]}`,\n * amortizes HTTP overhead). Operators with non-default cost or\n * latency requirements can still force the mode explicitly.\n */\nexport const AUTO_MODE_THRESHOLD = 10;\n\n/**\n * Resolve `mode: 'auto'` based on the built events count. Returns the\n * concrete `per-event` / `batch` value; pass-through for non-auto.\n */\nexport function resolveAutoMode(\n mode: 'per-event' | 'batch' | 'auto',\n eventCount: number,\n): 'per-event' | 'batch' {\n if (mode !== 'auto') return mode;\n return eventCount <= AUTO_MODE_THRESHOLD ? 'per-event' : 'batch';\n}\n\n/**\n * Validate `--emit-openlineage-mode <value>` against per-event / batch / auto.\n * Returns the lower-cased value when valid. Throws with operator-facing\n * message on unknown.\n */\nexport function validateMode(raw: string): 'per-event' | 'batch' | 'auto' {\n const lower = raw.toLowerCase();\n if (lower !== 'per-event' && lower !== 'batch' && lower !== 'auto') {\n throw new Error(\n `--emit-openlineage-mode ${JSON.stringify(raw)} is not valid. ` +\n `Use one of: per-event, batch, auto.`,\n );\n }\n return lower as 'per-event' | 'batch' | 'auto';\n}\n\n/**\n * Validate `--emit-openlineage-events-out-format <fmt>` value. Returns\n * the lower-cased value when valid (`json` or `jsonl`). Throws with\n * operator-facing message when unknown.\n */\nexport function validateEventsOutFormat(raw: string): 'json' | 'jsonl' {\n const lower = raw.toLowerCase();\n if (lower !== 'json' && lower !== 'jsonl') {\n throw new Error(\n `--emit-openlineage-events-out-format ${JSON.stringify(raw)} is not valid. ` +\n `Use one of: json, jsonl.`,\n );\n }\n return lower;\n}\n\n/**\n * Validate `--emit-openlineage-event-time <iso>` as a parseable timestamp.\n * Returns the canonical ISO 8601 form (`new Date(raw).toISOString()`) so\n * the value emitted in every OL event is normalized regardless of input\n * shape (`2026-05-18T20:00:00Z` and `2026-05-18T16:00:00-04:00` both\n * normalize to the same UTC instant). Throws with operator-facing\n * message on invalid input.\n */\nexport function validateEventTime(raw: string): string {\n const parsed = new Date(raw);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(\n `--emit-openlineage-event-time ${JSON.stringify(raw)} is not a valid ISO 8601 timestamp. ` +\n `Examples: 2026-05-18T20:00:00Z, 2026-05-18T16:00:00-04:00.`,\n );\n }\n return parsed.toISOString();\n}\n\n/**\n * Parse `--emit-openlineage-header name=value` repeatable strings into\n * an `{name: value}` record. Splits on the first `=` only so values\n * containing `=` (e.g. base64-encoded tokens) survive. Strings missing\n * `=` or with empty name are skipped with a stderr note.\n */\nexport function parseHeaderArgs(\n args: readonly string[] | undefined,\n stderr: (chunk: string) => void = () => {},\n): Record<string, string> {\n const out: Record<string, string> = {};\n if (!args || args.length === 0) return out;\n for (const raw of args) {\n const eq = raw.indexOf('=');\n if (eq <= 0) {\n stderr(\n `Ignoring malformed --emit-openlineage-header value ${JSON.stringify(raw)} (expected name=value).\\n`,\n );\n continue;\n }\n const name = raw.slice(0, eq).trim();\n const value = raw.slice(eq + 1);\n if (!name) {\n stderr(`Ignoring --emit-openlineage-header with empty name.\\n`);\n continue;\n }\n out[name] = value;\n }\n return out;\n}\n\nexport interface EmitOpenLineageCliDeps {\n readFile?: (p: string) => Promise<string>;\n writeFile?: (p: string, data: string) => Promise<void>;\n env?: Record<string, string | undefined>;\n fetchImpl?: typeof fetch;\n now?: () => Date;\n uuid?: () => string;\n stdout?: (chunk: string) => void;\n stderr?: (chunk: string) => void;\n}\n\nexport interface EmitOpenLineageCliOutcome {\n ok: boolean;\n events: number;\n succeeded?: number;\n failed?: number;\n error?: { code: string; message: string };\n}\n\nexport async function emitOpenLineageFromCli(\n inputs: EmitOpenLineageCliInputs,\n deps: EmitOpenLineageCliDeps = {},\n): Promise<EmitOpenLineageCliOutcome> {\n const stdout = deps.stdout ?? ((c: string) => process.stdout.write(c));\n const stderr = deps.stderr ?? ((c: string) => process.stderr.write(c));\n const readFile = deps.readFile ?? ((p: string) => fs.readFile(p, 'utf8'));\n const writeFile =\n deps.writeFile ??\n (async (p: string, data: string) => {\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, data, 'utf8');\n });\n const env = deps.env ?? (process.env as Record<string, string | undefined>);\n const now = deps.now ?? (() => new Date());\n const uuid = deps.uuid ?? (() => randomUUID());\n\n let loaded: columnLineage.OpenLineageConfig | undefined;\n const configPath = inputs.configPath ?? columnLineage.DEFAULT_OPENLINEAGE_CONFIG_FILE_REL;\n try {\n const raw = await readFile(configPath);\n const json = JSON.parse(raw);\n const parsed = columnLineage.parseOpenLineageConfig(json);\n if (!parsed.config) {\n const lines = parsed.errors.map((e) => ` - ${e.path}: ${e.message}`);\n stderr(`Failed to parse ${configPath}:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_PARSE_FAILED', message: `${configPath} did not validate` },\n };\n }\n loaded = parsed.config;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') {\n stderr(`Failed reading ${configPath}: ${(err as Error).message}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_READ_FAILED', message: (err as Error).message },\n };\n }\n // Missing config file is fine when the CLI flag supplies the endpoint.\n }\n\n const overrides: Partial<columnLineage.OpenLineageConfig> = {};\n if (inputs.endpointFlag) overrides.endpoint = inputs.endpointFlag;\n if (inputs.namespace) overrides.datasetNamespace = inputs.namespace;\n if (inputs.jobNamespace) overrides.jobNamespace = inputs.jobNamespace;\n if (inputs.job) overrides.jobName = inputs.job;\n // `auto` is a CLI-layer mode resolved AFTER buildOpenLineageEvents\n // based on events.length. Don't push it to the substrate; the\n // substrate's mode is always per-event or batch.\n if (inputs.mode && inputs.mode !== 'auto') overrides.mode = inputs.mode;\n if (\n typeof inputs.timeoutMs === 'number' &&\n Number.isFinite(inputs.timeoutMs) &&\n inputs.timeoutMs > 0\n ) {\n overrides.timeoutMs = Math.floor(inputs.timeoutMs);\n }\n if (inputs.token) overrides.bearerToken = inputs.token;\n if (inputs.producer && inputs.producer.trim().length > 0)\n overrides.producer = inputs.producer.trim();\n const cliHeaders = parseHeaderArgs(inputs.headerArgs, stderr);\n if (Object.keys(cliHeaders).length > 0) overrides.headers = cliHeaders;\n const merged = columnLineage.mergeOpenLineageCliOverrides(loaded, overrides);\n\n const validated = columnLineage.validateOpenLineageConfig(merged);\n if (!validated.ok) {\n const lines = validated.errors.map((e) => ` - ${e.path}: ${e.message}`);\n stderr(`OpenLineage emit refused:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_INCOMPLETE', message: validated.errors[0]!.message },\n };\n }\n\n const resolved = columnLineage.resolveEnvPlaceholders(validated.resolved, env);\n if (!resolved.ok) {\n const lines = resolved.missing.map((m) => ` - ${m.path}: missing env var ${m.envKey}`);\n stderr(`OpenLineage env placeholders unresolved:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'ENV_UNRESOLVED', message: resolved.missing[0]!.envKey },\n };\n }\n const final = resolved.resolved;\n\n const jobName = final.jobName ?? inputs.sourceHint ?? 'sdt-lineage';\n const eventType = inputs.eventType ?? 'COMPLETE';\n const events = columnLineage.buildOpenLineageEvents(inputs.dag, {\n runId: inputs.runId ?? uuid(),\n jobName,\n jobNamespace: final.jobNamespace ?? columnLineage.DEFAULT_OPENLINEAGE_JOB_NAMESPACE,\n ...(final.datasetNamespace ? { datasetNamespace: final.datasetNamespace } : {}),\n ...(final.producer ? { producer: final.producer } : {}),\n eventTime: inputs.eventTime ?? now().toISOString(),\n eventType,\n });\n\n if (inputs.eventsOutPath) {\n const format = inputs.eventsOutFormat ?? 'json';\n const payload =\n format === 'jsonl'\n ? events.map((e) => JSON.stringify(e)).join('\\n') + '\\n'\n : JSON.stringify({ events }, null, 2) + '\\n';\n await writeFile(inputs.eventsOutPath, payload);\n stderr(\n `OpenLineage: wrote ${events.length} event(s) to ${inputs.eventsOutPath} (${format}).\\n`,\n );\n }\n\n // CI guard: fail before dry-run / POST when events.length is below\n // the operator-supplied threshold. Catches silent lineage gaps after\n // a refactor that bypasses column-lineage extraction.\n if (\n typeof inputs.minEvents === 'number' &&\n Number.isFinite(inputs.minEvents) &&\n inputs.minEvents > 0 &&\n events.length < inputs.minEvents\n ) {\n stderr(\n `OpenLineage: built ${events.length} event(s), below --emit-openlineage-min-events=${inputs.minEvents}; refusing to emit.\\n`,\n );\n return {\n ok: false,\n events: events.length,\n error: {\n code: 'MIN_EVENTS_NOT_MET',\n message: `built ${events.length} events, expected >= ${inputs.minEvents}`,\n },\n };\n }\n\n if (inputs.dryRun) {\n stdout(JSON.stringify({ events }, null, 2) + '\\n');\n return { ok: true, events: events.length };\n }\n\n if (events.length === 0 && inputs.skipEmpty) {\n stderr(\n 'OpenLineage: 0 events to emit (DAG empty) and --emit-openlineage-skip-empty set; skipping POST.\\n',\n );\n return { ok: true, events: 0, succeeded: 0, failed: 0 };\n }\n\n // Resolve `mode: auto` AFTER buildOpenLineageEvents so the decision\n // sees the actual events count. Substrate's `final.mode` is always\n // per-event / batch — auto only lives at the CLI layer.\n const concreteMode: 'per-event' | 'batch' =\n inputs.mode === 'auto' ? resolveAutoMode('auto', events.length) : (final.mode ?? 'per-event');\n if (inputs.mode === 'auto') {\n stderr(\n `OpenLineage: --emit-openlineage-mode=auto resolved to ${concreteMode} ` +\n `(${events.length} event(s), threshold=${AUTO_MODE_THRESHOLD}).\\n`,\n );\n }\n\n const result = await columnLineage.emitOpenLineageEvents(events, final.endpoint!, {\n ...(final.bearerToken ? { bearerToken: final.bearerToken } : {}),\n ...(final.headers ? { headers: final.headers } : {}),\n mode: concreteMode,\n ...(typeof final.timeoutMs === 'number' ? { timeoutMs: final.timeoutMs } : {}),\n ...(deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}),\n });\n stderr(\n `OpenLineage: ${result.succeeded}/${result.totalEvents} events delivered to ${final.endpoint} (${result.failed} failed).\\n`,\n );\n return {\n ok: result.failed === 0,\n events: result.totalEvents,\n succeeded: result.succeeded,\n failed: result.failed,\n };\n}\n\n/**\n * `sdt lineage` — extract data-flow lineage from a `.sdtproj` or\n * `.sdtpac` and emit it as Mermaid, DOT, JSON, or Markdown.\n *\n * Distinct from `sdt graph`: graph is FQN-level dependency edges\n * (A references B). Lineage adds direction-of-data-flow classification\n * (READS_FROM vs WRITES_TO), upstream/downstream traversal, and\n * column-level best-effort tagging for view SELECT lists.\n *\n * Use cases:\n * - \"What does ANALYTICS.GOLD.CUSTOMER_360 depend on?\" (upstream slice)\n * - \"If I drop RAW.STAGING.ORDERS_RAW, what breaks?\" (downstream slice)\n * - \"Embed this graph in our PR template / docs / dashboard.\"\n *\n * Mirrors `ddt lineage`.\n */\nexport function lineageCommand(): Command {\n const cmd = new Command('lineage');\n cmd\n .description('Extract data-flow lineage from a .sdtproj, .sdtpac, or dbt manifest.json.')\n .option('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--dbt-manifest <path>',\n 'Extract column-level lineage from a dbt target/manifest.json (or project root).',\n )\n .option(\n '--fqn <name>',\n 'Focus on this fully-qualified name; restrict the graph to its upstream + downstream slice.',\n )\n .option(\n '--direction <kind>',\n 'When --fqn is set, restrict to upstream | downstream | both. Default both.',\n 'both',\n )\n .option('--depth <n>', 'Max traversal depth from --fqn. Default unbounded.', (v) =>\n parseInt(v, 10),\n )\n .option('--format <fmt>', 'mermaid | dot | json | markdown. Default mermaid.', 'mermaid')\n .option('--columns', 'Include best-effort column-level lineage for view SELECT lists.', false)\n .option(\n '--column-dag',\n 'Build a true per-column DAG via the CLL.1/2/3 substrate. Walks every VIEW / SECURE_VIEW / MATERIALIZED_VIEW / DYNAMIC_TABLE body in the project model, extracts column-level lineage, assembles the DAG, and emits Mermaid (default) or JSON. Composes with --fqn (focus to one object) and --out.',\n false,\n )\n .option('--max-edges <n>', 'Truncate large graphs at this edge count.', (v) => parseInt(v, 10))\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--emit-openlineage [endpoint]',\n 'CLL.7-followup: emit the column DAG as OpenLineage RunEvents to the given collector URL. When the flag is given without a value, the endpoint from .sdt/lineage.json is used. Requires --column-dag (or --dbt-manifest).',\n )\n .option(\n '--emit-openlineage-config <path>',\n 'Override the config-file location (default .sdt/lineage.json).',\n )\n .option(\n '--emit-openlineage-namespace <ns>',\n 'Override the OpenLineage dataset namespace (default snowflake).',\n )\n .option(\n '--emit-openlineage-job-namespace <ns>',\n 'Override the OpenLineage job.namespace (default sdt). Groups jobs across deployments in Marquez/OpenMetadata.',\n )\n .option(\n '--emit-openlineage-job <name>',\n 'Override the OpenLineage job.name (default derived from --source).',\n )\n .option(\n '--emit-openlineage-mode <mode>',\n 'OpenLineage emit mode: per-event (default) | batch | auto. `auto` resolves to per-event when the DAG has ≤10 events (easier to debug in Marquez UI) and batch when >10 (amortizes HTTP overhead).',\n )\n .option(\n '--emit-openlineage-timeout-ms <ms>',\n 'Override per-request timeout (positive integer, default 10000ms).',\n (v) => parseInt(v, 10),\n )\n .option(\n '--emit-openlineage-token <token>',\n 'Override bearer token (supports env:VAR_NAME for indirection).',\n )\n .option(\n '--emit-openlineage-header <k=v>',\n 'Extra HTTP header attached to every OpenLineage POST (repeatable). Format: name=value. Values support env:VAR_NAME for indirection.',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[],\n )\n .option(\n '--emit-openlineage-producer <url>',\n 'Override the OpenLineage producer URL (identifies the emitting tool to the collector). Default: https://github.com/GVOrganization/SDT.',\n )\n .option(\n '--emit-openlineage-event-type <type>',\n 'OpenLineage event type: COMPLETE (default), START, RUNNING, ABORT, FAIL, or OTHER. Use START + COMPLETE pairs (sharing --emit-openlineage-run-id) for run-lifecycle modelling.',\n )\n .option(\n '--emit-openlineage-event-time <iso>',\n 'Override the OpenLineage eventTime (ISO 8601). Default: now() at emit time. Use for backfill — replay historical pipeline runs into Marquez/OpenMetadata with their original timestamps instead of \"now\".',\n )\n .option(\n '--emit-openlineage-run-id <id>',\n 'Stable runId (UUID v4). Default: generated per invocation.',\n )\n .option(\n '--emit-openlineage-dry-run',\n 'Build OpenLineage events but do not POST — print the events JSON to stdout instead.',\n false,\n )\n .option(\n '--emit-openlineage-events-out <path>',\n 'Also write the built events JSON to <path> (audit / replay). Independent of --dry-run; combined yields write-only-no-POST.',\n )\n .option(\n '--emit-openlineage-events-out-format <fmt>',\n 'Output format for --emit-openlineage-events-out: json (default, `{events: [...]}` wrapper) or jsonl (newline-delimited, one event per line). Use jsonl for streaming-ingest pipelines (Vector, Fluent Bit, OpenTelemetry collectors, Snowflake VARIANT loaders).',\n )\n .option(\n '--emit-openlineage-skip-empty',\n 'Skip the POST when the built events array is empty (default behavior is to still hit the collector with 0 events in batch mode). Useful in CI when lineage extraction may produce an empty DAG and noisy 0-event traffic is undesirable.',\n false,\n )\n .option(\n '--emit-openlineage-min-events <n>',\n 'CI assertion: refuse to emit (exit 2) when the built events count is below this threshold. Catches silent lineage gaps after a refactor that bypasses column-lineage extraction. Skip-empty composes naturally — set min-events=1 to force every run to produce ≥1 event.',\n (v) => parseInt(v, 10),\n )\n .action(async (opts) => {\n // CLL.7-followup guard (iter 193): refuse --emit-openlineage when\n // neither --column-dag nor --dbt-manifest is in play, because the\n // default FQN-level lineage path doesn't produce a column DAG and\n // the OL columnLineage facet would be empty. Silent-no-op here was\n // a footgun — operators forgetting --column-dag got 0 events.\n if (opts.emitOpenlineage && !opts.columnDag && !opts.dbtManifest) {\n process.stderr.write(\n '--emit-openlineage requires --column-dag (CLL.2 DAG) or --dbt-manifest. ' +\n 'The default FQN-level lineage path has no column-level facet to emit. ' +\n 'Re-run with --column-dag --source <path> or --dbt-manifest <path>.\\n',\n );\n process.exitCode = 2;\n return;\n }\n\n // CLL.4: column-DAG mode — uses CLL.1/2/3 substrate, distinct from\n // the FQN-graph `--columns` hint above.\n if (opts.columnDag) {\n if (!opts.source) throw new Error('--column-dag requires --source <path>.');\n const model = await loadModel(String(opts.source));\n const inputs = collectColumnLineageInputs(model);\n const dag = columnLineage.buildColumnLineageDag(inputs);\n let renderedDag = dag;\n if (opts.fqn) {\n const focus = String(opts.fqn);\n const direction = String(opts.direction ?? 'both').toLowerCase() as\n | 'upstream'\n | 'downstream'\n | 'both';\n renderedDag = columnLineage.sliceColumnDag(dag, focus, direction);\n }\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n if (!['mermaid', 'json'].includes(fmt)) {\n throw new Error(`--column-dag only supports --format mermaid|json (got ${fmt}).`);\n }\n const payload =\n fmt === 'json'\n ? JSON.stringify(columnLineage.renderDagJson(renderedDag), null, 2)\n : columnLineage.renderDagMermaid(renderedDag);\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + '\\n', 'utf8');\n console.error(\n `Wrote ${out} (${renderedDag.nodes.size} nodes, ${renderedDag.edges.length} edges).`,\n );\n } else if (!opts.emitOpenlineage) {\n // Suppress stdout emission when we're piping into the OL --dry-run\n // path so the events JSON is the only thing on stdout.\n process.stdout.write(payload + '\\n');\n }\n if (opts.emitOpenlineage) {\n const endpointFlag =\n typeof opts.emitOpenlineage === 'string' && opts.emitOpenlineage.length > 0\n ? String(opts.emitOpenlineage)\n : undefined;\n const sourceHint = opts.source\n ? path.basename(String(opts.source)).replace(/\\.(sdtproj|sdtpac)$/i, '')\n : undefined;\n const outcome = await emitOpenLineageFromCli({\n dag: renderedDag,\n ...(endpointFlag ? { endpointFlag } : {}),\n ...(opts.emitOpenlineageConfig\n ? { configPath: String(opts.emitOpenlineageConfig) }\n : {}),\n ...(opts.emitOpenlineageNamespace\n ? { namespace: String(opts.emitOpenlineageNamespace) }\n : {}),\n ...(opts.emitOpenlineageJobNamespace\n ? { jobNamespace: String(opts.emitOpenlineageJobNamespace) }\n : {}),\n ...(opts.emitOpenlineageJob ? { job: String(opts.emitOpenlineageJob) } : {}),\n ...(opts.emitOpenlineageMode\n ? { mode: validateMode(String(opts.emitOpenlineageMode)) }\n : {}),\n ...(opts.emitOpenlineageEventType\n ? { eventType: validateEventType(String(opts.emitOpenlineageEventType)) }\n : {}),\n ...(opts.emitOpenlineageEventTime\n ? { eventTime: validateEventTime(String(opts.emitOpenlineageEventTime)) }\n : {}),\n ...(typeof opts.emitOpenlineageTimeoutMs === 'number'\n ? { timeoutMs: opts.emitOpenlineageTimeoutMs }\n : {}),\n ...(opts.emitOpenlineageToken ? { token: String(opts.emitOpenlineageToken) } : {}),\n ...(opts.emitOpenlineageProducer\n ? { producer: String(opts.emitOpenlineageProducer) }\n : {}),\n ...(Array.isArray(opts.emitOpenlineageHeader) && opts.emitOpenlineageHeader.length > 0\n ? { headerArgs: opts.emitOpenlineageHeader as string[] }\n : {}),\n ...(opts.emitOpenlineageRunId ? { runId: String(opts.emitOpenlineageRunId) } : {}),\n ...(opts.emitOpenlineageDryRun ? { dryRun: true } : {}),\n ...(opts.emitOpenlineageEventsOut\n ? { eventsOutPath: String(opts.emitOpenlineageEventsOut) }\n : {}),\n ...(opts.emitOpenlineageEventsOutFormat\n ? {\n eventsOutFormat: validateEventsOutFormat(\n String(opts.emitOpenlineageEventsOutFormat),\n ),\n }\n : {}),\n ...(opts.emitOpenlineageSkipEmpty ? { skipEmpty: true } : {}),\n ...(typeof opts.emitOpenlineageMinEvents === 'number' &&\n opts.emitOpenlineageMinEvents > 0\n ? { minEvents: opts.emitOpenlineageMinEvents }\n : {}),\n ...(sourceHint ? { sourceHint } : {}),\n });\n if (!outcome.ok) {\n process.exitCode = 2;\n }\n }\n return;\n }\n if (opts.dbtManifest) {\n const result = await columnLineage.extractDbtManifestLineage(String(opts.dbtManifest));\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n const payload =\n fmt === 'json'\n ? columnLineage.renderDbtLineageJson(result)\n : columnLineage.renderDbtLineageMermaid(result);\n if (result.skipped.length > 0) {\n for (const s of result.skipped) console.error(`Skipped ${s.nodeId}: ${s.reason}`);\n }\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + '\\n', 'utf8');\n console.error(\n `Wrote ${out} (${result.models.length} models, ${result.skipped.length} skipped).`,\n );\n } else if (!opts.emitOpenlineage) {\n process.stdout.write(payload + '\\n');\n }\n if (opts.emitOpenlineage) {\n const dag = columnLineage.buildColumnLineageDag(\n result.models.map((m) => ({ objectFqn: m.fqn, lineage: m.lineage })),\n );\n const endpointFlag =\n typeof opts.emitOpenlineage === 'string' && opts.emitOpenlineage.length > 0\n ? String(opts.emitOpenlineage)\n : undefined;\n const sourceHint = `dbt:${path.basename(String(opts.dbtManifest)).replace(/\\.json$/i, '')}`;\n const outcome = await emitOpenLineageFromCli({\n dag,\n ...(endpointFlag ? { endpointFlag } : {}),\n ...(opts.emitOpenlineageConfig\n ? { configPath: String(opts.emitOpenlineageConfig) }\n : {}),\n ...(opts.emitOpenlineageNamespace\n ? { namespace: String(opts.emitOpenlineageNamespace) }\n : {}),\n ...(opts.emitOpenlineageJobNamespace\n ? { jobNamespace: String(opts.emitOpenlineageJobNamespace) }\n : {}),\n ...(opts.emitOpenlineageJob ? { job: String(opts.emitOpenlineageJob) } : {}),\n ...(opts.emitOpenlineageMode\n ? { mode: validateMode(String(opts.emitOpenlineageMode)) }\n : {}),\n ...(opts.emitOpenlineageEventType\n ? { eventType: validateEventType(String(opts.emitOpenlineageEventType)) }\n : {}),\n ...(opts.emitOpenlineageEventTime\n ? { eventTime: validateEventTime(String(opts.emitOpenlineageEventTime)) }\n : {}),\n ...(typeof opts.emitOpenlineageTimeoutMs === 'number'\n ? { timeoutMs: opts.emitOpenlineageTimeoutMs }\n : {}),\n ...(opts.emitOpenlineageToken ? { token: String(opts.emitOpenlineageToken) } : {}),\n ...(opts.emitOpenlineageProducer\n ? { producer: String(opts.emitOpenlineageProducer) }\n : {}),\n ...(Array.isArray(opts.emitOpenlineageHeader) && opts.emitOpenlineageHeader.length > 0\n ? { headerArgs: opts.emitOpenlineageHeader as string[] }\n : {}),\n ...(opts.emitOpenlineageRunId ? { runId: String(opts.emitOpenlineageRunId) } : {}),\n ...(opts.emitOpenlineageDryRun ? { dryRun: true } : {}),\n ...(opts.emitOpenlineageEventsOut\n ? { eventsOutPath: String(opts.emitOpenlineageEventsOut) }\n : {}),\n ...(opts.emitOpenlineageEventsOutFormat\n ? {\n eventsOutFormat: validateEventsOutFormat(\n String(opts.emitOpenlineageEventsOutFormat),\n ),\n }\n : {}),\n ...(opts.emitOpenlineageSkipEmpty ? { skipEmpty: true } : {}),\n ...(typeof opts.emitOpenlineageMinEvents === 'number' &&\n opts.emitOpenlineageMinEvents > 0\n ? { minEvents: opts.emitOpenlineageMinEvents }\n : {}),\n sourceHint,\n });\n if (!outcome.ok) {\n process.exitCode = 2;\n }\n }\n return;\n }\n if (!opts.source) throw new Error('Either --source or --dbt-manifest is required.');\n const model = await loadModel(String(opts.source));\n const fullGraph = lineage.buildLineageGraph(model);\n\n const direction = String(opts.direction ?? 'both').toLowerCase() as\n | 'upstream'\n | 'downstream'\n | 'both';\n let graph = fullGraph;\n let focus: string | undefined;\n if (opts.fqn) {\n focus = String(opts.fqn);\n const depth: number = typeof opts.depth === 'number' ? opts.depth : Infinity;\n if (direction === 'upstream') {\n const keep = new Set([focus, ...lineage.upstreamOf(fullGraph, focus, depth)]);\n graph = subsetGraph(fullGraph, keep);\n } else if (direction === 'downstream') {\n const keep = new Set([focus, ...lineage.downstreamOf(fullGraph, focus, depth)]);\n graph = subsetGraph(fullGraph, keep);\n } else {\n graph = lineage.sliceAround(fullGraph, focus, depth);\n }\n }\n\n const fmt = String(opts.format ?? 'mermaid').toLowerCase() as lineage.LineageFormat;\n if (!['mermaid', 'dot', 'json', 'markdown'].includes(fmt)) {\n throw new Error(`Unknown --format: ${fmt}. Use mermaid | dot | json | markdown.`);\n }\n const renderOpts: lineage.RenderOptions = {\n ...(focus ? { focus } : {}),\n ...(typeof opts.maxEdges === 'number' ? { maxEdges: opts.maxEdges } : {}),\n ...(opts.columns ? { includeColumns: true } : {}),\n };\n const payload = lineage.renderLineage(graph, fmt, renderOpts);\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${graph.nodes.length} nodes, ${graph.edges.length} edges).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'lineage.explain',\n systemPrompt:\n 'You are a data-platform architect explaining a lineage graph. Describe the dominant data-flow shape, point out hot or fragile nodes, and recommend any decomposition / sharding the graph suggests.',\n },\n opts as { explain?: boolean },\n () => {\n const focused = focus ? ` (focused on ${focus}, direction=${direction})` : '';\n const summary = `Lineage graph${focused}: ${graph.nodes.length} nodes, ${graph.edges.length} edges.`;\n const sample = graph.edges\n .slice(0, 40)\n .map((e) => ` - ${e.from} ${e.kind === 'READS_FROM' ? '->' : '=>'} ${e.to}`);\n return [\n summary,\n '',\n 'Edges (up to 40):',\n ...sample,\n '',\n 'Narrate this graph in plain English.',\n ].join('\\n');\n },\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction subsetGraph(graph: lineage.LineageGraph, keep: Set<string>): lineage.LineageGraph {\n return {\n nodes: graph.nodes.filter((n) => keep.has(n.fqn)),\n edges: graph.edges.filter((e) => keep.has(e.from) && keep.has(e.to)),\n };\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\n/**\n * Walk a project model collecting `{objectFqn, lineage}` pairs for every\n * object whose body parses through CLL.1's `extractColumnLineage`. Covers\n * VIEW / SECURE_VIEW / MATERIALIZED_VIEW / DYNAMIC_TABLE — the four object\n * types whose `query: SqlExpression` is what downstream consumers depend\n * on for column-level lineage. CLL.4 entry point.\n */\nfunction collectColumnLineageInputs(model: unknown): columnLineage.ColumnLineageDagInput[] {\n const inputs: columnLineage.ColumnLineageDagInput[] = [];\n const matchTypes = new Set<string>(['VIEW', 'SECURE_VIEW', 'MATERIALIZED_VIEW', 'DYNAMIC_TABLE']);\n // parseProjectModel returns AnySnowflakeObject[]; readPac().model is the\n // same shape. Some legacy pac models nest objects under .objects so we\n // accept either form defensively.\n let flat: Array<{ objectType?: string; fqn?: unknown; query?: unknown }>;\n if (Array.isArray(model)) {\n flat = model as Array<{ objectType?: string; fqn?: unknown; query?: unknown }>;\n } else if (\n model &&\n typeof model === 'object' &&\n Array.isArray((model as { objects?: unknown }).objects)\n ) {\n flat = (model as { objects: Array<{ objectType?: string; fqn?: unknown; query?: unknown }> })\n .objects;\n } else {\n flat = [];\n }\n for (const obj of flat) {\n if (!obj.objectType || !matchTypes.has(obj.objectType)) continue;\n if (typeof obj.query !== 'string' || obj.query.length === 0) continue;\n const fqn =\n typeof obj.fqn === 'string'\n ? obj.fqn\n : obj.fqn && typeof obj.fqn === 'object'\n ? formatFqn(obj.fqn as { database?: string; schema?: string; name?: string })\n : '<unknown>';\n const lineage = columnLineage.extractColumnLineage(obj.query);\n inputs.push({ objectFqn: fqn, lineage });\n }\n return inputs;\n}\n\nfunction formatFqn(fqn: { database?: string; schema?: string; name?: string }): string {\n return [fqn.database, fqn.schema, fqn.name].filter(Boolean).join('.');\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { diagnostics, interop, pac, project } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt diagnose` — project-level health report. Bundles lint, lineage\n * smells (orphan / no-downstream / hot-table / cycle), object smells\n * (`SELECT *` in views, large tables without clustering, missing PK)\n * and cost smells (warehouse without AUTO_SUSPEND, long Time Travel)\n * into one ranked report. Every finding ships with a **reasoning**\n * line explaining *why* it matters — readers learn the engineering\n * motivation, not just the patch.\n *\n * Use cases:\n * - Pre-PR check: `sdt diagnose --source <proj> --min-severity warning`\n * - Periodic project audit: weekly cron emitting JSON to a dashboard\n * - Onboarding: a new engineer reads the report to learn what good\n * looks like in this codebase\n *\n * Mirrors `ddt diagnose`.\n */\nexport function diagnoseCommand(): Command {\n const cmd = new Command('diagnose');\n cmd\n .description(\n 'Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning.',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--category <c>',\n 'Filter to one category: lint | lineage | smell | cost | dim-modeling.',\n )\n .option(\n '--min-severity <s>',\n 'Filter to a minimum severity: error | warning | info. Default info (everything).',\n 'info',\n )\n .option(\n '--format <fmt>',\n 'table | json | markdown | sarif. sarif emits SARIF 2.1.0 for GitHub code-scanning / Azure DevOps. Default table.',\n 'table',\n )\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(\n async (opts: {\n source: string;\n category?: string;\n minSeverity?: string;\n format?: string;\n out?: string;\n explain?: boolean;\n }) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const report = diagnostics.analyzeProject(model, {\n source: sourcePath,\n ...(opts.category\n ? { category: String(opts.category) as diagnostics.DiagnosticCategory }\n : {}),\n ...(opts.minSeverity\n ? { minSeverity: String(opts.minSeverity) as diagnostics.DiagnosticSeverity }\n : {}),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(report, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderReportMarkdown(report);\n } else if (fmt === 'sarif') {\n payload = JSON.stringify(interop.diagnosticReportToSarif(report), null, 2);\n } else if (fmt === 'table') {\n payload = diagnostics.formatReport(report);\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown | sarif.`);\n }\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n // Non-zero exit when at least one error-severity finding fires so\n // `sdt diagnose` can gate a CI step.\n if (report.totals.error > 0) process.exitCode = 1;\n\n await runExplain({ feature: 'diagnose.explain' }, opts, () => buildDiagnosePrompt(report));\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction buildDiagnosePrompt(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`Source: ${report.source || '(unknown)'}`);\n lines.push(\n `Totals: ${report.totals.error} error, ${report.totals.warning} warning, ${report.totals.info} info`,\n );\n lines.push('');\n const top = report.findings\n .slice()\n .sort((a, b) => sevWeight(b.severity) - sevWeight(a.severity))\n .slice(0, 40);\n lines.push(`Top ${top.length} findings (highest severity first):`);\n for (const d of top) {\n lines.push(`- [${d.severity}] ${d.id} · ${d.fqn || '(project)'} — ${d.message}`);\n }\n if (report.findings.length > top.length) {\n lines.push(`(… ${report.findings.length - top.length} more truncated)`);\n }\n lines.push('');\n lines.push(\n 'Explain the dominant themes, what they suggest about the project health, and the highest-leverage fixes the team should tackle first.',\n );\n return lines.join('\\n');\n}\n\nfunction sevWeight(s: diagnostics.DiagnosticSeverity): number {\n return s === 'error' ? 3 : s === 'warning' ? 2 : 1;\n}\n\nfunction renderReportMarkdown(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`# Diagnostic report — \\`${report.source || '(no source)'}\\``);\n lines.push('');\n lines.push(`Generated: ${report.generatedAt}`);\n lines.push('');\n lines.push(\n `**Totals:** ${report.totals.error} error · ${report.totals.warning} warning · ${report.totals.info} info`,\n );\n lines.push('');\n lines.push('## By category');\n lines.push('');\n lines.push('| Category | Count |');\n lines.push('|---|---|');\n for (const [k, v] of Object.entries(report.byCategory)) {\n if (v > 0) lines.push(`| ${k} | ${v} |`);\n }\n lines.push('');\n if (report.findings.length === 0) {\n lines.push('_No findings._');\n return lines.join('\\n');\n }\n lines.push('## Findings');\n lines.push('');\n for (const d of report.findings) {\n const glyph = d.severity === 'error' ? '🛑' : d.severity === 'warning' ? '⚠️' : 'ℹ️';\n lines.push(`### ${glyph} \\`${d.id}\\` — ${d.fqn || '(project)'}`);\n lines.push('');\n lines.push(`**${d.message}**`);\n lines.push('');\n lines.push(`*Why:* ${d.reasoning}`);\n lines.push('');\n lines.push(`*Suggestion:* ${d.suggestion}`);\n lines.push('');\n if (d.related && d.related.length > 0) {\n lines.push(\n `*Related:* ${d.related\n .slice(0, 5)\n .map((r) => `\\`${r}\\``)\n .join(', ')}`,\n );\n lines.push('');\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { ai, aiReview, pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt review` — produce a senior-DBA Markdown report combining lint,\n * lineage findings, smell findings, cost findings, and safety\n * reasoning. The deliverable a reviewer can paste straight into a PR\n * or an architecture-review meeting.\n *\n * Default mode (project health): pure composition of existing modules —\n * every finding's reasoning + suggestion is generated by\n * `@sdt-tools/core/diagnostics`; the format is the value-add.\n *\n * `--senior-dba` mode (AI Phase 4): takes a compare-result JSON\n * (typically the output of `sdt compare --json`) + a safety-summary\n * JSON + optional target-metadata snapshot + truncated DDL preview,\n * asks the configured AI provider for a senior-DBA verdict, and emits\n * the parsed result as Markdown (or JSON via `--format json`).\n */\nexport function reviewCommand(): Command {\n const cmd = new Command('review');\n cmd\n .description(\n 'Senior-DBA-style health report (lint + lineage + smell + cost + safety, with reasoning).',\n )\n .option('--source <path>', '.sdtproj or .sdtpac to analyze (project-health mode).')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--senior-dba',\n 'AI-driven senior-DBA review of a deploy diff (requires --diff and --safety).',\n false,\n )\n .option(\n '--diff <path>',\n 'JSON file with compare summary { added, removed, modified, addedSample, removedSample, modifiedSample }.',\n )\n .option(\n '--safety <path>',\n 'JSON file with safety summary { unrecoverable, destructive, expensive, warning, sample }.',\n )\n .option(\n '--target-meta <path>',\n 'Optional file with target-metadata prose (existing tables, recent deploys, role grants).',\n )\n .option('--ddl <path>', 'Optional truncated DDL preview file.')\n .option('--format <fmt>', 'Output format: markdown | json. Default markdown.', 'markdown')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the AI call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(\n async (opts: {\n source?: string;\n out?: string;\n explain?: boolean;\n seniorDba?: boolean;\n diff?: string;\n safety?: string;\n targetMeta?: string;\n ddl?: string;\n format?: string;\n aiMaxSpend?: string;\n }) => {\n if (opts.seniorDba) {\n await runSeniorDbaReview(opts, 'sdt');\n return;\n }\n if (!opts.source) {\n throw new Error('--source is required in the default (project-health) mode.');\n }\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const md = review.renderReviewReport(model, { source: sourcePath });\n await emit(md, opts.out);\n await runExplain(\n {\n feature: 'review.explain',\n systemPrompt:\n 'You are a Snowflake principal engineer giving a senior-architect verbal walkthrough of an automated review report. Summarize the headline themes, recommend the top 3 follow-ups in order of leverage, and call out anything a junior reviewer might miss.',\n },\n opts,\n () =>\n `Review report follows:\\n\\n${md}\\n\\nNarrate this report for a teammate who has not read it.`,\n );\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\nexport async function runSeniorDbaReview(\n opts: {\n diff?: string;\n safety?: string;\n targetMeta?: string;\n ddl?: string;\n format?: string;\n out?: string;\n aiMaxSpend?: string;\n },\n toolName: 'sdt' | 'ddt',\n): Promise<void> {\n if (!opts.diff || !opts.safety) {\n throw new Error('--senior-dba requires both --diff and --safety (JSON files).');\n }\n const [diff, safety, targetMeta, ddl] = await Promise.all([\n readJson(opts.diff),\n readJson(opts.safety),\n opts.targetMeta\n ? fs.readFile(path.resolve(opts.targetMeta), 'utf8')\n : Promise.resolve<string | undefined>(undefined),\n opts.ddl\n ? fs.readFile(path.resolve(opts.ddl), 'utf8')\n : Promise.resolve<string | undefined>(undefined),\n ]);\n\n const compareSummary = normalizeCompareSummary(diff);\n const safetySummary = normalizeSafetySummary(safety);\n\n const result = await aiReview.runSeniorDbaReview(\n {\n compareSummary,\n safetySummary,\n ...(targetMeta ? { targetMetadata: targetMeta } : {}),\n ...(ddl ? { ddlPreview: ddl } : {}),\n },\n {\n completeFn: async (user, system) => {\n const r = await ai.complete(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n {\n feature: 'review.senior-dba',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n },\n );\n return r.text;\n },\n },\n toolName,\n );\n\n const format = String(opts.format ?? 'markdown').toLowerCase();\n const payload =\n format === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined }, null, 2)\n : aiReview.renderSeniorDbaReviewMarkdown(result, toolName);\n await emit(payload, opts.out);\n // Set exit code on request_changes so CI gates can rely on it.\n if (result.verdict === 'request_changes' && !opts.out) {\n process.exitCode = 2;\n }\n}\n\nfunction normalizeCompareSummary(raw: unknown): aiReview.CompareSummaryInput {\n const o = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>;\n const num = (k: string) => (typeof o[k] === 'number' ? (o[k] as number) : 0);\n const arr = (k: string) =>\n Array.isArray(o[k])\n ? (o[k] as unknown[]).filter((x): x is string => typeof x === 'string')\n : undefined;\n return {\n added: num('added'),\n removed: num('removed'),\n modified: num('modified'),\n ...(arr('addedSample') ? { addedSample: arr('addedSample') } : {}),\n ...(arr('removedSample') ? { removedSample: arr('removedSample') } : {}),\n ...(arr('modifiedSample') ? { modifiedSample: arr('modifiedSample') } : {}),\n };\n}\n\nfunction normalizeSafetySummary(raw: unknown): aiReview.SafetySummaryInput {\n const o = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>;\n const num = (k: string) => (typeof o[k] === 'number' ? (o[k] as number) : 0);\n const sample = Array.isArray(o.sample)\n ? (o.sample as unknown[]).filter((x): x is string => typeof x === 'string')\n : undefined;\n return {\n unrecoverable: num('unrecoverable'),\n destructive: num('destructive'),\n expensive: num('expensive'),\n warning: num('warning'),\n ...(sample ? { sample } : {}),\n };\n}\n\nasync function readJson(p: string): Promise<unknown> {\n const raw = await fs.readFile(path.resolve(p), 'utf8');\n return JSON.parse(raw);\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\nasync function emit(payload: string, out: unknown): Promise<void> {\n if (out) {\n const p = path.resolve(String(out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${payload.length} bytes).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt impact <fqn>` — single-FQN blast-radius answer. \"If I change\n * this, what breaks? What feeds it? What pending diagnostics\n * touch it?\" Composition of `@sdt-tools/core/lineage` (upstream/downstream)\n * and `@sdt-tools/core/diagnostics` (findings filtered to the FQN).\n *\n * Output is Markdown by default; `--format json` returns a structured\n * payload for CI integration.\n */\nexport function impactCommand(): Command {\n const cmd = new Command('impact');\n cmd\n .description(\n 'Single-FQN blast-radius: who feeds it, who reads from it, what findings apply to it.',\n )\n .argument('<fqn>', 'Fully-qualified name to analyze (e.g. ANALYTICS.GOLD.CUSTOMER).')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(async (fqn: string, opts: { source: string; out?: string; explain?: boolean }) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const md = review.renderImpactReport(model, String(fqn), { source: sourcePath });\n await emit(md, opts.out);\n await runExplain(\n {\n feature: 'impact.explain',\n systemPrompt:\n 'You are a senior Snowflake DBA explaining an impact analysis to a developer who is about to change one object. Be very direct about the blast radius and what they should test before merging.',\n },\n opts,\n () =>\n `Impact report for ${fqn} follows:\\n\\n${md}\\n\\nExplain the blast radius and what the engineer should pay attention to.`,\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\nasync function emit(payload: string, out: unknown): Promise<void> {\n if (out) {\n const p = path.resolve(String(out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${payload.length} bytes).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\ninterface HistoryEntry {\n sqlText?: string;\n durationMs?: number;\n}\n\n/**\n * `sdt cost-estimate` — static heuristic estimator for the Snowflake\n * credits a migration script will consume when applied.\n *\n * Approach: classify each statement by its observable cost-class\n * (TABLE rebuild, CREATE OR REPLACE VIEW, ADD COLUMN, ALTER TYPE,\n * dynamic-table refresh, etc.) and assign a credit-band estimate per\n * class. Estimates are intentionally **ranges** rather than point\n * values because actual cost depends on row count, warehouse size,\n * and data layout — we don't pretend otherwise.\n *\n * The framing alone is uniquely valuable: no other Snowflake schema\n * tool surfaces \"this migration will roughly cost X credits at S\n * warehouse\" before you apply it.\n *\n * The classifier is regex-based and conservative — when a statement\n * doesn't match a known cost-class it's reported as\n * \"unknown / negligible\" so the user knows the estimate didn't see it.\n */\nexport function costEstimateCommand(): Command {\n const cmd = new Command('cost-estimate');\n cmd\n .description('Heuristic Snowflake-credit estimate for a generated migration script.')\n .requiredOption(\n '--script <path>',\n 'Path to a generated migration script (.sql) from `sdt publish --out`.',\n )\n .option(\n '--warehouse-size <size>',\n 'Target warehouse size for the cost ladder: XS | S | M | L | XL | 2XL | 3XL | 4XL.',\n 'S',\n )\n .option('--format <fmt>', 'table | json | markdown. Default table.', 'table')\n .option('-o, --out <path>', 'Write output to file. Defaults to stdout.')\n .option(\n '--calibrate-from <path>',\n 'AI Phase 6 calibration: a JSON file of QueryHistoryEntry[] from prior deploys. Each historic statement is classified against the same cost-classes; classes with ≥3 samples adopt empirical min/max duration in place of the heuristic range.',\n )\n .action(\n async (opts: {\n script: string;\n warehouseSize?: string;\n format?: string;\n out?: string;\n calibrateFrom?: string;\n explain?: boolean;\n }) => {\n const sql = await fs.readFile(path.resolve(String(opts.script)), 'utf8');\n const wh = String(opts.warehouseSize ?? 'S').toUpperCase() as WarehouseSize;\n const wantedSizes: readonly WarehouseSize[] = [\n 'XS',\n 'S',\n 'M',\n 'L',\n 'XL',\n '2XL',\n '3XL',\n '4XL',\n ];\n if (!wantedSizes.includes(wh)) {\n throw new Error(\n `Unknown --warehouse-size: ${wh}. Use one of ${wantedSizes.join(' | ')}.`,\n );\n }\n let calibration: ClassCalibration | undefined;\n if (opts.calibrateFrom) {\n const histRaw = await fs.readFile(path.resolve(String(opts.calibrateFrom)), 'utf8');\n const parsed = JSON.parse(histRaw);\n const entries: HistoryEntry[] = Array.isArray(parsed)\n ? parsed\n : Array.isArray(parsed.entries)\n ? parsed.entries\n : [];\n calibration = buildCalibration(entries);\n }\n const report = estimateCost(sql, wh, calibration);\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(report, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderMarkdown(report);\n } else {\n payload = renderTable(report);\n }\n if (opts.out) {\n const p = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p}.`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'cost-estimate.explain',\n systemPrompt:\n 'You are a Snowflake cost engineer. Walk the team through this cost estimate: what is the dominant cost driver, what does the range mean in practice, and what knobs (warehouse size, sequencing, off-peak timing) would meaningfully reduce it.',\n },\n opts,\n () =>\n `Cost estimate (JSON) follows:\\n\\n${JSON.stringify(report, null, 2)}\\n\\nNarrate this for a teammate.`,\n );\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\ntype WarehouseSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | '2XL' | '3XL' | '4XL';\n\n/**\n * Snowflake's published credit-per-hour ladder, as of 2026-Q1.\n * XS = 1, S = 2, M = 4, L = 8, XL = 16, 2XL = 32, 3XL = 64, 4XL = 128.\n */\nconst CREDITS_PER_HOUR: Record<WarehouseSize, number> = {\n XS: 1,\n S: 2,\n M: 4,\n L: 8,\n XL: 16,\n '2XL': 32,\n '3XL': 64,\n '4XL': 128,\n};\n\ninterface CostClass {\n id: string;\n description: string;\n /** Conservative range estimate in **seconds of warehouse time**. */\n minSeconds: number;\n maxSeconds: number;\n /** Regex that matches the statement category. */\n test: (sql: string) => boolean;\n}\n\nconst COST_CLASSES: CostClass[] = [\n {\n id: 'table-rebuild',\n description: 'CREATE OR REPLACE TABLE or CTAS — rewrites the entire table',\n minSeconds: 30,\n maxSeconds: 1800,\n test: (s) =>\n /CREATE\\s+(?:OR\\s+REPLACE\\s+)?TABLE\\s+.+\\s+AS\\s+SELECT/i.test(s) ||\n /CREATE\\s+OR\\s+REPLACE\\s+TABLE\\b/i.test(s),\n },\n {\n id: 'add-column',\n description: 'ALTER TABLE ADD COLUMN — metadata-only, no scan',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bADD\\s+COLUMN\\b/i.test(s),\n },\n {\n id: 'drop-column',\n description: 'ALTER TABLE DROP COLUMN — metadata-only',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bDROP\\s+COLUMN\\b/i.test(s),\n },\n {\n id: 'alter-type-narrowing',\n description: 'ALTER COLUMN TYPE (narrowing) — full data scan + rewrite',\n minSeconds: 30,\n maxSeconds: 600,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bALTER\\s+COLUMN\\b.*\\bSET\\s+DATA\\s+TYPE\\b/i.test(s),\n },\n {\n id: 'create-view',\n description: 'CREATE OR REPLACE VIEW — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?VIEW\\b/i.test(s),\n },\n {\n id: 'create-mv',\n description: 'CREATE MATERIALIZED VIEW — initial population can be costly',\n minSeconds: 60,\n maxSeconds: 3600,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?MATERIALIZED\\s+VIEW\\b/i.test(s),\n },\n {\n id: 'create-dynamic-table',\n description: 'CREATE DYNAMIC TABLE — initial materialisation cost',\n minSeconds: 60,\n maxSeconds: 1800,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?DYNAMIC\\s+TABLE\\b/i.test(s),\n },\n {\n id: 'create-stream',\n description: 'CREATE STREAM — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?STREAM\\b/i.test(s),\n },\n {\n id: 'create-task',\n description: 'CREATE TASK — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?TASK\\b/i.test(s),\n },\n {\n id: 'create-warehouse',\n description: 'CREATE WAREHOUSE — metadata; cost depends on usage',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?WAREHOUSE\\b/i.test(s),\n },\n {\n id: 'pre-deploy-clone',\n description: 'CREATE DATABASE ... CLONE — Snowflake zero-copy clone (~instant)',\n minSeconds: 1,\n maxSeconds: 10,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?DATABASE\\s+\\S+\\s+CLONE\\b/i.test(s),\n },\n {\n id: 'drop',\n description: 'DROP statement — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /^\\s*DROP\\s+/i.test(s),\n },\n {\n id: 'grant',\n description: 'GRANT / REVOKE — metadata-only',\n minSeconds: 1,\n maxSeconds: 2,\n test: (s) => /^\\s*(?:GRANT|REVOKE)\\s+/i.test(s),\n },\n {\n id: 'comment',\n description: 'COMMENT-only statement (-- … no DDL) — free',\n minSeconds: 0,\n maxSeconds: 0,\n test: (s) =>\n s\n .replace(/--[^\\n]*/g, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .trim().length === 0,\n },\n];\n\ninterface CostReport {\n warehouseSize: WarehouseSize;\n creditsPerHour: number;\n totalStatements: number;\n classifiedStatements: number;\n unknownStatements: number;\n perClass: Array<{\n id: string;\n description: string;\n count: number;\n minSeconds: number;\n maxSeconds: number;\n minCredits: number;\n maxCredits: number;\n /** When set, the per-statement range came from this many empirical samples. */\n calibratedFromSamples?: number;\n }>;\n totals: {\n minSeconds: number;\n maxSeconds: number;\n minCredits: number;\n maxCredits: number;\n };\n}\n\n/**\n * AI Phase 6 calibration — per-class empirical duration ranges harvested\n * from prior `QueryHistoryEntry[]` (typed in `@<tool>/core/queryHistory`).\n * When a class has at least 3 historic samples, its heuristic min/max is\n * replaced with the observed min/max. Classes that fall back to the\n * heuristic are flagged in the report so the user can see what was\n * calibrated.\n */\ninterface ClassCalibration {\n /** Per-class empirical range; absent classes use the heuristic range. */\n perClass: Record<string, { sampleSize: number; minSeconds: number; maxSeconds: number }>;\n}\n\nfunction buildCalibration(entries: HistoryEntry[]): ClassCalibration {\n const samples = new Map<string, number[]>();\n for (const e of entries) {\n const sql = typeof e.sqlText === 'string' ? e.sqlText : '';\n const dur = typeof e.durationMs === 'number' ? e.durationMs : NaN;\n if (!sql || !isFinite(dur) || dur <= 0) continue;\n const matched = COST_CLASSES.find((c) => c.test(sql));\n if (!matched) continue;\n const arr = samples.get(matched.id) ?? [];\n arr.push(dur / 1000);\n samples.set(matched.id, arr);\n }\n const perClass: ClassCalibration['perClass'] = {};\n for (const [id, durs] of samples) {\n if (durs.length < 3) continue;\n durs.sort((a, b) => a - b);\n perClass[id] = {\n sampleSize: durs.length,\n minSeconds: Math.max(1, Math.round(durs[0]!)),\n maxSeconds: Math.max(1, Math.round(durs[durs.length - 1]!)),\n };\n }\n return { perClass };\n}\n\nfunction estimateCost(\n sql: string,\n warehouseSize: WarehouseSize,\n calibration?: ClassCalibration,\n): CostReport {\n const statements = splitStatements(sql);\n const classCounts = new Map<string, number>();\n let classifiedStatements = 0;\n let unknownStatements = 0;\n for (const stmt of statements) {\n const matched = COST_CLASSES.find((c) => c.test(stmt));\n if (matched) {\n classCounts.set(matched.id, (classCounts.get(matched.id) ?? 0) + 1);\n classifiedStatements++;\n } else if (stmt.trim().length > 0) {\n unknownStatements++;\n }\n }\n const creditsPerHour = CREDITS_PER_HOUR[warehouseSize];\n const perClass = COST_CLASSES.filter((c) => (classCounts.get(c.id) ?? 0) > 0).map((c) => {\n const count = classCounts.get(c.id) ?? 0;\n const cal = calibration?.perClass[c.id];\n const minSecondsPerStmt = cal ? cal.minSeconds : c.minSeconds;\n const maxSecondsPerStmt = cal ? cal.maxSeconds : c.maxSeconds;\n const minSeconds = minSecondsPerStmt * count;\n const maxSeconds = maxSecondsPerStmt * count;\n return {\n id: c.id,\n description: c.description,\n count,\n minSeconds,\n maxSeconds,\n minCredits: (minSeconds / 3600) * creditsPerHour,\n maxCredits: (maxSeconds / 3600) * creditsPerHour,\n ...(cal ? { calibratedFromSamples: cal.sampleSize } : {}),\n };\n });\n const totals = perClass.reduce(\n (acc, c) => ({\n minSeconds: acc.minSeconds + c.minSeconds,\n maxSeconds: acc.maxSeconds + c.maxSeconds,\n minCredits: acc.minCredits + c.minCredits,\n maxCredits: acc.maxCredits + c.maxCredits,\n }),\n { minSeconds: 0, maxSeconds: 0, minCredits: 0, maxCredits: 0 },\n );\n return {\n warehouseSize,\n creditsPerHour,\n totalStatements: statements.length,\n classifiedStatements,\n unknownStatements,\n perClass,\n totals,\n };\n}\n\nfunction splitStatements(sql: string): string[] {\n return sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .split(/;\\s*$/m)\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\nfunction renderTable(r: CostReport): string {\n const lines: string[] = [];\n lines.push(`Cost estimate — warehouse=${r.warehouseSize} (${r.creditsPerHour} credit/hour)`);\n lines.push('');\n lines.push(\n ` Statements: ${r.totalStatements} (${r.classifiedStatements} classified, ${r.unknownStatements} unknown).`,\n );\n lines.push('');\n const idW = Math.max(20, ...r.perClass.map((c) => c.id.length));\n for (const c of r.perClass) {\n lines.push(\n ` ${c.id.padEnd(idW)} ×${String(c.count).padStart(4)} ≈ ${c.minCredits.toFixed(3)} – ${c.maxCredits.toFixed(3)} credit`,\n );\n }\n lines.push('');\n lines.push(\n ` TOTAL ≈ ${r.totals.minCredits.toFixed(3)} – ${r.totals.maxCredits.toFixed(3)} credit`,\n );\n lines.push(` TOTAL (duration estimate) ≈ ${r.totals.minSeconds}s – ${r.totals.maxSeconds}s`);\n lines.push('');\n lines.push(' Note: ranges are heuristic. Actual cost depends on row counts, data layout,');\n lines.push(' and what other workloads share the warehouse. Treat the upper bound as a');\n lines.push(' pessimistic ceiling, not a likely outcome.');\n return lines.join('\\n');\n}\n\nfunction renderMarkdown(r: CostReport): string {\n const lines: string[] = [];\n lines.push(`# Cost estimate`);\n lines.push('');\n lines.push(`**Warehouse:** ${r.warehouseSize} (${r.creditsPerHour} credit/hour)`);\n lines.push(\n `**Statements:** ${r.totalStatements} total, ${r.classifiedStatements} classified, ${r.unknownStatements} unknown`,\n );\n lines.push('');\n lines.push(`## Estimate by statement class`);\n lines.push('');\n lines.push('| Class | Count | Credit range |');\n lines.push('|---|---|---|');\n for (const c of r.perClass) {\n lines.push(\n `| \\`${c.id}\\` (${c.description}) | ${c.count} | ${c.minCredits.toFixed(3)} – ${c.maxCredits.toFixed(3)} |`,\n );\n }\n lines.push('');\n lines.push(\n `**Total:** ${r.totals.minCredits.toFixed(3)} – ${r.totals.maxCredits.toFixed(3)} credit (${r.totals.minSeconds}–${r.totals.maxSeconds}s)`,\n );\n lines.push('');\n lines.push('> Ranges are heuristic. Actual cost depends on row counts and warehouse contention.');\n return lines.join('\\n');\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n PacSource,\n ProjectSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { safety } from '@sdt-tools/core';\nimport { pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\n/**\n * `sdt pr-comment` — produce a Markdown PR sticky-comment from a\n * source↔target compare. Bundles the diff summary, reversibility-\n * grouped safety findings, project health diagnostics, and a\n * collapsible per-object changelog into a single deliverable a CI\n * step can POST as a pull-request comment.\n *\n * Distinct from `sdt review`: `review` is project-only, `pr-comment`\n * is change-driven (here's what's *in this PR*).\n */\nexport function prCommentCommand(): Command {\n const cmd = new Command('pr-comment');\n cmd\n .description(\n 'Generate a Markdown PR comment from a source↔target compare (diff + safety + health).',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac (the desired state).')\n .requiredOption('--target <path>', '.sdtproj or .sdtpac (the current state).')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(async (opts: { source: string; target: string; out?: string; explain?: boolean }) => {\n const sourcePath = String(opts.source);\n const targetPath = String(opts.target);\n const engine = new CompareEngine();\n const src: CompareSource = sourcePath.endsWith('.sdtpac')\n ? new PacSource(sourcePath, 'source')\n : new ProjectSource(sourcePath, 'source');\n const tgt: CompareSource = targetPath.endsWith('.sdtpac')\n ? new PacSource(targetPath, 'target')\n : new ProjectSource(targetPath, 'target');\n const result = await engine.compare(src, tgt);\n const assessment = safety.assess(result);\n const model = await loadModel(sourcePath);\n const md = review.renderPrComment(model, result, assessment, { source: sourcePath });\n if (opts.out) {\n const p = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, md + (md.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${md.length} bytes).`);\n } else {\n process.stdout.write(md + (md.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'pr-comment.explain',\n systemPrompt:\n 'You are a release manager preparing the human summary for a code-review comment. Distill the structured PR comment into 3-5 sentences a reviewer can read in 30 seconds. Lead with the riskiest change.',\n },\n opts,\n () =>\n `PR comment payload follows:\\n\\n${md}\\n\\nWrite a tight executive summary a busy reviewer will appreciate.`,\n );\n });\n attachExplainFlag(cmd);\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n 'compare.excludeObjectPatterns',\n 'compare.includeObjectPatterns',\n ]);\n return cmd;\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\n/**\n * `sdt template <kind> <name>` — schema cookbook generator. Produces\n * a complete set of `.sql` files implementing a common pattern, ready\n * to drop into a `.sdtproj`'s object tree. Saves a junior engineer\n * from re-inventing the SCD2 pattern from scratch.\n *\n * Supported kinds:\n * - `scd1` — Slowly-changing-dimension type-1 (overwrite, no history).\n * - `scd2` — Slowly-changing-dimension type-2 (history-preserving).\n * - `scd3` — Slowly-changing-dimension type-3 (one previous value).\n * - `scd4` — Slowly-changing-dimension type-4 (current + history table).\n * - `scd6` — Hybrid 1+2+3 (current + valid_from/to + previous value).\n * - `star` — Star schema fact + N dimensions.\n * - `fact` — Fact table only, with surrogate-key FKs to named dims.\n * - `scd2-merge` — Canonical MERGE statement to load an SCD2 dimension.\n * - `current-view` — `CREATE VIEW` over an SCD2 table where IS_CURRENT = TRUE.\n * - `time-series` — Hash-partitioned time-series with retention.\n * - `audit` — Generic audit-log table with append-only constraints.\n *\n * Mirrors `ddt template`. Patterns are conservative: every template\n * sets a PK, populates COMMENT fields, and prefers `CREATE OR ALTER`\n * over `CREATE OR REPLACE` to play well with the safety classifier.\n */\nexport function templateCommand(): Command {\n const cmd = new Command('template');\n cmd\n .description(\n 'Scaffold a common schema pattern (scd1|scd2|scd3|scd4|scd6|star|fact|scd2-merge|current-view|time-series|audit). Writes .sql files into <out>/.',\n )\n .argument(\n '<kind>',\n 'Pattern to scaffold: scd1 | scd2 | scd3 | scd4 | scd6 | star | fact | scd2-merge | current-view | time-series | audit',\n )\n .argument('<name>', 'Base object name (e.g. CUSTOMER, ORDERS).')\n .option('--db <database>', 'Database name. Default DEMO_DB.', 'DEMO_DB')\n .option('--schema <schema>', 'Schema name. Default PUBLIC.', 'PUBLIC')\n .option('-o, --out <path>', 'Output directory. Default <kind>-<name>/.')\n .option(\n '--dims <dims>',\n '[star|fact] Comma-separated dimension names. Default: customer,product,date.',\n 'customer,product,date',\n )\n .option(\n '--track <cols>',\n '[scd3|scd6] Comma-separated columns to track previous-values for. Default: attribute_1.',\n 'attribute_1',\n )\n .option(\n '--source <fqn>',\n '[scd2-merge] Source/staging table fully-qualified name. Default DEMO_DB.PUBLIC.<name>_STAGE.',\n )\n .option('--retention-days <n>', '[time-series] Retention window in days. Default 90.', '90')\n .option(\n '--hybrid',\n 'Emit CREATE HYBRID TABLE (Unistore row-store) instead of CREATE OR ALTER TABLE. Constraints become enforced; CLUSTER BY is suppressed (not supported on Hybrid Tables).',\n )\n .action(async (kindArg, nameArg, opts) => {\n const kind = String(kindArg).toLowerCase();\n const name = String(nameArg);\n const db = String(opts.db);\n const schema = String(opts.schema);\n const hybrid = Boolean(opts.hybrid);\n const out = opts.out\n ? path.resolve(String(opts.out))\n : path.resolve(`${kind}-${name.toLowerCase()}`);\n await fs.mkdir(out, { recursive: true });\n\n if (hybrid && (kind === 'scd2-merge' || kind === 'current-view')) {\n console.error(`Warning: --hybrid has no effect on ${kind} (no table DDL emitted).`);\n }\n\n const ctx = { db, schema, name, hybrid };\n let files: Record<string, string>;\n const trackCols = String(opts.track)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const dims = String(opts.dims)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (kind === 'scd1') files = renderScd1(ctx);\n else if (kind === 'scd2') files = renderScd2(ctx);\n else if (kind === 'scd3') files = renderScd3(ctx, trackCols);\n else if (kind === 'scd4') files = renderScd4(ctx);\n else if (kind === 'scd6') files = renderScd6(ctx, trackCols);\n else if (kind === 'star') files = renderStar(ctx, dims);\n else if (kind === 'fact') files = renderFact(ctx, dims);\n else if (kind === 'scd2-merge')\n files = renderScd2Merge(\n ctx,\n opts.source ? String(opts.source) : `${db}.${schema}.${name.toUpperCase()}_STAGE`,\n );\n else if (kind === 'current-view') files = renderCurrentView(ctx);\n else if (kind === 'time-series') files = renderTimeSeries(ctx, Number(opts.retentionDays));\n else if (kind === 'audit') files = renderAudit(ctx);\n else\n throw new Error(\n `Unknown template kind: ${kind}. Use scd1 | scd2 | scd3 | scd4 | scd6 | star | fact | scd2-merge | current-view | time-series | audit.`,\n );\n\n for (const [rel, contents] of Object.entries(files)) {\n const filePath = path.join(out, rel);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, contents, 'utf8');\n console.error(\n ` wrote ${path.relative(process.cwd(), filePath)} (${contents.length} bytes)`,\n );\n }\n console.error(\n `Done. ${Object.keys(files).length} file(s) written to ${path.relative(process.cwd(), out)}.`,\n );\n });\n return cmd;\n}\n\ninterface Ctx {\n db: string;\n schema: string;\n name: string;\n /** When true, emit CREATE HYBRID TABLE with enforced constraints and no CLUSTER BY. */\n hybrid?: boolean;\n}\n\nfunction header(why: string): string {\n return `-- Generated by \\`sdt template\\`. Why this pattern is the right shape:\\n-- ${why}\\n--\\n-- Edit freely; this is just a starting point.\\n\\n`;\n}\n\n/** DDL verb for table creation — Hybrid Tables can't use CREATE OR ALTER. */\nfunction tableKw(c: Ctx, tableName: string): string {\n return c.hybrid\n ? `CREATE HYBRID TABLE ${c.db}.${c.schema}.${tableName}`\n : `CREATE OR ALTER TABLE ${c.db}.${c.schema}.${tableName}`;\n}\n\n/** Primary-key constraint. Hybrid Tables enforce PKs, regular tables don't. */\nfunction pkConstraint(name: string, cols: string, c: Ctx): string {\n return c.hybrid\n ? `CONSTRAINT ${name} PRIMARY KEY (${cols})`\n : `CONSTRAINT ${name} PRIMARY KEY (${cols}) NOT ENFORCED`;\n}\n\n/** Unique constraint. Hybrid Tables enforce UKs, regular tables don't. */\nfunction ukConstraint(name: string, cols: string, c: Ctx): string {\n return c.hybrid\n ? `CONSTRAINT ${name} UNIQUE (${cols})`\n : `CONSTRAINT ${name} UNIQUE (${cols}) NOT ENFORCED`;\n}\n\n/** CLUSTER BY clause — suppressed on Hybrid Tables (not supported). */\nfunction clusterBy(expr: string, c: Ctx): string {\n return c.hybrid ? '' : `\\nCLUSTER BY (${expr})`;\n}\n\nfunction renderScd1(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD1 overwrites the row in place when an attribute changes. No history is\n-- preserved. Use this when downstream consumers only care about the *current*\n-- state and the dimension is small enough that losing history is fine.\n-- LOAD_TS/UPDATED_TS give you minimal auditability without history-table cost.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — stable across overwrites',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was first inserted',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When the row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD1 dimension — overwrite-on-change. No history kept; join on ${upper}_BK.';\n`,\n };\n}\n\nfunction renderScd2(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD2 preserves every historical version of a row by closing the previous row's\n-- VALID_TO when the natural key reappears with new attribute values. Use this\n-- when downstream analytics needs \"what did this row look like on date X\".`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — unique per version',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key — stable across versions',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n VALID_FROM TIMESTAMP_NTZ NOT NULL COMMENT 'When this version became current',\n VALID_TO TIMESTAMP_NTZ COMMENT 'When this version was superseded; NULL while current',\n IS_CURRENT BOOLEAN NOT NULL COMMENT 'TRUE only on the latest row per BK',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)}\n)\nCOMMENT = 'SCD2 dimension — preserves history. Treat business key + IS_CURRENT as the natural join target.';\n`,\n [`${c.db}/${c.schema}/Streams/${upper}_STREAM.sql`]:\n header(\n `Stream over the SCD2 table lets downstream tasks consume only the rows that\n-- changed since they last read. Drop this if you don't have a downstream\n-- consumer that needs incremental updates.`,\n ) +\n `CREATE OR ALTER STREAM ${c.db}.${c.schema}.${upper}_STREAM ON TABLE ${c.db}.${c.schema}.${upper}\nCOMMENT = 'CDC stream over ${upper}. Read by downstream tasks for incremental processing.';\n`,\n };\n}\n\nfunction renderScd3(c: Ctx, tracked: string[]): Record<string, string> {\n const upper = c.name.toUpperCase();\n const cols = (tracked.length ? tracked : ['attribute_1']).map((t) => t.toUpperCase());\n const prevCols = cols\n .map(\n (t) =>\n ` PREV_${t} VARCHAR COMMENT 'Prior value of ${t}, captured on overwrite'`,\n )\n .join(',\\n');\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD3 keeps the current value plus one prior value per tracked column. Use\n-- this when downstream needs \"current vs immediately prior\" but doesn't need\n-- the full history. Cheaper than SCD2 but lossy beyond one change.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n${cols.map((t) => ` ${t} VARCHAR COMMENT 'Current value'`).join(',\\n')},\n${prevCols},\n PREV_CHANGED_TS TIMESTAMP_NTZ COMMENT 'When prior values were captured',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When this row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD3 dimension — current + one prior value for ${cols.join(', ')}.';\n`,\n };\n}\n\nfunction renderScd4(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD4 keeps a small, fast \"current\" table for joins and a separate history\n-- table for slow analytics. Use this when the current-state lookups are hot\n-- (every fact query joins to it) and you want to keep that join skinny.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was inserted',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When the row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD4 current-state table. Pair with ${upper}_HISTORY for change tracking.';\n`,\n [`${c.db}/${c.schema}/Tables/${upper}_HISTORY.sql`]:\n header(\n `Companion history table for SCD4. Rows are appended (never updated) when\n-- the current table is overwritten — same columns plus a CHANGED_TS so you\n-- can replay \"what did this BK look like at time T\".`,\n ) +\n `${tableKw(c, `${upper}_HISTORY`)} (\n ${upper}_HISTORY_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id for each historical snapshot',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Snapshot of column at CHANGED_TS',\n ATTRIBUTE_2 VARCHAR COMMENT 'Snapshot of column at CHANGED_TS',\n CHANGED_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When this snapshot was taken',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was appended',\n ${pkConstraint(`PK_${upper}_HISTORY`, `${upper}_HISTORY_SK`, c)}\n)${clusterBy(`${upper}_BK, CHANGED_TS`, c)}\nCOMMENT = 'SCD4 history-side. Append-only snapshots of ${upper}; reconstruct as-of state via window functions.';\n`,\n };\n}\n\nfunction renderScd6(c: Ctx, tracked: string[]): Record<string, string> {\n const upper = c.name.toUpperCase();\n const cols = (tracked.length ? tracked : ['attribute_1']).map((t) => t.toUpperCase());\n const prevCols = cols\n .map(\n (t) =>\n ` PREV_${t} VARCHAR COMMENT 'Prior value of ${t}'`,\n )\n .join(',\\n');\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD6 = 1 + 2 + 3 hybrid. You get full SCD2 history (rows per version),\n-- SCD3 \"current vs prior\" lookback on hot columns, and SCD1 \"current value\"\n-- denormalized onto every historical row. Heavyweight; use when downstream\n-- consumers ask both \"what was it at time T?\" and \"what's the current value\n-- for the BK on this old row?\" in the same query.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — unique per version',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key — stable across versions',\n${cols.map((t) => ` ${t} VARCHAR COMMENT 'Value on THIS version'`).join(',\\n')},\n${cols.map((t) => ` CURRENT_${t} VARCHAR COMMENT 'Current value for the BK (SCD1 denorm)'`).join(',\\n')},\n${prevCols},\n VALID_FROM TIMESTAMP_NTZ NOT NULL COMMENT 'When this version became current',\n VALID_TO TIMESTAMP_NTZ COMMENT 'When this version was superseded; NULL while current',\n IS_CURRENT BOOLEAN NOT NULL COMMENT 'TRUE only on the latest row per BK',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)}\n)\nCOMMENT = 'SCD6 dimension — hybrid 1+2+3. Heavy but answers every common BI question without re-joining.';\n`,\n };\n}\n\nfunction renderStar(c: Ctx, dims: string[]): Record<string, string> {\n const fact = c.name.toUpperCase();\n const out: Record<string, string> = {};\n for (const d of dims) {\n const upper = d.toUpperCase();\n out[`${c.db}/${c.schema}/Tables/DIM_${upper}.sql`] =\n header(`Dimension table — describes the WHAT. Joined by the fact via DIM_${upper}_SK.`) +\n `${tableKw(c, `DIM_${upper}`)} (\n DIM_${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ${upper}_NAME VARCHAR COMMENT 'Replace with real attributes',\n COUNTRY VARCHAR COMMENT 'Example attribute',\n ${pkConstraint(`PK_DIM_${upper}`, `DIM_${upper}_SK`, c)}\n)\nCOMMENT = 'Dimension table for the ${fact} star schema.';\n`;\n }\n out[`${c.db}/${c.schema}/Tables/FACT_${fact}.sql`] =\n header(\n `Fact table — the WHO/WHAT/WHEN/HOW-MUCH. One row per business event.\n-- Surrogate-key FKs to every dimension; measure columns hold the numbers.`,\n ) +\n `${tableKw(c, `FACT_${fact}`)} (\n FACT_${fact}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n${dims.map((d) => ` DIM_${d.toUpperCase()}_SK NUMBER(38,0) COMMENT 'FK to DIM_${d.toUpperCase()}'`).join(',\\n')},\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n MEASURE_AMOUNT NUMBER(38,4) COMMENT 'Primary measure — replace with real columns',\n MEASURE_QUANTITY NUMBER(38,0) COMMENT 'Secondary measure',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_FACT_${fact}`, `FACT_${fact}_SK`, c)}\n)${clusterBy('EVENT_TS', c)}\nCOMMENT = 'Fact table for the ${fact} star. CLUSTER BY date keeps recent-event scans cheap.';\n`;\n return out;\n}\n\nfunction renderFact(c: Ctx, dims: string[]): Record<string, string> {\n const fact = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/FACT_${fact}.sql`]:\n header(\n `Fact-only template — assumes the named dimensions already exist. Use this\n-- when adding a new fact to an existing star, rather than scaffolding the\n-- dims a second time. Surrogate-key FKs follow the DIM_<NAME>_SK convention.`,\n ) +\n `${tableKw(c, `FACT_${fact}`)} (\n FACT_${fact}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n${dims.map((d) => ` DIM_${d.toUpperCase()}_SK NUMBER(38,0) COMMENT 'FK to DIM_${d.toUpperCase()}'`).join(',\\n')},\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n MEASURE_AMOUNT NUMBER(38,4) COMMENT 'Primary measure — replace with real columns',\n MEASURE_QUANTITY NUMBER(38,0) COMMENT 'Secondary measure',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_FACT_${fact}`, `FACT_${fact}_SK`, c)}\n)${clusterBy('EVENT_TS', c)}\nCOMMENT = 'Fact table FACT_${fact}. Add this to an existing star — dimensions assumed to exist.';\n`,\n };\n}\n\nfunction renderScd2Merge(c: Ctx, source: string): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Scripts/MERGE_${upper}.sql`]:\n header(\n `Canonical SCD2 load. Step 1 closes the prior row when the BK reappears with\n-- different attributes (sets VALID_TO + IS_CURRENT=FALSE). Step 2 inserts the\n-- new version. Wrap both in a transaction so you don't end up with two current\n-- rows. Source: ${source}.`,\n ) +\n `-- Step 1 — close the previous version when attributes change for an existing BK.\nBEGIN TRANSACTION;\n\nMERGE INTO ${c.db}.${c.schema}.${upper} AS tgt\nUSING (\n SELECT\n src.${upper}_BK,\n src.ATTRIBUTE_1,\n src.ATTRIBUTE_2\n FROM ${source} AS src\n) AS src\nON tgt.${upper}_BK = src.${upper}_BK\n AND tgt.IS_CURRENT = TRUE\nWHEN MATCHED\n AND (tgt.ATTRIBUTE_1 IS DISTINCT FROM src.ATTRIBUTE_1\n OR tgt.ATTRIBUTE_2 IS DISTINCT FROM src.ATTRIBUTE_2)\n THEN UPDATE SET\n VALID_TO = CURRENT_TIMESTAMP(),\n IS_CURRENT = FALSE;\n\n-- Step 2 — insert the new version for changed BKs + brand-new BKs.\nINSERT INTO ${c.db}.${c.schema}.${upper} (\n ${upper}_BK, ATTRIBUTE_1, ATTRIBUTE_2,\n VALID_FROM, VALID_TO, IS_CURRENT\n)\nSELECT\n src.${upper}_BK,\n src.ATTRIBUTE_1,\n src.ATTRIBUTE_2,\n CURRENT_TIMESTAMP(),\n NULL,\n TRUE\nFROM ${source} AS src\nLEFT JOIN ${c.db}.${c.schema}.${upper} AS tgt\n ON tgt.${upper}_BK = src.${upper}_BK\n AND tgt.IS_CURRENT = TRUE\nWHERE tgt.${upper}_BK IS NULL\n OR (tgt.ATTRIBUTE_1 IS DISTINCT FROM src.ATTRIBUTE_1\n OR tgt.ATTRIBUTE_2 IS DISTINCT FROM src.ATTRIBUTE_2);\n\nCOMMIT;\n`,\n };\n}\n\nfunction renderCurrentView(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Views/V_${upper}_CURRENT.sql`]:\n header(\n `Current-state view over an SCD2 table. Lets downstream consumers join on\n-- one canonical \"current row per BK\" target without remembering the\n-- IS_CURRENT predicate. Cheap — Snowflake filter-pushdown handles it.`,\n ) +\n `CREATE OR REPLACE VIEW ${c.db}.${c.schema}.V_${upper}_CURRENT\nCOMMENT = 'Current rows from ${upper} (SCD2). Join here instead of filtering IS_CURRENT manually.'\nAS\nSELECT *\nFROM ${c.db}.${c.schema}.${upper}\nWHERE IS_CURRENT = TRUE;\n`,\n };\n}\n\nfunction renderTimeSeries(c: Ctx, retentionDays: number): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `Time-series table — append-only, clustered by event timestamp so recent-event\n-- scans prune to a small number of micropartitions. DATA_RETENTION_TIME_IN_DAYS\n-- bounds Time Travel cost; aged-out rows must be archived elsewhere.`,\n ) +\n `${tableKw(c, upper)} (\n EVENT_ID NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id',\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n EVENT_TYPE VARCHAR COMMENT 'Discriminator — index of partition by event_type if useful',\n ENTITY_ID VARCHAR COMMENT 'Foreign key to the entity the event is about',\n PAYLOAD VARIANT COMMENT 'Event-specific payload (semistructured)',\n INGESTED_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When SDT loaded the row',\n ${pkConstraint(`PK_${upper}`, 'EVENT_ID', c)}\n)${clusterBy('EVENT_TS', c)}\nDATA_RETENTION_TIME_IN_DAYS = ${Math.max(1, Math.min(retentionDays, 90))}\nCOMMENT = 'Time-series ${upper}. Aged out beyond DATA_RETENTION_TIME_IN_DAYS; archive separately if you need longer history.';\n`,\n };\n}\n\nfunction renderAudit(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}_AUDIT.sql`]:\n header(\n `Audit log — append-only by convention. INSERT-only INSERT-only permissions on\n-- downstream roles enforce the \"append-only\" property; this table itself doesn't\n-- block updates, but the role grants do. Pair with a row-access policy if\n-- stronger guarantees are needed.`,\n ) +\n `${tableKw(c, `${upper}_AUDIT`)} (\n AUDIT_ID NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id',\n AUDIT_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the event was logged',\n ACTOR VARCHAR NOT NULL COMMENT 'Who performed the action (user / service-account)',\n ACTION VARCHAR NOT NULL COMMENT 'What happened (e.g. CREATE_USER, ROLE_GRANT)',\n TARGET VARCHAR COMMENT 'What it was performed on',\n DETAILS VARIANT COMMENT 'Free-form payload — keep it small',\n ${pkConstraint(`PK_${upper}_AUDIT`, 'AUDIT_ID', c)}\n)\nCOMMENT = 'Audit log for ${upper}. Append-only by convention — grant INSERT only to writer roles.';\n`,\n };\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { pac, project } from '@sdt-tools/core';\nimport type { SnowflakeObject } from '@sdt-tools/core/model';\n\n/**\n * `sdt anonymize` — generate masking-policy DDL for PII columns\n * discovered in a project model. Pairs with the L012 `pii-without-mask`\n * lint rule: the lint surfaces *which* columns need masking; this\n * command writes the policy DDL ready to copy into the project.\n *\n * Use case: refresh prod → dev pipeline. Most teams need to\n * pseudonymize PII before any non-prod role sees the data. This\n * command auto-generates a starter set of MASKING POLICY statements\n * + the ALTER TABLE ... ALTER COLUMN ... SET MASKING POLICY calls\n * to apply them.\n *\n * Output is intentionally **conservative**: every emitted policy has\n * `RETURN VAL` (no-op) when the current role is in `('PROD_ETL')` so\n * production keeps working as-is; every other role sees a hashed /\n * redacted value. Adjust the role allow-list before applying.\n */\nexport function anonymizeCommand(): Command {\n const cmd = new Command('anonymize');\n cmd\n .description('Generate MASKING POLICY DDL for PII columns detected in the project model.')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--unmasked-role <name>',\n \"Role the unmasked value is visible to. Default 'PROD_ETL'.\",\n 'PROD_ETL',\n )\n .option('-o, --out <path>', 'Output file path. Default: ./anonymize.sql in CWD.')\n .action(async (opts) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const unmaskedRole = String(opts.unmaskedRole);\n const candidates = collectPiiColumns(model);\n if (candidates.length === 0) {\n console.error(\n 'No PII columns detected (heuristic on column names: email, phone, ssn, dob, …).',\n );\n console.error(\n 'If the schema has PII you know about, add a MASKING POLICY by hand and re-run lint to confirm.',\n );\n return;\n }\n const sql = renderAnonymizeSql(candidates, unmaskedRole);\n const outPath = opts.out ? path.resolve(String(opts.out)) : path.resolve('anonymize.sql');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, sql, 'utf8');\n console.error(`Wrote ${outPath} (${candidates.length} column(s), ${sql.length} bytes).`);\n console.error(\n 'Review the role allow-list (`unmaskedRole`) before applying. Default fully hides values from every role except the one passed in.',\n );\n });\n return cmd;\n}\n\ninterface PiiColumn {\n fqn: string;\n column: string;\n category: 'email' | 'phone' | 'name' | 'dob' | 'ssn' | 'address' | 'credit-card' | 'generic';\n}\n\n/**\n * Heuristic PII detector — matches column names against a curated\n * list of likely PII patterns. Same patterns the L012 lint rule\n * uses. We pick the masking strategy from the category.\n */\nfunction collectPiiColumns(model: readonly SnowflakeObject[]): PiiColumn[] {\n const out: PiiColumn[] = [];\n for (const o of model) {\n if (o.objectType !== 'TABLE') continue;\n const rec = o as unknown as Record<string, unknown>;\n const cols = rec.columns as Array<{ name: string }> | undefined;\n if (!Array.isArray(cols)) continue;\n const fqn = [o.fqn.database, o.fqn.schema, o.fqn.name].filter(Boolean).join('.');\n for (const c of cols) {\n const category = classify(c.name);\n if (category) out.push({ fqn, column: c.name, category });\n }\n }\n return out;\n}\n\nfunction classify(name: string): PiiColumn['category'] | undefined {\n const lower = name.toLowerCase();\n if (/(^|_)email(_|$)/.test(lower)) return 'email';\n if (/(^|_)(phone|mobile|cell)(_|$)/.test(lower)) return 'phone';\n if (/(^|_)(first_name|last_name|full_name|surname|given_name)(_|$)/.test(lower)) return 'name';\n if (/(^|_)(dob|birth_date|date_of_birth)(_|$)/.test(lower)) return 'dob';\n if (/(^|_)ssn(_|$)/.test(lower) || /(^|_)tax_id(_|$)/.test(lower)) return 'ssn';\n if (/(^|_)(address|street|zip_code|postal_code|postcode)(_|$)/.test(lower)) return 'address';\n if (/(^|_)(credit_card|card_number)(_|$)/.test(lower)) return 'credit-card';\n return undefined;\n}\n\nfunction renderAnonymizeSql(cols: PiiColumn[], unmaskedRole: string): string {\n const lines: string[] = [];\n lines.push(`-- Generated by \\`sdt anonymize\\`.`);\n lines.push(\n `-- Edit the role allow-list before applying. Default: only ${unmaskedRole} sees unmasked values.`,\n );\n lines.push('');\n // One reusable policy per category; the policies belong in a shared schema.\n const categoriesNeeded = new Set(cols.map((c) => c.category));\n for (const cat of categoriesNeeded) {\n lines.push(`-- Masking policy for ${cat} columns`);\n lines.push(\n `CREATE OR ALTER MASKING POLICY MASK_${cat.toUpperCase().replace(/-/g, '_')} AS (val STRING) RETURNS STRING ->`,\n );\n lines.push(` CASE`);\n lines.push(` WHEN CURRENT_ROLE() IN ('${unmaskedRole}') THEN val`);\n lines.push(` ELSE ${maskExpression(cat)}`);\n lines.push(` END;`);\n lines.push('');\n }\n lines.push('-- Apply policies to columns');\n for (const c of cols) {\n lines.push(\n `ALTER TABLE ${c.fqn} MODIFY COLUMN ${c.column} SET MASKING POLICY MASK_${c.category.toUpperCase().replace(/-/g, '_')};`,\n );\n }\n lines.push('');\n return lines.join('\\n') + '\\n';\n}\n\nfunction maskExpression(cat: PiiColumn['category']): string {\n switch (cat) {\n case 'email':\n return `REGEXP_REPLACE(val, '^(.).*(@.*)$', '\\\\\\\\1***\\\\\\\\2')`;\n case 'phone':\n return `'***-***-' || RIGHT(val, 4)`;\n case 'ssn':\n return `'***-**-' || RIGHT(val, 4)`;\n case 'credit-card':\n return `'****-****-****-' || RIGHT(val, 4)`;\n case 'dob':\n return `LEFT(val, 4) || '-XX-XX'`;\n case 'name':\n case 'address':\n case 'generic':\n default:\n return `SHA2(val, 256)`;\n }\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","/**\n * `sdt safety` — inspect safety-finding codes.\n *\n * Subcommands:\n * sdt safety list — list every known finding code with a one-line summary\n * sdt safety explain <code> — deep explainer for a single code: why it is dangerous,\n * what cannot be reversed, safer alternatives, required gates\n *\n * The finding codes are stable identifiers attached to every `SafetyFinding`\n * the classifier emits during `sdt compare` / `sdt publish`. When the user\n * sees a finding they don't understand, they can copy the code and ask:\n *\n * sdt safety explain DROP_UNRECOVERABLE\n *\n * See `docs/UX_PLAYBOOK.md` §3 (dangerous-op UX) and\n * `docs/AI_FEATURES.md` use case C2.\n */\nimport { Command } from 'commander';\nimport { safety as safetyApi } from '@sdt-tools/core';\nimport type { FindingExplanation, SafetyFindingCode } from '@sdt-tools/core/safety';\nimport { logger } from '../util/logger.js';\n\nexport function safetyCommand(): Command {\n const cmd = new Command('safety');\n cmd.description(\n 'Inspect the safety-finding catalog. See `sdt safety list` and `sdt safety explain <code>`.',\n );\n\n cmd\n .command('list')\n .description('List every known finding code with category + one-line summary.')\n .option('--format <format>', 'Output format: table | json', 'table')\n .option(\n '--category <kind>',\n 'Filter to one category: unrecoverable | destructive | expensive | warning. Default: all.',\n )\n .action((opts: { format?: string; category?: string }) => {\n const codes = safetyApi.listFindingCodes();\n let entries = codes\n .map((c) => safetyApi.explainFinding(c))\n .filter((e): e is FindingExplanation => e !== undefined);\n if (opts.category) {\n const want = opts.category.toUpperCase();\n const valid = ['UNRECOVERABLE', 'DESTRUCTIVE', 'EXPENSIVE', 'WARNING'];\n if (!valid.includes(want)) {\n logger.error(\n `Unknown --category \"${opts.category}\". Use one of: ${valid.join(' | ').toLowerCase()}.`,\n );\n process.exitCode = 1;\n return;\n }\n entries = entries.filter((e) => e.category === want);\n }\n if ((opts.format ?? 'table') === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n logger.dim('(no entries match the filter)');\n return;\n }\n printList(entries);\n });\n\n cmd\n .command('explain')\n .description('Expand a finding code into a deep \"why this is dangerous\" page.')\n .argument('<code>', 'The finding code (e.g. DROP_UNRECOVERABLE, COLUMN_TYPE_CHANGE)')\n .option('--format <format>', 'Output format: text | json | markdown', 'text')\n .action((codeArg: string, opts: { format?: string }) => {\n const code = codeArg.toUpperCase() as SafetyFindingCode;\n const entry = safetyApi.explainFinding(code);\n if (!entry) {\n logger.error(`Unknown safety finding code: \"${codeArg}\"`);\n logger.dim(' Try: sdt safety list');\n process.exitCode = 1;\n return;\n }\n const format = (opts.format ?? 'text').toLowerCase();\n if (format === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n if (format === 'markdown') {\n process.stdout.write(renderMarkdown(entry) + '\\n');\n return;\n }\n printDeep(entry);\n });\n\n return cmd;\n}\n\nfunction printList(entries: readonly FindingExplanation[]): void {\n const byCategory = new Map<FindingExplanation['category'], FindingExplanation[]>();\n for (const e of entries) {\n const arr = byCategory.get(e.category) ?? [];\n arr.push(e);\n byCategory.set(e.category, arr);\n }\n const order: FindingExplanation['category'][] = [\n 'UNRECOVERABLE',\n 'DESTRUCTIVE',\n 'EXPENSIVE',\n 'WARNING',\n ];\n for (const cat of order) {\n const arr = byCategory.get(cat);\n if (!arr || arr.length === 0) continue;\n console.log(`# ${cat} (${arr.length})`);\n for (const e of arr) {\n console.log(` ${e.code}`);\n console.log(` ${e.title}`);\n console.log(` ${e.summary}`);\n }\n console.log('');\n }\n console.log('Use `sdt safety explain <code>` for the full per-finding write-up.');\n}\n\nfunction printDeep(entry: FindingExplanation): void {\n console.log(`${entry.code} [${entry.category}]`);\n console.log(entry.title);\n console.log('');\n console.log('Summary');\n console.log(` ${entry.summary}`);\n console.log('');\n console.log('Why this is dangerous');\n for (const line of wrap(entry.whyDangerous, 76)) {\n console.log(` ${line}`);\n }\n console.log('');\n console.log('What cannot be reversed');\n for (const item of entry.cannotBeReversed) console.log(` - ${item}`);\n console.log('');\n console.log('Safer alternatives');\n for (const item of entry.saferAlternatives) console.log(` - ${item}`);\n console.log('');\n if (entry.requiredGates.length > 0) {\n console.log('Required gates to allow this finding through');\n for (const g of entry.requiredGates) console.log(` - ${g}`);\n console.log('');\n }\n if (entry.example) {\n console.log('Example');\n console.log(` ${entry.example}`);\n }\n}\n\nfunction renderMarkdown(entry: FindingExplanation): string {\n const lines: string[] = [];\n lines.push(`## ${entry.code} — ${entry.title}`);\n lines.push('');\n lines.push(`**Category:** ${entry.category}`);\n lines.push('');\n lines.push(`**Summary:** ${entry.summary}`);\n lines.push('');\n lines.push('### Why this is dangerous');\n lines.push(entry.whyDangerous);\n lines.push('');\n lines.push('### What cannot be reversed');\n for (const item of entry.cannotBeReversed) lines.push(`- ${item}`);\n lines.push('');\n lines.push('### Safer alternatives');\n for (const item of entry.saferAlternatives) lines.push(`- ${item}`);\n if (entry.requiredGates.length > 0) {\n lines.push('');\n lines.push('### Required gates');\n for (const g of entry.requiredGates) lines.push(`- \\`${g}\\``);\n }\n if (entry.example) {\n lines.push('');\n lines.push('### Example');\n lines.push('```');\n lines.push(entry.example);\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\n/** Word-wrap a paragraph to fit `width` characters per line. */\nfunction wrap(text: string, width: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let current = '';\n for (const word of words) {\n if (current.length === 0) {\n current = word;\n } else if (current.length + 1 + word.length <= width) {\n current += ' ' + word;\n } else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines;\n}\n","/**\n * `sdt safer-alternative` — call the AI provider to suggest a safer DDL\n * alternative for a flagged-as-dangerous migration step.\n *\n * Composes `@sdt-tools/core/saferAlternative.suggestSaferAlternative` with the\n * configured AI provider (`@sdt-tools/core/ai.complete`). The CLI is the thin\n * adapter; all the prompt-building and parsing lives in core so the\n * VS Code CodeLens / MCP server / future hosts share the same behavior.\n *\n * Inputs (all surfaced as flags):\n * --code SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE)\n * --fqn Object FQN the finding refers to\n * --object-type Object type (e.g. TABLE, STREAM)\n * --reason Short reason from the safety classifier\n * --gate Optional SafetyGate (preserved on the suggestion)\n * --sql <path> Path to a file with the dangerous DDL (or \"-\" for stdin)\n * --context <path> Optional path to the surrounding source DDL\n * --intent <text> Optional human-authored intent notes\n * --format text | json (default text)\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, saferAlternative, type safety } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nexport function saferAlternativeCommand(): Command {\n const cmd = new Command('safer-alternative');\n cmd\n .description(\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (sdt ai status).',\n )\n .requiredOption('--code <code>', 'SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE).')\n .requiredOption('--fqn <fqn>', 'Object FQN the finding refers to.')\n .requiredOption('--object-type <type>', 'Object type (e.g. TABLE, VIEW, STREAM).')\n .requiredOption('--reason <text>', 'Short reason text from the safety classifier.')\n .option(\n '--gate <gate>',\n 'Optional SafetyGate the finding raised (e.g. REQUIRE_ALLOW_DROP_COLUMN).',\n )\n .option('--sql <path>', 'Path to a file with the dangerous DDL. Use \"-\" to read from stdin.')\n .option('--context <path>', 'Optional path to the surrounding source DDL.')\n .option('--intent <text>', 'Optional human-authored intent notes.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (opts) => {\n const dangerousSql = await readInput(\n opts.sql,\n '--sql is required (use a path or \"-\" for stdin).',\n );\n const contextSql = opts.context ? await fs.readFile(String(opts.context), 'utf8') : undefined;\n\n const finding: safety.SafetyFinding = {\n code: String(opts.code) as safety.SafetyFindingCode,\n category: 'DESTRUCTIVE',\n fqn: String(opts.fqn),\n objectType: String(opts.objectType) as safety.SafetyFinding['objectType'],\n reason: String(opts.reason),\n gate: opts.gate ? (String(opts.gate) as safety.SafetyGate) : undefined,\n };\n\n const result = await saferAlternative.suggestSaferAlternative(\n {\n finding,\n dangerousSql,\n contextSql,\n intentNotes: opts.intent ? String(opts.intent) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'safer-alternative',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n if (String(opts.format).toLowerCase() === 'json') {\n // Strip rawModelText from JSON output by default — it bloats the\n // payload for downstream tooling. Keep it accessible via --format text.\n const { rawModelText: _omit, ...keep } = result;\n console.log(JSON.stringify(keep, null, 2));\n return;\n }\n\n logger.success(\n `Confidence: ${result.confidence}${result.parseFailed ? ' (parse failed)' : ''}`,\n );\n logger.dim(`Reasoning: ${result.reasoning}`);\n if (result.alternativeSql) {\n console.log('');\n console.log('--- Proposed safer DDL ---');\n console.log(result.alternativeSql);\n } else {\n logger.warn('No safer alternative SQL was returned.');\n }\n if (result.requiredGates.length > 0) {\n logger.dim(`Required gates: ${result.requiredGates.join(', ')}`);\n }\n });\n return cmd;\n}\n\nasync function readInput(pathOrDash: unknown, missingMessage: string): Promise<string> {\n if (!pathOrDash) throw new Error(missingMessage);\n const p = String(pathOrDash);\n if (p === '-') {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n }\n return fs.readFile(p, 'utf8');\n}\n","/**\n * `sdt sketch <kind>` — generate idiomatic Snowflake DDL from a free-form\n * prose description via the configured AI provider.\n *\n * Composes `@sdt-tools/core/objectSketch.sketchToDdl` with `@sdt-tools/core/ai.complete`.\n * Output is always wrapped in a \"REVIEW BEFORE DEPLOY\" header so the user\n * never confuses model output with hand-authored DDL.\n *\n * Inputs:\n * <kind> table | view | materialized-view | stream | task\n * | dynamic-table | procedure | function | sequence\n * --description <text> Free-form description (or \"-\" to read from stdin)\n * --target <fqn> Optional target FQN (e.g. ANALYTICS.PUBLIC.ORDERS)\n * --context <text> Optional additional context\n * --out <path> Optional output file. Default: stdout.\n * --format <fmt> text | json. Default text (just the DDL).\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, objectSketch } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nconst KINDS = [\n 'table',\n 'view',\n 'materialized-view',\n 'stream',\n 'task',\n 'dynamic-table',\n 'procedure',\n 'function',\n 'sequence',\n] as const;\n\ntype Kind = (typeof KINDS)[number];\n\nexport function sketchCommand(): Command {\n const cmd = new Command('sketch');\n cmd\n .description(\n 'AI-assist: scaffold idiomatic Snowflake DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n )\n .argument('<kind>', `Object kind: ${KINDS.join(' | ')}`)\n .requiredOption('--description <text>', 'Free-form description. Use \"-\" to read from stdin.')\n .option('--target <fqn>', 'Target FQN (e.g. ANALYTICS.PUBLIC.ORDERS).')\n .option('--context <text>', 'Optional additional context (e.g. \"use role MERGE_OPS\").')\n .option('--out <path>', 'Output file. Default stdout.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (kindArg, opts) => {\n const kind = String(kindArg).toLowerCase() as Kind;\n if (!KINDS.includes(kind)) {\n throw new Error(`Unknown kind \"${kindArg}\". Use one of: ${KINDS.join(' | ')}`);\n }\n\n const description =\n String(opts.description) === '-' ? await readStdin() : String(opts.description);\n const targetFqn = opts.target ? splitFqn(String(opts.target)) : undefined;\n\n const result = await objectSketch.sketchToDdl(\n {\n description,\n objectKind: kind,\n targetFqn,\n additionalContext: opts.context ? String(opts.context) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'object-sketch',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n const output =\n String(opts.format).toLowerCase() === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined } /* strip raw for JSON */, null, 2)\n : result.generatedSql;\n\n if (opts.out) {\n await fs.writeFile(String(opts.out), output, 'utf8');\n logger.success(`Wrote ${String(opts.out)} (${output.length} bytes)`);\n } else {\n console.log(output);\n }\n\n // Surface assumptions on stderr so they're visible even when stdout\n // is redirected into a project file.\n if (result.assumptions.length > 0) {\n logger.dim('');\n logger.dim('Model assumptions:');\n for (const a of result.assumptions) logger.dim(` - ${a}`);\n }\n if (result.parseFailed) {\n logger.warn('Model output could not be parsed — see the raw text via --format json.');\n }\n });\n return cmd;\n}\n\nfunction splitFqn(fqn: string): { database?: string; schema?: string; name: string } {\n const parts = fqn.split('.');\n if (parts.length === 1) return { name: parts[0]! };\n if (parts.length === 2) return { schema: parts[0], name: parts[1]! };\n if (parts.length === 3) return { database: parts[0], schema: parts[1], name: parts[2]! };\n throw new Error(`Invalid --target \"${fqn}\": expected 1, 2, or 3 dot-separated parts.`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `sdt compare-profiles` — manage saved comparison profiles.\n *\n * A profile is \"Source X (connection|pac|project) → Target Y, with these\n * mapping rules\", persisted to `<cwd>/.sdt/compare-profiles.json`. The\n * eventual VS Code webview reads/writes the same store; this CLI gives\n * power-users the same affordances headlessly.\n *\n * Subcommands:\n * list — list all saved profiles (table or JSON)\n * show <id> — print one profile (table or JSON)\n * save — upsert a profile from a JSON file (--json-file <path>) or stdin\n * remove <id> — delete a profile\n * preview <id> — run `previewMatch` over the saved profile's\n * source + target endpoints and report counts +\n * examples of matched / source-only / target-only\n * FQNs. Catches typo'd schema names before a\n * full extract + diff round-trip.\n *\n * `preview` resolves each endpoint locally:\n * - kind=connection — reads the EE1 catalog cache at\n * `<root>/.sdt/cache/<reference>/catalog.msgpack` (legacy\n * `catalog.json` also accepted). Run\n * `sdt catalog refresh --connection <reference>` first.\n * - kind=pac — reads the `.sdtpac` archive at `reference`.\n * - kind=project — reads the `.sdtproj` at `reference`.\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog, compareProfiles, pac, project } from '@sdt-tools/core';\nimport type { FullyQualifiedName, SnowflakeObject } from '@sdt-tools/core/model';\nimport { logger } from '../util/logger.js';\n\nexport function compareProfilesCommand(): Command {\n const cmd = new Command('compare-profiles');\n cmd.description('Manage saved compare profiles (.sdt/compare-profiles.json).');\n\n cmd\n .command('list')\n .description('List every saved profile.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const all = await store.list();\n if (opts.json) {\n console.log(JSON.stringify(all, null, 2));\n return;\n }\n if (all.length === 0) {\n logger.dim('(no compare profiles saved yet)');\n logger.dim(` store: ${store.path}`);\n return;\n }\n logger.success(`${all.length} compare profile(s):`);\n for (const p of all) {\n console.log(` ${p.id.padEnd(24)} ${p.name}`);\n logger.dim(` source: ${p.source.kind}=${p.source.reference}`);\n logger.dim(` target: ${p.target.kind}=${p.target.reference}`);\n logger.dim(` mappings: ${p.mappings.length} updated: ${p.updatedAt}`);\n }\n });\n\n cmd\n .command('show')\n .description('Show one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const p = await store.get(String(id));\n if (!p) {\n logger.error(`No profile with id \"${id}\". Run \\`sdt compare-profiles list\\` to enumerate.`);\n process.exitCode = 1;\n return;\n }\n if (opts.json) {\n console.log(JSON.stringify(p, null, 2));\n return;\n }\n logger.success(`Profile: ${p.name} (${p.id})`);\n if (p.description) logger.dim(` ${p.description}`);\n logger.dim(\n ` source: ${p.source.kind}=${p.source.reference}${p.source.database ? ` db=${p.source.database}` : ''}${p.source.schema ? ` schema=${p.source.schema}` : ''}`,\n );\n logger.dim(\n ` target: ${p.target.kind}=${p.target.reference}${p.target.database ? ` db=${p.target.database}` : ''}${p.target.schema ? ` schema=${p.target.schema}` : ''}`,\n );\n logger.dim(` case-sensitive: ${p.caseSensitive ? 'yes' : 'no'}`);\n logger.dim(` rewrite-inside-strings: ${p.rewriteInsideStrings ? 'yes' : 'no'}`);\n logger.dim(` updatedAt: ${p.updatedAt}`);\n if (p.mappings.length === 0) {\n logger.dim(' mappings: (none — identity)');\n } else {\n logger.dim(` mappings (${p.mappings.length}):`);\n for (const m of p.mappings) logger.dim(` ${m.source} => ${m.target}`);\n }\n });\n\n cmd\n .command('save')\n .description('Upsert a profile from a JSON file or stdin.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json-file <path>', 'Path to a JSON file containing one profile. Use \"-\" for stdin.')\n .action(async (opts) => {\n if (!opts.jsonFile) {\n throw new Error('--json-file is required (use a path or \"-\" for stdin).');\n }\n const raw =\n String(opts.jsonFile) === '-'\n ? await readStdin()\n : await fs.readFile(String(opts.jsonFile), 'utf8');\n const parsed = JSON.parse(raw) as compareProfiles.CompareProfile;\n if (!parsed?.id || !parsed?.name || !parsed?.source || !parsed?.target) {\n throw new Error(\n 'Profile JSON must contain at minimum: id, name, source, target. mappings defaults to [].',\n );\n }\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const stamped = await store.upsert({ ...parsed, mappings: parsed.mappings ?? [] });\n logger.success(`Saved profile \"${stamped.name}\" (${stamped.id})`);\n logger.dim(` store: ${store.path}`);\n });\n\n cmd\n .command('remove')\n .description('Delete one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const removed = await store.remove(String(id));\n if (removed) {\n logger.success(`Removed profile \"${id}\".`);\n } else {\n logger.warn(`No profile with id \"${id}\" — nothing to remove.`);\n }\n });\n\n cmd\n .command('preview')\n .description(\n \"Preview which FQNs match between the profile's source and target. Local-only — no warehouse round-trip.\",\n )\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option(\n '--examples <n>',\n 'Max example FQNs to show per bucket in human output. Default 5.',\n (v) => parseInt(v, 10),\n 5,\n )\n .option('--json', 'Emit the full PreviewSummary as JSON.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const profile = await store.get(String(id));\n if (!profile) {\n logger.error(`No profile with id \"${id}\". Run \\`sdt compare-profiles list\\` to enumerate.`);\n process.exitCode = 1;\n return;\n }\n\n const root = String(opts.root);\n const source = await resolveEndpointFqns(profile.source, root);\n const target = await resolveEndpointFqns(profile.target, root);\n\n const summary = compareProfiles.previewMatch({\n source: source.fqns,\n target: target.fqns,\n mappings: profile.mappings,\n ...(profile.caseSensitive ? { caseSensitive: true } : {}),\n });\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n profile: { id: profile.id, name: profile.name },\n source: {\n kind: profile.source.kind,\n reference: profile.source.reference,\n count: source.fqns.length,\n },\n target: {\n kind: profile.target.kind,\n reference: profile.target.reference,\n count: target.fqns.length,\n },\n summary,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n logger.success(`Preview: ${profile.name} (${profile.id})`);\n logger.dim(\n ` source (${profile.source.kind}=${profile.source.reference}): ${source.fqns.length} object(s)${source.note ? ` — ${source.note}` : ''}`,\n );\n logger.dim(\n ` target (${profile.target.kind}=${profile.target.reference}): ${target.fqns.length} object(s)${target.note ? ` — ${target.note}` : ''}`,\n );\n console.log('');\n console.log(` matched: ${summary.matchedCount}`);\n console.log(` source-only: ${summary.sourceOnlyCount}`);\n console.log(` target-only: ${summary.targetOnlyCount}`);\n\n const exN = Math.max(0, Number(opts.examples));\n printBucket('matched', summary.matched, exN);\n printBucket('source-only', summary.sourceOnly, exN);\n printBucket('target-only', summary.targetOnly, exN);\n\n if (\n summary.matchedCount === 0 &&\n (summary.sourceOnlyCount > 0 || summary.targetOnlyCount > 0)\n ) {\n logger.warn(\"No FQNs matched — check the profile's scope and mapping rules.\");\n }\n });\n\n return cmd;\n}\n\ninterface EndpointResolution {\n fqns: FullyQualifiedName[];\n note?: string;\n}\n\nasync function resolveEndpointFqns(\n endpoint: compareProfiles.CompareProfile['source'],\n root: string,\n): Promise<EndpointResolution> {\n if (endpoint.kind === 'connection') {\n const cache = new catalog.CatalogCache({ root, connection: endpoint.reference });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0) {\n return {\n fqns: [],\n note: `empty catalog cache at ${cache.path} — run \\`sdt catalog refresh --connection ${endpoint.reference}\\` first`,\n };\n }\n return { fqns: fqnsFromSnapshot(snapshot, endpoint.database, endpoint.schema) };\n }\n if (endpoint.kind === 'pac') {\n const contents = await pac.readPac(endpoint.reference);\n return { fqns: fqnsFromObjects(contents.model, endpoint.database, endpoint.schema) };\n }\n // kind === 'project'\n const loaded = await project.loadProject(endpoint.reference);\n const model = await project.parseProjectModel(loaded);\n return { fqns: fqnsFromObjects(model, endpoint.database, endpoint.schema) };\n}\n\nfunction fqnsFromSnapshot(\n snapshot: catalog.CatalogSnapshot,\n databaseScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const db of snapshot.databases) {\n if (databaseScope && !sameId(db.database, databaseScope)) continue;\n for (const sc of db.schemas) {\n if (schemaScope && !sameId(sc.schema, schemaScope)) continue;\n for (const obj of sc.objects) {\n out.push({ database: obj.database, schema: obj.schema, name: obj.name });\n }\n }\n }\n return out;\n}\n\nfunction fqnsFromObjects(\n model: readonly SnowflakeObject[],\n databaseScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const obj of model) {\n if (databaseScope && !sameId(obj.fqn.database, databaseScope)) continue;\n if (schemaScope && !sameId(obj.fqn.schema, schemaScope)) continue;\n out.push(obj.fqn);\n }\n return out;\n}\n\nfunction printBucket(label: string, items: readonly string[], exampleN: number): void {\n if (items.length === 0) return;\n console.log('');\n console.log(\n ` ${label} examples (showing ${Math.min(exampleN, items.length)} of ${items.length}):`,\n );\n for (const fqn of items.slice(0, exampleN)) console.log(` ${fqn}`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `sdt explorer` — ASCII tree dump of the live db/schema/object hierarchy\n * for a connected target, read from the EE1 catalog cache.\n *\n * The eventual VS Code TreeDataProvider walks the same `treeForSnapshot`\n * shape; this CLI gives non-VS-Code users the same browsable view of the\n * cached catalog. No live queries are issued — the cache is read-only.\n * Run `sdt catalog refresh --connection <name>` first to populate it.\n *\n * Inputs:\n * --connection <name> Required. Connection profile name to load the cache for.\n * --root <path> Project root (where .sdt/cache/ lives). Default cwd.\n * --filter <query> Typeahead filter; case-insensitive substring match.\n * Keeps every ancestor of a leaf match.\n * --json Emit the tree as JSON instead of an ASCII tree.\n */\nimport { Command } from 'commander';\nimport { catalog, objectExplorer } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nexport function explorerCommand(): Command {\n const cmd = new Command('explorer');\n cmd\n .description(\n 'ASCII tree dump of the cached catalog for a connection. Run `sdt catalog refresh` first to populate.',\n )\n .requiredOption('--connection <name>', 'Connection profile name (the cache subfolder).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--filter <query>', 'Typeahead substring filter (case-insensitive).')\n .option(\n '--depth <n>',\n 'Truncate tree at depth N (0 = root only, 1 = +databases, 2 = +schemas, 3 = +object-groups, 4 = +objects). Default unlimited.',\n (v) => parseInt(v, 10),\n )\n .option('--json', 'Emit tree as JSON instead of ASCII.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n let tree = objectExplorer.treeForSnapshot(snapshot);\n if (opts.filter) tree = objectExplorer.filterTree(tree, String(opts.filter));\n if (typeof opts.depth === 'number') tree = objectExplorer.truncateTree(tree, opts.depth);\n\n if (snapshot.databases.length === 0) {\n logger.warn(`Catalog cache is empty for connection \"${opts.connection}\".`);\n logger.dim(` Cache file: ${cache.path}`);\n logger.dim(` Run \\`sdt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n\n if (opts.json) {\n console.log(JSON.stringify(tree, null, 2));\n return;\n }\n\n renderAsciiTree(tree);\n });\n return cmd;\n}\n\n/**\n * Render the explorer tree as an ASCII tree (├──, │, └──). Mirrors the\n * GNU `tree`(1) glyph set for familiarity. Root prints without a\n * connector; descendants get the standard branch glyphs.\n */\nfunction renderAsciiTree(root: objectExplorer.ExplorerNode): void {\n const desc = root.description ? ` (${root.description})` : '';\n console.log(`${root.label}${desc}`);\n const children = root.children ?? [];\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, '', i === children.length - 1);\n }\n}\n\nfunction renderChild(node: objectExplorer.ExplorerNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const desc = node.description ? ` (${node.description})` : '';\n console.log(`${prefix}${connector}${node.label}${desc}`);\n const children = node.children ?? [];\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, childPrefix, i === children.length - 1);\n }\n}\n","/**\n * `sdt catalog` — manage the per-connection catalog cache (EE1 substrate).\n *\n * sdt catalog refresh --connection <name> [--databases <csv>] [--concurrency <n>]\n * sdt catalog show --connection <name> [--json]\n * sdt catalog clear --connection <name>\n *\n * `refresh` opens a live Snowflake connection, discovers databases via\n * `SHOW DATABASES`, runs the bulk-scan SQL per database via the bounded\n * promise pool, and writes the assembled snapshot to\n * `<root>/.sdt/cache/<conn>/catalog.msgpack` (RES.1 — was `catalog.json`\n * before 2026-05-16; the cache reader still accepts the legacy form for\n * one major version). Schema fingerprints (`MAX(LAST_ALTERED)`) are\n * checked first; databases that haven't changed since the last refresh\n * are skipped.\n *\n * `show` reads the cache file and pretty-prints (or emits JSON).\n * `clear` deletes the cache file (and its parent dir if empty).\n *\n * Object Explorer (`sdt explorer`) and the eventual EE2 intellisense\n * provider both consume this cache.\n */\nimport { Command } from 'commander';\nimport { catalog } from '@sdt-tools/core';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\n\n/**\n * Built-in databases that almost no one wants in their cache. Pass\n * `--include-builtins` to keep them.\n */\nconst BUILTIN_DATABASES = new Set(['SNOWFLAKE', 'SNOWFLAKE_SAMPLE_DATA', 'UTIL_DB']);\n\ninterface ShowDatabasesRow {\n name?: string;\n NAME?: string;\n}\n\nexport function catalogCommand(): Command {\n const cmd = new Command('catalog');\n cmd.description(\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n );\n\n cmd\n .command('refresh')\n .description('Open the connection, scan every (non-builtin) database, write the catalog cache.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--databases <csv>', 'Comma-separated list. Default: every non-builtin database.')\n .option('--include-builtins', 'Include SNOWFLAKE / SNOWFLAKE_SAMPLE_DATA / UTIL_DB.', false)\n .option(\n '--concurrency <n>',\n 'Bounded-concurrency cap for the bulk-scan pool. Default 10.',\n '10',\n )\n .option('--no-fingerprint-skip', 'Force a full scan even when fingerprints are unchanged.')\n .action(async (opts) => {\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: profile.name,\n });\n\n logger.step(`Connecting to ${profile.account} as ${profile.auth.username}…`);\n await conn.connect();\n try {\n const dbs = await resolveDatabases(conn, opts);\n if (dbs.length === 0) {\n logger.warn('No databases to scan. Pass --databases or --include-builtins.');\n return;\n }\n logger.dim(\n `Scanning ${dbs.length} database(s) with concurrency ${Number(opts.concurrency)}.`,\n );\n\n const cached = await cache.get();\n const cachedByDb = new Map(cached.databases.map((d) => [d.database, d] as const));\n\n const concurrency = Math.max(1, Number(opts.concurrency) || 10);\n const fingerprintSkip = opts.fingerprintSkip !== false;\n\n const { results, errors } = await catalog.mapPool(\n dbs,\n async (db) => {\n // Cheap fingerprint probe first.\n let freshFingerprint: number | null = null;\n try {\n const fpRes = await conn.query<{ MAX_LAST_ALTERED: unknown }>(\n catalog.fingerprintSqlForDatabase(db),\n );\n freshFingerprint = catalog.parseFingerprintRow(fpRes.rows);\n } catch (err) {\n logger.warn(\n `fingerprint(${db}) failed; falling through to full scan: ${(err as Error).message}`,\n );\n }\n\n const cachedDb = cachedByDb.get(db);\n if (\n fingerprintSkip &&\n cachedDb &&\n cachedDb.fingerprint != null &&\n freshFingerprint != null &&\n catalog.isFresh(cachedDb.fingerprint, freshFingerprint)\n ) {\n logger.dim(` ${db}: fresh; reusing cache`);\n return { database: db, fingerprint: cachedDb.fingerprint, schemas: cachedDb.schemas };\n }\n\n const scanRes = await conn.query(catalog.bulkScanSqlForDatabase(db));\n const schemas = catalog.parseBulkScanRows(db, scanRes.rows);\n const fingerprint = freshFingerprint ?? null;\n logger.dim(\n ` ${db}: ${schemas.length} schemas / ${schemas.reduce((sum, s) => sum + s.objects.length, 0)} objects`,\n );\n return { database: db, fingerprint, schemas };\n },\n { concurrency },\n );\n\n for (const e of errors) {\n logger.warn(`scan failed for \"${dbs[e.index]}\": ${(e.error as Error).message}`);\n }\n\n const snapshot = catalog.refreshFingerprints({\n version: catalog.CATALOG_SNAPSHOT_VERSION,\n connection: profile.name,\n snapshotAt: new Date().toISOString(),\n fingerprint: null,\n databases: results.filter((r): r is NonNullable<typeof r> => !!r),\n });\n await cache.set(snapshot);\n\n logger.success(`Wrote ${snapshot.databases.length} databases to ${cache.path}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n cmd\n .command('show')\n .description('Pretty-print or JSON-dump the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of summary.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n if (opts.json) {\n console.log(JSON.stringify(snapshot, null, 2));\n return;\n }\n if (snapshot.databases.length === 0) {\n logger.warn(`Catalog cache is empty for \"${opts.connection}\".`);\n logger.dim(` Cache file: ${cache.path}`);\n logger.dim(` Run \\`sdt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n logger.success(`Snapshot for \"${snapshot.connection}\" — ${snapshot.snapshotAt}`);\n logger.dim(\n ` Top-level fingerprint: ${snapshot.fingerprint != null ? new Date(snapshot.fingerprint).toISOString() : '(none)'}`,\n );\n for (const db of snapshot.databases) {\n const objCount = db.schemas.reduce((sum, s) => sum + s.objects.length, 0);\n console.log(\n ` ${db.database.padEnd(32)} ${db.schemas.length} schemas / ${objCount} objects`,\n );\n }\n });\n\n cmd\n .command('clear')\n .description('Delete the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n await cache.clear();\n logger.success(`Cleared cache for \"${opts.connection}\".`);\n logger.dim(` was: ${cache.path}`);\n });\n\n return cmd;\n}\n\nasync function resolveDatabases(\n conn: SnowflakeConnection,\n opts: { databases?: unknown; includeBuiltins?: unknown },\n): Promise<string[]> {\n if (opts.databases) {\n return String(opts.databases)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n const res = await conn.query<ShowDatabasesRow>('SHOW DATABASES');\n const names = res.rows.map((r) => String(r.name ?? r.NAME ?? '')).filter(Boolean);\n if (opts.includeBuiltins) return names;\n return names.filter((n) => !BUILTIN_DATABASES.has(n.toUpperCase()));\n}\n","/**\n * `sdt exec <file.sql> --profiles <list>` — AUTH.3.\n *\n * Runs a SQL script on one or more connection profiles in parallel and\n * prints a merged report. Guarded against any profile whose name matches\n * the word \"prod\" or \"production\" (case-insensitive) unless `--yes` is\n * passed.\n *\n * Mirrors `Databricks/packages/cli/src/commands/exec.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { queryExecution } from '@sdt-tools/core';\n\nexport interface ExecResult {\n profile: string;\n status: 'success' | 'error';\n rowsAffected?: number;\n durationMs: number;\n error?: string;\n}\n\nexport type ExecFn = (\n profile: string,\n sql: string,\n timeoutMs: number,\n) => Promise<Omit<ExecResult, 'profile' | 'durationMs'>>;\n\nconst PROD_PATTERN = /\\bprod(uction)?\\b/i;\n\nfunction isProductionProfile(name: string): boolean {\n return PROD_PATTERN.test(name);\n}\n\nasync function runOnProfile(\n execFn: ExecFn,\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<ExecResult> {\n const start = Date.now();\n try {\n const res = await execFn(profile, sql, timeoutMs);\n return { ...res, profile, durationMs: Date.now() - start };\n } catch (err) {\n return {\n profile,\n status: 'error',\n durationMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction renderText(results: ExecResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.status === 'success') {\n const rows = r.rowsAffected !== undefined ? ` (${r.rowsAffected} rows)` : '';\n lines.push(` ${r.profile}: ✓${rows} — ${(r.durationMs / 1000).toFixed(1)}s`);\n } else {\n lines.push(` ${r.profile}: ✗ ${r.error ?? 'unknown error'}`);\n }\n }\n const total = results.length;\n const succeeded = results.filter((r) => r.status === 'success').length;\n lines.push(`\\n${succeeded}/${total} profiles succeeded.`);\n return lines.join('\\n');\n}\n\n/**\n * Wire to the real Snowflake connection layer:\n * 1. Resolve the named profile (`~/.sdt/profiles.json`).\n * 2. Open a connection; on failure surface the underlying SDK error.\n * 3. Split the SQL via the shared `queryExecution.splitStatements`\n * (string-/comment-/dollar-quote-aware) and run each statement\n * sequentially through `SnowflakeConnection.query`. We do NOT\n * `failFast` so a script with N statements surfaces every error.\n * 4. Aggregate: success iff every statement succeeded; the first\n * error's message becomes the profile-level error. Total\n * `rowsAffected` is the sum of rowCount across statements.\n *\n * Injectable for tests via the `execFn` parameter on `execCommand`.\n */\nasync function defaultExecFn(\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<Omit<ExecResult, 'profile' | 'durationMs'>> {\n const profileObj = await getProfile(profile);\n const conn = new SnowflakeConnection(profileObj);\n await conn.connect();\n try {\n const timeoutSeconds = Math.max(1, Math.ceil(timeoutMs / 1000));\n const runner: queryExecution.QueryRunner = {\n executeStatement: async (statement: string) => {\n const result = await conn.query(statement, { timeoutSeconds });\n return {\n rows: result.rows as Record<string, unknown>[],\n durationMs: result.durationMs,\n };\n },\n };\n const result = await queryExecution.executeStatements(sql, runner, {\n failFast: false,\n toolName: 'sdt',\n });\n const firstError = result.statements.find((s) => s.error);\n if (firstError && firstError.error) {\n throw new Error(firstError.error.message);\n }\n const rowsAffected = result.statements.reduce((acc, s) => acc + (s.rowCount ?? 0), 0);\n return { status: 'success', rowsAffected };\n } finally {\n await conn.disconnect().catch(() => {\n /* best-effort cleanup */\n });\n }\n}\n\nexport function execCommand(execFn: ExecFn = defaultExecFn): Command {\n const cmd = new Command('exec');\n cmd\n .description('Run a SQL script on one or more connection profiles in parallel.')\n .argument('<file>', 'Path to the .sql file to execute.')\n .requiredOption('--profiles <list>', 'Comma-separated connection profile names.')\n .option('--yes', 'Confirm execution against production profiles without prompting.')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--timeout <ms>', 'Per-profile timeout in milliseconds.', '30000')\n .action(async (file: string, opts) => {\n const profiles = (opts.profiles as string)\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (profiles.length === 0) throw new Error('--profiles must list at least one profile.');\n\n const prodProfiles = profiles.filter(isProductionProfile);\n if (prodProfiles.length > 0 && !opts.yes) {\n throw new Error(\n `Profile(s) look like production: ${prodProfiles.join(', ')}. ` +\n `Pass --yes to confirm.`,\n );\n }\n\n let sql: string;\n try {\n sql = await fs.readFile(file, 'utf8');\n } catch {\n throw new Error(`Cannot read file: ${file}`);\n }\n if (!sql.trim()) throw new Error(`File is empty: ${file}`);\n\n const timeoutMs = parseInt(String(opts.timeout ?? '30000'), 10);\n const results = await Promise.all(\n profiles.map((p) => runOnProfile(execFn, p, sql, timeoutMs)),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n const failed = results.filter((r) => r.status === 'error').length;\n process.stdout.write(\n JSON.stringify(\n {\n results,\n summary: {\n total: results.length,\n succeeded: results.length - failed,\n failed,\n },\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n process.stdout.write(renderText(results) + '\\n');\n });\n return cmd;\n}\n","/**\n * `sdt search <pattern> --profiles <list|all>` — AUTH.4.\n *\n * Finds objects whose name matches a pattern across one or more connection\n * profiles. Surfaces presence/absence drift: if an object exists in some\n * profiles but not others, those profiles are flagged.\n *\n * The search is case-insensitive substring match by default; --exact\n * switches to exact name match; --type filters by objectType.\n *\n * Mirrors `Databricks/packages/cli/src/commands/search.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { catalog } from '@sdt-tools/core';\n\nexport interface SearchMatch {\n profile: string;\n fqn: string;\n objectType: string;\n}\n\nexport interface SearchResult {\n profile: string;\n matches: SearchMatch[];\n error?: string;\n}\n\nexport interface SearchFnOptions {\n exact: boolean;\n objectType?: string;\n /** Project / cache root. Defaults to `process.cwd()`. */\n root?: string;\n}\n\nexport type SearchFn = (\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n) => Promise<SearchMatch[]>;\n\nfunction buildDriftReport(results: SearchResult[]): string {\n const allFqns = new Set<string>();\n const byFqn = new Map<string, Set<string>>();\n for (const r of results) {\n if (r.error) continue;\n for (const m of r.matches) {\n allFqns.add(m.fqn);\n if (!byFqn.has(m.fqn)) byFqn.set(m.fqn, new Set());\n byFqn.get(m.fqn)!.add(r.profile);\n }\n }\n const successProfiles = results.filter((r) => !r.error).map((r) => r.profile);\n const driftLines: string[] = [];\n for (const fqn of allFqns) {\n const present = byFqn.get(fqn)!;\n if (present.size < successProfiles.length) {\n const absent = successProfiles.filter((p) => !present.has(p));\n driftLines.push(\n ` DRIFT ${fqn} [present: ${[...present].join(', ')} absent: ${absent.join(', ')}]`,\n );\n }\n }\n return driftLines.join('\\n');\n}\n\nfunction renderText(results: SearchResult[], showDrift: boolean): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.error) {\n lines.push(`[${r.profile}] ERROR: ${r.error}`);\n continue;\n }\n if (r.matches.length === 0) {\n lines.push(`[${r.profile}] no matches`);\n } else {\n for (const m of r.matches) {\n lines.push(`[${r.profile}] ${m.fqn} (${m.objectType})`);\n }\n }\n }\n if (showDrift) {\n const drift = buildDriftReport(results);\n if (drift) {\n lines.push('');\n lines.push('--- Drift detected ---');\n lines.push(drift);\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadProfileNames(profilesOpt: string, profilesDir: string): Promise<string[]> {\n if (profilesOpt.toLowerCase() !== 'all') {\n return profilesOpt\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n }\n // Scan profiles directory for known profile files\n try {\n const entries = await fs.readdir(profilesDir);\n return entries\n .filter((e) => e.endsWith('.json') || e.endsWith('.toml'))\n .map((e) => path.basename(e, path.extname(e)));\n } catch {\n return [];\n }\n}\n\n/**\n * Wire to the on-disk catalog cache (`<root>/.sdt/cache/<profile>/catalog.msgpack`\n * written by `sdt catalog refresh` / `sdt extract --write-catalog-cache`).\n *\n * 1. Open `catalog.CatalogCache({root, connection: profile})`.\n * 2. Read the snapshot — `get()` returns an empty snapshot when the\n * file is absent / corrupt / version-mismatched.\n * 3. If the snapshot is empty, surface an actionable error naming\n * the expected file path and the two commands that populate it.\n * 4. Walk every (database, schema, object), filter by `--type`, then\n * match the name (case-insensitive substring by default, exact\n * when `--exact` is set), and return `SearchMatch[]` with the\n * fully-qualified `database.schema.name`.\n *\n * Injectable for tests via the `searchFn` parameter on `searchCommand`.\n */\nasync function defaultSearchFn(\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n): Promise<SearchMatch[]> {\n const root = opts.root ?? process.cwd();\n const cache = new catalog.CatalogCache({ root, connection: profile });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0) {\n throw new Error(\n `No catalog cache for profile \"${profile}\" at ${cache.path}. ` +\n `Run \\`sdt catalog refresh --connection ${profile} --root ${root}\\` ` +\n `or \\`sdt extract --connection ${profile} --output ${root} --write-catalog-cache\\` first.`,\n );\n }\n const needle = pattern.toLowerCase();\n const typeFilter = opts.objectType ? opts.objectType.toUpperCase() : undefined;\n const matches: SearchMatch[] = [];\n for (const db of snapshot.databases) {\n for (const schema of db.schemas) {\n for (const obj of schema.objects) {\n if (typeFilter && obj.objectType !== typeFilter) continue;\n const name = obj.name.toLowerCase();\n const hit = opts.exact ? name === needle : name.includes(needle);\n if (hit) {\n matches.push({\n profile,\n fqn: `${obj.database}.${obj.schema}.${obj.name}`,\n objectType: obj.objectType,\n });\n }\n }\n }\n }\n return matches;\n}\n\nexport function searchCommand(searchFn: SearchFn = defaultSearchFn): Command {\n const cmd = new Command('search');\n cmd\n .description('Find objects matching a name pattern across one or more connection profiles.')\n .argument('<pattern>', 'Name pattern to search for (case-insensitive substring).')\n .requiredOption(\n '--profiles <list|all>',\n 'Comma-separated profile names, or \"all\" to scan every configured profile.',\n )\n .option('--exact', 'Exact name match instead of substring.', false)\n .option('--type <objectType>', 'Filter results to a specific object type (e.g. TABLE, VIEW).')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option(\n '--profiles-dir <dir>',\n 'Directory to scan when --profiles all is used.',\n path.join(os.homedir(), '.sdt', 'connections'),\n )\n .option(\n '--root <dir>',\n 'Project / cache root containing the .sdt/cache directory. Default: cwd.',\n process.cwd(),\n )\n .option('--no-drift', 'Suppress the drift section in text output.')\n .action(async (pattern: string, opts) => {\n const profiles = await loadProfileNames(opts.profiles as string, opts.profilesDir as string);\n if (profiles.length === 0) {\n throw new Error(\n opts.profiles.toLowerCase() === 'all'\n ? `No profiles found in ${opts.profilesDir}. Run \\`sdt connection add\\` first.`\n : '--profiles must list at least one profile.',\n );\n }\n\n const results: SearchResult[] = await Promise.all(\n profiles.map(async (p) => {\n try {\n const matches = await searchFn(p, pattern, {\n exact: opts.exact as boolean,\n objectType: opts.type as string | undefined,\n root: opts.root as string,\n });\n return { profile: p, matches };\n } catch (err) {\n return {\n profile: p,\n matches: [],\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(results, null, 2) + '\\n');\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n const text = renderText(results, opts.drift !== false);\n process.stdout.write(text ? text + '\\n' : 'No results.\\n');\n });\n return cmd;\n}\n","/**\n * `sdt query-log` — AUTH.5 local query log CLI.\n *\n * Subcommands:\n * sdt query-log list [--profile <p>] [--limit N] [--format text|json]\n * sdt query-log show <id> [--format text|json|sql]\n * sdt query-log add <sql> --profile <p> [--status success|error] [--store <path>]\n * sdt query-log clear [--profile <p>] [--yes]\n *\n * The log is stored at `~/.sdt/query-log.json` (override with --store).\n * EE3 will call `appendEntry()` on the substrate directly when a query\n * is executed. This CLI surfaces it for ad-hoc review + rerun.\n *\n * Mirrors `Databricks/packages/cli/src/commands/query-log.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { queryLog } from '@sdt-tools/core';\n\nconst DEFAULT_STORE = path.join(os.homedir(), '.sdt', 'query-log.json');\n\nasync function loadStore(storePath: string): Promise<queryLog.QueryLogStore> {\n try {\n const raw = await fs.readFile(storePath, 'utf8');\n return queryLog.QueryLogStore.deserialize(JSON.parse(raw));\n } catch {\n return new queryLog.QueryLogStore();\n }\n}\n\nasync function saveStore(storePath: string, store: queryLog.QueryLogStore): Promise<void> {\n await fs.mkdir(path.dirname(storePath), { recursive: true });\n await fs.writeFile(storePath, JSON.stringify(store.serialize(), null, 2), 'utf8');\n}\n\nexport function queryLogCommand(): Command {\n const cmd = new Command('query-log');\n cmd.description('Browse and manage the local query log from the EE3 query window (AUTH.5).');\n\n cmd\n .command('list')\n .description('List recent query log entries (newest first).')\n .option('--profile <p>', 'Filter to a specific connection profile.')\n .option('--limit <n>', 'Maximum entries to show (default 100).', '100')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n const store = await loadStore(opts.store as string);\n const entries = store.listEntries({\n profile: opts.profile as string | undefined,\n limit: parseInt(String(opts.limit ?? '100'), 10),\n });\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n process.stdout.write('No query log entries.\\n');\n return;\n }\n for (const e of entries) {\n const when = e.executedAt.slice(0, 19).replace('T', ' ');\n const dur = e.durationMs !== undefined ? ` ${e.durationMs}ms` : '';\n const rows = e.rowCount !== undefined ? ` ${e.rowCount} rows` : '';\n const status = e.status === 'error' ? ' ✗' : ' ✓';\n const sql = e.sql.replace(/\\s+/g, ' ').slice(0, 80);\n process.stdout.write(`[${e.id}] ${when} [${e.profile}]${status}${dur}${rows} ${sql}\\n`);\n }\n });\n\n cmd\n .command('show <id>')\n .description('Show a single query log entry by id.')\n .option('--format <fmt>', 'text | json | sql (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (id: string, opts) => {\n const store = await loadStore(opts.store as string);\n const entry = store.getEntry(id);\n if (!entry) throw new Error(`No entry with id '${id}'.`);\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'sql') {\n process.stdout.write(entry.sql + '\\n');\n return;\n }\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`id: ${entry.id}\\n`);\n process.stdout.write(`profile: ${entry.profile}\\n`);\n process.stdout.write(`executed: ${entry.executedAt}\\n`);\n process.stdout.write(`status: ${entry.status}\\n`);\n if (entry.durationMs !== undefined) process.stdout.write(`duration: ${entry.durationMs}ms\\n`);\n if (entry.rowCount !== undefined) process.stdout.write(`rows: ${entry.rowCount}\\n`);\n if (entry.error) process.stdout.write(`error: ${entry.error}\\n`);\n process.stdout.write(`\\n${entry.sql}\\n`);\n });\n\n cmd\n .command('add <sql>')\n .description('Manually append a query to the log (used by EE3 and for testing).')\n .requiredOption('--profile <p>', 'Connection profile the query was run against.')\n .option('--status <s>', 'success | error (default success).', 'success')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (sql: string, opts) => {\n if (opts.status !== 'success' && opts.status !== 'error') {\n throw new Error(`--status must be success or error, got: ${opts.status}`);\n }\n const store = await loadStore(opts.store as string);\n const entry = store.appendEntry({\n profile: opts.profile as string,\n sql,\n executedAt: new Date().toISOString(),\n status: opts.status as 'success' | 'error',\n });\n await saveStore(opts.store as string, store);\n process.stdout.write(`Added entry ${entry.id}.\\n`);\n });\n\n cmd\n .command('clear')\n .description('Remove query log entries.')\n .option('--profile <p>', 'Remove only entries for this profile (omit for all).')\n .option('--yes', 'Skip confirmation prompt.')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n if (!opts.yes) {\n const target = opts.profile ? `profile '${opts.profile as string}'` : 'all profiles';\n throw new Error(`Pass --yes to confirm clearing the query log for ${target}.`);\n }\n const store = await loadStore(opts.store as string);\n const removed = store.clearEntries(opts.profile as string | undefined);\n await saveStore(opts.store as string, store);\n process.stdout.write(`Cleared ${removed} entries.\\n`);\n });\n\n return cmd;\n}\n"],"mappings":"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","names":["project","Command","Command","path","fs","Command","Command","path","fs","path","fs","Command","getProfile","SnowflakeConnection","wrap","fs","getProfile","SnowflakeConnection","Command","path","fs","assessment","path","fs","Command","CompareEngine","LiveSource","compileSlice","ai","safety","getProfile","SnowflakeConnection","Command","path","pac","getProfile","SnowflakeConnection","LiveSource","safety","CompareEngine","compileSlice","fs","ai","bodyReport","Command","path","readPac","CompareEngine","LiveSource","getProfile","SnowflakeConnection","loadProject","ModelSource","Command","getProfile","SnowflakeConnection","loadProject","path","pac","readPac","LiveSource","CompareEngine","fs","path","Command","catalog","Command","path","catalog","fs","report","Command","getProfile","SnowflakeConnection","Command","getProfile","SnowflakeConnection","Command","fs","path","Command","compare","project","ai","ai","Command","compare","path","fs","project","fs","path","Command","getProfile","SnowflakeConnection","Command","path","entries","fs","getProfile","SnowflakeConnection","Command","pac","fs","path","Command","fs","path","Command","CompareEngine","PacSource","ProjectSource","ScriptGenerator","colorizeMigrationScript","mergeDeployOptions","loadProject","readPac","safety","Command","CompareEngine","mergeDeployOptions","readPac","loadProject","ScriptGenerator","safety","header","path","fs","colorizeMigrationScript","PacSource","ProjectSource","fs","Command","getProfile","SnowflakeConnection","SnowflakeExecutor","fs","path","Command","getProfile","SnowflakeConnection","SnowflakeExecutor","loadProject","fs","path","Command","pac","project","fs","path","Command","model","loadModel","focus","direction","fmt","payload","pac","project","lineage","fs","path","Command","pac","project","Command","loadModel","path","fs","pac","project","fs","path","Command","ai","pac","project","Command","loadModel","safety","fs","path","ai","pac","project","fs","path","Command","pac","project","review","Command","loadModel","review","emit","pac","project","path","fs","fs","path","Command","Command","fs","path","splitStatements","fs","path","Command","CompareEngine","PacSource","ProjectSource","safety","pac","project","review","Command","CompareEngine","PacSource","ProjectSource","safety","loadModel","review","path","fs","pac","project","fs","path","Command","fs","path","Command","pac","project","loadModel","Command","Command","renderMarkdown","fs","Command","ai","Command","fs","ai","fs","Command","ai","Command","ai","fs","fs","Command","catalog","pac","project","Command","readStdin","fs","catalog","pac","project","Command","catalog","Command","catalog","Command","catalog","getProfile","SnowflakeConnection","Command","getProfile","SnowflakeConnection","catalog","Command","fs","getProfile","SnowflakeConnection","result","Command","fs","path","catalog","renderText","Command","fs","os","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/init.ts","../src/util/logger.ts","../src/commands/build.ts","../src/commands/extract.ts","../src/commands/compare.ts","../src/util/help-catalog.ts","../src/util/color.ts","../src/util/mapping.ts","../src/commands/publish.ts","../src/commands/drift.ts","../src/commands/validate.ts","../src/commands/connection.ts","../src/commands/scaffold.ts","../src/commands/graph.ts","../src/util/ai-explain.ts","../src/commands/history.ts","../src/commands/verify.ts","../src/commands/install-hooks.ts","../src/commands/script.ts","../src/commands/revert.ts","../src/commands/seed.ts","../src/commands/lineage.ts","../src/commands/diagnose.ts","../src/commands/review.ts","../src/commands/impact.ts","../src/commands/cost-estimate.ts","../src/commands/pr-comment.ts","../src/commands/template.ts","../src/commands/anonymize.ts","../src/commands/safety.ts","../src/commands/safer-alternative.ts","../src/commands/sketch.ts","../src/commands/compare-profiles.ts","../src/commands/explorer.ts","../src/commands/catalog.ts","../src/commands/exec.ts","../src/commands/search.ts","../src/commands/query-log.ts"],"sourcesContent":["import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { newProjectTemplate, saveProject } from '@sdt-tools/core/project';\nimport type { ProjectScope } from '@sdt-tools/core/project';\nimport { logger } from '../util/logger.js';\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n cmd\n .description('Initialize a new SDT project in the current directory.')\n .option('--name <name>', 'Project name', 'NewSnowflakeProject')\n .option('--scope <scope>', 'Project scope: account | database | schema', 'database')\n .option('--db <database>', 'Database name (required for database/schema scope)')\n .option('--schema <schema>', 'Schema name (required for schema scope)')\n .option('--dir <dir>', 'Target directory (default: cwd)', process.cwd())\n .option(\n '--force',\n 'Overwrite an existing <name>.sdtproj in the target directory. Without ' +\n 'this flag, init refuses to clobber an existing project file so a ' +\n 're-run never silently discards your project configuration.',\n )\n .action(async (opts) => {\n const scopeType = String(opts.scope) as ProjectScope['type'];\n if (!['account', 'database', 'schema'].includes(scopeType)) {\n throw new Error(`Invalid --scope: ${opts.scope}. Use account | database | schema.`);\n }\n const scope: ProjectScope = { type: scopeType };\n if (scopeType !== 'account') {\n if (!opts.db) throw new Error(`--db is required for scope=${scopeType}`);\n scope.database = String(opts.db);\n }\n if (scopeType === 'schema') {\n if (!opts.schema) throw new Error('--schema is required for scope=schema');\n scope.schema = String(opts.schema);\n }\n const root = path.resolve(String(opts.dir));\n await fs.mkdir(root, { recursive: true });\n const project = newProjectTemplate(String(opts.name), scope);\n const projectPath = path.join(root, `${project.name}.sdtproj`);\n // Refuse to clobber an existing project file unless --force. Mirrors\n // the `sdt standards init --force` pattern: a silent overwrite can\n // discard hand-edited project configuration on an accidental re-run.\n if (!opts.force) {\n try {\n await fs.access(projectPath);\n logger.error(`${projectPath} already exists; pass --force to overwrite.`);\n process.exitCode = 1;\n return;\n } catch {\n // File doesn't exist — proceed.\n }\n }\n await saveProject(projectPath, project);\n // Seed conventional folders so the user sees the layout SDT expects.\n const seedFolders = ['databases', 'scripts/pre', 'scripts/post'];\n for (const f of seedFolders) await fs.mkdir(path.join(root, f), { recursive: true });\n logger.success(`Created ${projectPath}`);\n logger.dim(\n ` Scope: ${scopeType}${scope.database ? ' / ' + scope.database : ''}${scope.schema ? ' / ' + scope.schema : ''}`,\n );\n logger.dim(` Next: sdt extract --connection <profile> --output ${root}`);\n });\n return cmd;\n}\n","/**\n * Minimal logger used by the CLI. Wraps chalk/ora so a future move to a\n * non-tty mode is centralised.\n */\nimport chalk from 'chalk';\n\nexport const logger = {\n info: (msg: string) => console.log(msg),\n success: (msg: string) => console.log(chalk.green('✔'), msg),\n warn: (msg: string) => console.warn(chalk.yellow('!'), msg),\n error: (msg: string) => console.error(chalk.red('✖'), msg),\n step: (msg: string) => console.log(chalk.cyan('→'), msg),\n dim: (msg: string) => console.log(chalk.gray(msg)),\n};\n","import { Command } from 'commander';\nimport { buildProject } from '@sdt-tools/core/pac';\nimport { logger } from '../util/logger.js';\n\nexport function buildCommand(): Command {\n const cmd = new Command('build');\n cmd\n .description('Build a .sdtpac from a .sdtproj project.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file')\n .option('-o, --out <path>', 'Output .sdtpac path (default: <projectRoot>/bin/<name>.sdtpac)')\n .action(async (opts) => {\n const result = await buildProject(String(opts.project), {\n outputPath: opts.out ? String(opts.out) : undefined,\n });\n logger.success(`Built ${result.outputPath}`);\n logger.dim(` ${result.fileCount} source file(s), ${result.objectCount} object(s) in model`);\n });\n return cmd;\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog } from '@sdt-tools/core';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { AccountExtractor, defaultExtractors } from '@sdt-tools/core/extract';\nimport { writeProjectTree } from '@sdt-tools/core/project';\nimport { logger } from '../util/logger.js';\n\nexport function extractCommand(): Command {\n const cmd = new Command('extract');\n cmd\n .description('Extract a Snowflake account/database/schema into a project layout.')\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .requiredOption(\n '-o, --output <path>',\n 'Target project directory (must contain a .sdtproj or pass --init)',\n )\n .option('--db <database>', 'Limit to a single database')\n .option('--schema <schema>', 'Limit to a single schema (requires --db)')\n .option('--types <list>', 'Comma-separated object types to include (default: all implemented)')\n .option(\n '--write-catalog-cache',\n 'Also write the extracted model to the EE1 catalog cache (.sdt/cache/<connection>/catalog.msgpack) so subsequent editor sessions have a populated cache without an extra `catalog refresh` round-trip.',\n false,\n )\n .option(\n '--use-catalog-cache',\n 'Read object metadata from the on-disk EE1 catalog cache instead of querying Snowflake. Fast / offline — no live connection required. Writes a catalog-snapshot.json to the output dir. Requires a prior `sdt catalog refresh` or `sdt extract --write-catalog-cache` run.',\n false,\n )\n .action(async (opts) => {\n if (opts.useCatalogCache) {\n const out = path.resolve(String(opts.output));\n await fs.mkdir(out, { recursive: true });\n const cache = new catalog.CatalogCache({ root: out, connection: String(opts.connection) });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0 && snapshot.fingerprint === null) {\n logger.error(\n `No catalog cache found at ${cache.path}. Run \"sdt catalog refresh -c ${String(opts.connection)}\" or \"sdt extract --write-catalog-cache\" first.`,\n );\n process.exitCode = 1;\n return;\n }\n const outPath = path.join(out, '.sdt-cache', 'catalog-snapshot.json');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, JSON.stringify(snapshot, null, 2));\n const objCount = snapshot.databases.flatMap((d) =>\n d.schemas.flatMap((s) => s.objects),\n ).length;\n logger.success(\n `Loaded ${objCount} object(s) from catalog cache (${snapshot.databases.length} database(s)) → ${outPath}`,\n );\n logger.dim(\n `Cache was snapshotted at ${snapshot.snapshotAt}. Use \"sdt catalog refresh\" to update it.`,\n );\n return;\n }\n\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const include = opts.types\n ? new Set(\n String(opts.types)\n .split(',')\n .map((s) => s.trim().toUpperCase()),\n )\n : undefined;\n logger.step(`Connecting to ${profile.account} as ${profile.auth.username}…`);\n await conn.connect();\n try {\n const account = new AccountExtractor(defaultExtractors());\n const objects = await account.extract(\n conn,\n {\n database: opts.db ? String(opts.db) : undefined,\n schema: opts.schema ? String(opts.schema) : undefined,\n },\n { include },\n );\n const out = path.resolve(String(opts.output));\n await fs.mkdir(out, { recursive: true });\n const dumpPath = path.join(out, '.sdt-cache', 'extracted.json');\n await fs.mkdir(path.dirname(dumpPath), { recursive: true });\n await fs.writeFile(dumpPath, JSON.stringify(objects, null, 2));\n const filesCreated = await writeProjectTree(out, objects);\n logger.success(\n `Extracted ${objects.length} object(s) → ${filesCreated} .sql file(s) under ${out} (cache: ${dumpPath}).`,\n );\n\n if (opts.writeCatalogCache) {\n const snapshot = catalog.snapshotFromObjects(objects, {\n connection: String(opts.connection),\n });\n const cache = new catalog.CatalogCache({\n root: out,\n connection: String(opts.connection),\n });\n await cache.set(snapshot);\n logger.success(\n `Wrote catalog cache → ${cache.path} (${snapshot.databases.length} database(s), ${objects.length} object(s)).`,\n );\n }\n } finally {\n await conn.disconnect();\n }\n });\n return cmd;\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n LiveSource,\n PacSource,\n ProjectSource,\n writeCompareHistory,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { compileSlice, loadProject } from '@sdt-tools/core/project';\nimport { ai, safety, typecheck } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\nimport { makeColorizer, resolveColorMode } from '../util/color.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\n/**\n * Auto-load a slice from a `.sdtproj` argument. Returns `undefined` when\n * the argument is not a `.sdtproj` or the project doesn't declare a slice.\n * Suite-level invocations bypass this and pass a slice directly.\n */\nasync function maybeLoadSliceFromArg(\n arg: string,\n): Promise<ReturnType<typeof compileSlice> | undefined> {\n if (!arg.toLowerCase().endsWith('.sdtproj')) return undefined;\n const loaded = await loadProject(arg);\n if (!loaded.project.slice) return undefined;\n return compileSlice(loaded.project.slice);\n}\n\n/**\n * Resolve a polymorphic source/target argument. Supported forms:\n * - path/to/foo.sdtproj\n * - path/to/foo.sdtpac\n * - snowflake://<profile>[/db[/schema]]\n */\nasync function resolveSource(arg: string): Promise<CompareSource> {\n if (arg.startsWith('snowflake://')) {\n const rest = arg.slice('snowflake://'.length);\n const [profileName, db, schema] = rest.split('/');\n if (!profileName) throw new Error(`Invalid snowflake URI: ${arg}`);\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n return new LiveSource(conn, { database: db, schema });\n }\n const lower = arg.toLowerCase();\n if (lower.endsWith('.sdtproj')) return new ProjectSource(arg);\n if (lower.endsWith('.sdtpac')) return new PacSource(arg);\n throw new Error(\n `Unrecognized source: ${arg}. Use *.sdtproj, *.sdtpac, or snowflake://<profile>[/db[/schema]].`,\n );\n}\n\nexport function compareCommand(): Command {\n const cmd = new Command('compare');\n cmd\n .description(\n 'Compare two schemas. Sources may be .sdtproj, .sdtpac, or snowflake://<profile>[/db[/schema]].',\n )\n .argument('[source]', 'Left side of the comparison (or use --source)')\n .argument('[target]', 'Right side of the comparison (or use --target)')\n .option(\n '--source <path>',\n 'Left side of the comparison (flag form of the positional source arg)',\n )\n .option(\n '--target <path>',\n 'Right side of the comparison (flag form of the positional target arg)',\n )\n .option('-o, --output <path>', 'Write JSON result to this path')\n .option('--format <format>', 'Output format: json | summary | markdown', 'summary')\n .option('--ignore-case', 'Treat unquoted identifiers case-insensitively', false)\n .option(\n '--no-slice',\n \"Disable the source project's Slice (if it has one). Default: a project's slice is applied automatically.\",\n )\n .option(\n '--explain',\n 'After the diff, call the configured AI provider to narrate each change in plain English with reasoning. Requires `sdt ai` to be configured.',\n false,\n )\n .option(\n '--color <mode>',\n 'Colorize severity output: always | never | auto. Default auto (color on TTY).',\n 'auto',\n )\n .option(\n '--type-safe',\n 'After the compare, run the TYPECHECK.1 impact analyzer. Exits with code 2 if the configured --break-on threshold is reached (default `error`). CI-friendly gate — pair with `--format json` for machine-readable output.',\n false,\n )\n .option(\n '--break-on <severity>',\n 'TYPECHECK.2 threshold for --type-safe: `error` (exit 2 on any error ripple, default) | `warning` (exit 2 on any error OR warning ripple, strict CI mode).',\n 'error',\n )\n .option(\n '--write-impact [path]',\n 'Write the TYPECHECK.1 impact analysis to a JSON file the VS Code extension can surface as squiggle-underlines. Default path: `.sdt/impact.json` resolved relative to the source `.sdtproj` directory (or CWD if the source is not a project). Composes with `--type-safe` — the file is written before the gate decides exit code.',\n )\n .option(\n '--no-history',\n 'Skip writing the compare-history audit record (AUDITCMP.1). Default: every compare run writes a record to `.sdt/history/compare/`, exportable via `sdt audit-log emit`.',\n )\n .action(async (sourceArgPos, targetArgPos, opts) => {\n // Accept the source/target either positionally (`sdt compare X Y`) or via\n // flags (`--source X --target Y`). The flag form mirrors `ddt compare`\n // and `sdt script`, and is what GETTING_STARTED documents; the positional\n // form is kept for back-compat. Flags win when both are given.\n const sourceArg = opts.source\n ? String(opts.source)\n : sourceArgPos\n ? String(sourceArgPos)\n : '';\n const targetArg = opts.target\n ? String(opts.target)\n : targetArgPos\n ? String(targetArgPos)\n : '';\n if (!sourceArg || !targetArg) {\n throw new Error(\n 'compare needs a source and a target — pass them positionally (`sdt compare <source> <target>`) or via `--source`/`--target`.',\n );\n }\n\n // Logical-name mapping (`--map`, `--map-file`) — rewrites source-side\n // FQNs so two schemas whose database / schema names differ can compare\n // semantically. See docs/LOGICAL_NAME_MAPPING.md. Mirrors `ddt compare`.\n const nameMapping = await buildMappingFromOptions(opts);\n const source = await resolveSource(String(sourceArg));\n const target = await resolveSource(String(targetArg));\n\n // Auto-load slice from the source `.sdtproj` unless --no-slice was set.\n // The target side (live or pac) doesn't carry a slice; it's the\n // project's slice that defines the scope.\n const slice =\n opts.slice === false ? undefined : await maybeLoadSliceFromArg(String(sourceArg));\n\n const engine = new CompareEngine();\n const startedAt = new Date().toISOString();\n const result = await engine.compare(source, target, {\n ignoreCase: Boolean(opts.ignoreCase),\n ...(nameMapping ? { nameMapping } : {}),\n ...(slice ? { sliceFilter: slice } : {}),\n });\n\n // AUDITCMP.1 — compare operations leave the same audit trail deploys\n // do. Written before the format-specific early returns so every\n // output mode is covered. Best-effort: a failed write never breaks\n // the compare itself.\n if (opts.history !== false) {\n const finishedAt = new Date().toISOString();\n try {\n const histAssessment = safety.assess(result);\n const changed = result.summary.added + result.summary.removed + result.summary.modified;\n await writeCompareHistory(compareHistoryRoot(String(sourceArg)), {\n startedAt,\n finishedAt,\n durationMs: Date.parse(finishedAt) - Date.parse(startedAt),\n outcome: histAssessment.blocked\n ? 'BLOCKED'\n : changed === 0\n ? 'NO_CHANGES'\n : 'CHANGES_FOUND',\n source: { kind: result.source.kind, label: result.source.label },\n target: { kind: result.target.kind, label: result.target.label },\n summary: result.summary,\n sliceApplied: Boolean(slice),\n ...(histAssessment.blocked && histAssessment.blockReason\n ? { blockReason: histAssessment.blockReason }\n : {}),\n });\n } catch {\n /* audit trail is best-effort; never fail the compare over it */\n }\n }\n\n if (opts.output) {\n const out = path.resolve(String(opts.output));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, JSON.stringify(result, null, 2));\n logger.success(`Wrote ${out}`);\n }\n\n if (opts.format === 'json') {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n if (opts.format === 'markdown') {\n const assessment = safety.assess(result);\n process.stdout.write(renderCompareMarkdown(result, assessment) + '\\n');\n return;\n }\n logger.info(\n `Compare ${result.source.kind}:${result.source.label} → ${result.target.kind}:${result.target.label}`,\n );\n if (slice) {\n const outside = result.outsideScope?.length ?? 0;\n const refs = result.referenced?.length ?? 0;\n logger.info(\n ` Slice active: ${result.objects.length} owned · ${outside} outside scope (untouched) · ${refs} referenced`,\n );\n }\n logger.info(\n ` +${result.summary.added} added, -${result.summary.removed} removed, ~${result.summary.modified} modified, =${result.summary.unchanged} unchanged`,\n );\n for (const o of result.objects) {\n if (o.kind === 'unchanged') continue;\n logger.info(` ${o.kind.padEnd(8)} ${o.identity.objectType.padEnd(20)} ${o.identity.fqn}`);\n }\n\n // Reversibility-grouped safety findings. Three buckets — Unrecoverable\n // first (highest urgency), then Data-impacting, then Reversible.\n // Empty diff is silent; assessment.blocked is surfaced once findings\n // exist.\n const assessment = safety.assess(result);\n const buckets = safety.groupByReversibility(assessment);\n const total =\n buckets.unrecoverable.length + buckets.dataImpacting.length + buckets.reversible.length;\n if (total > 0) {\n const colorize = makeColorizer(resolveColorMode(opts.color));\n logger.info('');\n logger.info('Safety findings (grouped by reversibility):');\n const block = safety.formatReversibilityBuckets(buckets);\n const colored = colorize.applyToBlock(block);\n for (const line of colored.split('\\n')) logger.info(' ' + line);\n if (assessment.blocked && assessment.blockReason) {\n logger.error(' ' + colorize.unrecoverable('BLOCKED: ' + assessment.blockReason));\n }\n }\n\n // AI-narrated diff (--explain). Calls the configured provider with a\n // structured prompt containing the diff summary + per-object changes\n // + safety findings. Output is the assistant's plain-English narration.\n if (opts.explain) {\n logger.info('');\n logger.info('AI explanation:');\n try {\n const userPrompt = buildExplainPrompt(result, assessment);\n const reply = await ai.complete(\n [\n { role: 'system', content: SYSTEM_PROMPT },\n { role: 'user', content: userPrompt },\n ],\n { feature: 'compare.explain' },\n );\n for (const line of reply.text.split('\\n')) logger.info(' ' + line);\n } catch (err) {\n logger.error(' --explain failed: ' + (err instanceof Error ? err.message : String(err)));\n logger.error(\n ' Run `sdt ai status` to verify your AI provider is configured (`sdt ai test` to send a probe).',\n );\n }\n }\n\n // --write-impact: TYPECHECK.4 — write the impact analysis to a\n // JSON file the VS Code provider reads. Always runs the analyzer\n // (even when --type-safe is off) so the editor surface is\n // independent of the CI-gate flag. Composes with --type-safe.\n if (opts.writeImpact !== undefined) {\n await writeImpactJson(\n result,\n opts.writeImpact === true ? undefined : String(opts.writeImpact),\n String(sourceArg),\n );\n }\n\n // --type-safe: TYPECHECK.2 CI gate. Runs the TYPECHECK.1 impact\n // analyzer and exits with code 2 if any error-severity ripple\n // (column-drop or table-drop reaching a dependent object) is\n // detected. Stays silent on a clean diff so this composes well\n // with --format json (which already returned above).\n if (opts.typeSafe) {\n const breakOnRaw = String(opts.breakOn ?? 'error').toLowerCase();\n if (breakOnRaw !== 'error' && breakOnRaw !== 'warning') {\n throw new Error(\n `--break-on must be 'error' or 'warning' (got '${opts.breakOn}'). 'error' fails on any error-severity ripple (default); 'warning' fails on any warning or error ripple (strict CI).`,\n );\n }\n const breakOn = breakOnRaw as 'error' | 'warning';\n const impactFindings = typecheck.analyzeImpact(result);\n const impactSummary = typecheck.summarizeImpact(impactFindings);\n if (impactSummary.findingsCount > 0) {\n logger.info('');\n logger.info(\n `Type-safety gate (--break-on ${breakOn}) — ${impactSummary.findingsCount} breaking change(s); ${impactSummary.errors} error ripple(s), ${impactSummary.warnings} warning ripple(s); ${impactSummary.affectedObjects.length} dependent object(s).`,\n );\n for (const f of impactFindings) {\n for (const r of f.ripples) {\n const tag = r.severity === 'error' ? 'ERROR' : 'WARN ';\n logger.info(\n ` ${tag} ${r.fqn} ← ${f.breakingChangeOn.fqn} (${f.breakingChangeOn.kind})`,\n );\n }\n }\n const failOnError = impactSummary.errors > 0;\n const failOnWarning = breakOn === 'warning' && impactSummary.warnings > 0;\n if (failOnError) {\n logger.error(\n `Type-safety gate FAILED — ${impactSummary.errors} error ripple(s). Fix the dependents (drop / update / re-bind) before re-running compare, OR rerun with the change scoped out of the diff.`,\n );\n process.exitCode = 2;\n } else if (failOnWarning) {\n logger.error(\n `Type-safety gate FAILED (strict --break-on warning) — ${impactSummary.warnings} warning ripple(s). Tighten the dependent SQL to accept the new type, or drop --break-on warning to allow.`,\n );\n process.exitCode = 2;\n }\n } else {\n logger.info('Type-safety gate PASSED — no breaking-change ripples detected.');\n }\n }\n });\n addMappingFlags(cmd);\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n 'compare.excludeObjectPatterns',\n 'compare.includeObjectPatterns',\n ]);\n return cmd;\n}\n\n/**\n * TYPECHECK.4 — write the impact analysis JSON to disk so the VS Code\n * provider can surface it as squiggle-underlines. Defaults to\n * `<project-dir>/.sdt/impact.json` when the source is a `.sdtproj`,\n * otherwise `<cwd>/.sdt/impact.json`.\n */\nasync function writeImpactJson(\n result: Parameters<typeof typecheck.analyzeImpact>[0],\n explicitPath: string | undefined,\n sourceArg: string,\n): Promise<void> {\n const findings = typecheck.analyzeImpact(result);\n const summary = typecheck.summarizeImpact(findings);\n const file: typecheck.ImpactFile = {\n version: typecheck.IMPACT_FILE_VERSION,\n generatedAt: new Date().toISOString(),\n source: `${result.source.kind}:${result.source.label}`,\n target: `${result.target.kind}:${result.target.label}`,\n findings,\n summary,\n };\n const outPath = explicitPath ? path.resolve(explicitPath) : defaultImpactPath(sourceArg);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, typecheck.serializeImpactFile(file));\n logger.success(\n `Wrote ${outPath} — ${summary.findingsCount} finding(s), ${summary.errors} error / ${summary.warnings} warning ripple(s).`,\n );\n}\n\nfunction defaultImpactPath(sourceArg: string): string {\n if (sourceArg.toLowerCase().endsWith('.sdtproj')) {\n return path.resolve(path.dirname(sourceArg), '.sdt', 'impact.json');\n }\n return path.resolve('.sdt', 'impact.json');\n}\n\n/**\n * AUDITCMP.1 — workspace root for the compare-history record. Project /\n * pac sources anchor the audit trail next to the artifact being compared;\n * live (snowflake://) sources fall back to CWD.\n */\nfunction compareHistoryRoot(sourceArg: string): string {\n const lower = sourceArg.toLowerCase();\n if (lower.endsWith('.sdtproj') || lower.endsWith('.sdtpac')) {\n return path.dirname(path.resolve(sourceArg));\n }\n return process.cwd();\n}\n\nexport const SYSTEM_PROMPT = `You are a senior Snowflake DBA reviewing a schema diff. Your job is to narrate the changes in plain English to a teammate who hasn't seen the underlying SQL. For each change, briefly say:\n - what it is (e.g. \"a new fact table is added\")\n - why a reasonable engineer might do this (the intent)\n - what to watch out for (the risk, if any)\n\nBe concrete; use the FQNs you're given. Keep it to 3-6 sentences per object. Don't repeat the raw diff back — explain it.`;\n\nfunction renderCompareMarkdown(\n result: {\n source: { kind: string; label: string };\n target: { kind: string; label: string };\n objects: Array<{ kind: string; identity: { fqn: string; objectType: string } }>;\n summary: { added: number; removed: number; modified: number; unchanged: number };\n },\n assessment: {\n unrecoverable: unknown[];\n destructive: unknown[];\n expensive: unknown[];\n warnings: unknown[];\n blocked?: boolean;\n blockReason?: string;\n },\n): string {\n const lines: string[] = [];\n lines.push(\n `# Compare: ${result.source.kind}:${result.source.label} → ${result.target.kind}:${result.target.label}`,\n );\n lines.push('');\n lines.push(\n `**Summary**: +${result.summary.added} added · -${result.summary.removed} removed · ~${result.summary.modified} modified · =${result.summary.unchanged} unchanged.`,\n );\n lines.push('');\n lines.push('**Safety**:');\n lines.push(`- 🛑 Unrecoverable: ${assessment.unrecoverable.length}`);\n lines.push(`- 🔥 Destructive: ${assessment.destructive.length}`);\n lines.push(`- ⏱ Expensive: ${assessment.expensive.length}`);\n lines.push(`- ⚠ Warnings: ${assessment.warnings.length}`);\n if (assessment.blocked) {\n lines.push('');\n lines.push(\n `> **BLOCKED**: ${assessment.blockReason ?? 'safety classifier refuses to proceed'}`,\n );\n }\n lines.push('');\n const changed = result.objects.filter((o) => o.kind !== 'unchanged');\n if (changed.length === 0) {\n lines.push('_No object-level changes._');\n return lines.join('\\n');\n }\n lines.push('| Kind | Type | FQN |');\n lines.push('| --- | --- | --- |');\n for (const o of changed) {\n lines.push(`| ${o.kind} | \\`${o.identity.objectType}\\` | \\`${o.identity.fqn}\\` |`);\n }\n return lines.join('\\n');\n}\n\nexport function buildExplainPrompt(\n result: {\n source: { label: string };\n target: { label: string };\n objects: Array<{\n kind: string;\n identity: { fqn: string; objectType: string };\n changes?: unknown[];\n }>;\n summary: { added: number; removed: number; modified: number; unchanged: number };\n },\n assessment: {\n unrecoverable: unknown[];\n destructive: unknown[];\n expensive: unknown[];\n warnings: unknown[];\n },\n): string {\n const lines: string[] = [];\n lines.push(`Source: ${result.source.label}`);\n lines.push(`Target: ${result.target.label}`);\n lines.push(\n `Summary: +${result.summary.added} added, -${result.summary.removed} removed, ~${result.summary.modified} modified.`,\n );\n lines.push(\n `Safety: ${assessment.unrecoverable.length} unrecoverable, ${assessment.destructive.length} destructive, ${assessment.expensive.length} expensive, ${assessment.warnings.length} warnings.`,\n );\n lines.push('');\n lines.push('Changes (up to 40):');\n const changed = result.objects.filter((o) => o.kind !== 'unchanged').slice(0, 40);\n for (const o of changed) {\n lines.push(`- ${o.kind} ${o.identity.objectType} ${o.identity.fqn}`);\n }\n if (result.objects.filter((o) => o.kind !== 'unchanged').length > 40) {\n lines.push(\n ` (… ${result.objects.filter((o) => o.kind !== 'unchanged').length - 40} more truncated)`,\n );\n }\n lines.push('');\n lines.push(\n 'Please narrate this diff in plain English. Group related changes together when it helps.',\n );\n return lines.join('\\n');\n}\n","/**\n * Per-command --help enrichments — show 3-5 related catalog entries\n * under each command's help screen, with a one-line summary and a\n * pointer to `sdt explain <name>` for the full entry.\n *\n * Free-tier discoverability: a user who opens `sdt publish --help`\n * lands on a clear list of the deployment options that govern the\n * command's safety behaviour, without needing to know they exist or\n * read the project format reference first.\n *\n * Mirrors `Databricks/packages/cli/src/util/help-catalog.ts`.\n */\nimport type { Command } from 'commander';\nimport { DEPLOY_OPTIONS_CATALOG, type OptionEntry } from '@sdt-tools/core/options';\n\nconst CATALOG_BY_NAME: Map<string, OptionEntry> = new Map(\n DEPLOY_OPTIONS_CATALOG.map((entry) => [entry.name, entry]),\n);\n\n/**\n * Attach an \"After\" help block listing the named catalog entries with\n * one-line summaries. Unknown keys are silently skipped so a stale\n * mapping never breaks --help.\n */\nexport function attachRelatedOptions(cmd: Command, names: readonly string[]): void {\n const entries: OptionEntry[] = [];\n for (const n of names) {\n const e = CATALOG_BY_NAME.get(n);\n if (e) entries.push(e);\n }\n if (entries.length === 0) return;\n const maxName = entries.reduce((m, e) => Math.max(m, e.name.length), 0);\n const lines = [\n '',\n 'Related options (run `sdt explain <name>` for safety tier, default, and example):',\n ...entries.map((e) => ` ${e.name.padEnd(maxName)} ${e.summary}`),\n ];\n cmd.addHelpText('after', lines.join('\\n'));\n}\n","/**\n * ANSI severity coloring for CLI output. Resolves the `--color` flag\n * against the current TTY state and returns a `colorize` function\n * that wraps text in the right ANSI code (or returns it unchanged\n * when color is disabled).\n *\n * Conventions used across SDT/DDT CLI surfaces:\n * - UNRECOVERABLE → bold red\n * - DESTRUCTIVE → red\n * - EXPENSIVE → yellow\n * - WARNING → cyan\n * - SAFE / OK → green\n *\n * Paired with `Databricks/packages/cli/src/util/color.ts`.\n */\nexport type ColorMode = 'always' | 'never' | 'auto';\n\nconst ANSI = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n};\n\nexport function resolveColorMode(flag: string | undefined): boolean {\n const mode = (flag ?? 'auto').toLowerCase() as ColorMode;\n if (mode === 'always') return true;\n if (mode === 'never') return false;\n // auto — only color when stdout is a TTY AND NO_COLOR env isn't set.\n if (process.env.NO_COLOR) return false;\n return Boolean(process.stdout.isTTY);\n}\n\nexport interface Colorizer {\n unrecoverable(s: string): string;\n destructive(s: string): string;\n expensive(s: string): string;\n warning(s: string): string;\n safe(s: string): string;\n dim(s: string): string;\n /** Apply ANSI coloring to a multi-line block based on per-line severity tokens (🛑, ⚠, ✓, etc). */\n applyToBlock(block: string): string;\n}\n\nexport function makeColorizer(enabled: boolean): Colorizer {\n if (!enabled) {\n const identity = (s: string): string => s;\n return {\n unrecoverable: identity,\n destructive: identity,\n expensive: identity,\n warning: identity,\n safe: identity,\n dim: identity,\n applyToBlock: identity,\n };\n }\n const wrap =\n (codes: string) =>\n (s: string): string =>\n `${codes}${s}${ANSI.reset}`;\n return {\n unrecoverable: wrap(ANSI.bold + ANSI.red),\n destructive: wrap(ANSI.red),\n expensive: wrap(ANSI.yellow),\n warning: wrap(ANSI.cyan),\n safe: wrap(ANSI.green),\n dim: wrap(ANSI.gray),\n applyToBlock(block: string): string {\n // Walk each line; apply the strongest matching severity color.\n // The marker tokens (🛑/⚠/✓/info-prefixes) are stable across\n // `safety.formatReversibilityBuckets` and the diagnostics output.\n return block\n .split('\\n')\n .map((line) => {\n if (/UNRECOVERABLE/.test(line) || line.includes('🛑'))\n return ANSI.bold + ANSI.red + line + ANSI.reset;\n if (/DESTRUCTIVE/.test(line)) return ANSI.red + line + ANSI.reset;\n if (/EXPENSIVE/.test(line)) return ANSI.yellow + line + ANSI.reset;\n if (/WARNING/.test(line) || line.includes('⚠')) return ANSI.cyan + line + ANSI.reset;\n if (/\\bSAFE\\b|\\bOK\\b/.test(line) || line.includes('✓'))\n return ANSI.green + line + ANSI.reset;\n return line;\n })\n .join('\\n');\n },\n };\n}\n","import { promises as fs } from 'node:fs';\nimport { Option, type Command } from 'commander';\nimport { compare } from '@sdt-tools/core';\n\ntype NameMapping = compare.NameMapping;\n\nexport interface MappingOptions {\n map?: string[];\n mapFile?: string;\n mapCaseSensitive?: boolean;\n mapRewriteStandalone?: boolean;\n mapRewriteStrings?: boolean;\n}\n\n/** Attach `--map`, `--map-file`, `--map-case-sensitive`, `--map-rewrite-standalone`, `--map-rewrite-strings` to a command. */\nexport function addMappingFlags(cmd: Command): Command {\n return cmd\n .option(\n '--map <src=tgt>',\n 'Logical-name mapping (repeatable). Examples: DB_A=DB_B, DB_A.STAGING=DB_B.RAW. Rewrites source-side FQNs and DDL body refs.',\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option('--map-file <path>', 'JSON file of mappings.')\n .addOption(\n new Option(\n '--map-case-sensitive',\n 'Match identifiers case-sensitively. Default: insensitive.',\n ).default(false),\n )\n .addOption(\n new Option(\n '--map-rewrite-standalone',\n 'Rewrite standalone one-part refs (e.g. USE DATABASE DB_A). Default: off (safer).',\n ).default(false),\n )\n .addOption(\n new Option(\n '--map-rewrite-strings',\n 'Phase 3: also rewrite FQN-shaped tokens inside string literals (best-effort, may produce false positives in legitimate string content). Default: off.',\n ).default(false),\n );\n}\n\n/** Build a `NameMapping` from `--map`/`--map-file` flag values. Returns undefined when no mappings supplied. */\nexport async function buildMappingFromOptions(\n opts: MappingOptions,\n): Promise<NameMapping | undefined> {\n const flagMappings = Array.isArray(opts.map) ? opts.map : [];\n let mapping: NameMapping = { entries: [] };\n if (opts.mapFile) {\n const raw = await fs.readFile(String(opts.mapFile), 'utf8');\n mapping = compare.mappingFromFile(JSON.parse(raw));\n }\n if (flagMappings.length > 0) {\n const fromArgs = compare.mappingFromArgs(flagMappings);\n mapping = { entries: [...mapping.entries, ...fromArgs.entries] };\n }\n if (mapping.entries.length === 0) return undefined;\n if (opts.mapCaseSensitive) mapping.caseSensitive = true;\n if (opts.mapRewriteStandalone) mapping.rewriteStandaloneRefs = true;\n if (opts.mapRewriteStrings) mapping.rewriteInsideStrings = true;\n return mapping;\n}\n\n/** Render a one-line summary of a NameMapping for the operator's log output. */\nexport function describeMapping(mapping: NameMapping | undefined): string {\n if (!mapping || mapping.entries.length === 0) return '';\n return mapping.entries.map((e) => `${e.source}→${e.target}`).join(', ');\n}\n","import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { readPac } from '@sdt-tools/core/pac';\nimport {\n CompareEngine,\n LiveSource,\n buildExecutionPlan,\n defaultSafePlan,\n validatePlan,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport {\n ScriptGenerator,\n SnowflakeExecutor,\n buildDeployManifest,\n executePlan,\n resolveDeployScripts,\n formatDeployScript,\n colorizeMigrationScript,\n splitStatements as coreSplitStatements,\n type DeployScript,\n type DeploymentReport,\n type StepResult,\n} from '@sdt-tools/core/deploy';\nimport { compileSlice, mergeDeployOptions, type SdtDeployOptions } from '@sdt-tools/core/project';\nimport {\n ai,\n aiPreflight,\n approval,\n pacFreshness,\n protectedObjects,\n safety,\n license,\n testFramework,\n} from '@sdt-tools/core';\nimport { executeDcmProjectDeploy, mapDcmResultToDeploymentReport } from '@sdt-tools/core/exporters';\nimport { assessDcmCompatibility, formatDcmCompatibilityReport } from '@sdt-tools/core/safety';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\nclass ModelSource implements CompareSource {\n readonly kind = 'pac' as const;\n readonly platform = 'Snowflake' as const;\n readonly label: string;\n private readonly model: Awaited<ReturnType<typeof readPac>>['model'];\n constructor(label: string, model: Awaited<ReturnType<typeof readPac>>['model']) {\n this.label = label;\n this.model = model;\n }\n async load() {\n return this.model;\n }\n}\n\n/**\n * Split a multi-statement SQL block into individual statements. Thin\n * wrapper around `@sdt-tools/core/deploy.splitStatements` so callsites here\n * keep their `string[]` shape.\n */\nfunction splitStatements(sql: string): string[] {\n return coreSplitStatements(sql).map((s) => s.sql);\n}\n\nexport function publishCommand(): Command {\n const cmd = new Command('publish');\n cmd\n .description(\n 'Compare a .sdtpac (the desired state) to a live Snowflake target and apply (or dry-run) the migration. Shared form with `ddt publish`: `--source <desired> --connection <live-target>`.',\n )\n .option(\n '--source <path>',\n 'Path to the desired-state .sdtpac (canonical name; the same flag `ddt publish` uses). Required for a normal publish; omit only with --restore-from-snapshot.',\n )\n .option(\n '--pac <path>',\n 'Back-compat alias for --source (the desired-state .sdtpac). Prefer --source for cross-platform parity with `ddt publish`.',\n )\n .requiredOption('-c, --connection <profile>', 'Connection profile name (the live target).')\n .option(\n '--restore-from-snapshot <batchId>',\n 'Recovery mode: skip the compare step and emit ALTER TABLE … SWAP WITH against the snapshot batch <batchId> from the registry. ' +\n 'Dry-run by default; pass --apply --yes to execute. ' +\n \"This is the command printed by TRUST.4's post-deploy-smoke + TRUST.8's restore-hint when a deploy fails — they tell the operator to run `sdt publish --restore-from-snapshot <id>`.\",\n )\n .option(\n '--snapshot-dir <path>',\n 'Snapshot registry directory used with --restore-from-snapshot.',\n '.sdt/snapshots',\n )\n .option('--db <database>', 'Target database (defaults to pac scope.database)')\n .option('--schema <schema>', 'Target schema (defaults to pac scope.schema)')\n .option('--dry-run', 'Print the migration script without executing it', false)\n .option('--apply', 'Execute the migration against the live target (gated by safety)', false)\n .option('--out <path>', 'Write the generated migration script to this path')\n .option(\n '--color <mode>',\n 'Color stdout: auto | always | never. Honors NO_COLOR / SDT_NO_COLOR env vars in auto mode.',\n 'auto',\n )\n .option('--no-pre-scripts', 'Skip pre-deploy scripts even if the pac configures them')\n .option('--no-post-scripts', 'Skip post-deploy scripts even if the pac configures them')\n .option(\n '--no-slice',\n \"Disable the pac's Project Slice (if it has one). Default: the slice baked into the pac is applied automatically and target objects outside the slice are left untouched.\",\n )\n .option('--yes', 'Confirm REQUIRE_YES_FLAG safety gate (required for --apply)', false)\n .option(\n '--confirm-production',\n 'Confirm REQUIRE_CONFIRM_PRODUCTION gate (required for prod-named profiles with destructive changes)',\n false,\n )\n .option(\n '--query-tag <tag>',\n \"Set Snowflake QUERY_TAG for this deploy (audit / observability). The CLI runs ALTER SESSION SET QUERY_TAG='<tag>' before any migration statement so QUERY_HISTORY can attribute the deploy. Defaults to 'sdt:<projectName>@<projectVersion>:<unix-ms>'.\",\n )\n .option(\n '--manifest <path>',\n 'After --apply, write a JSON deploy manifest (every step + status + duration + reverse SQL) to <path>. Replayable via `sdt revert --manifest <path>`.',\n )\n .option(\n '--ai-preflight',\n \"Before --apply, ask AI to grade the operator's plain-language deploy description against the actual diff + safety findings. Blocks on 'mismatch' unless --confirm-after-preflight-mismatch is also passed.\",\n false,\n )\n .option(\n '--ai-preflight-text <narrative>',\n 'Non-interactive form of --ai-preflight. Supplies the narrative directly instead of reading from stdin.',\n )\n .option(\n '--strict-ai-preflight',\n \"Also block on 'partial' (not just 'mismatch'). Useful for production deploys.\",\n false,\n )\n .option(\n '--confirm-after-preflight-mismatch',\n 'Proceed even when --ai-preflight returns a mismatch verdict. Acknowledges that the AI grader flagged a discrepancy.',\n false,\n )\n .option(\n '--require-approvals <n>',\n 'Multi-approver gate: refuse --apply until <n> distinct approvers have signed off via `sdt approval add <deploy-id> --as <user>`. Team-tier.',\n )\n .option(\n '--approver <ids>',\n 'Comma-separated allow-list of approver IDs honoured by --require-approvals. Empty = any approver counts.',\n )\n .option(\n '--deploy-id <id>',\n 'Stable deploy identifier paired with --require-approvals (default: <connection>:<db>.<schema>).',\n )\n .option(\n '--approvals-root <path>',\n 'Approvals directory (default: .sdt/approvals).',\n path.join('.sdt', 'approvals'),\n )\n .option(\n '--allow-protected <fqns>',\n 'Comma-separated FQNs to allow despite .sdt-protection.json protection. Repeatable.',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[],\n )\n .option(\n '--allow-all-protected',\n 'Override all protection config entries (caution: disables DSR.4 guardrails).',\n false,\n )\n .option(\n '--freshness <mode>',\n 'Pac age check: warn (log if stale, continue), strict (block if stale), skip (no check). Default warn.',\n 'warn',\n )\n .option(\n '--post-deploy-tests <project>',\n 'After a successful --apply, discover YAML tests under <project>/tests/ and run them against the same connection. Exits 2 on any blocking (error-severity) DQ failure. Emits POST_DEPLOY_DQ_FAILED hint with --restore-from-snapshot recipe when tests fail.',\n )\n .option(\n '--via-dcm <stage>',\n 'Enterprise: delegate execution to Snowflake DCM Projects. <stage> is the DCM project FQN (e.g. @MY_DB.PUBLIC.MY_STAGE/my_project). SDT runs its safety pre-flight and DCM compatibility check, then executes EXECUTE DCM PROJECT DEPLOY. DCM must have been populated via `sdt export --dcm` first.',\n )\n .option(\n '--profile <name>',\n 'VARSYNTAX.2 — look up `deploymentProfiles[<name>].variables` from the pac manifest and substitute `$(VAR)` references in the generated migration script. Errors if the named profile is absent from the pac (e.g. pac built before VARSYNTAX.2, or profile not declared in .sdtproj). Distinct from `--connection`, which selects the Snowflake credential profile.',\n )\n .option(\n '--variables <kv>',\n 'VARSYNTAX.2 — comma-separated KEY=VALUE pairs for `$(VAR)` substitution. Merged on top of `--profile <name>` variables (CLI values win on key collision).',\n )\n .action(async (opts) => {\n if (opts.apply && opts.dryRun) {\n logger.error('--apply and --dry-run are mutually exclusive.');\n process.exitCode = 1;\n return;\n }\n\n // Recovery mode — branch out of the normal compare/apply flow and\n // emit ALTER TABLE … SWAP WITH from a recorded snapshot batch.\n if (opts.restoreFromSnapshot) {\n await runRestoreFromSnapshot(opts);\n return;\n }\n\n const pacRef = opts.source ?? opts.pac;\n if (!pacRef) {\n logger.error(\n '--source <path> (or its alias --pac) is required (unless --restore-from-snapshot is given).',\n );\n process.exitCode = 1;\n return;\n }\n const pacPath = path.resolve(String(pacRef));\n const pac = await readPac(pacPath);\n\n // Freshness gate — runs before any network call so stale artifacts\n // are caught fast, before an expensive live-extract round trip.\n const freshnessMode = (opts.freshness as pacFreshness.FreshnessMode | undefined) ?? 'warn';\n if (freshnessMode !== 'skip') {\n const fr = pacFreshness.checkPacFreshness(pac.manifest.builtAt);\n if (fr.status !== 'fresh') {\n const msg = pacFreshness.formatFreshnessWarning(fr, pacPath);\n if (freshnessMode === 'strict') {\n logger.error(msg);\n process.exitCode = 1;\n return;\n } else {\n logger.warn(msg);\n }\n }\n }\n\n const profileName = String(opts.connection);\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n const db = opts.db ? String(opts.db) : pac.manifest.scope.database;\n const schema = opts.schema ? String(opts.schema) : pac.manifest.scope.schema;\n const live = new LiveSource(conn, { database: db, schema });\n const source = new ModelSource(pacPath, pac.model);\n\n const baseline: SdtDeployOptions | undefined = pac.manifest.deployOptions;\n const merged = mergeDeployOptions(baseline);\n // Apply the production safety floor: if the profile name looks like\n // production, force preDeployClone=true regardless of what the user\n // authored. Documented in docs/UX_PLAYBOOK.md §\"Per-profile safety\n // floor\". Compose by mutating the `deployment` block in place.\n const isProd = safety.looksLikeProduction(profileName);\n const resolved = {\n ...merged,\n deployment: safety.applyProductionSafetyFloor(merged.deployment, isProd),\n };\n if (isProd && merged.deployment.preDeployClone !== true) {\n logger.info(\n ' Profile \"' +\n profileName +\n '\" looks like production — forcing deployOptions.deployment.preDeployClone=true (safety floor).',\n );\n }\n const preScripts: DeployScript[] =\n opts.preScripts === false\n ? []\n : resolveDeployScripts(pac.source, resolved.deployment.preDeployScriptPatterns);\n const postScripts: DeployScript[] =\n opts.postScripts === false\n ? []\n : resolveDeployScripts(pac.source, resolved.deployment.postDeployScriptPatterns);\n\n // Logical-name mapping (`--map`, `--map-file`) — rewrites pac-side FQNs\n // so a pac built against DB_A can publish into DB_B. See\n // docs/LOGICAL_NAME_MAPPING.md. Mirrors `ddt publish`.\n const nameMapping = await buildMappingFromOptions(opts);\n const engine = new CompareEngine();\n logger.step('Comparing pac to live...');\n\n // Apply the pac's Slice (if any) so target objects outside the slice\n // are partitioned into `outsideScope` rather than treated as removals.\n // --no-slice on the publish command bypasses this.\n const sliceConfig = opts.slice === false ? undefined : pac.manifest.slice;\n const slice = sliceConfig ? compileSlice(sliceConfig) : undefined;\n\n const result = await engine.compare(source, live, {\n ...(nameMapping ? { nameMapping } : {}),\n ...(slice ? { sliceFilter: slice } : {}),\n });\n if (slice) {\n const outside = result.outsideScope?.length ?? 0;\n const refs = result.referenced?.length ?? 0;\n logger.info(\n ' Slice active: ' +\n result.objects.length +\n ' owned · ' +\n outside +\n ' outside scope (untouched) · ' +\n refs +\n ' referenced',\n );\n }\n logger.info(\n ' +' +\n result.summary.added +\n ' -' +\n result.summary.removed +\n ' ~' +\n result.summary.modified +\n ' =' +\n result.summary.unchanged,\n );\n\n // Protection check — refuse to touch protected objects unless overridden.\n const protConfig = await protectedObjects.loadProtectionConfig(path.dirname(pacPath));\n if (protConfig) {\n const ops = result.objects\n .filter((o) => o.kind !== 'unchanged' && o.kind !== 'added')\n .map((o) => ({\n fqn: o.identity.fqn,\n objectType: String(o.identity.objectType),\n kind: o.kind,\n }));\n const allowedFqns = ((opts.allowProtected as string[]) ?? []).flatMap((s) =>\n s.split(',').map((f) => f.trim()),\n );\n const violations = protectedObjects.checkProtectedObjects(ops, protConfig, {\n allowedFqns,\n allowAll: Boolean(opts.allowAllProtected),\n });\n if (violations.length > 0) {\n logger.error(protectedObjects.formatProtectionViolations(violations));\n process.exitCode = 1;\n await conn.disconnect();\n return;\n }\n }\n\n // VARSYNTAX.2 — resolve `$(VAR)` variables from the pac's\n // deployment-profile snapshot (when `--profile <name>` is given)\n // merged with `--variables KEY=VALUE` (CLI wins on key collision).\n // Absent / empty leaves `$(VAR)` references literal so the prior\n // behavior is preserved when no flag is passed.\n const deploymentProfileName = opts.profile ? String(opts.profile) : undefined;\n let publishVariables: Record<string, string> | undefined;\n if (deploymentProfileName) {\n const profileBlock = pac.manifest.deploymentProfiles?.[deploymentProfileName];\n if (!profileBlock) {\n const available = Object.keys(pac.manifest.deploymentProfiles ?? {});\n logger.error(\n `--profile ${deploymentProfileName}: no deploymentProfile by that name in the pac manifest. ` +\n (available.length === 0\n ? 'The pac carries no deploymentProfiles (was it built before VARSYNTAX.2, or does the .sdtproj declare any?).'\n : `Available: ${available.join(', ')}.`),\n );\n process.exitCode = 1;\n await conn.disconnect();\n return;\n }\n if (profileBlock.variables) publishVariables = { ...profileBlock.variables };\n }\n const cliVariables = parsePublishVariables(opts.variables);\n if (cliVariables) {\n publishVariables = { ...(publishVariables ?? {}), ...cliVariables };\n }\n\n const gen = new ScriptGenerator();\n // VARSYNTAX.3 — supply the deploy context so `$(SDT_PROFILE)`,\n // `$(SDT_PROJECT_NAME)`, `$(SDT_PROJECT_VERSION)`, `$(SDT_PLATFORM)`,\n // `$(SDT_TIMESTAMP)`, `$(SDT_USER)` substitute without the operator\n // having to pass them via `--variables`.\n const generateContext: {\n profile?: string;\n projectName?: string;\n projectVersion?: string;\n user?: string;\n } = {\n projectName: pac.manifest.projectName,\n projectVersion: pac.manifest.projectVersion,\n ...(deploymentProfileName ? { profile: deploymentProfileName } : {}),\n ...(profile.auth?.username ? { user: profile.auth.username } : {}),\n };\n const body = gen.generate(result, {\n banner: 'SDT publish: ' + pac.manifest.projectName + ' v' + pac.manifest.projectVersion,\n deployment: resolved.deployment,\n ...(publishVariables ? { variables: publishVariables } : {}),\n context: generateContext,\n });\n\n const sections: string[] = [];\n if (preScripts.length > 0) {\n sections.push('-- ' + '='.repeat(68));\n sections.push('-- PRE-DEPLOY (' + preScripts.length + ' script(s))');\n sections.push('-- ' + '='.repeat(68));\n for (const s of preScripts) sections.push(formatDeployScript(s, 'pre'));\n }\n sections.push(body.sql);\n if (postScripts.length > 0) {\n sections.push('');\n sections.push('-- ' + '='.repeat(68));\n sections.push('-- POST-DEPLOY (' + postScripts.length + ' script(s))');\n sections.push('-- ' + '='.repeat(68));\n for (const s of postScripts) sections.push(formatDeployScript(s, 'post'));\n }\n const fullScript = sections.join('\\n');\n\n logger.info(\n ' pre-deploy: ' +\n preScripts.length +\n ' script(s); post-deploy: ' +\n postScripts.length +\n ' script(s)',\n );\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, fullScript);\n logger.success('Wrote migration script to ' + out);\n }\n\n if (opts.dryRun || !opts.apply) {\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n process.stdout.write(colorizeMigrationScript(fullScript, { mode: colorMode }) + '\\n');\n await conn.disconnect();\n return;\n }\n\n // --apply path: run safety classifier and check gates.\n const assessment = safety.assess(result, { deployment: resolved.deployment });\n logger.info(\n ' safety: ' +\n assessment.unrecoverable.length +\n ' unrecoverable, ' +\n assessment.destructive.length +\n ' destructive, ' +\n assessment.expensive.length +\n ' expensive, ' +\n assessment.warnings.length +\n ' warnings',\n );\n if (assessment.blocked) {\n logger.error('Deploy refused: ' + assessment.blockReason);\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n\n const satisfied = safety.satisfiedGates({\n yes: Boolean(opts.yes),\n confirmProduction:\n Boolean(opts.confirmProduction) || !safety.looksLikeProduction(profileName),\n allowDropTable: resolved.deployment.allowDropTable,\n allowDropColumn: resolved.deployment.allowDropColumn,\n allowNarrowing: resolved.deployment.allowNarrowingTypes,\n allowTableRebuild: resolved.deployment.allowTableRebuild,\n allowUnrecoverableDrop: resolved.deployment.allowUnrecoverableDrop,\n });\n const outstanding = safety.outstandingGates(assessment, satisfied);\n if (outstanding.length > 0) {\n logger.error(\n 'Outstanding safety gate(s): ' +\n outstanding.join(', ') +\n '. Pass --yes / --confirm-production or set the matching deployOptions.deployment.* flag in the profile.',\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n\n // Approval gate (Team-tier): refuse to apply until N distinct\n // approvers have recorded approval tokens for this deploy id.\n if (opts.requireApprovals !== undefined && opts.requireApprovals !== false) {\n const required = Number(opts.requireApprovals) || 0;\n const allowed = opts.approver\n ? String(opts.approver)\n .split(',')\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n const deployId = String(opts.deployId ?? `${profileName}:${db}.${schema}`);\n const approvalsRoot = String(opts.approvalsRoot);\n const file = await approval.readApprovalFile(approvalsRoot, deployId);\n const outcome = approval.evaluateApprovalGate(\n { deployId, required, allowedApprovers: allowed },\n file.approvals,\n );\n if (!outcome.satisfied) {\n logger.error(\n 'Approval gate blocked deploy: ' +\n (outcome.blockReason ?? 'gate not satisfied') +\n `. Record approvals with \\`sdt approval add ${deployId} --as <user>\\`.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n logger.info(\n ` approvals: ${outcome.satisfiedBy.length}/${required} ` +\n `(${outcome.satisfiedBy.join(', ')})`,\n );\n }\n\n // AI preflight grader: ask the operator to type what they expect\n // this deploy to do, then let an AI compare that narrative to the\n // actual SQL + safety findings. Blocks deploy on `mismatch`.\n if (opts.aiPreflight) {\n const narrative = await readPreflightNarrative(opts.aiPreflightText);\n if (!narrative) {\n logger.error(\n '--ai-preflight needs a narrative. Provide it inline via --ai-preflight-text or via stdin.',\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n logger.step('Grading deploy narrative with AI...');\n try {\n const findings = [\n ...assessment.unrecoverable.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ...assessment.destructive.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ...assessment.expensive.map((f) => ({\n code: String(f.code),\n fqn: f.fqn,\n reason: f.reason,\n })),\n ];\n const compareSummary = `added ${result.summary.added}, modified ${result.summary.modified}, removed ${result.summary.removed}, unchanged ${result.summary.unchanged}`;\n const verdict = await aiPreflight.gradePreflight(\n {\n narrative,\n compareSummary,\n safetyFindings: findings,\n diffSampleDdl: fullScript,\n target: `${db}.${schema}@${profileName}`,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'ai-preflight',\n });\n return r.text;\n },\n },\n );\n logger.info(' preflight verdict: ' + verdict.verdict);\n if (verdict.reasoning) logger.info(' preflight reasoning: ' + verdict.reasoning);\n for (const d of verdict.discrepancies) logger.info(' • ' + d);\n\n const isBlocking =\n verdict.verdict === 'mismatch' ||\n (opts.strictAiPreflight && verdict.verdict === 'partial');\n if (isBlocking && !opts.confirmAfterPreflightMismatch) {\n logger.error(\n `Deploy refused: AI preflight returned \"${verdict.verdict}\". Re-run with --confirm-after-preflight-mismatch to override, or revise the narrative.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n if (verdict.parseFailed) {\n logger.warn(\n ' preflight verdict could not be parsed — continuing without a clean alignment signal.',\n );\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\n `--ai-preflight failed: ${msg}. Configure an AI provider via \\`sdt ai status\\` or omit --ai-preflight.`,\n );\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n }\n\n // ── DCM path — replaces the standard executor when --via-dcm is set ──\n if (opts.viaDcm) {\n const dcmStage = String(opts.viaDcm);\n\n // Enterprise license check (warn mode for v0.1 — feature is allowed with warning if no license).\n const lic = await license.loadLicense();\n const licCheck = license.checkProFeature(lic, 'dcm-deploy');\n if (licCheck.warning) logger.warn('[Enterprise] ' + licCheck.warning);\n\n // DCM compatibility pre-flight — always runs, even for --dry-run.\n const dcmCompatReport = assessDcmCompatibility(result);\n if (dcmCompatReport.blocked) {\n logger.error('--via-dcm blocked:\\n' + formatDcmCompatibilityReport(dcmCompatReport));\n await conn.disconnect();\n process.exitCode = 1;\n return;\n }\n if (dcmCompatReport.findings.length > 0) {\n logger.warn(\n 'DCM compatibility warnings:\\n' + formatDcmCompatibilityReport(dcmCompatReport),\n );\n }\n\n if (opts.dryRun || !opts.apply) {\n logger.info(\n 'DCM compatibility check passed (' +\n dcmCompatReport.findings.length +\n ' warning(s)). Use --apply to execute via DCM.',\n );\n await conn.disconnect();\n return;\n }\n\n // Execute via DCM.\n logger.step('Executing via DCM: EXECUTE DCM PROJECT ' + dcmStage + ' DEPLOY');\n const dcmResult = await executeDcmProjectDeploy(conn, dcmStage);\n const bodyReport = mapDcmResultToDeploymentReport(dcmResult);\n\n if (dcmResult.overallStatus === 'SUCCESS') {\n logger.success(\n 'DCM deploy complete. ' + dcmResult.objects.length + ' object(s) processed.',\n );\n } else {\n logger.error(\n 'DCM deploy finished with failures: ' +\n dcmResult.failures.length +\n ' failed, ' +\n dcmResult.objects.length +\n ' total.',\n );\n process.exitCode = 1;\n }\n\n if (opts.manifest) {\n const m = buildDeployManifest(bodyReport, profile.account);\n const mPath = path.resolve(String(opts.manifest));\n await fs.mkdir(path.dirname(mPath), { recursive: true });\n await fs.writeFile(mPath, JSON.stringify(m, null, 2) + '\\n', 'utf8');\n logger.success('Wrote deploy manifest → ' + mPath);\n }\n\n await conn.disconnect();\n return;\n }\n // ── End DCM path ────────────────────────────────────────────────────────\n\n // Set the Snowflake QUERY_TAG before executing any migration\n // statement. Threading the tag into QUERY_HISTORY is what makes a\n // deploy auditable after the fact (\"which statements ran as part of\n // sdt-vX.Y.Z published at 13:42?\"). Default tag encodes the project\n // identity + a millisecond timestamp so two back-to-back applies are\n // distinguishable.\n const queryTag =\n typeof opts.queryTag === 'string' && opts.queryTag.length > 0\n ? String(opts.queryTag)\n : `sdt:${pac.manifest.projectName}@${pac.manifest.projectVersion}:${Date.now()}`;\n try {\n await conn.query(`ALTER SESSION SET QUERY_TAG = '${queryTag.replace(/'/g, \"''\")}'`);\n logger.info(' query_tag: ' + queryTag);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\n 'Failed to set QUERY_TAG: ' +\n msg +\n '. Continuing without tag — audit attribution will be missing.',\n );\n }\n\n // Execute. Statements run sequentially. Snowflake DDL auto-commits per\n // statement, so partial deploys do not roll back automatically; if\n // preDeployClone was enabled, use UNDROP DATABASE or clone-swap to\n // recover. The main body runs through executePlan + SnowflakeExecutor\n // so every step's reverseSql is captured for `sdt revert`. Pre/post\n // scripts are file-based (no emitter, no reverseSql) so they keep the\n // simpler sequential-query path.\n logger.step('Applying migration...');\n let executed = 0;\n let failed = 0;\n const runOne = async (sql: string, label: string): Promise<boolean> => {\n const stmts = splitStatements(sql);\n for (const stmt of stmts) {\n try {\n await conn.query(stmt);\n executed += 1;\n } catch (err) {\n failed += 1;\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(' [' + label + '] failed: ' + msg + '\\n ' + stmt);\n return false;\n }\n }\n return true;\n };\n\n let ok = true;\n for (const s of preScripts) {\n logger.info(' pre: ' + s.path);\n ok = await runOne(s.sql, 'pre/' + s.path);\n if (!ok) break;\n }\n\n let bodyReport: DeploymentReport | undefined;\n if (ok) {\n const plan = defaultSafePlan(result);\n const validated = validatePlan(result, plan);\n const steps = buildExecutionPlan(result, validated, {\n deployment: resolved.deployment,\n });\n if (steps.length > 0) {\n const executor = new SnowflakeExecutor(conn, {\n onStatement: (sql) => {\n executed += 1;\n const head = sql.split('\\n')[0]?.slice(0, 100) ?? '';\n logger.info(' → ' + head + (sql.length > 100 ? ' …' : ''));\n },\n });\n bodyReport = await executePlan(steps, executor, {\n rollbackOnFailure: false,\n onStepEnd: (r: StepResult) => {\n if (r.status === 'FAILED') {\n failed += 1;\n logger.error(\n ' [' +\n r.step.fqn +\n '] failed: ' +\n (r.error ?? 'unknown') +\n '\\n ' +\n r.step.forwardSql,\n );\n }\n },\n });\n if (bodyReport.finalState !== 'CLEAN_SUCCESS') ok = false;\n }\n }\n\n if (ok) {\n for (const s of postScripts) {\n logger.info(' post: ' + s.path);\n ok = await runOne(s.sql, 'post/' + s.path);\n if (!ok) break;\n }\n }\n\n // Write deploy manifest if requested. The manifest captures every\n // body step (forwardSql + reverseSql + status + duration) and is\n // replayable via `sdt revert --manifest <path>`. Pre/post scripts are\n // not in the manifest (they have no inverse).\n if (opts.manifest && bodyReport) {\n const m = buildDeployManifest(bodyReport, profile.account);\n const mPath = path.resolve(String(opts.manifest));\n await fs.mkdir(path.dirname(mPath), { recursive: true });\n await fs.writeFile(mPath, JSON.stringify(m, null, 2) + '\\n', 'utf8');\n logger.success('Wrote deploy manifest → ' + mPath);\n }\n\n if (ok) {\n logger.success('Deploy complete. ' + executed + ' statement(s) executed.');\n\n // Post-deploy DQ tests (DQ.6).\n if (opts.postDeployTests) {\n const projectRoot = path.resolve(String(opts.postDeployTests));\n logger.step('Running post-deploy DQ tests from ' + projectRoot + '...');\n const testFiles = await testFramework.discoverTests(projectRoot);\n if (testFiles.length === 0) {\n logger.warn(\n ' POST_DEPLOY_DQ: no tests found under ' + projectRoot + '/tests/ — skipping.',\n );\n } else {\n const report = await testFramework.runTestFiles(testFiles, conn);\n process.stdout.write(testFramework.renderTextReport(report));\n if (report.summary.blocking) {\n logger.error(\n 'POST_DEPLOY_DQ_FAILED: ' +\n report.summary.fail +\n ' fail / ' +\n report.summary.error +\n ' error.' +\n (opts.manifest\n ? ' Recover: `sdt revert --manifest ' + String(opts.manifest) + '`'\n : ' Consider re-deploying prior version or using `sdt revert --manifest` if --manifest was used.'),\n );\n process.exitCode = 2;\n } else {\n logger.success(\n ' POST_DEPLOY_DQ: ' + report.summary.pass + '/' + report.summary.total + ' pass.',\n );\n }\n }\n }\n } else {\n logger.error(\n 'Deploy aborted after ' +\n executed +\n ' statement(s); ' +\n failed +\n ' failure(s). Recover via UNDROP / clone-swap if preDeployClone was set.',\n );\n process.exitCode = 1;\n }\n await conn.disconnect();\n });\n addMappingFlags(cmd);\n attachRelatedOptions(cmd, [\n 'deployment.allowDropTable',\n 'deployment.allowDropColumn',\n 'deployment.allowUnrecoverableDrop',\n 'deployment.allowNarrowingTypes',\n 'deployment.preDeployClone',\n 'deployment.blockOnPossibleDataLoss',\n 'deployment.preserveTargetOnlyObjects',\n ]);\n return cmd;\n}\n\n/**\n * `sdt publish --restore-from-snapshot <batchId>` recovery path.\n *\n * Loads the batch from the registry, emits the restore SQL (one\n * `ALTER TABLE … SWAP WITH` per source object, or a MANUAL hint row for\n * materialised objects), and either prints it (dry-run / no --apply) or\n * executes it against the live target (--apply --yes, --confirm-production\n * for prod-named profiles).\n *\n * Skips: pac freshness, compare, safety classifier, AI preflight, approval\n * gate, DCM path, manifest writing. Recovery is an emergency lever — the\n * gates that protect the forward path don't apply when we're restoring a\n * known-good snapshot the safety classifier itself authored.\n */\nasync function runRestoreFromSnapshot(opts: Record<string, unknown>): Promise<void> {\n const batchId = String(opts.restoreFromSnapshot);\n const registryDir = path.resolve(String(opts.snapshotDir ?? '.sdt/snapshots'));\n const profileName = String(opts.connection);\n\n let batch: safety.SnapshotBatch;\n try {\n batch = await safety.readSnapshotBatch(registryDir, batchId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Snapshot batch \"${batchId}\" not found in ${registryDir}: ${msg}`);\n process.exitCode = 1;\n return;\n }\n\n const sqlLines = safety.emitRestoreFromSnapshotSql(batch);\n const sql = sqlLines.join('\\n');\n\n logger.info(`Restoring from batch ${batch.batchId} (createdAt=${batch.createdAt})`);\n logger.info(\n ` ${batch.entries.length} object(s) recorded; ${sqlLines.filter((l) => !l.startsWith('--')).length} statement(s) will run.`,\n );\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, sql + '\\n', 'utf8');\n logger.success(`Wrote restore SQL → ${out}`);\n }\n\n if (opts.dryRun || !opts.apply) {\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n process.stdout.write(colorizeMigrationScript(sql, { mode: colorMode }) + '\\n');\n return;\n }\n\n if (!opts.yes) {\n logger.error('--apply requires --yes (restore replaces production tables via SWAP WITH).');\n process.exitCode = 1;\n return;\n }\n if (safety.looksLikeProduction(profileName) && !opts.confirmProduction) {\n logger.error(\n `Profile \"${profileName}\" looks like production — also pass --confirm-production to restore.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const profile = await getProfile(profileName);\n const conn = new SnowflakeConnection(profile);\n let executed = 0;\n let failed = 0;\n try {\n for (const stmt of coreSplitStatements(sql).map((s) => s.sql)) {\n try {\n await conn.query(stmt);\n executed += 1;\n const head = stmt.split('\\n')[0]?.slice(0, 100) ?? '';\n logger.info(' → ' + head + (stmt.length > 100 ? ' …' : ''));\n } catch (err) {\n failed += 1;\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(` [restore ${batch.batchId}] ${msg}\\n ${stmt}`);\n }\n }\n } finally {\n await conn.disconnect();\n }\n\n if (failed === 0) {\n logger.success(`Restore complete. ${executed} statement(s) executed.`);\n } else {\n logger.error(\n `Restore finished with failures: ${executed} ok, ${failed} failed. ` +\n `Inspect the snapshot tables under ${registryDir} and recover by hand.`,\n );\n process.exitCode = 1;\n }\n}\n\n/**\n * Read the AI-preflight narrative from --ai-preflight-text (preferred for CI)\n * or from stdin (interactive). Returns trimmed text, or undefined when no\n * narrative was supplied.\n */\nasync function readPreflightNarrative(inlineText: unknown): Promise<string | undefined> {\n if (typeof inlineText === 'string' && inlineText.trim().length > 0) {\n return inlineText.trim();\n }\n if (process.stdin.isTTY) {\n process.stdout.write(\n '\\n--ai-preflight is active. In one paragraph, describe what you expect this deploy to do.\\nEnd with an empty line (or Ctrl-D):\\n> ',\n );\n }\n process.stdin.setEncoding('utf8');\n let buffer = '';\n await new Promise<void>((resolve) => {\n const onData = (chunk: string): void => {\n buffer += chunk;\n if (/\\n\\s*\\n/.test(buffer)) {\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n resolve();\n }\n };\n const onEnd = (): void => {\n process.stdin.removeListener('data', onData);\n resolve();\n };\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n });\n const trimmed = buffer.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\n/**\n * VARSYNTAX.2 — parse the `--variables KEY=VALUE,KEY=VALUE,...` flag.\n * Returns undefined when nothing is parsed (no KV pairs, missing values,\n * empty string) so callers can `...(parsed ? { variables: parsed } : {})`\n * without leaking an empty object.\n */\nexport function parsePublishVariables(raw: unknown): Record<string, string> | undefined {\n if (!raw) return undefined;\n const out: Record<string, string> = {};\n for (const pair of String(raw).split(',')) {\n const eq = pair.indexOf('=');\n if (eq <= 0) continue;\n const k = pair.slice(0, eq).trim();\n const v = pair.slice(eq + 1).trim();\n if (k.length > 0) out[k] = v;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n","import { Command } from 'commander';\nimport path from 'node:path';\nimport { readPac } from '@sdt-tools/core/pac';\nimport {\n CompareEngine,\n DbtManifestSource,\n LiveSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { loadProject } from '@sdt-tools/core/project';\nimport { driftAnomaly } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\nclass ModelSource implements CompareSource {\n readonly kind = 'pac' as const;\n readonly platform = 'Snowflake' as const;\n readonly label: string;\n private readonly model: Awaited<ReturnType<typeof readPac>>['model'];\n constructor(label: string, model: Awaited<ReturnType<typeof readPac>>['model']) {\n this.label = label;\n this.model = model;\n }\n async load() {\n return this.model;\n }\n}\n\nfunction driftWatchSubcommand(): Command {\n const sub = new Command('watch');\n sub\n .description(\n 'Poll a project against the live Snowflake account on a fixed interval. Prints DRIFT_DETECTED events to stdout (or POSTs to --webhook) when the catalog diverges from the project pac.',\n )\n .requiredOption('-p, --project <path>', 'Path to .sdtproj')\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .option('--interval <seconds>', 'Poll interval in seconds (min 5).', '60')\n .option(\n '--webhook <url>',\n 'POST drift events as JSON to this URL (Slack/Teams/generic receiver).',\n )\n .option('--format <fmt>', 'Output format: text | json.', 'text')\n .option(\n '--quiet',\n 'Suppress CLEAN status lines; emit only DRIFT_DETECTED and error events.',\n false,\n )\n .action(async (opts) => {\n const intervalSecs = Math.max(5, parseInt(String(opts.interval), 10) || 60);\n const format = String(opts.format) === 'json' ? 'json' : 'text';\n const webhookUrl = opts.webhook ? String(opts.webhook) : undefined;\n const quiet = !!opts.quiet;\n\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const loaded = await loadProject(String(opts.project));\n const pacPath = path.join(loaded.rootDir, 'bin', `${loaded.project.name}.sdtpac`);\n const scope = {\n database: loaded.project.scope.database,\n schema: loaded.project.scope.schema,\n };\n\n if (!quiet && format === 'text') {\n logger.info(\n `drift watch: polling every ${intervalSecs}s — ${loaded.project.name} → ${profile.account}`,\n );\n logger.info('Press Ctrl+C to stop.');\n }\n\n const postToWebhook = async (event: Record<string, unknown>): Promise<void> => {\n if (!webhookUrl) return;\n try {\n const res = await fetch(webhookUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(event),\n });\n if (!res.ok && format === 'text') logger.warn(`Webhook POST failed: HTTP ${res.status}`);\n } catch (err) {\n if (format === 'text')\n logger.warn(`Webhook error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n\n const pollOnce = async (): Promise<void> => {\n const ts = new Date().toISOString();\n try {\n const pac = await readPac(pacPath);\n const declared = new ModelSource(pacPath, pac.model);\n const live = new LiveSource(conn, scope);\n const engine = new CompareEngine();\n const result = await engine.compare(declared, live);\n const s = result.summary;\n const drifted = s.added + s.removed + s.modified;\n if (drifted > 0) {\n const event = {\n type: 'DRIFT_DETECTED',\n timestamp: ts,\n project: loaded.project.name,\n added: s.added,\n removed: s.removed,\n modified: s.modified,\n };\n if (format === 'json') process.stdout.write(JSON.stringify(event) + '\\n');\n else logger.warn(`[${ts}] DRIFT_DETECTED +${s.added} -${s.removed} ~${s.modified}`);\n await postToWebhook(event);\n } else if (!quiet) {\n if (format === 'json')\n process.stdout.write(\n JSON.stringify({ type: 'CLEAN', timestamp: ts, project: loaded.project.name }) +\n '\\n',\n );\n else logger.info(`[${ts}] clean`);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (format === 'json')\n process.stdout.write(\n JSON.stringify({ type: 'POLL_ERROR', timestamp: ts, error: message }) + '\\n',\n );\n else logger.error(`[${ts}] poll error: ${message}`);\n }\n };\n\n await pollOnce();\n const timer = setInterval(() => {\n void pollOnce();\n }, intervalSecs * 1000);\n process.once('SIGINT', () => {\n clearInterval(timer);\n void conn.disconnect().then(() => process.exit(0));\n });\n await new Promise<void>(() => {});\n });\n return sub;\n}\n\nexport function driftCommand(): Command {\n const cmd = new Command('drift');\n cmd\n .description(\n 'Check whether a live Snowflake target has drifted from the project pac or a dbt manifest.',\n )\n .option('-p, --project <path>', 'Path to .sdtproj (required unless --vs-dbt-project is used)')\n .option(\n '--vs-dbt-project <path>',\n 'Compare a compiled dbt project (or target/manifest.json) against the live target. ' +\n 'Run `dbt compile` first. When set, --project is not required.',\n )\n .requiredOption('-c, --connection <profile>', 'Connection profile name')\n .option(\n '--anomalies',\n 'Also classify drift via the anomaly detector (new grants to PUBLIC, bypass-role grants, owner changes, audit-column drops, mask removals, new bypass-named roles).',\n false,\n )\n .option(\n '--anomalies-only',\n 'Skip the simple drift summary and emit only the anomaly report. Implies --anomalies.',\n false,\n )\n .option(\n '--fail-on-anomaly <severity>',\n 'Exit non-zero when any anomaly at or above this severity fires. Values: critical | high | medium | low. Default: drift presence alone determines exit code.',\n );\n // Logical-name mapping (`--map`, `--map-file`) — rewrites declared-side\n // FQNs so a project authored against DEV names can be drift-checked\n // against a PROD target. See docs/LOGICAL_NAME_MAPPING.md. Mirrors\n // `ddt drift` (RH3.2 parity).\n addMappingFlags(cmd);\n cmd.action(async (opts) => {\n if (!opts.project && !opts.vsDBtProject) {\n logger.error('Provide either --project <path> or --vs-dbt-project <path>.');\n process.exitCode = 1;\n return;\n }\n\n const nameMapping = await buildMappingFromOptions(opts);\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n\n let declared: CompareSource;\n let scope: { database?: string; schema?: string };\n\n if (opts.vsDBtProject) {\n declared = new DbtManifestSource(String(opts.vsDBtProject), `dbt:${opts.vsDBtProject}`);\n scope = {};\n } else {\n const loaded = await loadProject(String(opts.project));\n const pacPath = path.join(loaded.rootDir, 'bin', `${loaded.project.name}.sdtpac`);\n const pac = await readPac(pacPath);\n declared = new ModelSource(pacPath, pac.model);\n scope = {\n database: loaded.project.scope.database,\n schema: loaded.project.scope.schema,\n };\n }\n\n const live = new LiveSource(conn, scope);\n const engine = new CompareEngine();\n const result = await engine.compare(declared, live, {\n ...(nameMapping ? { nameMapping } : {}),\n });\n const drifted = result.summary.added + result.summary.removed + result.summary.modified;\n if (!opts.anomaliesOnly) {\n if (drifted === 0) {\n logger.success('No drift detected.');\n } else {\n logger.warn(\n `Drift: +${result.summary.added} -${result.summary.removed} ~${result.summary.modified}`,\n );\n process.exitCode = 1;\n }\n }\n\n if (opts.anomalies || opts.anomaliesOnly) {\n const report = driftAnomaly.detectAnomalies(result);\n if (report.totalAnomalies === 0) {\n logger.info('Anomaly scan: 0 findings.');\n } else {\n logger.warn(`Anomaly scan: ${report.totalAnomalies} finding(s):`);\n for (const a of report.anomalies) {\n logger.info(` [${a.severity}] ${a.category}: ${a.fqn} — ${a.reason}`);\n }\n const failOn = (opts.failOnAnomaly as string | undefined)?.toLowerCase();\n if (failOn && ['critical', 'high', 'medium', 'low'].includes(failOn)) {\n const failRank = driftAnomaly.anomalySeverityRank(failOn as driftAnomaly.AnomalySeverity);\n const triggered = report.anomalies.some(\n (a) => driftAnomaly.anomalySeverityRank(a.severity) <= failRank,\n );\n if (triggered) process.exitCode = 1;\n }\n }\n }\n await conn.disconnect();\n });\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n ]);\n cmd.addCommand(driftWatchSubcommand());\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n catalog,\n project,\n validate as validateNs,\n variables as variablesNs,\n} from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\n/**\n * `sdt validate` — schema-shape sanity check on a `.sdtproj`. Default\n * mode confirms the project file parses, scope resolves, and object\n * files discover successfully. The `--references` flag adds the\n * Microsoft-SSDT-style build-time semantic resolution: every object reference in every\n * project body is classified as resolved / dangling / external /\n * temporary / dynamic, with warnings for unresolved references.\n *\n * Column-level resolution is Phase 2 (BACKLOG-tracked).\n */\nexport function validateCommand(): Command {\n const cmd = new Command('validate');\n cmd\n .description(\n 'Validate a .sdtproj — schema check; optionally resolve every object reference (--references).',\n )\n .requiredOption('-p, --project <path>', 'Path to .sdtproj')\n .option(\n '--references',\n 'Run the build-time semantic resolver — flag dangling/external/temp/dynamic references.',\n )\n .option(\n '--columns',\n '[--references] Also resolve every column reference. ERROR on missing column on a known table. Phase 2 of the SSDT-build-equivalent resolver.',\n )\n .option(\n '--min-severity <s>',\n '[--references] Filter findings: error | warning | info. Default info.',\n 'info',\n )\n .option('--format <fmt>', '[--references] table | json. Default table.', 'table')\n .option('-o, --out <path>', '[--references] Write report to file instead of stdout.')\n .option(\n '--check-variables',\n 'VARSYNTAX.4 — refuse if any `$(VAR)` reference in a tracked `.sql` file is not declared in built-ins / deploymentProfiles[*].variables. Exits 1 when undeclared references are found.',\n )\n .action(async (opts) => {\n const loaded = await project.loadProject(String(opts.project));\n const files = await project.discoverObjectFiles(loaded);\n logger.success(`Project ${loaded.project.name} v${loaded.project.version} is valid.`);\n logger.dim(\n ` Scope: ${loaded.project.scope.type}${loaded.project.scope.database ? '/' + loaded.project.scope.database : ''}`,\n );\n logger.dim(` Files: ${files.length}`);\n logger.dim(` Profiles: ${Object.keys(loaded.project.deploymentProfiles ?? {}).length}`);\n\n if (opts.checkVariables) {\n const projRoot = path.dirname(path.resolve(String(opts.project)));\n // RH4.3 — bounded-concurrency reads (cap FDs on large projects).\n // stopOnError preserves the prior Promise.all reject-on-first-error\n // semantics; results stay dense + in input order.\n const { results } = await catalog.mapPool(\n files,\n async (f) => {\n const relPath = path.relative(projRoot, f).split(path.sep).join('/');\n const content = await fs.readFile(f, 'utf8');\n return { path: relPath, content };\n },\n { concurrency: 16, stopOnError: true },\n );\n const fileContents = results.filter(\n (r): r is { path: string; content: string } => r !== undefined,\n );\n const profilesBlock = loaded.project.deploymentProfiles ?? {};\n const profileVariableKeys = Object.values(profilesBlock).map((p) =>\n Object.keys(p.variables ?? {}),\n );\n const report = variablesNs.checkVariableReferences({\n files: fileContents,\n deploymentProfileVariables: profileVariableKeys,\n });\n if (report.undeclared.length > 0) {\n const msg = variablesNs.formatCheckVariablesReport(report);\n process.stdout.write(msg + '\\n');\n process.exitCode = 1;\n return;\n }\n logger.dim(` Variables: ${report.references.length} reference(s), all declared.`);\n }\n\n if (!opts.references) return;\n\n logger.dim('');\n logger.dim('Resolving references…');\n const model = await project.parseProjectModel(loaded);\n const report = validateNs.validateProject(model, {\n source: String(opts.project),\n minSeverity: opts.minSeverity as validateNs.BuildSeverity,\n columns: Boolean(opts.columns),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n const payload =\n fmt === 'json' ? JSON.stringify(report, null, 2) : validateNs.formatBuildReport(report);\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n logger.dim(`Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n // Non-zero exit when at least one ERROR-severity finding fires so\n // `sdt validate --references` can gate a CI step.\n if (report.totals.error > 0) process.exitCode = 1;\n });\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n ]);\n return cmd;\n}\n","import { Command } from 'commander';\nimport {\n getProfile,\n loadProfiles,\n removeProfile,\n SnowflakeConnection,\n upsertProfile,\n type ConnectionProfile,\n type SnowflakeAuth,\n} from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\n\nexport function connectionCommand(): Command {\n const cmd = new Command('connection');\n cmd.description('Manage Snowflake connection profiles.');\n\n cmd\n .command('list')\n .description('List configured connection profiles.')\n .action(async () => {\n const profiles = await loadProfiles();\n if (!profiles.length) {\n logger.dim('(no profiles configured — run `sdt connection add` to add one)');\n return;\n }\n for (const p of profiles) {\n logger.info(\n ` ${p.name.padEnd(20)} ${p.account.padEnd(28)} ${p.auth.method} as ${p.auth.username}`,\n );\n }\n });\n\n cmd\n .command('add')\n .description('Add or replace a connection profile.')\n .requiredOption('--name <name>', 'Profile name')\n .requiredOption('--account <account>', 'Snowflake account locator (e.g. xy12345.us-east-1)')\n .requiredOption('--user <user>', 'Snowflake username')\n .option(\n '--auth <method>',\n 'Auth method: PASSWORD | KEY_PAIR | OAUTH | EXTERNAL_BROWSER | MFA',\n 'PASSWORD',\n )\n .option('--password <value>', 'Password or env:VAR_NAME placeholder')\n .option('--key <path>', 'Path to RSA private key (for KEY_PAIR auth)')\n .option('--key-passphrase <value>', 'Passphrase or env:VAR_NAME placeholder')\n .option('--role <role>', 'Default role')\n .option('--warehouse <wh>', 'Default warehouse')\n .option('--database <db>', 'Default database')\n .option('--schema <schema>', 'Default schema')\n .action(async (opts) => {\n const auth = String(opts.auth).toUpperCase() as ConnectionProfile['auth']['method'];\n let authBlock: ConnectionProfile['auth'];\n switch (auth) {\n case 'PASSWORD':\n if (!opts.password) throw new Error('--password is required for PASSWORD auth');\n authBlock = {\n method: 'PASSWORD',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n case 'KEY_PAIR':\n if (!opts.key) throw new Error('--key is required for KEY_PAIR auth');\n authBlock = {\n method: 'KEY_PAIR',\n username: String(opts.user),\n privateKeyPath: String(opts.key),\n privateKeyPassphrase: opts.keyPassphrase ? String(opts.keyPassphrase) : undefined,\n };\n break;\n case 'OAUTH':\n if (!opts.password)\n throw new Error('--password (token, or env:VAR) is required for OAUTH auth');\n authBlock = {\n method: 'OAUTH',\n username: String(opts.user),\n token: String(opts.password),\n };\n break;\n case 'EXTERNAL_BROWSER':\n authBlock = { method: 'EXTERNAL_BROWSER', username: String(opts.user) };\n break;\n case 'MFA':\n if (!opts.password) throw new Error('--password is required for MFA auth');\n authBlock = {\n method: 'MFA',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n default:\n throw new Error(`Unsupported auth method: ${auth}`);\n }\n const profile: ConnectionProfile = {\n name: String(opts.name),\n account: String(opts.account),\n auth: authBlock,\n role: opts.role ? String(opts.role) : undefined,\n warehouse: opts.warehouse ? String(opts.warehouse) : undefined,\n database: opts.database ? String(opts.database) : undefined,\n schema: opts.schema ? String(opts.schema) : undefined,\n };\n await upsertProfile(profile);\n logger.success(`Saved profile \"${profile.name}\".`);\n });\n\n cmd\n .command('get <name>')\n .description('Print a profile (secrets are redacted).')\n .action(async (name) => {\n const profile = await getProfile(String(name));\n const redacted: ConnectionProfile = { ...profile, auth: redactAuth(profile.auth) };\n logger.info(JSON.stringify(redacted, null, 2));\n });\n\n cmd\n .command('remove')\n .description('Remove a connection profile.')\n .argument('<name>')\n .action(async (name) => {\n const ok = await removeProfile(String(name));\n if (ok) logger.success(`Removed profile \"${name}\".`);\n else logger.warn(`No profile named \"${name}\".`);\n });\n\n cmd\n .command('test')\n .description('Test connectivity for a profile.')\n .argument('<name>')\n .action(async (name) => {\n const profile = await getProfile(String(name));\n const conn = new SnowflakeConnection(profile);\n try {\n const result = await conn.test();\n logger.success(`OK — Snowflake ${result.version}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n return cmd;\n}\n\n/**\n * Redact inline secrets for `connection get`. `env:`/`keyring:` placeholders are\n * not secrets (they only name where the value resolves from at runtime), so they\n * are preserved; literal secret values are replaced with `<redacted>`.\n */\nfunction redactAuth(auth: SnowflakeAuth): SnowflakeAuth {\n const isPlaceholder = (v: string): boolean => v.startsWith('env:') || v.startsWith('keyring:');\n switch (auth.method) {\n case 'PASSWORD':\n case 'MFA':\n return auth.password && !isPlaceholder(auth.password)\n ? { ...auth, password: '<redacted>' }\n : auth;\n case 'OAUTH':\n return auth.token && !isPlaceholder(auth.token) ? { ...auth, token: '<redacted>' } : auth;\n case 'KEY_PAIR':\n return auth.privateKeyPassphrase && !isPlaceholder(auth.privateKeyPassphrase)\n ? { ...auth, privateKeyPassphrase: '<redacted>' }\n : auth;\n case 'EXTERNAL_BROWSER':\n return auth;\n default: {\n const _exhaustive: never = auth;\n return _exhaustive;\n }\n }\n}\n","import { Command } from 'commander';\n\n/**\n * Placeholder factory for commands whose backing engine is a later\n * deliverable. Prints a clear \"not yet implemented\" message and exits\n * non-zero so CI notices.\n *\n * Mirrors `ddt scaffold` — exported for embedders, not wired into the\n * SDT CLI itself.\n */\nexport function scaffoldCommand(name: string): Command {\n return new Command(name)\n .description(`${name} — Snowflake (scaffold; later-release deliverable).`)\n .action(() => {\n console.error(\n `sdt ${name}: scaffold — the Snowflake engine for this command is a later deliverable.\\n` +\n `Track progress at Snowflake/docs/ROADMAP.md.`,\n );\n process.exitCode = 2;\n });\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { compare, pac, project } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt graph` — emit an object-dependency DAG (Mermaid or DOT) from a\n * `.sdtproj` or `.sdtpac`. Lets reviewers see blast radius before a\n * drop. Inspired by DBeaver's \"Object References\" panel — but at the\n * cross-object level rather than column level.\n *\n * With `--compare-to <other-source>`, diffs the two graphs and (when\n * `--explain` is on) narrates the DAG changes in plain English — the\n * AI Phase 6 \"lineage explanation\" surface.\n *\n * Mirrors `ddt graph`.\n */\nexport function graphCommand(): Command {\n const cmd = new Command('graph');\n cmd\n .description('Build an object-dependency DAG and emit it as Mermaid or DOT.')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--format <fmt>',\n 'mermaid | dot | md (Mermaid wrapped in a markdown fenced block)',\n 'mermaid',\n )\n .option('--json', 'Emit the raw { nodes, edges } JSON instead of a renderer.', false)\n .option(\n '--compare-to <path>',\n 'A second .sdtproj or .sdtpac. When set, emit added / removed / changed nodes + edges (the DAG delta) instead of the static graph.',\n )\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const graph = compare.buildDependencyGraph(model);\n\n let diff: compare.DependencyGraphDiff | undefined;\n if (opts.compareTo) {\n const otherModel = await loadModel(String(opts.compareTo));\n const otherGraph = compare.buildDependencyGraph(otherModel);\n // Source = \"after\", compareTo = \"before\" → the user is asking\n // \"what did the source side add vs the reference snapshot?\"\n diff = compare.diffDependencyGraphs(otherGraph, graph);\n }\n\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n let payload: string;\n if (opts.json) {\n payload = JSON.stringify(diff ?? graph, null, 2);\n } else if (diff) {\n payload = renderDiffMarkdown(diff);\n } else if (fmt === 'mermaid') {\n payload = compare.renderGraphMermaid(graph);\n } else if (fmt === 'dot') {\n payload = compare.renderGraphDot(graph);\n } else if (fmt === 'md') {\n payload = `# Schema dependency graph\\n\\n${graph.nodes.length} node(s), ${graph.edges.length} edge(s).\\n\\n\\`\\`\\`mermaid\\n${compare.renderGraphMermaid(graph)}\\n\\`\\`\\`\\n`;\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use mermaid | dot | md.`);\n }\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${graph.nodes.length} nodes, ${graph.edges.length} edges).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n await runExplain(\n {\n feature: 'graph.explain',\n systemPrompt: diff\n ? 'You are a data-platform architect narrating a dependency-graph DELTA between two snapshots. Walk through added / removed / changed nodes and edges in plain English. Call out structural shifts (new sources, dropped consumers, type changes) and likely-but-not-yet-broken downstream consequences.'\n : 'You are a data-platform architect explaining a dependency graph. Describe the dominant data-flow shape, point out hot or fragile nodes, and recommend any decomposition the graph suggests.',\n },\n opts as { explain?: boolean },\n () => (diff ? buildDiffPrompt(diff) : buildGraphPrompt(graph)),\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction renderDiffMarkdown(d: compare.DependencyGraphDiff): string {\n const lines: string[] = ['# Dependency-graph delta', ''];\n lines.push(\n `**Summary**: ${d.summary.nodeDelta >= 0 ? '+' : ''}${d.summary.nodeDelta} nodes, ` +\n `${d.summary.edgeDelta >= 0 ? '+' : ''}${d.summary.edgeDelta} edges. ` +\n `${d.addedNodes.length} added node(s), ${d.removedNodes.length} removed node(s), ` +\n `${d.changedNodes.length} changed node(s).`,\n );\n lines.push('');\n if (d.addedNodes.length > 0) {\n lines.push('## Added nodes');\n for (const n of d.addedNodes) lines.push(`- \\`${n.fqn}\\` (${n.objectType})`);\n lines.push('');\n }\n if (d.removedNodes.length > 0) {\n lines.push('## Removed nodes');\n for (const n of d.removedNodes) lines.push(`- \\`${n.fqn}\\` (${n.objectType})`);\n lines.push('');\n }\n if (d.changedNodes.length > 0) {\n lines.push('## Changed nodes (objectType)');\n for (const c of d.changedNodes) lines.push(`- \\`${c.fqn}\\`: ${c.before} → ${c.after}`);\n lines.push('');\n }\n if (d.addedEdges.length > 0) {\n lines.push('## Added edges');\n for (const e of d.addedEdges) lines.push(`- \\`${e.from}\\` → \\`${e.to}\\` (${e.kind})`);\n lines.push('');\n }\n if (d.removedEdges.length > 0) {\n lines.push('## Removed edges');\n for (const e of d.removedEdges) lines.push(`- \\`${e.from}\\` → \\`${e.to}\\` (${e.kind})`);\n }\n return lines.join('\\n');\n}\n\nfunction buildGraphPrompt(g: compare.DependencyGraph): string {\n const sample = g.edges.slice(0, 40).map((e) => ` - ${e.from} -> ${e.to}`);\n return [\n `Dependency graph: ${g.nodes.length} nodes, ${g.edges.length} edges.`,\n '',\n 'Edges (up to 40):',\n ...sample,\n '',\n 'Narrate this graph in plain English.',\n ].join('\\n');\n}\n\nfunction buildDiffPrompt(d: compare.DependencyGraphDiff): string {\n const lines: string[] = [];\n lines.push(\n `Graph delta: ${d.summary.nodeDelta >= 0 ? '+' : ''}${d.summary.nodeDelta} nodes, ` +\n `${d.summary.edgeDelta >= 0 ? '+' : ''}${d.summary.edgeDelta} edges.`,\n );\n if (d.addedNodes.length > 0) {\n lines.push('', `Added nodes (${d.addedNodes.length}, up to 20):`);\n for (const n of d.addedNodes.slice(0, 20)) lines.push(` + ${n.fqn} (${n.objectType})`);\n }\n if (d.removedNodes.length > 0) {\n lines.push('', `Removed nodes (${d.removedNodes.length}, up to 20):`);\n for (const n of d.removedNodes.slice(0, 20)) lines.push(` - ${n.fqn} (${n.objectType})`);\n }\n if (d.changedNodes.length > 0) {\n lines.push('', `Changed nodes (${d.changedNodes.length}):`);\n for (const c of d.changedNodes.slice(0, 20))\n lines.push(` ~ ${c.fqn}: ${c.before} -> ${c.after}`);\n }\n if (d.addedEdges.length > 0) {\n lines.push('', `Added edges (${d.addedEdges.length}, up to 20):`);\n for (const e of d.addedEdges.slice(0, 20)) lines.push(` + ${e.from} -> ${e.to}`);\n }\n if (d.removedEdges.length > 0) {\n lines.push('', `Removed edges (${d.removedEdges.length}, up to 20):`);\n for (const e of d.removedEdges.slice(0, 20)) lines.push(` - ${e.from} -> ${e.to}`);\n }\n lines.push(\n '',\n 'Narrate this delta in plain English. Highlight structural shifts and likely downstream consequences.',\n );\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","/**\n * `--explain` flag helper — shared across every command that produces a\n * structured report (compare, diagnose, review, impact, cost-estimate,\n * lineage, lint, pr-comment, test, …).\n *\n * Each consumer calls `attachExplainFlag(cmd, { feature, systemPrompt })`\n * during command construction, then awaits `runExplain(buildPrompt, opts)`\n * after the structured output has been printed. The helper:\n *\n * - declares the `--explain` (alias `--ai-explain`) flag,\n * - reads the configured AI provider via `@sdt-tools/core/ai`,\n * - calls `complete()` with a stable system prompt + the consumer's\n * prompt body,\n * - prints the narration to stdout under an \"AI explanation:\" header,\n * - gracefully degrades when no provider is configured (a friendly\n * hint pointing at `sdt ai status` is printed; non-zero exit code is\n * NOT set — `--explain` is best-effort decoration on top of the\n * structured output).\n *\n * Mirrors `Databricks/packages/cli/src/util/ai-explain.ts`.\n */\nimport type { Command } from 'commander';\nimport { ai } from '@sdt-tools/core';\nimport { logger } from './logger.js';\n\nexport interface ExplainContext {\n /**\n * Stable feature identifier surfaced to the AI usage telemetry so we\n * can analyze which command surfaces actually drive AI traffic.\n * Convention: `<command>.explain` (e.g. `diagnose.explain`).\n */\n feature: string;\n /**\n * System prompt setting the assistant's persona. Each command picks\n * the wording that matches its role (senior DBA / senior data eng /\n * release-manager / etc.). The default is a generic Snowflake-savvy\n * narrator suitable for most commands.\n */\n systemPrompt?: string;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are a senior Snowflake DBA reviewing structured output from the SDT CLI. Narrate it for a teammate who has not seen the underlying SQL. Be concrete and specific — reference identifiers by name. Group related items together. Skip information that is already obvious from the structured output; add the missing intent, risks, and follow-up actions. 4-10 sentences total unless the data warrants more.`;\n\n/**\n * Attach the `--explain` flag to a command. Idempotent — safe to call on\n * any command, including ones that already define `--explain`\n * (commander will throw, so we guard against double-attach).\n */\nexport function attachExplainFlag(cmd: Command, description?: string): Command {\n const hasExplain = cmd.options.some((o) => o.long === '--explain' || o.long === '--ai-explain');\n if (hasExplain) return cmd;\n cmd.option(\n '--explain',\n description ??\n 'After the structured output, call the configured AI provider to narrate the result in plain English. Requires `sdt ai` to be configured.',\n false,\n );\n return cmd;\n}\n\n/**\n * Run the AI narration step. Call this AFTER the structured output is\n * printed so the user sees the deterministic result first and the AI\n * commentary second.\n *\n * `opts.explain` is the parsed value of the `--explain` flag — when\n * falsy, this is a no-op. The consumer passes a `buildPrompt` callback\n * that returns the user message body; the callback is only invoked when\n * `--explain` is on, so consumers don't pay the prompt-construction cost\n * when AI is off.\n */\nexport async function runExplain(\n ctx: ExplainContext,\n opts: { explain?: boolean },\n buildPrompt: () => string,\n): Promise<void> {\n if (!opts.explain) return;\n const system = ctx.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n logger.info('');\n logger.info('AI explanation:');\n try {\n const reply = await ai.complete(\n [\n { role: 'system', content: system },\n { role: 'user', content: buildPrompt() },\n ],\n { feature: ctx.feature },\n );\n for (const line of reply.text.split('\\n')) logger.info(' ' + line);\n } catch (err) {\n logger.error(' --explain failed: ' + (err instanceof Error ? err.message : String(err)));\n logger.error(\n ' Run `sdt ai status` to verify your AI provider is configured (`sdt ai test` to send a probe).',\n );\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { SnowflakeQueryHistoryReader } from '@sdt-tools/core/queryHistory';\nimport { logger } from '../util/logger.js';\nimport type { QueryHistoryEntry } from '@sdt-tools/core/queryHistory';\n\n/**\n * `sdt history` — two modes.\n *\n * 1. **Manifest mode** (default) — read deploy manifests from a\n * directory (written by `sdt publish --apply --manifest <path>`)\n * and show a chronological summary.\n *\n * 2. **Live mode** (triggered by `--last`, `--query`, or `--verify`)\n * — query the Snowflake account's QUERY_HISTORY views via the\n * SnowflakeQueryHistoryReader. Requires `--connection <profile>`.\n */\ninterface Manifest {\n version: 1;\n deployedAt?: string;\n account?: string;\n warehouse?: string;\n finalState?: string;\n failedStepId?: string | null;\n steps?: Array<{\n status?: string;\n objectType?: string;\n fqn?: string;\n forwardSql?: string;\n reverseSql?: string;\n }>;\n}\n\nexport function historyCommand(): Command {\n const cmd = new Command('history');\n cmd\n .description(\n 'List deploy manifests (default) or query the live Snowflake QUERY_HISTORY views via --last/--query/--verify.',\n )\n // Manifest mode\n .option(\n '--dir <path>',\n 'Directory containing *.json manifests (manifest mode).',\n './.sdt/history',\n )\n .option(\n '--limit <n>',\n 'Manifest mode: most-recent N entries. Live mode: max rows returned.',\n '20',\n )\n .option('--json', 'Emit JSON instead of human-readable table.', false)\n .option(\n '--full-sql',\n 'Include full SQL text in the output (default: truncated to 120 chars).',\n false,\n )\n // Live mode\n .option(\n '--connection <profile>',\n 'Connection profile (required for --last / --query / --verify).',\n )\n .option('--last [n]', 'Live mode: show the N most-recent queries. Default 20.')\n .option('--query <id>', 'Live mode: look up a single query by its QUERY_ID.')\n .option(\n '--verify <tag>',\n 'Live mode: read all queries tagged with this string. Use the auto-generated tag from `sdt publish --apply` for deploy verification.',\n )\n .option('--since <iso>', 'Live mode: only include entries after this ISO 8601 timestamp.')\n .option(\n '--view <kind>',\n \"Live mode: which view to query — 'session' | 'user' | 'account'. Default 'session'.\",\n 'session',\n )\n .action(\n async (opts: {\n dir?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n connection?: string;\n last?: boolean | string;\n query?: string;\n verify?: string;\n since?: string;\n view?: string;\n }) => {\n const isLive =\n opts.last !== undefined || opts.query !== undefined || opts.verify !== undefined;\n if (isLive) {\n await runLive(opts);\n } else {\n await runManifests(opts);\n }\n },\n );\n return cmd;\n}\n\nasync function runManifests(opts: {\n dir?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n}): Promise<void> {\n const dir = path.resolve(String(opts.dir ?? './.sdt/history'));\n let files: string[];\n try {\n const entries = await fs.readdir(dir);\n files = entries.filter((f) => f.endsWith('.json')).map((f) => path.join(dir, f));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n console.error(\n `No history directory at ${dir}. Pass --dir <path> or pipe deploys to write manifests there.`,\n );\n process.exitCode = 1;\n return;\n }\n throw err;\n }\n\n const entries: Array<{ path: string; mtime: Date; manifest: Manifest }> = [];\n for (const f of files) {\n try {\n const raw = await fs.readFile(f, 'utf8');\n const m = JSON.parse(raw) as Manifest;\n const stat = await fs.stat(f);\n entries.push({ path: f, mtime: stat.mtime, manifest: m });\n } catch {\n // skip files that don't parse\n }\n }\n entries.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n const limit = parseInt(String(opts.limit ?? 20), 10);\n const visible = entries.slice(0, limit > 0 ? limit : entries.length);\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n visible.map((e) => ({ path: e.path, mtime: e.mtime.toISOString(), ...e.manifest })),\n null,\n 2,\n ),\n );\n return;\n }\n\n if (visible.length === 0) {\n console.log(`No manifests found in ${dir}.`);\n return;\n }\n console.log(`History: ${visible.length} of ${entries.length} deploys at ${dir}`);\n console.log('');\n console.log(\n ' DEPLOYED AT ACCOUNT FINAL STATE STEPS',\n );\n console.log(\n ' ─────────────────── ────────────────────────────────── ────────────────── ─────',\n );\n for (const e of visible) {\n const m = e.manifest;\n const when = m.deployedAt\n ? new Date(m.deployedAt).toISOString().slice(0, 19).replace('T', ' ')\n : e.mtime.toISOString().slice(0, 19).replace('T', ' ');\n const host = (m.account ?? '?').padEnd(34).slice(0, 34);\n const state = (m.finalState ?? '?').padEnd(18).slice(0, 18);\n const succ = m.steps?.filter((s) => s.status === 'SUCCESS').length ?? 0;\n const tot = m.steps?.length ?? 0;\n console.log(` ${when} ${host} ${state} ${succ}/${tot}`);\n if (opts.fullSql) {\n for (const s of m.steps ?? []) {\n if (s.forwardSql) console.log(` [forward] ${s.fqn ?? ''}\\n${indent(s.forwardSql, 8)}`);\n }\n }\n }\n console.log('');\n console.log(\n `Pass --json for machine-readable output, --limit <n> to control depth, --full-sql to expand each step.`,\n );\n}\n\nasync function runLive(opts: {\n connection?: string;\n last?: boolean | string;\n query?: string;\n verify?: string;\n since?: string;\n view?: string;\n limit?: string;\n json?: boolean;\n fullSql?: boolean;\n}): Promise<void> {\n if (!opts.connection) {\n logger.error('Live history mode requires --connection <profile>.');\n process.exitCode = 1;\n return;\n }\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n await conn.connect();\n try {\n const view = String(opts.view ?? 'session').toLowerCase() as 'session' | 'user' | 'account';\n const reader = new SnowflakeQueryHistoryReader(conn, { defaultView: view });\n const limit = Math.max(1, parseInt(String(opts.limit ?? '20'), 10) || 20);\n const since = opts.since ? new Date(opts.since) : undefined;\n\n let entries: QueryHistoryEntry[] = [];\n if (opts.query) {\n const e = await reader.readById(String(opts.query));\n entries = e ? [e] : [];\n } else if (opts.verify) {\n entries = await reader.readByTag(String(opts.verify), {\n ...(since ? { since } : {}),\n limit,\n });\n } else {\n // --last [n]\n const n = typeof opts.last === 'string' ? parseInt(opts.last, 10) || limit : limit;\n // Reuse readByUser with the current user; if that's not set on the\n // reader, the underlying view still respects the current session's\n // user via INFORMATION_SCHEMA semantics.\n entries = await reader.readByUser(profile.auth.username ?? '', {\n ...(since ? { since } : {}),\n limit: n,\n });\n }\n\n if (opts.json) {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n renderEntries(entries, Boolean(opts.fullSql));\n } finally {\n await conn.disconnect();\n }\n}\n\nfunction renderEntries(entries: readonly QueryHistoryEntry[], fullSql: boolean): void {\n if (entries.length === 0) {\n console.log('No matching queries found.');\n return;\n }\n console.log(`${entries.length} quer${entries.length === 1 ? 'y' : 'ies'}:`);\n console.log('');\n console.log(' STARTED STATUS DURATION USER QUERY_ID');\n console.log(\n ' ─────────────────── ──────── ──────── ───────────────────── ────────────────────────────',\n );\n for (const e of entries) {\n const when = e.startedAt.slice(0, 19).replace('T', ' ');\n const status = e.status.toUpperCase().padEnd(8);\n const dur = `${e.durationMs}ms`.padEnd(8);\n const user = (e.user ?? '?').padEnd(20).slice(0, 20);\n console.log(` ${when} ${status} ${dur} ${user} ${e.queryId}`);\n const sql = fullSql ? e.sqlText : truncate(e.sqlText, 120);\n if (sql)\n console.log(\n ` ${sql\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean)\n .join(' ')}`,\n );\n if (e.queryTag) console.log(` tag: ${e.queryTag}`);\n if (e.errorMessage) console.log(` ERROR: ${e.errorMessage}`);\n }\n}\n\nfunction indent(text: string, n: number): string {\n const pad = ' '.repeat(n);\n return text\n .split('\\n')\n .map((l) => pad + l)\n .join('\\n');\n}\n\nfunction truncate(s: string, max: number): string {\n if (!s) return '';\n const collapsed = s.replace(/\\s+/g, ' ').trim();\n if (collapsed.length <= max) return collapsed;\n return collapsed.slice(0, max - 1) + '…';\n}\n","import { Command } from 'commander';\nimport { pac } from '@sdt-tools/core';\n\n/**\n * `sdt verify <pac>` — recompute checksums and confirm the .sdtpac is\n * intact. Catches tampering / corruption / partial-extraction\n * accidents. Sets up the Enterprise-tier signing chain — a signed pac\n * is `verify` + `signature-check` together.\n */\nexport function verifyCommand(): Command {\n const cmd = new Command('verify');\n cmd\n .description('Recompute checksums on a .sdtpac and confirm every object matches the manifest.')\n .requiredOption('--pac <path>', 'Path to the .sdtpac to verify.')\n .option('--json', 'Emit JSON instead of human-readable output.', false)\n .action(async (opts) => {\n const contents = await pac.readPac(String(opts.pac));\n const expected = contents.checksums;\n const actual = pac.computeChecksums(contents.model);\n\n const missing: string[] = [];\n const mismatched: Array<{ id: string; expected: string; actual: string }> = [];\n const orphaned: string[] = [];\n\n const expectedIds = new Set(Object.keys(expected));\n const actualIds = new Set(Object.keys(actual));\n for (const id of expectedIds) {\n if (!actualIds.has(id)) {\n missing.push(id);\n continue;\n }\n if (expected[id] !== actual[id]) {\n mismatched.push({ id, expected: expected[id]!, actual: actual[id]! });\n }\n }\n for (const id of actualIds) {\n if (!expectedIds.has(id)) orphaned.push(id);\n }\n\n const ok = missing.length === 0 && mismatched.length === 0 && orphaned.length === 0;\n if (opts.json) {\n console.log(\n JSON.stringify(\n { ok, missing, mismatched, orphaned, objectCount: contents.model.length },\n null,\n 2,\n ),\n );\n } else {\n console.log(`Pac: ${opts.pac}`);\n console.log(\n `Project: ${contents.manifest.projectName} v${contents.manifest.projectVersion}`,\n );\n console.log(\n `Built: ${contents.manifest.builtAt} by ${contents.manifest.builtBy.name} ${contents.manifest.builtBy.version}`,\n );\n console.log(`Objects: ${contents.model.length}`);\n console.log('');\n if (ok) {\n console.log('✓ verify OK — every checksum matches.');\n } else {\n console.log('✗ verify FAILED');\n if (missing.length > 0) {\n console.log(` missing checksums (${missing.length}):`);\n for (const id of missing) console.log(` ${id}`);\n }\n if (mismatched.length > 0) {\n console.log(` mismatched (${mismatched.length}):`);\n for (const m of mismatched)\n console.log(\n ` ${m.id} expected=${m.expected.slice(0, 12)}… actual=${m.actual.slice(0, 12)}…`,\n );\n }\n if (orphaned.length > 0) {\n console.log(` orphaned (in model but not in checksums) (${orphaned.length}):`);\n for (const id of orphaned) console.log(` ${id}`);\n }\n }\n }\n if (!ok) process.exitCode = 1;\n });\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\n/**\n * `sdt install-hooks` — install a git pre-commit hook that runs\n * `sdt format --check` + `sdt validate` before allowing a commit.\n *\n * Husky-style: writes a single shell script to `.git/hooks/pre-commit`\n * that delegates to the CLI. Refuses to overwrite an existing hook\n * unless --force.\n */\nconst HOOK_MARKER = '# sdt-managed-hook';\n\nconst HOOK_BODY = `#!/bin/sh\n${HOOK_MARKER} — installed by \\`sdt install-hooks\\`. Remove this hook or re-install with --force to update.\n\n# Find the project file relative to the repo root.\nproject=$(find . -maxdepth 3 -name '*.sdtproj' -not -path '*/node_modules/*' -not -path '*/dist/*' | head -1)\nif [ -z \"$project\" ]; then\n echo \"sdt pre-commit hook: no .sdtproj found (skipping).\"\n exit 0\nfi\n\necho \"sdt pre-commit: validate + format-check on $project\"\n\nif ! command -v sdt >/dev/null 2>&1; then\n echo \"sdt CLI not on PATH. Install with \\`npm i -g @sdt-tools/cli\\`, or remove the hook at .git/hooks/pre-commit.\"\n exit 1\nfi\n\nif ! sdt validate -p \"$project\"; then\n echo \"\"\n echo \"Refusing commit: \\`sdt validate\\` failed.\"\n exit 1\nfi\n\nif ! sdt format -p \"$project\" --check; then\n echo \"\"\n echo \"Refusing commit: some .sql files are not formatted. Run \\`sdt format -p $project\\` and re-stage.\"\n exit 1\nfi\n`;\n\nexport function installHooksCommand(): Command {\n const cmd = new Command('install-hooks');\n cmd\n .description(\n 'Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit.',\n )\n .option('--force', 'Overwrite an existing hook (refuses by default if the file exists).', false)\n .option('--uninstall', 'Remove the sdt-managed pre-commit hook instead of installing.', false)\n .action(async (opts) => {\n const cwd = process.cwd();\n const gitDir = await findGitDir(cwd);\n if (!gitDir) {\n throw new Error(`No .git directory found at or above ${cwd}.`);\n }\n const hookPath = path.join(gitDir, 'hooks', 'pre-commit');\n\n if (opts.uninstall) {\n if (!existsSync(hookPath)) {\n console.log('No pre-commit hook installed.');\n return;\n }\n const existing = await fs.readFile(hookPath, 'utf8');\n if (!existing.includes(HOOK_MARKER)) {\n console.error(\n `Refusing to remove: ${hookPath} is not a sdt-managed hook (missing marker).`,\n );\n process.exitCode = 1;\n return;\n }\n await fs.unlink(hookPath);\n console.log(`Removed ${hookPath}.`);\n return;\n }\n\n if (existsSync(hookPath) && !opts.force) {\n const existing = await fs.readFile(hookPath, 'utf8');\n if (existing.includes(HOOK_MARKER)) {\n console.log(`Hook already installed at ${hookPath}. Re-run with --force to overwrite.`);\n } else {\n console.error(`Refusing to overwrite: ${hookPath} exists and is NOT a sdt-managed hook.`);\n console.error('Inspect it, then re-run with --force if you want to replace it.');\n process.exitCode = 1;\n }\n return;\n }\n\n await fs.mkdir(path.dirname(hookPath), { recursive: true });\n await fs.writeFile(hookPath, HOOK_BODY, { mode: 0o755 });\n console.log(`Installed pre-commit hook at ${hookPath}.`);\n console.log(' Runs `sdt validate` + `sdt format --check` on every commit.');\n console.log(\n ' Bypass once with `git commit --no-verify`. Remove with `sdt install-hooks --uninstall`.',\n );\n });\n return cmd;\n}\n\nasync function findGitDir(start: string): Promise<string | undefined> {\n let dir = path.resolve(start);\n while (true) {\n const candidate = path.join(dir, '.git');\n if (existsSync(candidate)) {\n const stat = await fs.stat(candidate);\n if (stat.isDirectory()) return candidate;\n const ptr = await fs.readFile(candidate, 'utf8');\n const m = ptr.match(/^gitdir:\\s*(.+)$/m);\n if (m && m[1]) {\n const resolved = path.isAbsolute(m[1]) ? m[1] : path.resolve(dir, m[1]);\n return resolved;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n PacSource,\n ProjectSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { ScriptGenerator, colorizeMigrationScript } from '@sdt-tools/core/deploy';\nimport { mergeDeployOptions, loadProject } from '@sdt-tools/core/project';\nimport { readPac } from '@sdt-tools/core/pac';\nimport { safety } from '@sdt-tools/core';\nimport type { DeploymentProfile } from '@sdt-tools/core/project';\nimport { addMappingFlags, buildMappingFromOptions } from '../util/mapping.js';\n\n/**\n * `sdt script` — generate a deploy SQL script for source → target. Mirrors\n * SqlPackage `/Action:Script` / SSDT's \"Generate Script\" affordance. Always\n * offline — does not touch a live Snowflake account.\n *\n * Output formats:\n * - sql (default): human-readable migration script with banner comments\n * - json: raw CompareResult + safety assessment + per-statement\n * metadata, suitable for CI gates or UI rendering\n *\n * Mirrors `ddt script`. To compare against a live account, use\n * `sdt compare` or `sdt publish`.\n */\nexport function scriptCommand(): Command {\n const cmd = new Command('script');\n cmd\n .description(\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the account.',\n )\n .requiredOption('--source <path>', 'Source: .sdtproj or .sdtpac (the desired state).')\n .requiredOption('--target <path>', 'Target: .sdtproj or .sdtpac (the current state).')\n .option('-o, --out <path>', 'Write the script to <path>. Defaults to stdout.')\n .option('--format <fmt>', 'sql | json', 'sql')\n .option('--variables <kv>', 'Comma-separated KEY=VALUE pairs for $(VAR) substitution.')\n .option(\n '--profile <name>',\n 'VARSYNTAX.5 — look up `deploymentProfiles[<name>].variables` from the --source artifact (`.sdtproj` reads `project.deploymentProfiles`; `.sdtpac` reads `manifest.deploymentProfiles`) and substitute `$(VAR)` references at script-emission time. `--variables` overrides on key collision.',\n )\n .option('--ignore-case', 'Compare object FQNs case-insensitively.', false)\n .option('--banner <text>', 'Banner line prepended to the script.')\n .option(\n '--color <mode>',\n 'Color stdout: auto | always | never. Honors NO_COLOR / SDT_NO_COLOR env vars in auto mode. Files written via -o are never colorized.',\n 'auto',\n );\n addMappingFlags(cmd);\n cmd.action(async (opts) => {\n const format = String(opts.format ?? 'sql').toLowerCase();\n if (format !== 'sql' && format !== 'json') {\n throw new Error(`Unknown --format: ${opts.format}. Use sql or json.`);\n }\n const nameMapping = await buildMappingFromOptions(opts);\n const source = await sourceFor(String(opts.source), 'source');\n const target = await sourceFor(String(opts.target), 'target');\n const engine = new CompareEngine();\n const result = await engine.compare(source, target, {\n ignoreCase: !!opts.ignoreCase,\n ...(nameMapping ? { nameMapping } : {}),\n });\n\n const deployment = mergeDeployOptions().deployment;\n const cliVariables = parseVariables(opts.variables);\n\n // VARSYNTAX.5 — resolve --profile <name> from the --source artifact's\n // deploymentProfiles bag (if present), merge with --variables CLI\n // override (CLI wins on key collision). Also gather the project context\n // (name / version) so VARSYNTAX.3 built-ins (`$(SDT_PROFILE)`,\n // `$(SDT_PROJECT_NAME)`, `$(SDT_PROJECT_VERSION)`, …) auto-populate.\n let profileVariables: Record<string, string> | undefined;\n let ctxProjectName: string | undefined;\n let ctxProjectVersion: string | undefined;\n const sourcePath = String(opts.source);\n if (opts.profile || sourcePath.endsWith('.sdtproj') || sourcePath.endsWith('.sdtpac')) {\n try {\n if (sourcePath.endsWith('.sdtpac')) {\n const srcPac = await readPac(sourcePath);\n ctxProjectName = srcPac.manifest.projectName;\n ctxProjectVersion = srcPac.manifest.projectVersion;\n if (opts.profile) {\n const block: DeploymentProfile | undefined =\n srcPac.manifest.deploymentProfiles?.[String(opts.profile)];\n if (!block) {\n const available = Object.keys(srcPac.manifest.deploymentProfiles ?? {});\n throw new Error(\n `--profile ${String(opts.profile)}: no deploymentProfile by that name in the --source pac manifest. ` +\n (available.length === 0\n ? 'The pac carries no deploymentProfiles (was it built before VARSYNTAX.2, or does the .sdtproj declare any?).'\n : `Available: ${available.join(', ')}.`),\n );\n }\n if (block.variables) profileVariables = { ...block.variables };\n }\n } else if (sourcePath.endsWith('.sdtproj')) {\n const loaded = await loadProject(sourcePath);\n ctxProjectName = loaded.project.name;\n ctxProjectVersion = loaded.project.version;\n if (opts.profile) {\n const block: DeploymentProfile | undefined =\n loaded.project.deploymentProfiles?.[String(opts.profile)];\n if (!block) {\n const available = Object.keys(loaded.project.deploymentProfiles ?? {});\n throw new Error(\n `--profile ${String(opts.profile)}: no deploymentProfile by that name in the --source .sdtproj. ` +\n (available.length === 0\n ? 'The project declares no deploymentProfiles.'\n : `Available: ${available.join(', ')}.`),\n );\n }\n if (block.variables) profileVariables = { ...block.variables };\n }\n }\n } catch (e) {\n // If the user passed --profile, hard-fail. Otherwise best-effort:\n // built-ins stay defaulted on a partial / unreadable source.\n if (opts.profile) throw e;\n }\n }\n const variables =\n profileVariables || cliVariables\n ? { ...(profileVariables ?? {}), ...(cliVariables ?? {}) }\n : undefined;\n\n const generator = new ScriptGenerator();\n const script = generator.generate(result, {\n deployment,\n ...(variables ? { variables } : {}),\n ...(opts.banner ? { banner: String(opts.banner) } : {}),\n context: {\n ...(opts.profile ? { profile: String(opts.profile) } : {}),\n ...(ctxProjectName ? { projectName: ctxProjectName } : {}),\n ...(ctxProjectVersion ? { projectVersion: ctxProjectVersion } : {}),\n },\n });\n const assessment = safety.assess(result);\n\n let payload: string;\n if (format === 'json') {\n payload = JSON.stringify(\n {\n source: result.source,\n target: result.target,\n summary: { ...result.summary, ...script.summary },\n safety: assessment,\n statements: script.statements,\n },\n null,\n 2,\n );\n } else {\n const header = [\n `-- ${assessment.blocked ? 'BLOCKED: ' + assessment.blockReason : 'Generated by sdt script'}`,\n `-- unrecoverable=${assessment.unrecoverable.length} destructive=${assessment.destructive.length} expensive=${assessment.expensive.length} warnings=${assessment.warnings.length}`,\n '',\n ].join('\\n');\n payload = header + script.sql;\n }\n\n if (opts.out) {\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${outPath} (${payload.length} bytes).`);\n } else {\n // Colorize stdout for SQL only — JSON stays raw so downstream tools can\n // parse it. ANSI escapes are stripped when stdout is not a TTY (auto mode).\n const colorMode = (opts.color as 'auto' | 'always' | 'never' | undefined) ?? 'auto';\n const rendered =\n format === 'sql' ? colorizeMigrationScript(payload, { mode: colorMode }) : payload;\n process.stdout.write(rendered);\n if (!rendered.endsWith('\\n')) process.stdout.write('\\n');\n }\n if (assessment.blocked) {\n process.exitCode = 2;\n }\n });\n return cmd;\n}\n\nasync function sourceFor(filePath: string, label: string): Promise<CompareSource> {\n return filePath.endsWith('.sdtpac')\n ? new PacSource(filePath, label)\n : new ProjectSource(filePath, label);\n}\n\nfunction parseVariables(raw: unknown): Record<string, string> | undefined {\n if (!raw) return undefined;\n const out: Record<string, string> = {};\n for (const pair of String(raw).split(',')) {\n const [k, v] = pair.split('=');\n if (k && v !== undefined) out[k.trim()] = v.trim();\n }\n return out;\n}\n","import { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport {\n SnowflakeExecutor,\n revertStepsFromManifest,\n type DeployManifest,\n} from '@sdt-tools/core/deploy';\n\n/**\n * `sdt revert --manifest <path>` — undo a previous deploy by executing\n * each step's `reverseSql` in reverse order. Manifests come from\n * `sdt publish --apply --manifest <path>` (the JSON deploy manifest\n * captured after `--apply`).\n *\n * Steps without `reverseSql` are inherently irreversible (DROP, etc.)\n * and skipped with a clear warning. The command exits non-zero if any\n * reverse fails or if any step was irreversible (the user must inspect\n * by hand).\n *\n * Mirrors `Databricks/packages/cli/src/commands/revert.ts`. Use case: a\n * deploy succeeded but something downstream broke; revert it. Use case:\n * drift is detected and you need to roll back to the last-known-good\n * state.\n */\nexport function revertCommand(): Command {\n const cmd = new Command('revert');\n cmd\n .description(\n 'Replay a previous deploy manifest in reverse, executing reverseSql for each successful step.',\n )\n .requiredOption(\n '--manifest <path>',\n 'Path to a JSON deploy manifest from `sdt publish --apply --manifest`.',\n )\n .requiredOption(\n '--connection <name>',\n 'Connection profile to revert against. Should match the original deploy.',\n )\n .requiredOption('--yes', 'Explicit confirmation. Required because revert is destructive.')\n .option(\n '--continue-on-error',\n 'Continue past failed reverse statements. Default: stop on first failure.',\n false,\n )\n .option('--dry-run', 'Print what would be reverted without executing.', false)\n .action(async (opts) => {\n const raw = await fs.readFile(String(opts.manifest), 'utf8');\n const manifest = JSON.parse(raw) as DeployManifest;\n if (manifest.version !== 1) {\n throw new Error(\n `Unsupported manifest version: ${manifest.version}. This CLI understands v1.`,\n );\n }\n\n const profile = await getProfile(String(opts.connection));\n if (profile.account !== manifest.account) {\n console.error('');\n console.error(\n `WARNING: manifest's account (${manifest.account}) doesn't match the profile's account (${profile.account}).`,\n );\n console.error(\n 'Reverting against a different account than the original deploy may have unintended effects.',\n );\n console.error('Re-run with the correct --connection, or proceed carefully.');\n console.error('');\n }\n\n // Reverse-iterate; only successful steps need undoing.\n const reverseSteps = revertStepsFromManifest(manifest);\n\n console.log(`Reverting ${reverseSteps.length} step(s) from ${opts.manifest}`);\n console.log(`Original deploy: ${manifest.deployedAt} → ${manifest.account}`);\n console.log('');\n\n if (opts.dryRun) {\n for (const s of reverseSteps) {\n const tag = s.reverseSql ? '↩' : '⚠';\n console.log(`${tag} ${s.objectType} ${s.fqn}`);\n if (s.reverseSql) {\n console.log(` ${s.reverseSql.split('\\n')[0]?.slice(0, 100) ?? ''}`);\n } else {\n console.log(` (no reverseSql — IRREVERSIBLE; would be skipped)`);\n }\n }\n const skippable = reverseSteps.filter((s) => !s.reverseSql).length;\n console.log('');\n console.log(\n `Dry-run summary: ${reverseSteps.length - skippable} reversible, ${skippable} irreversible.`,\n );\n return;\n }\n\n const conn = new SnowflakeConnection(profile);\n let succeeded = 0;\n let failed = 0;\n let irreversible = 0;\n try {\n await conn.connect();\n const executor = new SnowflakeExecutor(conn);\n for (const s of reverseSteps) {\n if (!s.reverseSql) {\n console.log(`⚠ skip ${s.objectType} ${s.fqn} — irreversible (no reverseSql captured)`);\n irreversible++;\n continue;\n }\n process.stdout.write(`↩ ${s.objectType} ${s.fqn} …`);\n const t0 = Date.now();\n try {\n await executor.execute(s.reverseSql);\n console.log(` ✓ (${Date.now() - t0}ms)`);\n succeeded++;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.log(` ✗ ${msg}`);\n failed++;\n if (!opts.continueOnError) {\n console.error('');\n console.error('Stopping on first failure. Use --continue-on-error to push through.');\n break;\n }\n }\n }\n } finally {\n await conn.disconnect();\n }\n\n console.log('');\n console.log(\n `Summary: ${succeeded} reverted, ${failed} failed, ${irreversible} irreversible.`,\n );\n if (failed > 0 || irreversible > 0) process.exitCode = 1;\n });\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { SnowflakeExecutor } from '@sdt-tools/core/deploy';\nimport { discoverSeeds, loadProject, renderSeedMerge } from '@sdt-tools/core/project';\n\n/**\n * `sdt seed` — declare static reference rows next to DDL; engine\n * generates MERGE statements to keep them in sync.\n *\n * Mirrors `Databricks/packages/cli/src/commands/seed.ts`. Subcommands:\n * list enumerate seed files + row counts\n * render -p <project> emit MERGEs to stdout (offline)\n * apply -p <project> -c <conn> execute the MERGEs against an account\n */\nexport function seedCommand(): Command {\n const cmd = new Command('seed').description(\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n );\n\n cmd\n .command('list')\n .description('Enumerate seed files under <project>/seeds/.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n if (seeds.length === 0) {\n console.log(\n 'No seeds found. Add files under <project>/seeds/<database>/<schema>/<table>.{json,csv}.',\n );\n return;\n }\n for (const s of seeds) {\n console.log(\n ` ${s.database}.${s.schema}.${s.table.padEnd(28)} ${String(s.rows.length).padStart(5)} rows keys=[${s.keys.join(', ')}]`,\n );\n }\n console.log('');\n console.log(`${seeds.length} seed(s).`);\n });\n\n cmd\n .command('render')\n .description('Emit MERGE statements for every seed file. Offline; no account contact.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .option('-o, --out <path>', 'Write to file. Defaults to stdout.')\n .option(\n '--delete-not-in-source',\n 'Prepend a DELETE so target-only rows are removed (Snowflake equivalent of WHEN NOT MATCHED BY SOURCE). Default off (safer).',\n false,\n )\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n const renderOpts = { deleteNotInSource: !!opts.deleteNotInSource };\n const sql = seeds.map((s) => renderSeedMerge(s, renderOpts)).join('\\n\\n') + '\\n';\n if (opts.out) {\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, sql, 'utf8');\n console.error(`Wrote ${outPath} (${sql.length} bytes, ${seeds.length} seed(s)).`);\n } else {\n process.stdout.write(sql);\n }\n });\n\n cmd\n .command('apply')\n .description('Execute every seed MERGE against a connection profile.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .requiredOption('--connection <name>', 'Connection profile to apply against.')\n .requiredOption('--yes', 'Explicit confirmation. Required because apply writes data.')\n .option('--dry-run', 'Print the MERGEs without executing.', false)\n .option(\n '--delete-not-in-source',\n 'Prepend a DELETE so target-only rows are removed (Snowflake equivalent of WHEN NOT MATCHED BY SOURCE). Default off (safer).',\n false,\n )\n .action(async (opts) => {\n const loaded = await loadProject(String(opts.project));\n const seeds = await discoverSeeds(loaded.rootDir);\n if (seeds.length === 0) {\n console.log('No seeds found. Nothing to apply.');\n return;\n }\n const renderOpts = { deleteNotInSource: !!opts.deleteNotInSource };\n if (opts.dryRun) {\n for (const s of seeds) console.log(renderSeedMerge(s, renderOpts) + '\\n');\n return;\n }\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n let succeeded = 0;\n let failed = 0;\n try {\n await conn.connect();\n const exec = new SnowflakeExecutor(conn);\n for (const s of seeds) {\n process.stdout.write(`▶ ${s.database}.${s.schema}.${s.table} (${s.rows.length} rows) …`);\n const t0 = Date.now();\n try {\n await exec.execute(renderSeedMerge(s, renderOpts));\n console.log(` ✓ (${Date.now() - t0}ms)`);\n succeeded++;\n } catch (err) {\n console.log(` ✗ ${err instanceof Error ? err.message : String(err)}`);\n failed++;\n }\n }\n } finally {\n await conn.disconnect();\n }\n console.log('');\n console.log(`Summary: ${succeeded} succeeded, ${failed} failed.`);\n if (failed > 0) process.exitCode = 1;\n });\n\n return cmd;\n}\n","import { promises as fs } from 'node:fs';\nimport { randomUUID } from 'node:crypto';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { lineage, pac, project, columnLineage } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * CLL.7-followup runtime: thread CLI flags + `.sdt/lineage.json` config\n * through the OpenLineage substrate. Exported so vitest can drive it\n * directly with a stub fetchImpl + readFile (no real network / disk).\n */\nexport interface EmitOpenLineageCliInputs {\n dag: columnLineage.ColumnLineageDag;\n endpointFlag?: string;\n configPath?: string;\n namespace?: string;\n jobNamespace?: string;\n job?: string;\n /**\n * OpenLineage emit mode. `auto` resolves to `per-event` when the\n * built events array has ≤ AUTO_MODE_THRESHOLD entries, `batch`\n * otherwise. Resolution happens at the CLI layer; the substrate\n * only ever sees the concrete `per-event` or `batch`.\n */\n mode?: 'per-event' | 'batch' | 'auto';\n /** OpenLineage event type (subset of the spec enum). Default `COMPLETE`. */\n eventType?: 'START' | 'RUNNING' | 'COMPLETE' | 'ABORT' | 'FAIL' | 'OTHER';\n /**\n * Override the event timestamp (ISO 8601). Default: now() at emit time.\n * Useful for backfill — historical pipeline runs replayed into Marquez/\n * OpenMetadata keep their original eventTime instead of being collapsed\n * onto \"now\".\n */\n eventTime?: string;\n /** Per-request timeout in ms (positive integer; 0/negative/NaN are ignored). */\n timeoutMs?: number;\n token?: string;\n /** Override OpenLineage producer URL identifying the emitting tool. */\n producer?: string;\n /** Repeatable `name=value` strings from `--emit-openlineage-header`. */\n headerArgs?: readonly string[];\n runId?: string;\n dryRun?: boolean;\n /** Persist built events JSON to this path on disk (audit / replay). */\n eventsOutPath?: string;\n /**\n * Output format for the events-out file. `json` (default) writes the\n * familiar `{events: [...]}` wrapper with pretty-printed indentation;\n * `jsonl` writes one event per line (newline-delimited JSON) for\n * streaming-ingest pipelines (Vector / Fluent Bit / OpenTelemetry\n * collectors / Snowflake VARIANT loaders).\n */\n eventsOutFormat?: 'json' | 'jsonl';\n /** Skip the POST when the events array is empty (no DAG produced 0 events). */\n skipEmpty?: boolean;\n /**\n * Refuse to emit when the built events count is below this threshold.\n * Returns `ok: false` with `MIN_EVENTS_NOT_MET`. CI-friendly guard\n * against silent lineage gaps — a refactor that accidentally bypasses\n * column-lineage extraction would otherwise quietly emit zero events\n * and pass the build.\n */\n minEvents?: number;\n sourceHint?: string;\n}\n\nconst VALID_OL_EVENT_TYPES = new Set<EmitOpenLineageCliInputs['eventType']>([\n 'START',\n 'RUNNING',\n 'COMPLETE',\n 'ABORT',\n 'FAIL',\n 'OTHER',\n]);\n\n/**\n * Validate `--emit-openlineage-event-type <value>` against the OL enum.\n * Returns the upper-cased value when valid. Throws with operator-facing\n * message when unknown — the action handler surfaces the throw as exit\n * code 1 (uncaught throw from commander action) which is the same\n * convention used by other input-validation throws in this CLI.\n */\nexport function validateEventType(raw: string): EmitOpenLineageCliInputs['eventType'] {\n const upper = raw.toUpperCase() as EmitOpenLineageCliInputs['eventType'];\n if (!VALID_OL_EVENT_TYPES.has(upper)) {\n throw new Error(\n `--emit-openlineage-event-type ${JSON.stringify(raw)} is not a valid OpenLineage event type. ` +\n `Use one of: ${[...VALID_OL_EVENT_TYPES].join(', ')}.`,\n );\n }\n return upper;\n}\n\n/**\n * Threshold at which `--emit-openlineage-mode auto` flips from\n * `per-event` (one HTTP POST per event, easier to debug in the\n * collector UI) to `batch` (single POST with `{events: [...]}`,\n * amortizes HTTP overhead). Operators with non-default cost or\n * latency requirements can still force the mode explicitly.\n */\nexport const AUTO_MODE_THRESHOLD = 10;\n\n/**\n * Resolve `mode: 'auto'` based on the built events count. Returns the\n * concrete `per-event` / `batch` value; pass-through for non-auto.\n */\nexport function resolveAutoMode(\n mode: 'per-event' | 'batch' | 'auto',\n eventCount: number,\n): 'per-event' | 'batch' {\n if (mode !== 'auto') return mode;\n return eventCount <= AUTO_MODE_THRESHOLD ? 'per-event' : 'batch';\n}\n\n/**\n * Validate `--emit-openlineage-mode <value>` against per-event / batch / auto.\n * Returns the lower-cased value when valid. Throws with operator-facing\n * message on unknown.\n */\nexport function validateMode(raw: string): 'per-event' | 'batch' | 'auto' {\n const lower = raw.toLowerCase();\n if (lower !== 'per-event' && lower !== 'batch' && lower !== 'auto') {\n throw new Error(\n `--emit-openlineage-mode ${JSON.stringify(raw)} is not valid. ` +\n `Use one of: per-event, batch, auto.`,\n );\n }\n return lower as 'per-event' | 'batch' | 'auto';\n}\n\n/**\n * Validate `--emit-openlineage-events-out-format <fmt>` value. Returns\n * the lower-cased value when valid (`json` or `jsonl`). Throws with\n * operator-facing message when unknown.\n */\nexport function validateEventsOutFormat(raw: string): 'json' | 'jsonl' {\n const lower = raw.toLowerCase();\n if (lower !== 'json' && lower !== 'jsonl') {\n throw new Error(\n `--emit-openlineage-events-out-format ${JSON.stringify(raw)} is not valid. ` +\n `Use one of: json, jsonl.`,\n );\n }\n return lower;\n}\n\n/**\n * Validate `--emit-openlineage-event-time <iso>` as a parseable timestamp.\n * Returns the canonical ISO 8601 form (`new Date(raw).toISOString()`) so\n * the value emitted in every OL event is normalized regardless of input\n * shape (`2026-05-18T20:00:00Z` and `2026-05-18T16:00:00-04:00` both\n * normalize to the same UTC instant). Throws with operator-facing\n * message on invalid input.\n */\nexport function validateEventTime(raw: string): string {\n const parsed = new Date(raw);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(\n `--emit-openlineage-event-time ${JSON.stringify(raw)} is not a valid ISO 8601 timestamp. ` +\n `Examples: 2026-05-18T20:00:00Z, 2026-05-18T16:00:00-04:00.`,\n );\n }\n return parsed.toISOString();\n}\n\n/**\n * Parse `--emit-openlineage-header name=value` repeatable strings into\n * an `{name: value}` record. Splits on the first `=` only so values\n * containing `=` (e.g. base64-encoded tokens) survive. Strings missing\n * `=` or with empty name are skipped with a stderr note.\n */\nexport function parseHeaderArgs(\n args: readonly string[] | undefined,\n stderr: (chunk: string) => void = () => {},\n): Record<string, string> {\n const out: Record<string, string> = {};\n if (!args || args.length === 0) return out;\n for (const raw of args) {\n const eq = raw.indexOf('=');\n if (eq <= 0) {\n stderr(\n `Ignoring malformed --emit-openlineage-header value ${JSON.stringify(raw)} (expected name=value).\\n`,\n );\n continue;\n }\n const name = raw.slice(0, eq).trim();\n const value = raw.slice(eq + 1);\n if (!name) {\n stderr(`Ignoring --emit-openlineage-header with empty name.\\n`);\n continue;\n }\n out[name] = value;\n }\n return out;\n}\n\nexport interface EmitOpenLineageCliDeps {\n readFile?: (p: string) => Promise<string>;\n writeFile?: (p: string, data: string) => Promise<void>;\n env?: Record<string, string | undefined>;\n fetchImpl?: typeof fetch;\n now?: () => Date;\n uuid?: () => string;\n stdout?: (chunk: string) => void;\n stderr?: (chunk: string) => void;\n}\n\nexport interface EmitOpenLineageCliOutcome {\n ok: boolean;\n events: number;\n succeeded?: number;\n failed?: number;\n error?: { code: string; message: string };\n}\n\nexport async function emitOpenLineageFromCli(\n inputs: EmitOpenLineageCliInputs,\n deps: EmitOpenLineageCliDeps = {},\n): Promise<EmitOpenLineageCliOutcome> {\n const stdout = deps.stdout ?? ((c: string) => process.stdout.write(c));\n const stderr = deps.stderr ?? ((c: string) => process.stderr.write(c));\n const readFile = deps.readFile ?? ((p: string) => fs.readFile(p, 'utf8'));\n const writeFile =\n deps.writeFile ??\n (async (p: string, data: string) => {\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, data, 'utf8');\n });\n const env = deps.env ?? (process.env as Record<string, string | undefined>);\n const now = deps.now ?? (() => new Date());\n const uuid = deps.uuid ?? (() => randomUUID());\n\n let loaded: columnLineage.OpenLineageConfig | undefined;\n const configPath = inputs.configPath ?? columnLineage.DEFAULT_OPENLINEAGE_CONFIG_FILE_REL;\n try {\n const raw = await readFile(configPath);\n const json = JSON.parse(raw);\n const parsed = columnLineage.parseOpenLineageConfig(json);\n if (!parsed.config) {\n const lines = parsed.errors.map((e) => ` - ${e.path}: ${e.message}`);\n stderr(`Failed to parse ${configPath}:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_PARSE_FAILED', message: `${configPath} did not validate` },\n };\n }\n loaded = parsed.config;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') {\n stderr(`Failed reading ${configPath}: ${(err as Error).message}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_READ_FAILED', message: (err as Error).message },\n };\n }\n // Missing config file is fine when the CLI flag supplies the endpoint.\n }\n\n const overrides: Partial<columnLineage.OpenLineageConfig> = {};\n if (inputs.endpointFlag) overrides.endpoint = inputs.endpointFlag;\n if (inputs.namespace) overrides.datasetNamespace = inputs.namespace;\n if (inputs.jobNamespace) overrides.jobNamespace = inputs.jobNamespace;\n if (inputs.job) overrides.jobName = inputs.job;\n // `auto` is a CLI-layer mode resolved AFTER buildOpenLineageEvents\n // based on events.length. Don't push it to the substrate; the\n // substrate's mode is always per-event or batch.\n if (inputs.mode && inputs.mode !== 'auto') overrides.mode = inputs.mode;\n if (\n typeof inputs.timeoutMs === 'number' &&\n Number.isFinite(inputs.timeoutMs) &&\n inputs.timeoutMs > 0\n ) {\n overrides.timeoutMs = Math.floor(inputs.timeoutMs);\n }\n if (inputs.token) overrides.bearerToken = inputs.token;\n if (inputs.producer && inputs.producer.trim().length > 0)\n overrides.producer = inputs.producer.trim();\n const cliHeaders = parseHeaderArgs(inputs.headerArgs, stderr);\n if (Object.keys(cliHeaders).length > 0) overrides.headers = cliHeaders;\n const merged = columnLineage.mergeOpenLineageCliOverrides(loaded, overrides);\n\n const validated = columnLineage.validateOpenLineageConfig(merged);\n if (!validated.ok) {\n const lines = validated.errors.map((e) => ` - ${e.path}: ${e.message}`);\n stderr(`OpenLineage emit refused:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'CONFIG_INCOMPLETE', message: validated.errors[0]!.message },\n };\n }\n\n const resolved = columnLineage.resolveEnvPlaceholders(validated.resolved, env);\n if (!resolved.ok) {\n const lines = resolved.missing.map((m) => ` - ${m.path}: missing env var ${m.envKey}`);\n stderr(`OpenLineage env placeholders unresolved:\\n${lines.join('\\n')}\\n`);\n return {\n ok: false,\n events: 0,\n error: { code: 'ENV_UNRESOLVED', message: resolved.missing[0]!.envKey },\n };\n }\n const final = resolved.resolved;\n\n const jobName = final.jobName ?? inputs.sourceHint ?? 'sdt-lineage';\n const eventType = inputs.eventType ?? 'COMPLETE';\n const events = columnLineage.buildOpenLineageEvents(inputs.dag, {\n runId: inputs.runId ?? uuid(),\n jobName,\n jobNamespace: final.jobNamespace ?? columnLineage.DEFAULT_OPENLINEAGE_JOB_NAMESPACE,\n ...(final.datasetNamespace ? { datasetNamespace: final.datasetNamespace } : {}),\n ...(final.producer ? { producer: final.producer } : {}),\n eventTime: inputs.eventTime ?? now().toISOString(),\n eventType,\n });\n\n if (inputs.eventsOutPath) {\n const format = inputs.eventsOutFormat ?? 'json';\n const payload =\n format === 'jsonl'\n ? events.map((e) => JSON.stringify(e)).join('\\n') + '\\n'\n : JSON.stringify({ events }, null, 2) + '\\n';\n await writeFile(inputs.eventsOutPath, payload);\n stderr(\n `OpenLineage: wrote ${events.length} event(s) to ${inputs.eventsOutPath} (${format}).\\n`,\n );\n }\n\n // CI guard: fail before dry-run / POST when events.length is below\n // the operator-supplied threshold. Catches silent lineage gaps after\n // a refactor that bypasses column-lineage extraction.\n if (\n typeof inputs.minEvents === 'number' &&\n Number.isFinite(inputs.minEvents) &&\n inputs.minEvents > 0 &&\n events.length < inputs.minEvents\n ) {\n stderr(\n `OpenLineage: built ${events.length} event(s), below --emit-openlineage-min-events=${inputs.minEvents}; refusing to emit.\\n`,\n );\n return {\n ok: false,\n events: events.length,\n error: {\n code: 'MIN_EVENTS_NOT_MET',\n message: `built ${events.length} events, expected >= ${inputs.minEvents}`,\n },\n };\n }\n\n if (inputs.dryRun) {\n stdout(JSON.stringify({ events }, null, 2) + '\\n');\n return { ok: true, events: events.length };\n }\n\n if (events.length === 0 && inputs.skipEmpty) {\n stderr(\n 'OpenLineage: 0 events to emit (DAG empty) and --emit-openlineage-skip-empty set; skipping POST.\\n',\n );\n return { ok: true, events: 0, succeeded: 0, failed: 0 };\n }\n\n // Resolve `mode: auto` AFTER buildOpenLineageEvents so the decision\n // sees the actual events count. Substrate's `final.mode` is always\n // per-event / batch — auto only lives at the CLI layer.\n const concreteMode: 'per-event' | 'batch' =\n inputs.mode === 'auto' ? resolveAutoMode('auto', events.length) : (final.mode ?? 'per-event');\n if (inputs.mode === 'auto') {\n stderr(\n `OpenLineage: --emit-openlineage-mode=auto resolved to ${concreteMode} ` +\n `(${events.length} event(s), threshold=${AUTO_MODE_THRESHOLD}).\\n`,\n );\n }\n\n const result = await columnLineage.emitOpenLineageEvents(events, final.endpoint!, {\n ...(final.bearerToken ? { bearerToken: final.bearerToken } : {}),\n ...(final.headers ? { headers: final.headers } : {}),\n mode: concreteMode,\n ...(typeof final.timeoutMs === 'number' ? { timeoutMs: final.timeoutMs } : {}),\n ...(deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}),\n });\n stderr(\n `OpenLineage: ${result.succeeded}/${result.totalEvents} events delivered to ${final.endpoint} (${result.failed} failed).\\n`,\n );\n return {\n ok: result.failed === 0,\n events: result.totalEvents,\n succeeded: result.succeeded,\n failed: result.failed,\n };\n}\n\n/**\n * `sdt lineage` — extract data-flow lineage from a `.sdtproj` or\n * `.sdtpac` and emit it as Mermaid, DOT, JSON, or Markdown.\n *\n * Distinct from `sdt graph`: graph is FQN-level dependency edges\n * (A references B). Lineage adds direction-of-data-flow classification\n * (READS_FROM vs WRITES_TO), upstream/downstream traversal, and\n * column-level best-effort tagging for view SELECT lists.\n *\n * Use cases:\n * - \"What does ANALYTICS.GOLD.CUSTOMER_360 depend on?\" (upstream slice)\n * - \"If I drop RAW.STAGING.ORDERS_RAW, what breaks?\" (downstream slice)\n * - \"Embed this graph in our PR template / docs / dashboard.\"\n *\n * Mirrors `ddt lineage`.\n */\nexport function lineageCommand(): Command {\n const cmd = new Command('lineage');\n cmd\n .description('Extract data-flow lineage from a .sdtproj, .sdtpac, or dbt manifest.json.')\n .option('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--dbt-manifest <path>',\n 'Extract column-level lineage from a dbt target/manifest.json (or project root).',\n )\n .option(\n '--fqn <name>',\n 'Focus on this fully-qualified name; restrict the graph to its upstream + downstream slice.',\n )\n .option(\n '--direction <kind>',\n 'When --fqn is set, restrict to upstream | downstream | both. Default both.',\n 'both',\n )\n .option('--depth <n>', 'Max traversal depth from --fqn. Default unbounded.', (v) =>\n parseInt(v, 10),\n )\n .option('--format <fmt>', 'mermaid | dot | json | markdown. Default mermaid.', 'mermaid')\n .option('--columns', 'Include best-effort column-level lineage for view SELECT lists.', false)\n .option(\n '--column-dag',\n 'Build a true per-column DAG via the CLL.1/2/3 substrate. Walks every VIEW / SECURE_VIEW / MATERIALIZED_VIEW / DYNAMIC_TABLE body in the project model, extracts column-level lineage, assembles the DAG, and emits Mermaid (default) or JSON. Composes with --fqn (focus to one object) and --out.',\n false,\n )\n .option('--max-edges <n>', 'Truncate large graphs at this edge count.', (v) => parseInt(v, 10))\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--emit-openlineage [endpoint]',\n 'CLL.7-followup: emit the column DAG as OpenLineage RunEvents to the given collector URL. When the flag is given without a value, the endpoint from .sdt/lineage.json is used. Requires --column-dag (or --dbt-manifest).',\n )\n .option(\n '--emit-openlineage-config <path>',\n 'Override the config-file location (default .sdt/lineage.json).',\n )\n .option(\n '--emit-openlineage-namespace <ns>',\n 'Override the OpenLineage dataset namespace (default snowflake).',\n )\n .option(\n '--emit-openlineage-job-namespace <ns>',\n 'Override the OpenLineage job.namespace (default sdt). Groups jobs across deployments in Marquez/OpenMetadata.',\n )\n .option(\n '--emit-openlineage-job <name>',\n 'Override the OpenLineage job.name (default derived from --source).',\n )\n .option(\n '--emit-openlineage-mode <mode>',\n 'OpenLineage emit mode: per-event (default) | batch | auto. `auto` resolves to per-event when the DAG has ≤10 events (easier to debug in Marquez UI) and batch when >10 (amortizes HTTP overhead).',\n )\n .option(\n '--emit-openlineage-timeout-ms <ms>',\n 'Override per-request timeout (positive integer, default 10000ms).',\n (v) => parseInt(v, 10),\n )\n .option(\n '--emit-openlineage-token <token>',\n 'Override bearer token (supports env:VAR_NAME for indirection).',\n )\n .option(\n '--emit-openlineage-header <k=v>',\n 'Extra HTTP header attached to every OpenLineage POST (repeatable). Format: name=value. Values support env:VAR_NAME for indirection.',\n (val: string, prev: string[]) => [...prev, val],\n [] as string[],\n )\n .option(\n '--emit-openlineage-producer <url>',\n 'Override the OpenLineage producer URL (identifies the emitting tool to the collector). Default: https://github.com/GVOrganization/SDT.',\n )\n .option(\n '--emit-openlineage-event-type <type>',\n 'OpenLineage event type: COMPLETE (default), START, RUNNING, ABORT, FAIL, or OTHER. Use START + COMPLETE pairs (sharing --emit-openlineage-run-id) for run-lifecycle modelling.',\n )\n .option(\n '--emit-openlineage-event-time <iso>',\n 'Override the OpenLineage eventTime (ISO 8601). Default: now() at emit time. Use for backfill — replay historical pipeline runs into Marquez/OpenMetadata with their original timestamps instead of \"now\".',\n )\n .option(\n '--emit-openlineage-run-id <id>',\n 'Stable runId (UUID v4). Default: generated per invocation.',\n )\n .option(\n '--emit-openlineage-dry-run',\n 'Build OpenLineage events but do not POST — print the events JSON to stdout instead.',\n false,\n )\n .option(\n '--emit-openlineage-events-out <path>',\n 'Also write the built events JSON to <path> (audit / replay). Independent of --dry-run; combined yields write-only-no-POST.',\n )\n .option(\n '--emit-openlineage-events-out-format <fmt>',\n 'Output format for --emit-openlineage-events-out: json (default, `{events: [...]}` wrapper) or jsonl (newline-delimited, one event per line). Use jsonl for streaming-ingest pipelines (Vector, Fluent Bit, OpenTelemetry collectors, Snowflake VARIANT loaders).',\n )\n .option(\n '--emit-openlineage-skip-empty',\n 'Skip the POST when the built events array is empty (default behavior is to still hit the collector with 0 events in batch mode). Useful in CI when lineage extraction may produce an empty DAG and noisy 0-event traffic is undesirable.',\n false,\n )\n .option(\n '--emit-openlineage-min-events <n>',\n 'CI assertion: refuse to emit (exit 2) when the built events count is below this threshold. Catches silent lineage gaps after a refactor that bypasses column-lineage extraction. Skip-empty composes naturally — set min-events=1 to force every run to produce ≥1 event.',\n (v) => parseInt(v, 10),\n )\n .action(async (opts) => {\n // CLL.7-followup guard (iter 193): refuse --emit-openlineage when\n // neither --column-dag nor --dbt-manifest is in play, because the\n // default FQN-level lineage path doesn't produce a column DAG and\n // the OL columnLineage facet would be empty. Silent-no-op here was\n // a footgun — operators forgetting --column-dag got 0 events.\n if (opts.emitOpenlineage && !opts.columnDag && !opts.dbtManifest) {\n process.stderr.write(\n '--emit-openlineage requires --column-dag (CLL.2 DAG) or --dbt-manifest. ' +\n 'The default FQN-level lineage path has no column-level facet to emit. ' +\n 'Re-run with --column-dag --source <path> or --dbt-manifest <path>.\\n',\n );\n process.exitCode = 2;\n return;\n }\n\n // CLL.4: column-DAG mode — uses CLL.1/2/3 substrate, distinct from\n // the FQN-graph `--columns` hint above.\n if (opts.columnDag) {\n if (!opts.source) throw new Error('--column-dag requires --source <path>.');\n const model = await loadModel(String(opts.source));\n const inputs = collectColumnLineageInputs(model);\n const dag = columnLineage.buildColumnLineageDag(inputs);\n let renderedDag = dag;\n if (opts.fqn) {\n const focus = String(opts.fqn);\n const direction = String(opts.direction ?? 'both').toLowerCase() as\n | 'upstream'\n | 'downstream'\n | 'both';\n renderedDag = columnLineage.sliceColumnDag(dag, focus, direction);\n }\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n if (!['mermaid', 'json'].includes(fmt)) {\n throw new Error(`--column-dag only supports --format mermaid|json (got ${fmt}).`);\n }\n const payload =\n fmt === 'json'\n ? JSON.stringify(columnLineage.renderDagJson(renderedDag), null, 2)\n : columnLineage.renderDagMermaid(renderedDag);\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + '\\n', 'utf8');\n console.error(\n `Wrote ${out} (${renderedDag.nodes.size} nodes, ${renderedDag.edges.length} edges).`,\n );\n } else if (!opts.emitOpenlineage) {\n // Suppress stdout emission when we're piping into the OL --dry-run\n // path so the events JSON is the only thing on stdout.\n process.stdout.write(payload + '\\n');\n }\n if (opts.emitOpenlineage) {\n const endpointFlag =\n typeof opts.emitOpenlineage === 'string' && opts.emitOpenlineage.length > 0\n ? String(opts.emitOpenlineage)\n : undefined;\n const sourceHint = opts.source\n ? path.basename(String(opts.source)).replace(/\\.(sdtproj|sdtpac)$/i, '')\n : undefined;\n const outcome = await emitOpenLineageFromCli({\n dag: renderedDag,\n ...(endpointFlag ? { endpointFlag } : {}),\n ...(opts.emitOpenlineageConfig\n ? { configPath: String(opts.emitOpenlineageConfig) }\n : {}),\n ...(opts.emitOpenlineageNamespace\n ? { namespace: String(opts.emitOpenlineageNamespace) }\n : {}),\n ...(opts.emitOpenlineageJobNamespace\n ? { jobNamespace: String(opts.emitOpenlineageJobNamespace) }\n : {}),\n ...(opts.emitOpenlineageJob ? { job: String(opts.emitOpenlineageJob) } : {}),\n ...(opts.emitOpenlineageMode\n ? { mode: validateMode(String(opts.emitOpenlineageMode)) }\n : {}),\n ...(opts.emitOpenlineageEventType\n ? { eventType: validateEventType(String(opts.emitOpenlineageEventType)) }\n : {}),\n ...(opts.emitOpenlineageEventTime\n ? { eventTime: validateEventTime(String(opts.emitOpenlineageEventTime)) }\n : {}),\n ...(typeof opts.emitOpenlineageTimeoutMs === 'number'\n ? { timeoutMs: opts.emitOpenlineageTimeoutMs }\n : {}),\n ...(opts.emitOpenlineageToken ? { token: String(opts.emitOpenlineageToken) } : {}),\n ...(opts.emitOpenlineageProducer\n ? { producer: String(opts.emitOpenlineageProducer) }\n : {}),\n ...(Array.isArray(opts.emitOpenlineageHeader) && opts.emitOpenlineageHeader.length > 0\n ? { headerArgs: opts.emitOpenlineageHeader as string[] }\n : {}),\n ...(opts.emitOpenlineageRunId ? { runId: String(opts.emitOpenlineageRunId) } : {}),\n ...(opts.emitOpenlineageDryRun ? { dryRun: true } : {}),\n ...(opts.emitOpenlineageEventsOut\n ? { eventsOutPath: String(opts.emitOpenlineageEventsOut) }\n : {}),\n ...(opts.emitOpenlineageEventsOutFormat\n ? {\n eventsOutFormat: validateEventsOutFormat(\n String(opts.emitOpenlineageEventsOutFormat),\n ),\n }\n : {}),\n ...(opts.emitOpenlineageSkipEmpty ? { skipEmpty: true } : {}),\n ...(typeof opts.emitOpenlineageMinEvents === 'number' &&\n opts.emitOpenlineageMinEvents > 0\n ? { minEvents: opts.emitOpenlineageMinEvents }\n : {}),\n ...(sourceHint ? { sourceHint } : {}),\n });\n if (!outcome.ok) {\n process.exitCode = 2;\n }\n }\n return;\n }\n if (opts.dbtManifest) {\n const result = await columnLineage.extractDbtManifestLineage(String(opts.dbtManifest));\n const fmt = String(opts.format ?? 'mermaid').toLowerCase();\n const payload =\n fmt === 'json'\n ? columnLineage.renderDbtLineageJson(result)\n : columnLineage.renderDbtLineageMermaid(result);\n if (result.skipped.length > 0) {\n for (const s of result.skipped) console.error(`Skipped ${s.nodeId}: ${s.reason}`);\n }\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + '\\n', 'utf8');\n console.error(\n `Wrote ${out} (${result.models.length} models, ${result.skipped.length} skipped).`,\n );\n } else if (!opts.emitOpenlineage) {\n process.stdout.write(payload + '\\n');\n }\n if (opts.emitOpenlineage) {\n const dag = columnLineage.buildColumnLineageDag(\n result.models.map((m) => ({ objectFqn: m.fqn, lineage: m.lineage })),\n );\n const endpointFlag =\n typeof opts.emitOpenlineage === 'string' && opts.emitOpenlineage.length > 0\n ? String(opts.emitOpenlineage)\n : undefined;\n const sourceHint = `dbt:${path.basename(String(opts.dbtManifest)).replace(/\\.json$/i, '')}`;\n const outcome = await emitOpenLineageFromCli({\n dag,\n ...(endpointFlag ? { endpointFlag } : {}),\n ...(opts.emitOpenlineageConfig\n ? { configPath: String(opts.emitOpenlineageConfig) }\n : {}),\n ...(opts.emitOpenlineageNamespace\n ? { namespace: String(opts.emitOpenlineageNamespace) }\n : {}),\n ...(opts.emitOpenlineageJobNamespace\n ? { jobNamespace: String(opts.emitOpenlineageJobNamespace) }\n : {}),\n ...(opts.emitOpenlineageJob ? { job: String(opts.emitOpenlineageJob) } : {}),\n ...(opts.emitOpenlineageMode\n ? { mode: validateMode(String(opts.emitOpenlineageMode)) }\n : {}),\n ...(opts.emitOpenlineageEventType\n ? { eventType: validateEventType(String(opts.emitOpenlineageEventType)) }\n : {}),\n ...(opts.emitOpenlineageEventTime\n ? { eventTime: validateEventTime(String(opts.emitOpenlineageEventTime)) }\n : {}),\n ...(typeof opts.emitOpenlineageTimeoutMs === 'number'\n ? { timeoutMs: opts.emitOpenlineageTimeoutMs }\n : {}),\n ...(opts.emitOpenlineageToken ? { token: String(opts.emitOpenlineageToken) } : {}),\n ...(opts.emitOpenlineageProducer\n ? { producer: String(opts.emitOpenlineageProducer) }\n : {}),\n ...(Array.isArray(opts.emitOpenlineageHeader) && opts.emitOpenlineageHeader.length > 0\n ? { headerArgs: opts.emitOpenlineageHeader as string[] }\n : {}),\n ...(opts.emitOpenlineageRunId ? { runId: String(opts.emitOpenlineageRunId) } : {}),\n ...(opts.emitOpenlineageDryRun ? { dryRun: true } : {}),\n ...(opts.emitOpenlineageEventsOut\n ? { eventsOutPath: String(opts.emitOpenlineageEventsOut) }\n : {}),\n ...(opts.emitOpenlineageEventsOutFormat\n ? {\n eventsOutFormat: validateEventsOutFormat(\n String(opts.emitOpenlineageEventsOutFormat),\n ),\n }\n : {}),\n ...(opts.emitOpenlineageSkipEmpty ? { skipEmpty: true } : {}),\n ...(typeof opts.emitOpenlineageMinEvents === 'number' &&\n opts.emitOpenlineageMinEvents > 0\n ? { minEvents: opts.emitOpenlineageMinEvents }\n : {}),\n sourceHint,\n });\n if (!outcome.ok) {\n process.exitCode = 2;\n }\n }\n return;\n }\n if (!opts.source) throw new Error('Either --source or --dbt-manifest is required.');\n const model = await loadModel(String(opts.source));\n const fullGraph = lineage.buildLineageGraph(model);\n\n const direction = String(opts.direction ?? 'both').toLowerCase() as\n | 'upstream'\n | 'downstream'\n | 'both';\n let graph = fullGraph;\n let focus: string | undefined;\n if (opts.fqn) {\n focus = String(opts.fqn);\n const depth: number = typeof opts.depth === 'number' ? opts.depth : Infinity;\n if (direction === 'upstream') {\n const keep = new Set([focus, ...lineage.upstreamOf(fullGraph, focus, depth)]);\n graph = subsetGraph(fullGraph, keep);\n } else if (direction === 'downstream') {\n const keep = new Set([focus, ...lineage.downstreamOf(fullGraph, focus, depth)]);\n graph = subsetGraph(fullGraph, keep);\n } else {\n graph = lineage.sliceAround(fullGraph, focus, depth);\n }\n }\n\n const fmt = String(opts.format ?? 'mermaid').toLowerCase() as lineage.LineageFormat;\n if (!['mermaid', 'dot', 'json', 'markdown'].includes(fmt)) {\n throw new Error(`Unknown --format: ${fmt}. Use mermaid | dot | json | markdown.`);\n }\n const renderOpts: lineage.RenderOptions = {\n ...(focus ? { focus } : {}),\n ...(typeof opts.maxEdges === 'number' ? { maxEdges: opts.maxEdges } : {}),\n ...(opts.columns ? { includeColumns: true } : {}),\n };\n const payload = lineage.renderLineage(graph, fmt, renderOpts);\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${graph.nodes.length} nodes, ${graph.edges.length} edges).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'lineage.explain',\n systemPrompt:\n 'You are a data-platform architect explaining a lineage graph. Describe the dominant data-flow shape, point out hot or fragile nodes, and recommend any decomposition / sharding the graph suggests.',\n },\n opts as { explain?: boolean },\n () => {\n const focused = focus ? ` (focused on ${focus}, direction=${direction})` : '';\n const summary = `Lineage graph${focused}: ${graph.nodes.length} nodes, ${graph.edges.length} edges.`;\n const sample = graph.edges\n .slice(0, 40)\n .map((e) => ` - ${e.from} ${e.kind === 'READS_FROM' ? '->' : '=>'} ${e.to}`);\n return [\n summary,\n '',\n 'Edges (up to 40):',\n ...sample,\n '',\n 'Narrate this graph in plain English.',\n ].join('\\n');\n },\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction subsetGraph(graph: lineage.LineageGraph, keep: Set<string>): lineage.LineageGraph {\n return {\n nodes: graph.nodes.filter((n) => keep.has(n.fqn)),\n edges: graph.edges.filter((e) => keep.has(e.from) && keep.has(e.to)),\n };\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\n/**\n * Walk a project model collecting `{objectFqn, lineage}` pairs for every\n * object whose body parses through CLL.1's `extractColumnLineage`. Covers\n * VIEW / SECURE_VIEW / MATERIALIZED_VIEW / DYNAMIC_TABLE — the four object\n * types whose `query: SqlExpression` is what downstream consumers depend\n * on for column-level lineage. CLL.4 entry point.\n */\nfunction collectColumnLineageInputs(model: unknown): columnLineage.ColumnLineageDagInput[] {\n const inputs: columnLineage.ColumnLineageDagInput[] = [];\n const matchTypes = new Set<string>(['VIEW', 'SECURE_VIEW', 'MATERIALIZED_VIEW', 'DYNAMIC_TABLE']);\n // parseProjectModel returns AnySnowflakeObject[]; readPac().model is the\n // same shape. Some legacy pac models nest objects under .objects so we\n // accept either form defensively.\n let flat: Array<{ objectType?: string; fqn?: unknown; query?: unknown }>;\n if (Array.isArray(model)) {\n flat = model as Array<{ objectType?: string; fqn?: unknown; query?: unknown }>;\n } else if (\n model &&\n typeof model === 'object' &&\n Array.isArray((model as { objects?: unknown }).objects)\n ) {\n flat = (model as { objects: Array<{ objectType?: string; fqn?: unknown; query?: unknown }> })\n .objects;\n } else {\n flat = [];\n }\n for (const obj of flat) {\n if (!obj.objectType || !matchTypes.has(obj.objectType)) continue;\n if (typeof obj.query !== 'string' || obj.query.length === 0) continue;\n const fqn =\n typeof obj.fqn === 'string'\n ? obj.fqn\n : obj.fqn && typeof obj.fqn === 'object'\n ? formatFqn(obj.fqn as { database?: string; schema?: string; name?: string })\n : '<unknown>';\n const lineage = columnLineage.extractColumnLineage(obj.query);\n inputs.push({ objectFqn: fqn, lineage });\n }\n return inputs;\n}\n\nfunction formatFqn(fqn: { database?: string; schema?: string; name?: string }): string {\n return [fqn.database, fqn.schema, fqn.name].filter(Boolean).join('.');\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { diagnostics, interop, pac, project } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt diagnose` — project-level health report. Bundles lint, lineage\n * smells (orphan / no-downstream / hot-table / cycle), object smells\n * (`SELECT *` in views, large tables without clustering, missing PK)\n * and cost smells (warehouse without AUTO_SUSPEND, long Time Travel)\n * into one ranked report. Every finding ships with a **reasoning**\n * line explaining *why* it matters — readers learn the engineering\n * motivation, not just the patch.\n *\n * Use cases:\n * - Pre-PR check: `sdt diagnose --source <proj> --min-severity warning`\n * - Periodic project audit: weekly cron emitting JSON to a dashboard\n * - Onboarding: a new engineer reads the report to learn what good\n * looks like in this codebase\n *\n * Mirrors `ddt diagnose`.\n */\nexport function diagnoseCommand(): Command {\n const cmd = new Command('diagnose');\n cmd\n .description(\n 'Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning.',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--category <c>',\n 'Filter to one category: lint | lineage | smell | cost | dim-modeling.',\n )\n .option(\n '--min-severity <s>',\n 'Filter to a minimum severity: error | warning | info. Default info (everything).',\n 'info',\n )\n .option(\n '--format <fmt>',\n 'table | json | markdown | sarif. sarif emits SARIF 2.1.0 for GitHub code-scanning / Azure DevOps. Default table.',\n 'table',\n )\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(\n async (opts: {\n source: string;\n category?: string;\n minSeverity?: string;\n format?: string;\n out?: string;\n explain?: boolean;\n }) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const report = diagnostics.analyzeProject(model, {\n source: sourcePath,\n ...(opts.category\n ? { category: String(opts.category) as diagnostics.DiagnosticCategory }\n : {}),\n ...(opts.minSeverity\n ? { minSeverity: String(opts.minSeverity) as diagnostics.DiagnosticSeverity }\n : {}),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(report, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderReportMarkdown(report);\n } else if (fmt === 'sarif') {\n payload = JSON.stringify(interop.diagnosticReportToSarif(report), null, 2);\n } else if (fmt === 'table') {\n payload = diagnostics.formatReport(report);\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown | sarif.`);\n }\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n // Non-zero exit when at least one error-severity finding fires so\n // `sdt diagnose` can gate a CI step.\n if (report.totals.error > 0) process.exitCode = 1;\n\n await runExplain({ feature: 'diagnose.explain' }, opts, () => buildDiagnosePrompt(report));\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction buildDiagnosePrompt(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`Source: ${report.source || '(unknown)'}`);\n lines.push(\n `Totals: ${report.totals.error} error, ${report.totals.warning} warning, ${report.totals.info} info`,\n );\n lines.push('');\n const top = report.findings\n .slice()\n .sort((a, b) => sevWeight(b.severity) - sevWeight(a.severity))\n .slice(0, 40);\n lines.push(`Top ${top.length} findings (highest severity first):`);\n for (const d of top) {\n lines.push(`- [${d.severity}] ${d.id} · ${d.fqn || '(project)'} — ${d.message}`);\n }\n if (report.findings.length > top.length) {\n lines.push(`(… ${report.findings.length - top.length} more truncated)`);\n }\n lines.push('');\n lines.push(\n 'Explain the dominant themes, what they suggest about the project health, and the highest-leverage fixes the team should tackle first.',\n );\n return lines.join('\\n');\n}\n\nfunction sevWeight(s: diagnostics.DiagnosticSeverity): number {\n return s === 'error' ? 3 : s === 'warning' ? 2 : 1;\n}\n\nfunction renderReportMarkdown(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`# Diagnostic report — \\`${report.source || '(no source)'}\\``);\n lines.push('');\n lines.push(`Generated: ${report.generatedAt}`);\n lines.push('');\n lines.push(\n `**Totals:** ${report.totals.error} error · ${report.totals.warning} warning · ${report.totals.info} info`,\n );\n lines.push('');\n lines.push('## By category');\n lines.push('');\n lines.push('| Category | Count |');\n lines.push('|---|---|');\n for (const [k, v] of Object.entries(report.byCategory)) {\n if (v > 0) lines.push(`| ${k} | ${v} |`);\n }\n lines.push('');\n if (report.findings.length === 0) {\n lines.push('_No findings._');\n return lines.join('\\n');\n }\n lines.push('## Findings');\n lines.push('');\n for (const d of report.findings) {\n const glyph = d.severity === 'error' ? '🛑' : d.severity === 'warning' ? '⚠️' : 'ℹ️';\n lines.push(`### ${glyph} \\`${d.id}\\` — ${d.fqn || '(project)'}`);\n lines.push('');\n lines.push(`**${d.message}**`);\n lines.push('');\n lines.push(`*Why:* ${d.reasoning}`);\n lines.push('');\n lines.push(`*Suggestion:* ${d.suggestion}`);\n lines.push('');\n if (d.related && d.related.length > 0) {\n lines.push(\n `*Related:* ${d.related\n .slice(0, 5)\n .map((r) => `\\`${r}\\``)\n .join(', ')}`,\n );\n lines.push('');\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { ai, aiReview, pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt review` — produce a senior-DBA Markdown report combining lint,\n * lineage findings, smell findings, cost findings, and safety\n * reasoning. The deliverable a reviewer can paste straight into a PR\n * or an architecture-review meeting.\n *\n * Default mode (project health): pure composition of existing modules —\n * every finding's reasoning + suggestion is generated by\n * `@sdt-tools/core/diagnostics`; the format is the value-add.\n *\n * `--senior-dba` mode (AI Phase 4): takes a compare-result JSON\n * (typically the output of `sdt compare --json`) + a safety-summary\n * JSON + optional target-metadata snapshot + truncated DDL preview,\n * asks the configured AI provider for a senior-DBA verdict, and emits\n * the parsed result as Markdown (or JSON via `--format json`).\n */\nexport function reviewCommand(): Command {\n const cmd = new Command('review');\n cmd\n .description(\n 'Senior-DBA-style health report (lint + lineage + smell + cost + safety, with reasoning).',\n )\n .option('--source <path>', '.sdtproj or .sdtpac to analyze (project-health mode).')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .option(\n '--senior-dba',\n 'AI-driven senior-DBA review of a deploy diff (requires --diff and --safety).',\n false,\n )\n .option(\n '--diff <path>',\n 'JSON file with compare summary { added, removed, modified, addedSample, removedSample, modifiedSample }.',\n )\n .option(\n '--safety <path>',\n 'JSON file with safety summary { unrecoverable, destructive, expensive, warning, sample }.',\n )\n .option(\n '--target-meta <path>',\n 'Optional file with target-metadata prose (existing tables, recent deploys, role grants).',\n )\n .option('--ddl <path>', 'Optional truncated DDL preview file.')\n .option('--format <fmt>', 'Output format: markdown | json. Default markdown.', 'markdown')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the AI call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(\n async (opts: {\n source?: string;\n out?: string;\n explain?: boolean;\n seniorDba?: boolean;\n diff?: string;\n safety?: string;\n targetMeta?: string;\n ddl?: string;\n format?: string;\n aiMaxSpend?: string;\n }) => {\n if (opts.seniorDba) {\n await runSeniorDbaReview(opts, 'sdt');\n return;\n }\n if (!opts.source) {\n throw new Error('--source is required in the default (project-health) mode.');\n }\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const md = review.renderReviewReport(model, { source: sourcePath });\n await emit(md, opts.out);\n await runExplain(\n {\n feature: 'review.explain',\n systemPrompt:\n 'You are a Snowflake principal engineer giving a senior-architect verbal walkthrough of an automated review report. Summarize the headline themes, recommend the top 3 follow-ups in order of leverage, and call out anything a junior reviewer might miss.',\n },\n opts,\n () =>\n `Review report follows:\\n\\n${md}\\n\\nNarrate this report for a teammate who has not read it.`,\n );\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\nexport async function runSeniorDbaReview(\n opts: {\n diff?: string;\n safety?: string;\n targetMeta?: string;\n ddl?: string;\n format?: string;\n out?: string;\n aiMaxSpend?: string;\n },\n toolName: 'sdt' | 'ddt',\n): Promise<void> {\n if (!opts.diff || !opts.safety) {\n throw new Error('--senior-dba requires both --diff and --safety (JSON files).');\n }\n const [diff, safety, targetMeta, ddl] = await Promise.all([\n readJson(opts.diff),\n readJson(opts.safety),\n opts.targetMeta\n ? fs.readFile(path.resolve(opts.targetMeta), 'utf8')\n : Promise.resolve<string | undefined>(undefined),\n opts.ddl\n ? fs.readFile(path.resolve(opts.ddl), 'utf8')\n : Promise.resolve<string | undefined>(undefined),\n ]);\n\n const compareSummary = normalizeCompareSummary(diff);\n const safetySummary = normalizeSafetySummary(safety);\n\n const result = await aiReview.runSeniorDbaReview(\n {\n compareSummary,\n safetySummary,\n ...(targetMeta ? { targetMetadata: targetMeta } : {}),\n ...(ddl ? { ddlPreview: ddl } : {}),\n },\n {\n completeFn: async (user, system) => {\n const r = await ai.complete(\n [\n { role: 'system', content: system },\n { role: 'user', content: user },\n ],\n {\n feature: 'review.senior-dba',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n },\n );\n return r.text;\n },\n },\n toolName,\n );\n\n const format = String(opts.format ?? 'markdown').toLowerCase();\n const payload =\n format === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined }, null, 2)\n : aiReview.renderSeniorDbaReviewMarkdown(result, toolName);\n await emit(payload, opts.out);\n // Set exit code on request_changes so CI gates can rely on it.\n if (result.verdict === 'request_changes' && !opts.out) {\n process.exitCode = 2;\n }\n}\n\nfunction normalizeCompareSummary(raw: unknown): aiReview.CompareSummaryInput {\n const o = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>;\n const num = (k: string) => (typeof o[k] === 'number' ? (o[k] as number) : 0);\n const arr = (k: string) =>\n Array.isArray(o[k])\n ? (o[k] as unknown[]).filter((x): x is string => typeof x === 'string')\n : undefined;\n return {\n added: num('added'),\n removed: num('removed'),\n modified: num('modified'),\n ...(arr('addedSample') ? { addedSample: arr('addedSample') } : {}),\n ...(arr('removedSample') ? { removedSample: arr('removedSample') } : {}),\n ...(arr('modifiedSample') ? { modifiedSample: arr('modifiedSample') } : {}),\n };\n}\n\nfunction normalizeSafetySummary(raw: unknown): aiReview.SafetySummaryInput {\n const o = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>;\n const num = (k: string) => (typeof o[k] === 'number' ? (o[k] as number) : 0);\n const sample = Array.isArray(o.sample)\n ? (o.sample as unknown[]).filter((x): x is string => typeof x === 'string')\n : undefined;\n return {\n unrecoverable: num('unrecoverable'),\n destructive: num('destructive'),\n expensive: num('expensive'),\n warning: num('warning'),\n ...(sample ? { sample } : {}),\n };\n}\n\nasync function readJson(p: string): Promise<unknown> {\n const raw = await fs.readFile(path.resolve(p), 'utf8');\n return JSON.parse(raw);\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\nasync function emit(payload: string, out: unknown): Promise<void> {\n if (out) {\n const p = path.resolve(String(out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${payload.length} bytes).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `sdt impact <fqn>` — single-FQN blast-radius answer. \"If I change\n * this, what breaks? What feeds it? What pending diagnostics\n * touch it?\" Composition of `@sdt-tools/core/lineage` (upstream/downstream)\n * and `@sdt-tools/core/diagnostics` (findings filtered to the FQN).\n *\n * Output is Markdown by default; `--format json` returns a structured\n * payload for CI integration.\n */\nexport function impactCommand(): Command {\n const cmd = new Command('impact');\n cmd\n .description(\n 'Single-FQN blast-radius: who feeds it, who reads from it, what findings apply to it.',\n )\n .argument('<fqn>', 'Fully-qualified name to analyze (e.g. ANALYTICS.GOLD.CUSTOMER).')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(async (fqn: string, opts: { source: string; out?: string; explain?: boolean }) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const md = review.renderImpactReport(model, String(fqn), { source: sourcePath });\n await emit(md, opts.out);\n await runExplain(\n {\n feature: 'impact.explain',\n systemPrompt:\n 'You are a senior Snowflake DBA explaining an impact analysis to a developer who is about to change one object. Be very direct about the blast radius and what they should test before merging.',\n },\n opts,\n () =>\n `Impact report for ${fqn} follows:\\n\\n${md}\\n\\nExplain the blast radius and what the engineer should pay attention to.`,\n );\n });\n attachExplainFlag(cmd);\n return cmd;\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\nasync function emit(payload: string, out: unknown): Promise<void> {\n if (out) {\n const p = path.resolve(String(out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${payload.length} bytes).`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\ninterface HistoryEntry {\n sqlText?: string;\n durationMs?: number;\n}\n\n/**\n * `sdt cost-estimate` — static heuristic estimator for the Snowflake\n * credits a migration script will consume when applied.\n *\n * Approach: classify each statement by its observable cost-class\n * (TABLE rebuild, CREATE OR REPLACE VIEW, ADD COLUMN, ALTER TYPE,\n * dynamic-table refresh, etc.) and assign a credit-band estimate per\n * class. Estimates are intentionally **ranges** rather than point\n * values because actual cost depends on row count, warehouse size,\n * and data layout — we don't pretend otherwise.\n *\n * The framing alone is uniquely valuable: no other Snowflake schema\n * tool surfaces \"this migration will roughly cost X credits at S\n * warehouse\" before you apply it.\n *\n * The classifier is regex-based and conservative — when a statement\n * doesn't match a known cost-class it's reported as\n * \"unknown / negligible\" so the user knows the estimate didn't see it.\n */\nexport function costEstimateCommand(): Command {\n const cmd = new Command('cost-estimate');\n cmd\n .description('Heuristic Snowflake-credit estimate for a generated migration script.')\n .requiredOption(\n '--script <path>',\n 'Path to a generated migration script (.sql) from `sdt publish --out`.',\n )\n .option(\n '--warehouse-size <size>',\n 'Target warehouse size for the cost ladder: XS | S | M | L | XL | 2XL | 3XL | 4XL.',\n 'S',\n )\n .option('--format <fmt>', 'table | json | markdown. Default table.', 'table')\n .option('-o, --out <path>', 'Write output to file. Defaults to stdout.')\n .option(\n '--calibrate-from <path>',\n 'AI Phase 6 calibration: a JSON file of QueryHistoryEntry[] from prior deploys. Each historic statement is classified against the same cost-classes; classes with ≥3 samples adopt empirical min/max duration in place of the heuristic range.',\n )\n .action(\n async (opts: {\n script: string;\n warehouseSize?: string;\n format?: string;\n out?: string;\n calibrateFrom?: string;\n explain?: boolean;\n }) => {\n const sql = await fs.readFile(path.resolve(String(opts.script)), 'utf8');\n const wh = String(opts.warehouseSize ?? 'S').toUpperCase() as WarehouseSize;\n const wantedSizes: readonly WarehouseSize[] = [\n 'XS',\n 'S',\n 'M',\n 'L',\n 'XL',\n '2XL',\n '3XL',\n '4XL',\n ];\n if (!wantedSizes.includes(wh)) {\n throw new Error(\n `Unknown --warehouse-size: ${wh}. Use one of ${wantedSizes.join(' | ')}.`,\n );\n }\n let calibration: ClassCalibration | undefined;\n if (opts.calibrateFrom) {\n const histRaw = await fs.readFile(path.resolve(String(opts.calibrateFrom)), 'utf8');\n const parsed = JSON.parse(histRaw);\n const entries: HistoryEntry[] = Array.isArray(parsed)\n ? parsed\n : Array.isArray(parsed.entries)\n ? parsed.entries\n : [];\n calibration = buildCalibration(entries);\n }\n const report = estimateCost(sql, wh, calibration);\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(report, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderMarkdown(report);\n } else {\n payload = renderTable(report);\n }\n if (opts.out) {\n const p = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p}.`);\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'cost-estimate.explain',\n systemPrompt:\n 'You are a Snowflake cost engineer. Walk the team through this cost estimate: what is the dominant cost driver, what does the range mean in practice, and what knobs (warehouse size, sequencing, off-peak timing) would meaningfully reduce it.',\n },\n opts,\n () =>\n `Cost estimate (JSON) follows:\\n\\n${JSON.stringify(report, null, 2)}\\n\\nNarrate this for a teammate.`,\n );\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\ntype WarehouseSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | '2XL' | '3XL' | '4XL';\n\n/**\n * Snowflake's published credit-per-hour ladder, as of 2026-Q1.\n * XS = 1, S = 2, M = 4, L = 8, XL = 16, 2XL = 32, 3XL = 64, 4XL = 128.\n */\nconst CREDITS_PER_HOUR: Record<WarehouseSize, number> = {\n XS: 1,\n S: 2,\n M: 4,\n L: 8,\n XL: 16,\n '2XL': 32,\n '3XL': 64,\n '4XL': 128,\n};\n\ninterface CostClass {\n id: string;\n description: string;\n /** Conservative range estimate in **seconds of warehouse time**. */\n minSeconds: number;\n maxSeconds: number;\n /** Regex that matches the statement category. */\n test: (sql: string) => boolean;\n}\n\nconst COST_CLASSES: CostClass[] = [\n {\n id: 'table-rebuild',\n description: 'CREATE OR REPLACE TABLE or CTAS — rewrites the entire table',\n minSeconds: 30,\n maxSeconds: 1800,\n test: (s) =>\n /CREATE\\s+(?:OR\\s+REPLACE\\s+)?TABLE\\s+.+\\s+AS\\s+SELECT/i.test(s) ||\n /CREATE\\s+OR\\s+REPLACE\\s+TABLE\\b/i.test(s),\n },\n {\n id: 'add-column',\n description: 'ALTER TABLE ADD COLUMN — metadata-only, no scan',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bADD\\s+COLUMN\\b/i.test(s),\n },\n {\n id: 'drop-column',\n description: 'ALTER TABLE DROP COLUMN — metadata-only',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bDROP\\s+COLUMN\\b/i.test(s),\n },\n {\n id: 'alter-type-narrowing',\n description: 'ALTER COLUMN TYPE (narrowing) — full data scan + rewrite',\n minSeconds: 30,\n maxSeconds: 600,\n test: (s) => /ALTER\\s+TABLE\\b.*\\bALTER\\s+COLUMN\\b.*\\bSET\\s+DATA\\s+TYPE\\b/i.test(s),\n },\n {\n id: 'create-view',\n description: 'CREATE OR REPLACE VIEW — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?VIEW\\b/i.test(s),\n },\n {\n id: 'create-mv',\n description: 'CREATE MATERIALIZED VIEW — initial population can be costly',\n minSeconds: 60,\n maxSeconds: 3600,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?MATERIALIZED\\s+VIEW\\b/i.test(s),\n },\n {\n id: 'create-dynamic-table',\n description: 'CREATE DYNAMIC TABLE — initial materialisation cost',\n minSeconds: 60,\n maxSeconds: 1800,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?DYNAMIC\\s+TABLE\\b/i.test(s),\n },\n {\n id: 'create-stream',\n description: 'CREATE STREAM — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?STREAM\\b/i.test(s),\n },\n {\n id: 'create-task',\n description: 'CREATE TASK — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?TASK\\b/i.test(s),\n },\n {\n id: 'create-warehouse',\n description: 'CREATE WAREHOUSE — metadata; cost depends on usage',\n minSeconds: 1,\n maxSeconds: 5,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?WAREHOUSE\\b/i.test(s),\n },\n {\n id: 'pre-deploy-clone',\n description: 'CREATE DATABASE ... CLONE — Snowflake zero-copy clone (~instant)',\n minSeconds: 1,\n maxSeconds: 10,\n test: (s) => /CREATE\\s+(?:OR\\s+REPLACE\\s+)?DATABASE\\s+\\S+\\s+CLONE\\b/i.test(s),\n },\n {\n id: 'drop',\n description: 'DROP statement — metadata-only',\n minSeconds: 1,\n maxSeconds: 3,\n test: (s) => /^\\s*DROP\\s+/i.test(s),\n },\n {\n id: 'grant',\n description: 'GRANT / REVOKE — metadata-only',\n minSeconds: 1,\n maxSeconds: 2,\n test: (s) => /^\\s*(?:GRANT|REVOKE)\\s+/i.test(s),\n },\n {\n id: 'comment',\n description: 'COMMENT-only statement (-- … no DDL) — free',\n minSeconds: 0,\n maxSeconds: 0,\n test: (s) =>\n s\n .replace(/--[^\\n]*/g, '')\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .trim().length === 0,\n },\n];\n\ninterface CostReport {\n warehouseSize: WarehouseSize;\n creditsPerHour: number;\n totalStatements: number;\n classifiedStatements: number;\n unknownStatements: number;\n perClass: Array<{\n id: string;\n description: string;\n count: number;\n minSeconds: number;\n maxSeconds: number;\n minCredits: number;\n maxCredits: number;\n /** When set, the per-statement range came from this many empirical samples. */\n calibratedFromSamples?: number;\n }>;\n totals: {\n minSeconds: number;\n maxSeconds: number;\n minCredits: number;\n maxCredits: number;\n };\n}\n\n/**\n * AI Phase 6 calibration — per-class empirical duration ranges harvested\n * from prior `QueryHistoryEntry[]` (typed in `@<tool>/core/queryHistory`).\n * When a class has at least 3 historic samples, its heuristic min/max is\n * replaced with the observed min/max. Classes that fall back to the\n * heuristic are flagged in the report so the user can see what was\n * calibrated.\n */\ninterface ClassCalibration {\n /** Per-class empirical range; absent classes use the heuristic range. */\n perClass: Record<string, { sampleSize: number; minSeconds: number; maxSeconds: number }>;\n}\n\nfunction buildCalibration(entries: HistoryEntry[]): ClassCalibration {\n const samples = new Map<string, number[]>();\n for (const e of entries) {\n const sql = typeof e.sqlText === 'string' ? e.sqlText : '';\n const dur = typeof e.durationMs === 'number' ? e.durationMs : NaN;\n if (!sql || !isFinite(dur) || dur <= 0) continue;\n const matched = COST_CLASSES.find((c) => c.test(sql));\n if (!matched) continue;\n const arr = samples.get(matched.id) ?? [];\n arr.push(dur / 1000);\n samples.set(matched.id, arr);\n }\n const perClass: ClassCalibration['perClass'] = {};\n for (const [id, durs] of samples) {\n if (durs.length < 3) continue;\n durs.sort((a, b) => a - b);\n perClass[id] = {\n sampleSize: durs.length,\n minSeconds: Math.max(1, Math.round(durs[0]!)),\n maxSeconds: Math.max(1, Math.round(durs[durs.length - 1]!)),\n };\n }\n return { perClass };\n}\n\nfunction estimateCost(\n sql: string,\n warehouseSize: WarehouseSize,\n calibration?: ClassCalibration,\n): CostReport {\n const statements = splitStatements(sql);\n const classCounts = new Map<string, number>();\n let classifiedStatements = 0;\n let unknownStatements = 0;\n for (const stmt of statements) {\n const matched = COST_CLASSES.find((c) => c.test(stmt));\n if (matched) {\n classCounts.set(matched.id, (classCounts.get(matched.id) ?? 0) + 1);\n classifiedStatements++;\n } else if (stmt.trim().length > 0) {\n unknownStatements++;\n }\n }\n const creditsPerHour = CREDITS_PER_HOUR[warehouseSize];\n const perClass = COST_CLASSES.filter((c) => (classCounts.get(c.id) ?? 0) > 0).map((c) => {\n const count = classCounts.get(c.id) ?? 0;\n const cal = calibration?.perClass[c.id];\n const minSecondsPerStmt = cal ? cal.minSeconds : c.minSeconds;\n const maxSecondsPerStmt = cal ? cal.maxSeconds : c.maxSeconds;\n const minSeconds = minSecondsPerStmt * count;\n const maxSeconds = maxSecondsPerStmt * count;\n return {\n id: c.id,\n description: c.description,\n count,\n minSeconds,\n maxSeconds,\n minCredits: (minSeconds / 3600) * creditsPerHour,\n maxCredits: (maxSeconds / 3600) * creditsPerHour,\n ...(cal ? { calibratedFromSamples: cal.sampleSize } : {}),\n };\n });\n const totals = perClass.reduce(\n (acc, c) => ({\n minSeconds: acc.minSeconds + c.minSeconds,\n maxSeconds: acc.maxSeconds + c.maxSeconds,\n minCredits: acc.minCredits + c.minCredits,\n maxCredits: acc.maxCredits + c.maxCredits,\n }),\n { minSeconds: 0, maxSeconds: 0, minCredits: 0, maxCredits: 0 },\n );\n return {\n warehouseSize,\n creditsPerHour,\n totalStatements: statements.length,\n classifiedStatements,\n unknownStatements,\n perClass,\n totals,\n };\n}\n\nfunction splitStatements(sql: string): string[] {\n return sql\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .split(/;\\s*$/m)\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\nfunction renderTable(r: CostReport): string {\n const lines: string[] = [];\n lines.push(`Cost estimate — warehouse=${r.warehouseSize} (${r.creditsPerHour} credit/hour)`);\n lines.push('');\n lines.push(\n ` Statements: ${r.totalStatements} (${r.classifiedStatements} classified, ${r.unknownStatements} unknown).`,\n );\n lines.push('');\n const idW = Math.max(20, ...r.perClass.map((c) => c.id.length));\n for (const c of r.perClass) {\n lines.push(\n ` ${c.id.padEnd(idW)} ×${String(c.count).padStart(4)} ≈ ${c.minCredits.toFixed(3)} – ${c.maxCredits.toFixed(3)} credit`,\n );\n }\n lines.push('');\n lines.push(\n ` TOTAL ≈ ${r.totals.minCredits.toFixed(3)} – ${r.totals.maxCredits.toFixed(3)} credit`,\n );\n lines.push(` TOTAL (duration estimate) ≈ ${r.totals.minSeconds}s – ${r.totals.maxSeconds}s`);\n lines.push('');\n lines.push(' Note: ranges are heuristic. Actual cost depends on row counts, data layout,');\n lines.push(' and what other workloads share the warehouse. Treat the upper bound as a');\n lines.push(' pessimistic ceiling, not a likely outcome.');\n return lines.join('\\n');\n}\n\nfunction renderMarkdown(r: CostReport): string {\n const lines: string[] = [];\n lines.push(`# Cost estimate`);\n lines.push('');\n lines.push(`**Warehouse:** ${r.warehouseSize} (${r.creditsPerHour} credit/hour)`);\n lines.push(\n `**Statements:** ${r.totalStatements} total, ${r.classifiedStatements} classified, ${r.unknownStatements} unknown`,\n );\n lines.push('');\n lines.push(`## Estimate by statement class`);\n lines.push('');\n lines.push('| Class | Count | Credit range |');\n lines.push('|---|---|---|');\n for (const c of r.perClass) {\n lines.push(\n `| \\`${c.id}\\` (${c.description}) | ${c.count} | ${c.minCredits.toFixed(3)} – ${c.maxCredits.toFixed(3)} |`,\n );\n }\n lines.push('');\n lines.push(\n `**Total:** ${r.totals.minCredits.toFixed(3)} – ${r.totals.maxCredits.toFixed(3)} credit (${r.totals.minSeconds}–${r.totals.maxSeconds}s)`,\n );\n lines.push('');\n lines.push('> Ranges are heuristic. Actual cost depends on row counts and warehouse contention.');\n return lines.join('\\n');\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n CompareEngine,\n PacSource,\n ProjectSource,\n type CompareSource,\n} from '@sdt-tools/core/compare';\nimport { safety } from '@sdt-tools/core';\nimport { pac, project, review } from '@sdt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\nimport { attachRelatedOptions } from '../util/help-catalog.js';\n\n/**\n * `sdt pr-comment` — produce a Markdown PR sticky-comment from a\n * source↔target compare. Bundles the diff summary, reversibility-\n * grouped safety findings, project health diagnostics, and a\n * collapsible per-object changelog into a single deliverable a CI\n * step can POST as a pull-request comment.\n *\n * Distinct from `sdt review`: `review` is project-only, `pr-comment`\n * is change-driven (here's what's *in this PR*).\n */\nexport function prCommentCommand(): Command {\n const cmd = new Command('pr-comment');\n cmd\n .description(\n 'Generate a Markdown PR comment from a source↔target compare (diff + safety + health).',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac (the desired state).')\n .requiredOption('--target <path>', '.sdtproj or .sdtpac (the current state).')\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(async (opts: { source: string; target: string; out?: string; explain?: boolean }) => {\n const sourcePath = String(opts.source);\n const targetPath = String(opts.target);\n const engine = new CompareEngine();\n const src: CompareSource = sourcePath.endsWith('.sdtpac')\n ? new PacSource(sourcePath, 'source')\n : new ProjectSource(sourcePath, 'source');\n const tgt: CompareSource = targetPath.endsWith('.sdtpac')\n ? new PacSource(targetPath, 'target')\n : new ProjectSource(targetPath, 'target');\n const result = await engine.compare(src, tgt);\n const assessment = safety.assess(result);\n const model = await loadModel(sourcePath);\n const md = review.renderPrComment(model, result, assessment, { source: sourcePath });\n if (opts.out) {\n const p = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, md + (md.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p} (${md.length} bytes).`);\n } else {\n process.stdout.write(md + (md.endsWith('\\n') ? '' : '\\n'));\n }\n await runExplain(\n {\n feature: 'pr-comment.explain',\n systemPrompt:\n 'You are a release manager preparing the human summary for a code-review comment. Distill the structured PR comment into 3-5 sentences a reviewer can read in 30 seconds. Lead with the riskiest change.',\n },\n opts,\n () =>\n `PR comment payload follows:\\n\\n${md}\\n\\nWrite a tight executive summary a busy reviewer will appreciate.`,\n );\n });\n attachExplainFlag(cmd);\n attachRelatedOptions(cmd, [\n 'compare.ignoreCase',\n 'compare.ignoreComments',\n 'compare.ignoreFormattingDifferences',\n 'compare.excludeObjectTypes',\n 'compare.excludeObjectPatterns',\n 'compare.includeObjectPatterns',\n ]);\n return cmd;\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\n/**\n * `sdt template <kind> <name>` — schema cookbook generator. Produces\n * a complete set of `.sql` files implementing a common pattern, ready\n * to drop into a `.sdtproj`'s object tree. Saves a junior engineer\n * from re-inventing the SCD2 pattern from scratch.\n *\n * Supported kinds:\n * - `scd1` — Slowly-changing-dimension type-1 (overwrite, no history).\n * - `scd2` — Slowly-changing-dimension type-2 (history-preserving).\n * - `scd3` — Slowly-changing-dimension type-3 (one previous value).\n * - `scd4` — Slowly-changing-dimension type-4 (current + history table).\n * - `scd6` — Hybrid 1+2+3 (current + valid_from/to + previous value).\n * - `star` — Star schema fact + N dimensions.\n * - `fact` — Fact table only, with surrogate-key FKs to named dims.\n * - `scd2-merge` — Canonical MERGE statement to load an SCD2 dimension.\n * - `current-view` — `CREATE VIEW` over an SCD2 table where IS_CURRENT = TRUE.\n * - `time-series` — Hash-partitioned time-series with retention.\n * - `audit` — Generic audit-log table with append-only constraints.\n *\n * Mirrors `ddt template`. Patterns are conservative: every template\n * sets a PK, populates COMMENT fields, and prefers `CREATE OR ALTER`\n * over `CREATE OR REPLACE` to play well with the safety classifier.\n */\nexport function templateCommand(): Command {\n const cmd = new Command('template');\n cmd\n .description(\n 'Scaffold a common schema pattern (scd1|scd2|scd3|scd4|scd6|star|fact|scd2-merge|current-view|time-series|audit). Writes .sql files into <out>/.',\n )\n .argument(\n '<kind>',\n 'Pattern to scaffold: scd1 | scd2 | scd3 | scd4 | scd6 | star | fact | scd2-merge | current-view | time-series | audit',\n )\n .argument('<name>', 'Base object name (e.g. CUSTOMER, ORDERS).')\n .option('--db <database>', 'Database name. Default DEMO_DB.', 'DEMO_DB')\n .option('--schema <schema>', 'Schema name. Default PUBLIC.', 'PUBLIC')\n .option('-o, --out <path>', 'Output directory. Default <kind>-<name>/.')\n .option(\n '--dims <dims>',\n '[star|fact] Comma-separated dimension names. Default: customer,product,date.',\n 'customer,product,date',\n )\n .option(\n '--track <cols>',\n '[scd3|scd6] Comma-separated columns to track previous-values for. Default: attribute_1.',\n 'attribute_1',\n )\n .option(\n '--source <fqn>',\n '[scd2-merge] Source/staging table fully-qualified name. Default DEMO_DB.PUBLIC.<name>_STAGE.',\n )\n .option('--retention-days <n>', '[time-series] Retention window in days. Default 90.', '90')\n .option(\n '--hybrid',\n 'Emit CREATE HYBRID TABLE (Unistore row-store) instead of CREATE OR ALTER TABLE. Constraints become enforced; CLUSTER BY is suppressed (not supported on Hybrid Tables).',\n )\n .action(async (kindArg, nameArg, opts) => {\n const kind = String(kindArg).toLowerCase();\n const name = String(nameArg);\n const db = String(opts.db);\n const schema = String(opts.schema);\n const hybrid = Boolean(opts.hybrid);\n const out = opts.out\n ? path.resolve(String(opts.out))\n : path.resolve(`${kind}-${name.toLowerCase()}`);\n await fs.mkdir(out, { recursive: true });\n\n if (hybrid && (kind === 'scd2-merge' || kind === 'current-view')) {\n console.error(`Warning: --hybrid has no effect on ${kind} (no table DDL emitted).`);\n }\n\n const ctx = { db, schema, name, hybrid };\n let files: Record<string, string>;\n const trackCols = String(opts.track)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const dims = String(opts.dims)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (kind === 'scd1') files = renderScd1(ctx);\n else if (kind === 'scd2') files = renderScd2(ctx);\n else if (kind === 'scd3') files = renderScd3(ctx, trackCols);\n else if (kind === 'scd4') files = renderScd4(ctx);\n else if (kind === 'scd6') files = renderScd6(ctx, trackCols);\n else if (kind === 'star') files = renderStar(ctx, dims);\n else if (kind === 'fact') files = renderFact(ctx, dims);\n else if (kind === 'scd2-merge')\n files = renderScd2Merge(\n ctx,\n opts.source ? String(opts.source) : `${db}.${schema}.${name.toUpperCase()}_STAGE`,\n );\n else if (kind === 'current-view') files = renderCurrentView(ctx);\n else if (kind === 'time-series') files = renderTimeSeries(ctx, Number(opts.retentionDays));\n else if (kind === 'audit') files = renderAudit(ctx);\n else\n throw new Error(\n `Unknown template kind: ${kind}. Use scd1 | scd2 | scd3 | scd4 | scd6 | star | fact | scd2-merge | current-view | time-series | audit.`,\n );\n\n for (const [rel, contents] of Object.entries(files)) {\n const filePath = path.join(out, rel);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, contents, 'utf8');\n console.error(\n ` wrote ${path.relative(process.cwd(), filePath)} (${contents.length} bytes)`,\n );\n }\n console.error(\n `Done. ${Object.keys(files).length} file(s) written to ${path.relative(process.cwd(), out)}.`,\n );\n });\n return cmd;\n}\n\ninterface Ctx {\n db: string;\n schema: string;\n name: string;\n /** When true, emit CREATE HYBRID TABLE with enforced constraints and no CLUSTER BY. */\n hybrid?: boolean;\n}\n\nfunction header(why: string): string {\n return `-- Generated by \\`sdt template\\`. Why this pattern is the right shape:\\n-- ${why}\\n--\\n-- Edit freely; this is just a starting point.\\n\\n`;\n}\n\n/** DDL verb for table creation — Hybrid Tables can't use CREATE OR ALTER. */\nfunction tableKw(c: Ctx, tableName: string): string {\n return c.hybrid\n ? `CREATE HYBRID TABLE ${c.db}.${c.schema}.${tableName}`\n : `CREATE OR ALTER TABLE ${c.db}.${c.schema}.${tableName}`;\n}\n\n/** Primary-key constraint. Hybrid Tables enforce PKs, regular tables don't. */\nfunction pkConstraint(name: string, cols: string, c: Ctx): string {\n return c.hybrid\n ? `CONSTRAINT ${name} PRIMARY KEY (${cols})`\n : `CONSTRAINT ${name} PRIMARY KEY (${cols}) NOT ENFORCED`;\n}\n\n/** Unique constraint. Hybrid Tables enforce UKs, regular tables don't. */\nfunction ukConstraint(name: string, cols: string, c: Ctx): string {\n return c.hybrid\n ? `CONSTRAINT ${name} UNIQUE (${cols})`\n : `CONSTRAINT ${name} UNIQUE (${cols}) NOT ENFORCED`;\n}\n\n/** CLUSTER BY clause — suppressed on Hybrid Tables (not supported). */\nfunction clusterBy(expr: string, c: Ctx): string {\n return c.hybrid ? '' : `\\nCLUSTER BY (${expr})`;\n}\n\nfunction renderScd1(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD1 overwrites the row in place when an attribute changes. No history is\n-- preserved. Use this when downstream consumers only care about the *current*\n-- state and the dimension is small enough that losing history is fine.\n-- LOAD_TS/UPDATED_TS give you minimal auditability without history-table cost.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — stable across overwrites',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was first inserted',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When the row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD1 dimension — overwrite-on-change. No history kept; join on ${upper}_BK.';\n`,\n };\n}\n\nfunction renderScd2(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD2 preserves every historical version of a row by closing the previous row's\n-- VALID_TO when the natural key reappears with new attribute values. Use this\n-- when downstream analytics needs \"what did this row look like on date X\".`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — unique per version',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key — stable across versions',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n VALID_FROM TIMESTAMP_NTZ NOT NULL COMMENT 'When this version became current',\n VALID_TO TIMESTAMP_NTZ COMMENT 'When this version was superseded; NULL while current',\n IS_CURRENT BOOLEAN NOT NULL COMMENT 'TRUE only on the latest row per BK',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)}\n)\nCOMMENT = 'SCD2 dimension — preserves history. Treat business key + IS_CURRENT as the natural join target.';\n`,\n [`${c.db}/${c.schema}/Streams/${upper}_STREAM.sql`]:\n header(\n `Stream over the SCD2 table lets downstream tasks consume only the rows that\n-- changed since they last read. Drop this if you don't have a downstream\n-- consumer that needs incremental updates.`,\n ) +\n `CREATE OR ALTER STREAM ${c.db}.${c.schema}.${upper}_STREAM ON TABLE ${c.db}.${c.schema}.${upper}\nCOMMENT = 'CDC stream over ${upper}. Read by downstream tasks for incremental processing.';\n`,\n };\n}\n\nfunction renderScd3(c: Ctx, tracked: string[]): Record<string, string> {\n const upper = c.name.toUpperCase();\n const cols = (tracked.length ? tracked : ['attribute_1']).map((t) => t.toUpperCase());\n const prevCols = cols\n .map(\n (t) =>\n ` PREV_${t} VARCHAR COMMENT 'Prior value of ${t}, captured on overwrite'`,\n )\n .join(',\\n');\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD3 keeps the current value plus one prior value per tracked column. Use\n-- this when downstream needs \"current vs immediately prior\" but doesn't need\n-- the full history. Cheaper than SCD2 but lossy beyond one change.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n${cols.map((t) => ` ${t} VARCHAR COMMENT 'Current value'`).join(',\\n')},\n${prevCols},\n PREV_CHANGED_TS TIMESTAMP_NTZ COMMENT 'When prior values were captured',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When this row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD3 dimension — current + one prior value for ${cols.join(', ')}.';\n`,\n };\n}\n\nfunction renderScd4(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD4 keeps a small, fast \"current\" table for joins and a separate history\n-- table for slow analytics. Use this when the current-state lookups are hot\n-- (every fact query joins to it) and you want to keep that join skinny.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Replace with real columns',\n ATTRIBUTE_2 VARCHAR COMMENT 'Replace with real columns',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was inserted',\n UPDATED_TS TIMESTAMP_NTZ COMMENT 'When the row was last overwritten',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)},\n ${ukConstraint(`UK_${upper}_BK`, `${upper}_BK`, c)}\n)\nCOMMENT = 'SCD4 current-state table. Pair with ${upper}_HISTORY for change tracking.';\n`,\n [`${c.db}/${c.schema}/Tables/${upper}_HISTORY.sql`]:\n header(\n `Companion history table for SCD4. Rows are appended (never updated) when\n-- the current table is overwritten — same columns plus a CHANGED_TS so you\n-- can replay \"what did this BK look like at time T\".`,\n ) +\n `${tableKw(c, `${upper}_HISTORY`)} (\n ${upper}_HISTORY_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id for each historical snapshot',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ATTRIBUTE_1 VARCHAR COMMENT 'Snapshot of column at CHANGED_TS',\n ATTRIBUTE_2 VARCHAR COMMENT 'Snapshot of column at CHANGED_TS',\n CHANGED_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When this snapshot was taken',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the row was appended',\n ${pkConstraint(`PK_${upper}_HISTORY`, `${upper}_HISTORY_SK`, c)}\n)${clusterBy(`${upper}_BK, CHANGED_TS`, c)}\nCOMMENT = 'SCD4 history-side. Append-only snapshots of ${upper}; reconstruct as-of state via window functions.';\n`,\n };\n}\n\nfunction renderScd6(c: Ctx, tracked: string[]): Record<string, string> {\n const upper = c.name.toUpperCase();\n const cols = (tracked.length ? tracked : ['attribute_1']).map((t) => t.toUpperCase());\n const prevCols = cols\n .map(\n (t) =>\n ` PREV_${t} VARCHAR COMMENT 'Prior value of ${t}'`,\n )\n .join(',\\n');\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `SCD6 = 1 + 2 + 3 hybrid. You get full SCD2 history (rows per version),\n-- SCD3 \"current vs prior\" lookback on hot columns, and SCD1 \"current value\"\n-- denormalized onto every historical row. Heavyweight; use when downstream\n-- consumers ask both \"what was it at time T?\" and \"what's the current value\n-- for the BK on this old row?\" in the same query.`,\n ) +\n `${tableKw(c, upper)} (\n ${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key — unique per version',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key — stable across versions',\n${cols.map((t) => ` ${t} VARCHAR COMMENT 'Value on THIS version'`).join(',\\n')},\n${cols.map((t) => ` CURRENT_${t} VARCHAR COMMENT 'Current value for the BK (SCD1 denorm)'`).join(',\\n')},\n${prevCols},\n VALID_FROM TIMESTAMP_NTZ NOT NULL COMMENT 'When this version became current',\n VALID_TO TIMESTAMP_NTZ COMMENT 'When this version was superseded; NULL while current',\n IS_CURRENT BOOLEAN NOT NULL COMMENT 'TRUE only on the latest row per BK',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_${upper}`, `${upper}_SK`, c)}\n)\nCOMMENT = 'SCD6 dimension — hybrid 1+2+3. Heavy but answers every common BI question without re-joining.';\n`,\n };\n}\n\nfunction renderStar(c: Ctx, dims: string[]): Record<string, string> {\n const fact = c.name.toUpperCase();\n const out: Record<string, string> = {};\n for (const d of dims) {\n const upper = d.toUpperCase();\n out[`${c.db}/${c.schema}/Tables/DIM_${upper}.sql`] =\n header(`Dimension table — describes the WHAT. Joined by the fact via DIM_${upper}_SK.`) +\n `${tableKw(c, `DIM_${upper}`)} (\n DIM_${upper}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n ${upper}_BK VARCHAR NOT NULL COMMENT 'Business key',\n ${upper}_NAME VARCHAR COMMENT 'Replace with real attributes',\n COUNTRY VARCHAR COMMENT 'Example attribute',\n ${pkConstraint(`PK_DIM_${upper}`, `DIM_${upper}_SK`, c)}\n)\nCOMMENT = 'Dimension table for the ${fact} star schema.';\n`;\n }\n out[`${c.db}/${c.schema}/Tables/FACT_${fact}.sql`] =\n header(\n `Fact table — the WHO/WHAT/WHEN/HOW-MUCH. One row per business event.\n-- Surrogate-key FKs to every dimension; measure columns hold the numbers.`,\n ) +\n `${tableKw(c, `FACT_${fact}`)} (\n FACT_${fact}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n${dims.map((d) => ` DIM_${d.toUpperCase()}_SK NUMBER(38,0) COMMENT 'FK to DIM_${d.toUpperCase()}'`).join(',\\n')},\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n MEASURE_AMOUNT NUMBER(38,4) COMMENT 'Primary measure — replace with real columns',\n MEASURE_QUANTITY NUMBER(38,0) COMMENT 'Secondary measure',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_FACT_${fact}`, `FACT_${fact}_SK`, c)}\n)${clusterBy('EVENT_TS', c)}\nCOMMENT = 'Fact table for the ${fact} star. CLUSTER BY date keeps recent-event scans cheap.';\n`;\n return out;\n}\n\nfunction renderFact(c: Ctx, dims: string[]): Record<string, string> {\n const fact = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/FACT_${fact}.sql`]:\n header(\n `Fact-only template — assumes the named dimensions already exist. Use this\n-- when adding a new fact to an existing star, rather than scaffolding the\n-- dims a second time. Surrogate-key FKs follow the DIM_<NAME>_SK convention.`,\n ) +\n `${tableKw(c, `FACT_${fact}`)} (\n FACT_${fact}_SK NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate key',\n${dims.map((d) => ` DIM_${d.toUpperCase()}_SK NUMBER(38,0) COMMENT 'FK to DIM_${d.toUpperCase()}'`).join(',\\n')},\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n MEASURE_AMOUNT NUMBER(38,4) COMMENT 'Primary measure — replace with real columns',\n MEASURE_QUANTITY NUMBER(38,0) COMMENT 'Secondary measure',\n LOAD_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'Insertion timestamp',\n ${pkConstraint(`PK_FACT_${fact}`, `FACT_${fact}_SK`, c)}\n)${clusterBy('EVENT_TS', c)}\nCOMMENT = 'Fact table FACT_${fact}. Add this to an existing star — dimensions assumed to exist.';\n`,\n };\n}\n\nfunction renderScd2Merge(c: Ctx, source: string): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Scripts/MERGE_${upper}.sql`]:\n header(\n `Canonical SCD2 load. Step 1 closes the prior row when the BK reappears with\n-- different attributes (sets VALID_TO + IS_CURRENT=FALSE). Step 2 inserts the\n-- new version. Wrap both in a transaction so you don't end up with two current\n-- rows. Source: ${source}.`,\n ) +\n `-- Step 1 — close the previous version when attributes change for an existing BK.\nBEGIN TRANSACTION;\n\nMERGE INTO ${c.db}.${c.schema}.${upper} AS tgt\nUSING (\n SELECT\n src.${upper}_BK,\n src.ATTRIBUTE_1,\n src.ATTRIBUTE_2\n FROM ${source} AS src\n) AS src\nON tgt.${upper}_BK = src.${upper}_BK\n AND tgt.IS_CURRENT = TRUE\nWHEN MATCHED\n AND (tgt.ATTRIBUTE_1 IS DISTINCT FROM src.ATTRIBUTE_1\n OR tgt.ATTRIBUTE_2 IS DISTINCT FROM src.ATTRIBUTE_2)\n THEN UPDATE SET\n VALID_TO = CURRENT_TIMESTAMP(),\n IS_CURRENT = FALSE;\n\n-- Step 2 — insert the new version for changed BKs + brand-new BKs.\nINSERT INTO ${c.db}.${c.schema}.${upper} (\n ${upper}_BK, ATTRIBUTE_1, ATTRIBUTE_2,\n VALID_FROM, VALID_TO, IS_CURRENT\n)\nSELECT\n src.${upper}_BK,\n src.ATTRIBUTE_1,\n src.ATTRIBUTE_2,\n CURRENT_TIMESTAMP(),\n NULL,\n TRUE\nFROM ${source} AS src\nLEFT JOIN ${c.db}.${c.schema}.${upper} AS tgt\n ON tgt.${upper}_BK = src.${upper}_BK\n AND tgt.IS_CURRENT = TRUE\nWHERE tgt.${upper}_BK IS NULL\n OR (tgt.ATTRIBUTE_1 IS DISTINCT FROM src.ATTRIBUTE_1\n OR tgt.ATTRIBUTE_2 IS DISTINCT FROM src.ATTRIBUTE_2);\n\nCOMMIT;\n`,\n };\n}\n\nfunction renderCurrentView(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Views/V_${upper}_CURRENT.sql`]:\n header(\n `Current-state view over an SCD2 table. Lets downstream consumers join on\n-- one canonical \"current row per BK\" target without remembering the\n-- IS_CURRENT predicate. Cheap — Snowflake filter-pushdown handles it.`,\n ) +\n `CREATE OR REPLACE VIEW ${c.db}.${c.schema}.V_${upper}_CURRENT\nCOMMENT = 'Current rows from ${upper} (SCD2). Join here instead of filtering IS_CURRENT manually.'\nAS\nSELECT *\nFROM ${c.db}.${c.schema}.${upper}\nWHERE IS_CURRENT = TRUE;\n`,\n };\n}\n\nfunction renderTimeSeries(c: Ctx, retentionDays: number): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}.sql`]:\n header(\n `Time-series table — append-only, clustered by event timestamp so recent-event\n-- scans prune to a small number of micropartitions. DATA_RETENTION_TIME_IN_DAYS\n-- bounds Time Travel cost; aged-out rows must be archived elsewhere.`,\n ) +\n `${tableKw(c, upper)} (\n EVENT_ID NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id',\n EVENT_TS TIMESTAMP_NTZ NOT NULL COMMENT 'When the event occurred',\n EVENT_TYPE VARCHAR COMMENT 'Discriminator — index of partition by event_type if useful',\n ENTITY_ID VARCHAR COMMENT 'Foreign key to the entity the event is about',\n PAYLOAD VARIANT COMMENT 'Event-specific payload (semistructured)',\n INGESTED_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When SDT loaded the row',\n ${pkConstraint(`PK_${upper}`, 'EVENT_ID', c)}\n)${clusterBy('EVENT_TS', c)}\nDATA_RETENTION_TIME_IN_DAYS = ${Math.max(1, Math.min(retentionDays, 90))}\nCOMMENT = 'Time-series ${upper}. Aged out beyond DATA_RETENTION_TIME_IN_DAYS; archive separately if you need longer history.';\n`,\n };\n}\n\nfunction renderAudit(c: Ctx): Record<string, string> {\n const upper = c.name.toUpperCase();\n return {\n [`${c.db}/${c.schema}/Tables/${upper}_AUDIT.sql`]:\n header(\n `Audit log — append-only by convention. INSERT-only INSERT-only permissions on\n-- downstream roles enforce the \"append-only\" property; this table itself doesn't\n-- block updates, but the role grants do. Pair with a row-access policy if\n-- stronger guarantees are needed.`,\n ) +\n `${tableKw(c, `${upper}_AUDIT`)} (\n AUDIT_ID NUMBER(38,0) NOT NULL AUTOINCREMENT COMMENT 'Surrogate id',\n AUDIT_TS TIMESTAMP_NTZ NOT NULL DEFAULT CURRENT_TIMESTAMP() COMMENT 'When the event was logged',\n ACTOR VARCHAR NOT NULL COMMENT 'Who performed the action (user / service-account)',\n ACTION VARCHAR NOT NULL COMMENT 'What happened (e.g. CREATE_USER, ROLE_GRANT)',\n TARGET VARCHAR COMMENT 'What it was performed on',\n DETAILS VARIANT COMMENT 'Free-form payload — keep it small',\n ${pkConstraint(`PK_${upper}_AUDIT`, 'AUDIT_ID', c)}\n)\nCOMMENT = 'Audit log for ${upper}. Append-only by convention — grant INSERT only to writer roles.';\n`,\n };\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { pac, project } from '@sdt-tools/core';\nimport type { SnowflakeObject } from '@sdt-tools/core/model';\n\n/**\n * `sdt anonymize` — generate masking-policy DDL for PII columns\n * discovered in a project model. Pairs with the L012 `pii-without-mask`\n * lint rule: the lint surfaces *which* columns need masking; this\n * command writes the policy DDL ready to copy into the project.\n *\n * Use case: refresh prod → dev pipeline. Most teams need to\n * pseudonymize PII before any non-prod role sees the data. This\n * command auto-generates a starter set of MASKING POLICY statements\n * + the ALTER TABLE ... ALTER COLUMN ... SET MASKING POLICY calls\n * to apply them.\n *\n * Output is intentionally **conservative**: every emitted policy has\n * `RETURN VAL` (no-op) when the current role is in `('PROD_ETL')` so\n * production keeps working as-is; every other role sees a hashed /\n * redacted value. Adjust the role allow-list before applying.\n */\nexport function anonymizeCommand(): Command {\n const cmd = new Command('anonymize');\n cmd\n .description('Generate MASKING POLICY DDL for PII columns detected in the project model.')\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to analyze.')\n .option(\n '--unmasked-role <name>',\n \"Role the unmasked value is visible to. Default 'PROD_ETL'.\",\n 'PROD_ETL',\n )\n .option('-o, --out <path>', 'Output file path. Default: ./anonymize.sql in CWD.')\n .action(async (opts) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const unmaskedRole = String(opts.unmaskedRole);\n const candidates = collectPiiColumns(model);\n if (candidates.length === 0) {\n console.error(\n 'No PII columns detected (heuristic on column names: email, phone, ssn, dob, …).',\n );\n console.error(\n 'If the schema has PII you know about, add a MASKING POLICY by hand and re-run lint to confirm.',\n );\n return;\n }\n const sql = renderAnonymizeSql(candidates, unmaskedRole);\n const outPath = opts.out ? path.resolve(String(opts.out)) : path.resolve('anonymize.sql');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, sql, 'utf8');\n console.error(`Wrote ${outPath} (${candidates.length} column(s), ${sql.length} bytes).`);\n console.error(\n 'Review the role allow-list (`unmaskedRole`) before applying. Default fully hides values from every role except the one passed in.',\n );\n });\n return cmd;\n}\n\ninterface PiiColumn {\n fqn: string;\n column: string;\n category: 'email' | 'phone' | 'name' | 'dob' | 'ssn' | 'address' | 'credit-card' | 'generic';\n}\n\n/**\n * Heuristic PII detector — matches column names against a curated\n * list of likely PII patterns. Same patterns the L012 lint rule\n * uses. We pick the masking strategy from the category.\n */\nfunction collectPiiColumns(model: readonly SnowflakeObject[]): PiiColumn[] {\n const out: PiiColumn[] = [];\n for (const o of model) {\n if (o.objectType !== 'TABLE') continue;\n const rec = o as unknown as Record<string, unknown>;\n const cols = rec.columns as Array<{ name: string }> | undefined;\n if (!Array.isArray(cols)) continue;\n const fqn = [o.fqn.database, o.fqn.schema, o.fqn.name].filter(Boolean).join('.');\n for (const c of cols) {\n const category = classify(c.name);\n if (category) out.push({ fqn, column: c.name, category });\n }\n }\n return out;\n}\n\nfunction classify(name: string): PiiColumn['category'] | undefined {\n const lower = name.toLowerCase();\n if (/(^|_)email(_|$)/.test(lower)) return 'email';\n if (/(^|_)(phone|mobile|cell)(_|$)/.test(lower)) return 'phone';\n if (/(^|_)(first_name|last_name|full_name|surname|given_name)(_|$)/.test(lower)) return 'name';\n if (/(^|_)(dob|birth_date|date_of_birth)(_|$)/.test(lower)) return 'dob';\n if (/(^|_)ssn(_|$)/.test(lower) || /(^|_)tax_id(_|$)/.test(lower)) return 'ssn';\n if (/(^|_)(address|street|zip_code|postal_code|postcode)(_|$)/.test(lower)) return 'address';\n if (/(^|_)(credit_card|card_number)(_|$)/.test(lower)) return 'credit-card';\n return undefined;\n}\n\nfunction renderAnonymizeSql(cols: PiiColumn[], unmaskedRole: string): string {\n const lines: string[] = [];\n lines.push(`-- Generated by \\`sdt anonymize\\`.`);\n lines.push(\n `-- Edit the role allow-list before applying. Default: only ${unmaskedRole} sees unmasked values.`,\n );\n lines.push('');\n // One reusable policy per category; the policies belong in a shared schema.\n const categoriesNeeded = new Set(cols.map((c) => c.category));\n for (const cat of categoriesNeeded) {\n lines.push(`-- Masking policy for ${cat} columns`);\n lines.push(\n `CREATE OR ALTER MASKING POLICY MASK_${cat.toUpperCase().replace(/-/g, '_')} AS (val STRING) RETURNS STRING ->`,\n );\n lines.push(` CASE`);\n lines.push(` WHEN CURRENT_ROLE() IN ('${unmaskedRole}') THEN val`);\n lines.push(` ELSE ${maskExpression(cat)}`);\n lines.push(` END;`);\n lines.push('');\n }\n lines.push('-- Apply policies to columns');\n for (const c of cols) {\n lines.push(\n `ALTER TABLE ${c.fqn} MODIFY COLUMN ${c.column} SET MASKING POLICY MASK_${c.category.toUpperCase().replace(/-/g, '_')};`,\n );\n }\n lines.push('');\n return lines.join('\\n') + '\\n';\n}\n\nfunction maskExpression(cat: PiiColumn['category']): string {\n switch (cat) {\n case 'email':\n return `REGEXP_REPLACE(val, '^(.).*(@.*)$', '\\\\\\\\1***\\\\\\\\2')`;\n case 'phone':\n return `'***-***-' || RIGHT(val, 4)`;\n case 'ssn':\n return `'***-**-' || RIGHT(val, 4)`;\n case 'credit-card':\n return `'****-****-****-' || RIGHT(val, 4)`;\n case 'dob':\n return `LEFT(val, 4) || '-XX-XX'`;\n case 'name':\n case 'address':\n case 'generic':\n default:\n return `SHA2(val, 256)`;\n }\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n","/**\n * `sdt safety` — inspect safety-finding codes.\n *\n * Subcommands:\n * sdt safety list — list every known finding code with a one-line summary\n * sdt safety explain <code> — deep explainer for a single code: why it is dangerous,\n * what cannot be reversed, safer alternatives, required gates\n *\n * The finding codes are stable identifiers attached to every `SafetyFinding`\n * the classifier emits during `sdt compare` / `sdt publish`. When the user\n * sees a finding they don't understand, they can copy the code and ask:\n *\n * sdt safety explain DROP_UNRECOVERABLE\n *\n * See `docs/UX_PLAYBOOK.md` §3 (dangerous-op UX) and\n * `docs/AI_FEATURES.md` use case C2.\n */\nimport { Command } from 'commander';\nimport { safety as safetyApi } from '@sdt-tools/core';\nimport type { FindingExplanation, SafetyFindingCode } from '@sdt-tools/core/safety';\nimport { logger } from '../util/logger.js';\n\nexport function safetyCommand(): Command {\n const cmd = new Command('safety');\n cmd.description(\n 'Inspect the safety-finding catalog. See `sdt safety list` and `sdt safety explain <code>`.',\n );\n\n cmd\n .command('list')\n .description('List every known finding code with category + one-line summary.')\n .option('--format <format>', 'Output format: table | json', 'table')\n .option(\n '--category <kind>',\n 'Filter to one category: unrecoverable | destructive | expensive | warning. Default: all.',\n )\n .action((opts: { format?: string; category?: string }) => {\n const codes = safetyApi.listFindingCodes();\n let entries = codes\n .map((c) => safetyApi.explainFinding(c))\n .filter((e): e is FindingExplanation => e !== undefined);\n if (opts.category) {\n const want = opts.category.toUpperCase();\n const valid = ['UNRECOVERABLE', 'DESTRUCTIVE', 'EXPENSIVE', 'WARNING'];\n if (!valid.includes(want)) {\n logger.error(\n `Unknown --category \"${opts.category}\". Use one of: ${valid.join(' | ').toLowerCase()}.`,\n );\n process.exitCode = 1;\n return;\n }\n entries = entries.filter((e) => e.category === want);\n }\n if ((opts.format ?? 'table') === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n logger.dim('(no entries match the filter)');\n return;\n }\n printList(entries);\n });\n\n cmd\n .command('explain')\n .description('Expand a finding code into a deep \"why this is dangerous\" page.')\n .argument('<code>', 'The finding code (e.g. DROP_UNRECOVERABLE, COLUMN_TYPE_CHANGE)')\n .option('--format <format>', 'Output format: text | json | markdown', 'text')\n .action((codeArg: string, opts: { format?: string }) => {\n const code = codeArg.toUpperCase() as SafetyFindingCode;\n const entry = safetyApi.explainFinding(code);\n if (!entry) {\n logger.error(`Unknown safety finding code: \"${codeArg}\"`);\n logger.dim(' Try: sdt safety list');\n process.exitCode = 1;\n return;\n }\n const format = (opts.format ?? 'text').toLowerCase();\n if (format === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n if (format === 'markdown') {\n process.stdout.write(renderMarkdown(entry) + '\\n');\n return;\n }\n printDeep(entry);\n });\n\n return cmd;\n}\n\nfunction printList(entries: readonly FindingExplanation[]): void {\n const byCategory = new Map<FindingExplanation['category'], FindingExplanation[]>();\n for (const e of entries) {\n const arr = byCategory.get(e.category) ?? [];\n arr.push(e);\n byCategory.set(e.category, arr);\n }\n const order: FindingExplanation['category'][] = [\n 'UNRECOVERABLE',\n 'DESTRUCTIVE',\n 'EXPENSIVE',\n 'WARNING',\n ];\n for (const cat of order) {\n const arr = byCategory.get(cat);\n if (!arr || arr.length === 0) continue;\n console.log(`# ${cat} (${arr.length})`);\n for (const e of arr) {\n console.log(` ${e.code}`);\n console.log(` ${e.title}`);\n console.log(` ${e.summary}`);\n }\n console.log('');\n }\n console.log('Use `sdt safety explain <code>` for the full per-finding write-up.');\n}\n\nfunction printDeep(entry: FindingExplanation): void {\n console.log(`${entry.code} [${entry.category}]`);\n console.log(entry.title);\n console.log('');\n console.log('Summary');\n console.log(` ${entry.summary}`);\n console.log('');\n console.log('Why this is dangerous');\n for (const line of wrap(entry.whyDangerous, 76)) {\n console.log(` ${line}`);\n }\n console.log('');\n console.log('What cannot be reversed');\n for (const item of entry.cannotBeReversed) console.log(` - ${item}`);\n console.log('');\n console.log('Safer alternatives');\n for (const item of entry.saferAlternatives) console.log(` - ${item}`);\n console.log('');\n if (entry.requiredGates.length > 0) {\n console.log('Required gates to allow this finding through');\n for (const g of entry.requiredGates) console.log(` - ${g}`);\n console.log('');\n }\n if (entry.example) {\n console.log('Example');\n console.log(` ${entry.example}`);\n }\n}\n\nfunction renderMarkdown(entry: FindingExplanation): string {\n const lines: string[] = [];\n lines.push(`## ${entry.code} — ${entry.title}`);\n lines.push('');\n lines.push(`**Category:** ${entry.category}`);\n lines.push('');\n lines.push(`**Summary:** ${entry.summary}`);\n lines.push('');\n lines.push('### Why this is dangerous');\n lines.push(entry.whyDangerous);\n lines.push('');\n lines.push('### What cannot be reversed');\n for (const item of entry.cannotBeReversed) lines.push(`- ${item}`);\n lines.push('');\n lines.push('### Safer alternatives');\n for (const item of entry.saferAlternatives) lines.push(`- ${item}`);\n if (entry.requiredGates.length > 0) {\n lines.push('');\n lines.push('### Required gates');\n for (const g of entry.requiredGates) lines.push(`- \\`${g}\\``);\n }\n if (entry.example) {\n lines.push('');\n lines.push('### Example');\n lines.push('```');\n lines.push(entry.example);\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\n/** Word-wrap a paragraph to fit `width` characters per line. */\nfunction wrap(text: string, width: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let current = '';\n for (const word of words) {\n if (current.length === 0) {\n current = word;\n } else if (current.length + 1 + word.length <= width) {\n current += ' ' + word;\n } else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines;\n}\n","/**\n * `sdt safer-alternative` — call the AI provider to suggest a safer DDL\n * alternative for a flagged-as-dangerous migration step.\n *\n * Composes `@sdt-tools/core/saferAlternative.suggestSaferAlternative` with the\n * configured AI provider (`@sdt-tools/core/ai.complete`). The CLI is the thin\n * adapter; all the prompt-building and parsing lives in core so the\n * VS Code CodeLens / MCP server / future hosts share the same behavior.\n *\n * Inputs (all surfaced as flags):\n * --code SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE)\n * --fqn Object FQN the finding refers to\n * --object-type Object type (e.g. TABLE, STREAM)\n * --reason Short reason from the safety classifier\n * --gate Optional SafetyGate (preserved on the suggestion)\n * --sql <path> Path to a file with the dangerous DDL (or \"-\" for stdin)\n * --context <path> Optional path to the surrounding source DDL\n * --intent <text> Optional human-authored intent notes\n * --format text | json (default text)\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, saferAlternative, type safety } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nexport function saferAlternativeCommand(): Command {\n const cmd = new Command('safer-alternative');\n cmd\n .description(\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (sdt ai status).',\n )\n .requiredOption('--code <code>', 'SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE).')\n .requiredOption('--fqn <fqn>', 'Object FQN the finding refers to.')\n .requiredOption('--object-type <type>', 'Object type (e.g. TABLE, VIEW, STREAM).')\n .requiredOption('--reason <text>', 'Short reason text from the safety classifier.')\n .option(\n '--gate <gate>',\n 'Optional SafetyGate the finding raised (e.g. REQUIRE_ALLOW_DROP_COLUMN).',\n )\n .option('--sql <path>', 'Path to a file with the dangerous DDL. Use \"-\" to read from stdin.')\n .option('--context <path>', 'Optional path to the surrounding source DDL.')\n .option('--intent <text>', 'Optional human-authored intent notes.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (opts) => {\n const dangerousSql = await readInput(\n opts.sql,\n '--sql is required (use a path or \"-\" for stdin).',\n );\n const contextSql = opts.context ? await fs.readFile(String(opts.context), 'utf8') : undefined;\n\n const finding: safety.SafetyFinding = {\n code: String(opts.code) as safety.SafetyFindingCode,\n category: 'DESTRUCTIVE',\n fqn: String(opts.fqn),\n objectType: String(opts.objectType) as safety.SafetyFinding['objectType'],\n reason: String(opts.reason),\n gate: opts.gate ? (String(opts.gate) as safety.SafetyGate) : undefined,\n };\n\n const result = await saferAlternative.suggestSaferAlternative(\n {\n finding,\n dangerousSql,\n contextSql,\n intentNotes: opts.intent ? String(opts.intent) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'safer-alternative',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n if (String(opts.format).toLowerCase() === 'json') {\n // Strip rawModelText from JSON output by default — it bloats the\n // payload for downstream tooling. Keep it accessible via --format text.\n const { rawModelText: _omit, ...keep } = result;\n console.log(JSON.stringify(keep, null, 2));\n return;\n }\n\n logger.success(\n `Confidence: ${result.confidence}${result.parseFailed ? ' (parse failed)' : ''}`,\n );\n logger.dim(`Reasoning: ${result.reasoning}`);\n if (result.alternativeSql) {\n console.log('');\n console.log('--- Proposed safer DDL ---');\n console.log(result.alternativeSql);\n } else {\n logger.warn('No safer alternative SQL was returned.');\n }\n if (result.requiredGates.length > 0) {\n logger.dim(`Required gates: ${result.requiredGates.join(', ')}`);\n }\n });\n return cmd;\n}\n\nasync function readInput(pathOrDash: unknown, missingMessage: string): Promise<string> {\n if (!pathOrDash) throw new Error(missingMessage);\n const p = String(pathOrDash);\n if (p === '-') {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n }\n return fs.readFile(p, 'utf8');\n}\n","/**\n * `sdt sketch <kind>` — generate idiomatic Snowflake DDL from a free-form\n * prose description via the configured AI provider.\n *\n * Composes `@sdt-tools/core/objectSketch.sketchToDdl` with `@sdt-tools/core/ai.complete`.\n * Output is always wrapped in a \"REVIEW BEFORE DEPLOY\" header so the user\n * never confuses model output with hand-authored DDL.\n *\n * Inputs:\n * <kind> table | view | materialized-view | stream | task\n * | dynamic-table | procedure | function | sequence\n * --description <text> Free-form description (or \"-\" to read from stdin)\n * --target <fqn> Optional target FQN (e.g. ANALYTICS.PUBLIC.ORDERS)\n * --context <text> Optional additional context\n * --out <path> Optional output file. Default: stdout.\n * --format <fmt> text | json. Default text (just the DDL).\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, objectSketch } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nconst KINDS = [\n 'table',\n 'view',\n 'materialized-view',\n 'stream',\n 'task',\n 'dynamic-table',\n 'procedure',\n 'function',\n 'sequence',\n] as const;\n\ntype Kind = (typeof KINDS)[number];\n\nexport function sketchCommand(): Command {\n const cmd = new Command('sketch');\n cmd\n .description(\n 'AI-assist: scaffold idiomatic Snowflake DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n )\n .argument('<kind>', `Object kind: ${KINDS.join(' | ')}`)\n .requiredOption('--description <text>', 'Free-form description. Use \"-\" to read from stdin.')\n .option('--target <fqn>', 'Target FQN (e.g. ANALYTICS.PUBLIC.ORDERS).')\n .option('--context <text>', 'Optional additional context (e.g. \"use role MERGE_OPS\").')\n .option('--out <path>', 'Output file. Default stdout.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (kindArg, opts) => {\n const kind = String(kindArg).toLowerCase() as Kind;\n if (!KINDS.includes(kind)) {\n throw new Error(`Unknown kind \"${kindArg}\". Use one of: ${KINDS.join(' | ')}`);\n }\n\n const description =\n String(opts.description) === '-' ? await readStdin() : String(opts.description);\n const targetFqn = opts.target ? splitFqn(String(opts.target)) : undefined;\n\n const result = await objectSketch.sketchToDdl(\n {\n description,\n objectKind: kind,\n targetFqn,\n additionalContext: opts.context ? String(opts.context) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'object-sketch',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n const output =\n String(opts.format).toLowerCase() === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined } /* strip raw for JSON */, null, 2)\n : result.generatedSql;\n\n if (opts.out) {\n await fs.writeFile(String(opts.out), output, 'utf8');\n logger.success(`Wrote ${String(opts.out)} (${output.length} bytes)`);\n } else {\n console.log(output);\n }\n\n // Surface assumptions on stderr so they're visible even when stdout\n // is redirected into a project file.\n if (result.assumptions.length > 0) {\n logger.dim('');\n logger.dim('Model assumptions:');\n for (const a of result.assumptions) logger.dim(` - ${a}`);\n }\n if (result.parseFailed) {\n logger.warn('Model output could not be parsed — see the raw text via --format json.');\n }\n });\n return cmd;\n}\n\nfunction splitFqn(fqn: string): { database?: string; schema?: string; name: string } {\n const parts = fqn.split('.');\n if (parts.length === 1) return { name: parts[0]! };\n if (parts.length === 2) return { schema: parts[0], name: parts[1]! };\n if (parts.length === 3) return { database: parts[0], schema: parts[1], name: parts[2]! };\n throw new Error(`Invalid --target \"${fqn}\": expected 1, 2, or 3 dot-separated parts.`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `sdt compare-profiles` — manage saved comparison profiles.\n *\n * A profile is \"Source X (connection|pac|project) → Target Y, with these\n * mapping rules\", persisted to `<cwd>/.sdt/compare-profiles.json`. The\n * eventual VS Code webview reads/writes the same store; this CLI gives\n * power-users the same affordances headlessly.\n *\n * Subcommands:\n * list — list all saved profiles (table or JSON)\n * show <id> — print one profile (table or JSON)\n * save — upsert a profile from a JSON file (--json-file <path>) or stdin\n * remove <id> — delete a profile\n * preview <id> — run `previewMatch` over the saved profile's\n * source + target endpoints and report counts +\n * examples of matched / source-only / target-only\n * FQNs. Catches typo'd schema names before a\n * full extract + diff round-trip.\n *\n * `preview` resolves each endpoint locally:\n * - kind=connection — reads the EE1 catalog cache at\n * `<root>/.sdt/cache/<reference>/catalog.msgpack` (legacy\n * `catalog.json` also accepted). Run\n * `sdt catalog refresh --connection <reference>` first.\n * - kind=pac — reads the `.sdtpac` archive at `reference`.\n * - kind=project — reads the `.sdtproj` at `reference`.\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog, compareProfiles, pac, project } from '@sdt-tools/core';\nimport type { FullyQualifiedName, SnowflakeObject } from '@sdt-tools/core/model';\nimport { logger } from '../util/logger.js';\n\nexport function compareProfilesCommand(): Command {\n const cmd = new Command('compare-profiles');\n cmd.description('Manage saved compare profiles (.sdt/compare-profiles.json).');\n\n cmd\n .command('list')\n .description('List every saved profile.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const all = await store.list();\n if (opts.json) {\n console.log(JSON.stringify(all, null, 2));\n return;\n }\n if (all.length === 0) {\n logger.dim('(no compare profiles saved yet)');\n logger.dim(` store: ${store.path}`);\n return;\n }\n logger.success(`${all.length} compare profile(s):`);\n for (const p of all) {\n console.log(` ${p.id.padEnd(24)} ${p.name}`);\n logger.dim(` source: ${p.source.kind}=${p.source.reference}`);\n logger.dim(` target: ${p.target.kind}=${p.target.reference}`);\n logger.dim(` mappings: ${p.mappings.length} updated: ${p.updatedAt}`);\n }\n });\n\n cmd\n .command('show')\n .description('Show one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const p = await store.get(String(id));\n if (!p) {\n logger.error(`No profile with id \"${id}\". Run \\`sdt compare-profiles list\\` to enumerate.`);\n process.exitCode = 1;\n return;\n }\n if (opts.json) {\n console.log(JSON.stringify(p, null, 2));\n return;\n }\n logger.success(`Profile: ${p.name} (${p.id})`);\n if (p.description) logger.dim(` ${p.description}`);\n logger.dim(\n ` source: ${p.source.kind}=${p.source.reference}${p.source.database ? ` db=${p.source.database}` : ''}${p.source.schema ? ` schema=${p.source.schema}` : ''}`,\n );\n logger.dim(\n ` target: ${p.target.kind}=${p.target.reference}${p.target.database ? ` db=${p.target.database}` : ''}${p.target.schema ? ` schema=${p.target.schema}` : ''}`,\n );\n logger.dim(` case-sensitive: ${p.caseSensitive ? 'yes' : 'no'}`);\n logger.dim(` rewrite-inside-strings: ${p.rewriteInsideStrings ? 'yes' : 'no'}`);\n logger.dim(` updatedAt: ${p.updatedAt}`);\n if (p.mappings.length === 0) {\n logger.dim(' mappings: (none — identity)');\n } else {\n logger.dim(` mappings (${p.mappings.length}):`);\n for (const m of p.mappings) logger.dim(` ${m.source} => ${m.target}`);\n }\n });\n\n cmd\n .command('save')\n .description('Upsert a profile from a JSON file or stdin.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json-file <path>', 'Path to a JSON file containing one profile. Use \"-\" for stdin.')\n .action(async (opts) => {\n if (!opts.jsonFile) {\n throw new Error('--json-file is required (use a path or \"-\" for stdin).');\n }\n const raw =\n String(opts.jsonFile) === '-'\n ? await readStdin()\n : await fs.readFile(String(opts.jsonFile), 'utf8');\n const parsed = JSON.parse(raw) as compareProfiles.CompareProfile;\n if (!parsed?.id || !parsed?.name || !parsed?.source || !parsed?.target) {\n throw new Error(\n 'Profile JSON must contain at minimum: id, name, source, target. mappings defaults to [].',\n );\n }\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const stamped = await store.upsert({ ...parsed, mappings: parsed.mappings ?? [] });\n logger.success(`Saved profile \"${stamped.name}\" (${stamped.id})`);\n logger.dim(` store: ${store.path}`);\n });\n\n cmd\n .command('remove')\n .description('Delete one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const removed = await store.remove(String(id));\n if (removed) {\n logger.success(`Removed profile \"${id}\".`);\n } else {\n logger.warn(`No profile with id \"${id}\" — nothing to remove.`);\n }\n });\n\n cmd\n .command('preview')\n .description(\n \"Preview which FQNs match between the profile's source and target. Local-only — no warehouse round-trip.\",\n )\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option(\n '--examples <n>',\n 'Max example FQNs to show per bucket in human output. Default 5.',\n (v) => parseInt(v, 10),\n 5,\n )\n .option('--json', 'Emit the full PreviewSummary as JSON.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const profile = await store.get(String(id));\n if (!profile) {\n logger.error(`No profile with id \"${id}\". Run \\`sdt compare-profiles list\\` to enumerate.`);\n process.exitCode = 1;\n return;\n }\n\n const root = String(opts.root);\n const source = await resolveEndpointFqns(profile.source, root);\n const target = await resolveEndpointFqns(profile.target, root);\n\n const summary = compareProfiles.previewMatch({\n source: source.fqns,\n target: target.fqns,\n mappings: profile.mappings,\n ...(profile.caseSensitive ? { caseSensitive: true } : {}),\n });\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n profile: { id: profile.id, name: profile.name },\n source: {\n kind: profile.source.kind,\n reference: profile.source.reference,\n count: source.fqns.length,\n },\n target: {\n kind: profile.target.kind,\n reference: profile.target.reference,\n count: target.fqns.length,\n },\n summary,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n logger.success(`Preview: ${profile.name} (${profile.id})`);\n logger.dim(\n ` source (${profile.source.kind}=${profile.source.reference}): ${source.fqns.length} object(s)${source.note ? ` — ${source.note}` : ''}`,\n );\n logger.dim(\n ` target (${profile.target.kind}=${profile.target.reference}): ${target.fqns.length} object(s)${target.note ? ` — ${target.note}` : ''}`,\n );\n console.log('');\n console.log(` matched: ${summary.matchedCount}`);\n console.log(` source-only: ${summary.sourceOnlyCount}`);\n console.log(` target-only: ${summary.targetOnlyCount}`);\n\n const exN = Math.max(0, Number(opts.examples));\n printBucket('matched', summary.matched, exN);\n printBucket('source-only', summary.sourceOnly, exN);\n printBucket('target-only', summary.targetOnly, exN);\n\n if (\n summary.matchedCount === 0 &&\n (summary.sourceOnlyCount > 0 || summary.targetOnlyCount > 0)\n ) {\n logger.warn(\"No FQNs matched — check the profile's scope and mapping rules.\");\n }\n });\n\n return cmd;\n}\n\ninterface EndpointResolution {\n fqns: FullyQualifiedName[];\n note?: string;\n}\n\nasync function resolveEndpointFqns(\n endpoint: compareProfiles.CompareProfile['source'],\n root: string,\n): Promise<EndpointResolution> {\n if (endpoint.kind === 'connection') {\n const cache = new catalog.CatalogCache({ root, connection: endpoint.reference });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0) {\n return {\n fqns: [],\n note: `empty catalog cache at ${cache.path} — run \\`sdt catalog refresh --connection ${endpoint.reference}\\` first`,\n };\n }\n return { fqns: fqnsFromSnapshot(snapshot, endpoint.database, endpoint.schema) };\n }\n if (endpoint.kind === 'pac') {\n const contents = await pac.readPac(endpoint.reference);\n return { fqns: fqnsFromObjects(contents.model, endpoint.database, endpoint.schema) };\n }\n // kind === 'project'\n const loaded = await project.loadProject(endpoint.reference);\n const model = await project.parseProjectModel(loaded);\n return { fqns: fqnsFromObjects(model, endpoint.database, endpoint.schema) };\n}\n\nfunction fqnsFromSnapshot(\n snapshot: catalog.CatalogSnapshot,\n databaseScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const db of snapshot.databases) {\n if (databaseScope && !sameId(db.database, databaseScope)) continue;\n for (const sc of db.schemas) {\n if (schemaScope && !sameId(sc.schema, schemaScope)) continue;\n for (const obj of sc.objects) {\n out.push({ database: obj.database, schema: obj.schema, name: obj.name });\n }\n }\n }\n return out;\n}\n\nfunction fqnsFromObjects(\n model: readonly SnowflakeObject[],\n databaseScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const obj of model) {\n if (databaseScope && !sameId(obj.fqn.database, databaseScope)) continue;\n if (schemaScope && !sameId(obj.fqn.schema, schemaScope)) continue;\n out.push(obj.fqn);\n }\n return out;\n}\n\nfunction printBucket(label: string, items: readonly string[], exampleN: number): void {\n if (items.length === 0) return;\n console.log('');\n console.log(\n ` ${label} examples (showing ${Math.min(exampleN, items.length)} of ${items.length}):`,\n );\n for (const fqn of items.slice(0, exampleN)) console.log(` ${fqn}`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `sdt explorer` — ASCII tree dump of the live db/schema/object hierarchy\n * for a connected target, read from the EE1 catalog cache.\n *\n * The eventual VS Code TreeDataProvider walks the same `treeForSnapshot`\n * shape; this CLI gives non-VS-Code users the same browsable view of the\n * cached catalog. No live queries are issued — the cache is read-only.\n * Run `sdt catalog refresh --connection <name>` first to populate it.\n *\n * Inputs:\n * --connection <name> Required. Connection profile name to load the cache for.\n * --root <path> Project root (where .sdt/cache/ lives). Default cwd.\n * --filter <query> Typeahead filter; case-insensitive substring match.\n * Keeps every ancestor of a leaf match.\n * --json Emit the tree as JSON instead of an ASCII tree.\n */\nimport { Command } from 'commander';\nimport { catalog, objectExplorer } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nexport function explorerCommand(): Command {\n const cmd = new Command('explorer');\n cmd\n .description(\n 'ASCII tree dump of the cached catalog for a connection. Run `sdt catalog refresh` first to populate.',\n )\n .requiredOption('--connection <name>', 'Connection profile name (the cache subfolder).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--filter <query>', 'Typeahead substring filter (case-insensitive).')\n .option(\n '--depth <n>',\n 'Truncate tree at depth N (0 = root only, 1 = +databases, 2 = +schemas, 3 = +object-groups, 4 = +objects). Default unlimited.',\n (v) => parseInt(v, 10),\n )\n .option('--json', 'Emit tree as JSON instead of ASCII.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n let tree = objectExplorer.treeForSnapshot(snapshot);\n if (opts.filter) tree = objectExplorer.filterTree(tree, String(opts.filter));\n if (typeof opts.depth === 'number') tree = objectExplorer.truncateTree(tree, opts.depth);\n\n if (snapshot.databases.length === 0) {\n logger.warn(`Catalog cache is empty for connection \"${opts.connection}\".`);\n logger.dim(` Cache file: ${cache.path}`);\n logger.dim(` Run \\`sdt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n\n if (opts.json) {\n console.log(JSON.stringify(tree, null, 2));\n return;\n }\n\n renderAsciiTree(tree);\n });\n return cmd;\n}\n\n/**\n * Render the explorer tree as an ASCII tree (├──, │, └──). Mirrors the\n * GNU `tree`(1) glyph set for familiarity. Root prints without a\n * connector; descendants get the standard branch glyphs.\n */\nfunction renderAsciiTree(root: objectExplorer.ExplorerNode): void {\n const desc = root.description ? ` (${root.description})` : '';\n console.log(`${root.label}${desc}`);\n const children = root.children ?? [];\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, '', i === children.length - 1);\n }\n}\n\nfunction renderChild(node: objectExplorer.ExplorerNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const desc = node.description ? ` (${node.description})` : '';\n console.log(`${prefix}${connector}${node.label}${desc}`);\n const children = node.children ?? [];\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, childPrefix, i === children.length - 1);\n }\n}\n","/**\n * `sdt catalog` — manage the per-connection catalog cache (EE1 substrate).\n *\n * sdt catalog refresh --connection <name> [--databases <csv>] [--concurrency <n>]\n * sdt catalog show --connection <name> [--json]\n * sdt catalog clear --connection <name>\n *\n * `refresh` opens a live Snowflake connection, discovers databases via\n * `SHOW DATABASES`, runs the bulk-scan SQL per database via the bounded\n * promise pool, and writes the assembled snapshot to\n * `<root>/.sdt/cache/<conn>/catalog.msgpack` (RES.1 — was `catalog.json`\n * before 2026-05-16; the cache reader still accepts the legacy form for\n * one major version). Schema fingerprints (`MAX(LAST_ALTERED)`) are\n * checked first; databases that haven't changed since the last refresh\n * are skipped.\n *\n * `show` reads the cache file and pretty-prints (or emits JSON).\n * `clear` deletes the cache file (and its parent dir if empty).\n *\n * Object Explorer (`sdt explorer`) and the eventual EE2 intellisense\n * provider both consume this cache.\n */\nimport { Command } from 'commander';\nimport { catalog } from '@sdt-tools/core';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\n\n/**\n * Built-in databases that almost no one wants in their cache. Pass\n * `--include-builtins` to keep them.\n */\nconst BUILTIN_DATABASES = new Set(['SNOWFLAKE', 'SNOWFLAKE_SAMPLE_DATA', 'UTIL_DB']);\n\ninterface ShowDatabasesRow {\n name?: string;\n NAME?: string;\n}\n\nexport function catalogCommand(): Command {\n const cmd = new Command('catalog');\n cmd.description(\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n );\n\n cmd\n .command('refresh')\n .description('Open the connection, scan every (non-builtin) database, write the catalog cache.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--databases <csv>', 'Comma-separated list. Default: every non-builtin database.')\n .option('--include-builtins', 'Include SNOWFLAKE / SNOWFLAKE_SAMPLE_DATA / UTIL_DB.', false)\n .option(\n '--concurrency <n>',\n 'Bounded-concurrency cap for the bulk-scan pool. Default 10.',\n '10',\n )\n .option('--no-fingerprint-skip', 'Force a full scan even when fingerprints are unchanged.')\n .action(async (opts) => {\n const profile = await getProfile(String(opts.connection));\n const conn = new SnowflakeConnection(profile);\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: profile.name,\n });\n\n logger.step(`Connecting to ${profile.account} as ${profile.auth.username}…`);\n await conn.connect();\n try {\n const dbs = await resolveDatabases(conn, opts);\n if (dbs.length === 0) {\n logger.warn('No databases to scan. Pass --databases or --include-builtins.');\n return;\n }\n logger.dim(\n `Scanning ${dbs.length} database(s) with concurrency ${Number(opts.concurrency)}.`,\n );\n\n const cached = await cache.get();\n const cachedByDb = new Map(cached.databases.map((d) => [d.database, d] as const));\n\n const concurrency = Math.max(1, Number(opts.concurrency) || 10);\n const fingerprintSkip = opts.fingerprintSkip !== false;\n\n const { results, errors } = await catalog.mapPool(\n dbs,\n async (db) => {\n // Cheap fingerprint probe first.\n let freshFingerprint: number | null = null;\n try {\n const fpRes = await conn.query<{ MAX_LAST_ALTERED: unknown }>(\n catalog.fingerprintSqlForDatabase(db),\n );\n freshFingerprint = catalog.parseFingerprintRow(fpRes.rows);\n } catch (err) {\n logger.warn(\n `fingerprint(${db}) failed; falling through to full scan: ${(err as Error).message}`,\n );\n }\n\n const cachedDb = cachedByDb.get(db);\n if (\n fingerprintSkip &&\n cachedDb &&\n cachedDb.fingerprint != null &&\n freshFingerprint != null &&\n catalog.isFresh(cachedDb.fingerprint, freshFingerprint)\n ) {\n logger.dim(` ${db}: fresh; reusing cache`);\n return { database: db, fingerprint: cachedDb.fingerprint, schemas: cachedDb.schemas };\n }\n\n const scanRes = await conn.query(catalog.bulkScanSqlForDatabase(db));\n const schemas = catalog.parseBulkScanRows(db, scanRes.rows);\n const fingerprint = freshFingerprint ?? null;\n logger.dim(\n ` ${db}: ${schemas.length} schemas / ${schemas.reduce((sum, s) => sum + s.objects.length, 0)} objects`,\n );\n return { database: db, fingerprint, schemas };\n },\n { concurrency },\n );\n\n for (const e of errors) {\n logger.warn(`scan failed for \"${dbs[e.index]}\": ${(e.error as Error).message}`);\n }\n\n const snapshot = catalog.refreshFingerprints({\n version: catalog.CATALOG_SNAPSHOT_VERSION,\n connection: profile.name,\n snapshotAt: new Date().toISOString(),\n fingerprint: null,\n databases: results.filter((r): r is NonNullable<typeof r> => !!r),\n });\n await cache.set(snapshot);\n\n logger.success(`Wrote ${snapshot.databases.length} databases to ${cache.path}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n cmd\n .command('show')\n .description('Pretty-print or JSON-dump the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of summary.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n if (opts.json) {\n console.log(JSON.stringify(snapshot, null, 2));\n return;\n }\n if (snapshot.databases.length === 0) {\n logger.warn(`Catalog cache is empty for \"${opts.connection}\".`);\n logger.dim(` Cache file: ${cache.path}`);\n logger.dim(` Run \\`sdt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n logger.success(`Snapshot for \"${snapshot.connection}\" — ${snapshot.snapshotAt}`);\n logger.dim(\n ` Top-level fingerprint: ${snapshot.fingerprint != null ? new Date(snapshot.fingerprint).toISOString() : '(none)'}`,\n );\n for (const db of snapshot.databases) {\n const objCount = db.schemas.reduce((sum, s) => sum + s.objects.length, 0);\n console.log(\n ` ${db.database.padEnd(32)} ${db.schemas.length} schemas / ${objCount} objects`,\n );\n }\n });\n\n cmd\n .command('clear')\n .description('Delete the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n await cache.clear();\n logger.success(`Cleared cache for \"${opts.connection}\".`);\n logger.dim(` was: ${cache.path}`);\n });\n\n return cmd;\n}\n\nasync function resolveDatabases(\n conn: SnowflakeConnection,\n opts: { databases?: unknown; includeBuiltins?: unknown },\n): Promise<string[]> {\n if (opts.databases) {\n return String(opts.databases)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n const res = await conn.query<ShowDatabasesRow>('SHOW DATABASES');\n const names = res.rows.map((r) => String(r.name ?? r.NAME ?? '')).filter(Boolean);\n if (opts.includeBuiltins) return names;\n return names.filter((n) => !BUILTIN_DATABASES.has(n.toUpperCase()));\n}\n","/**\n * `sdt exec <file.sql> --profiles <list>` — AUTH.3.\n *\n * Runs a SQL script on one or more connection profiles in parallel and\n * prints a merged report. Guarded against any profile whose name matches\n * the word \"prod\" or \"production\" (case-insensitive) unless `--yes` is\n * passed.\n *\n * Mirrors `Databricks/packages/cli/src/commands/exec.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport { getProfile, SnowflakeConnection } from '@sdt-tools/core/connection';\nimport { queryExecution } from '@sdt-tools/core';\n\nexport interface ExecResult {\n profile: string;\n status: 'success' | 'error';\n rowsAffected?: number;\n durationMs: number;\n error?: string;\n}\n\nexport type ExecFn = (\n profile: string,\n sql: string,\n timeoutMs: number,\n) => Promise<Omit<ExecResult, 'profile' | 'durationMs'>>;\n\nconst PROD_PATTERN = /\\bprod(uction)?\\b/i;\n\nfunction isProductionProfile(name: string): boolean {\n return PROD_PATTERN.test(name);\n}\n\nasync function runOnProfile(\n execFn: ExecFn,\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<ExecResult> {\n const start = Date.now();\n try {\n const res = await execFn(profile, sql, timeoutMs);\n return { ...res, profile, durationMs: Date.now() - start };\n } catch (err) {\n return {\n profile,\n status: 'error',\n durationMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction renderText(results: ExecResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.status === 'success') {\n const rows = r.rowsAffected !== undefined ? ` (${r.rowsAffected} rows)` : '';\n lines.push(` ${r.profile}: ✓${rows} — ${(r.durationMs / 1000).toFixed(1)}s`);\n } else {\n lines.push(` ${r.profile}: ✗ ${r.error ?? 'unknown error'}`);\n }\n }\n const total = results.length;\n const succeeded = results.filter((r) => r.status === 'success').length;\n lines.push(`\\n${succeeded}/${total} profiles succeeded.`);\n return lines.join('\\n');\n}\n\n/**\n * Wire to the real Snowflake connection layer:\n * 1. Resolve the named profile (`~/.sdt/profiles.json`).\n * 2. Open a connection; on failure surface the underlying SDK error.\n * 3. Split the SQL via the shared `queryExecution.splitStatements`\n * (string-/comment-/dollar-quote-aware) and run each statement\n * sequentially through `SnowflakeConnection.query`. We do NOT\n * `failFast` so a script with N statements surfaces every error.\n * 4. Aggregate: success iff every statement succeeded; the first\n * error's message becomes the profile-level error. Total\n * `rowsAffected` is the sum of rowCount across statements.\n *\n * Injectable for tests via the `execFn` parameter on `execCommand`.\n */\nasync function defaultExecFn(\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<Omit<ExecResult, 'profile' | 'durationMs'>> {\n const profileObj = await getProfile(profile);\n const conn = new SnowflakeConnection(profileObj);\n await conn.connect();\n try {\n const timeoutSeconds = Math.max(1, Math.ceil(timeoutMs / 1000));\n const runner: queryExecution.QueryRunner = {\n executeStatement: async (statement: string) => {\n const result = await conn.query(statement, { timeoutSeconds });\n return {\n rows: result.rows as Record<string, unknown>[],\n durationMs: result.durationMs,\n };\n },\n };\n const result = await queryExecution.executeStatements(sql, runner, {\n failFast: false,\n toolName: 'sdt',\n });\n const firstError = result.statements.find((s) => s.error);\n if (firstError && firstError.error) {\n throw new Error(firstError.error.message);\n }\n const rowsAffected = result.statements.reduce((acc, s) => acc + (s.rowCount ?? 0), 0);\n return { status: 'success', rowsAffected };\n } finally {\n await conn.disconnect().catch(() => {\n /* best-effort cleanup */\n });\n }\n}\n\nexport function execCommand(execFn: ExecFn = defaultExecFn): Command {\n const cmd = new Command('exec');\n cmd\n .description('Run a SQL script on one or more connection profiles in parallel.')\n .argument('<file>', 'Path to the .sql file to execute.')\n .requiredOption('--profiles <list>', 'Comma-separated connection profile names.')\n .option('--yes', 'Confirm execution against production profiles without prompting.')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--timeout <ms>', 'Per-profile timeout in milliseconds.', '30000')\n .action(async (file: string, opts) => {\n const profiles = (opts.profiles as string)\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (profiles.length === 0) throw new Error('--profiles must list at least one profile.');\n\n const prodProfiles = profiles.filter(isProductionProfile);\n if (prodProfiles.length > 0 && !opts.yes) {\n throw new Error(\n `Profile(s) look like production: ${prodProfiles.join(', ')}. ` +\n `Pass --yes to confirm.`,\n );\n }\n\n let sql: string;\n try {\n sql = await fs.readFile(file, 'utf8');\n } catch {\n throw new Error(`Cannot read file: ${file}`);\n }\n if (!sql.trim()) throw new Error(`File is empty: ${file}`);\n\n const timeoutMs = parseInt(String(opts.timeout ?? '30000'), 10);\n const results = await Promise.all(\n profiles.map((p) => runOnProfile(execFn, p, sql, timeoutMs)),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n const failed = results.filter((r) => r.status === 'error').length;\n process.stdout.write(\n JSON.stringify(\n {\n results,\n summary: {\n total: results.length,\n succeeded: results.length - failed,\n failed,\n },\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n process.stdout.write(renderText(results) + '\\n');\n });\n return cmd;\n}\n","/**\n * `sdt search <pattern> --profiles <list|all>` — AUTH.4.\n *\n * Finds objects whose name matches a pattern across one or more connection\n * profiles. Surfaces presence/absence drift: if an object exists in some\n * profiles but not others, those profiles are flagged.\n *\n * The search is case-insensitive substring match by default; --exact\n * switches to exact name match; --type filters by objectType.\n *\n * Mirrors `Databricks/packages/cli/src/commands/search.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { catalog } from '@sdt-tools/core';\n\nexport interface SearchMatch {\n profile: string;\n fqn: string;\n objectType: string;\n}\n\nexport interface SearchResult {\n profile: string;\n matches: SearchMatch[];\n error?: string;\n}\n\nexport interface SearchFnOptions {\n exact: boolean;\n objectType?: string;\n /** Project / cache root. Defaults to `process.cwd()`. */\n root?: string;\n}\n\nexport type SearchFn = (\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n) => Promise<SearchMatch[]>;\n\nfunction buildDriftReport(results: SearchResult[]): string {\n const allFqns = new Set<string>();\n const byFqn = new Map<string, Set<string>>();\n for (const r of results) {\n if (r.error) continue;\n for (const m of r.matches) {\n allFqns.add(m.fqn);\n if (!byFqn.has(m.fqn)) byFqn.set(m.fqn, new Set());\n byFqn.get(m.fqn)!.add(r.profile);\n }\n }\n const successProfiles = results.filter((r) => !r.error).map((r) => r.profile);\n const driftLines: string[] = [];\n for (const fqn of allFqns) {\n const present = byFqn.get(fqn)!;\n if (present.size < successProfiles.length) {\n const absent = successProfiles.filter((p) => !present.has(p));\n driftLines.push(\n ` DRIFT ${fqn} [present: ${[...present].join(', ')} absent: ${absent.join(', ')}]`,\n );\n }\n }\n return driftLines.join('\\n');\n}\n\nfunction renderText(results: SearchResult[], showDrift: boolean): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.error) {\n lines.push(`[${r.profile}] ERROR: ${r.error}`);\n continue;\n }\n if (r.matches.length === 0) {\n lines.push(`[${r.profile}] no matches`);\n } else {\n for (const m of r.matches) {\n lines.push(`[${r.profile}] ${m.fqn} (${m.objectType})`);\n }\n }\n }\n if (showDrift) {\n const drift = buildDriftReport(results);\n if (drift) {\n lines.push('');\n lines.push('--- Drift detected ---');\n lines.push(drift);\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadProfileNames(profilesOpt: string, profilesDir: string): Promise<string[]> {\n if (profilesOpt.toLowerCase() !== 'all') {\n return profilesOpt\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n }\n // Scan profiles directory for known profile files\n try {\n const entries = await fs.readdir(profilesDir);\n return entries\n .filter((e) => e.endsWith('.json') || e.endsWith('.toml'))\n .map((e) => path.basename(e, path.extname(e)));\n } catch {\n return [];\n }\n}\n\n/**\n * Wire to the on-disk catalog cache (`<root>/.sdt/cache/<profile>/catalog.msgpack`\n * written by `sdt catalog refresh` / `sdt extract --write-catalog-cache`).\n *\n * 1. Open `catalog.CatalogCache({root, connection: profile})`.\n * 2. Read the snapshot — `get()` returns an empty snapshot when the\n * file is absent / corrupt / version-mismatched.\n * 3. If the snapshot is empty, surface an actionable error naming\n * the expected file path and the two commands that populate it.\n * 4. Walk every (database, schema, object), filter by `--type`, then\n * match the name (case-insensitive substring by default, exact\n * when `--exact` is set), and return `SearchMatch[]` with the\n * fully-qualified `database.schema.name`.\n *\n * Injectable for tests via the `searchFn` parameter on `searchCommand`.\n */\nasync function defaultSearchFn(\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n): Promise<SearchMatch[]> {\n const root = opts.root ?? process.cwd();\n const cache = new catalog.CatalogCache({ root, connection: profile });\n const snapshot = await cache.get();\n if (snapshot.databases.length === 0) {\n throw new Error(\n `No catalog cache for profile \"${profile}\" at ${cache.path}. ` +\n `Run \\`sdt catalog refresh --connection ${profile} --root ${root}\\` ` +\n `or \\`sdt extract --connection ${profile} --output ${root} --write-catalog-cache\\` first.`,\n );\n }\n const needle = pattern.toLowerCase();\n const typeFilter = opts.objectType ? opts.objectType.toUpperCase() : undefined;\n const matches: SearchMatch[] = [];\n for (const db of snapshot.databases) {\n for (const schema of db.schemas) {\n for (const obj of schema.objects) {\n if (typeFilter && obj.objectType !== typeFilter) continue;\n const name = obj.name.toLowerCase();\n const hit = opts.exact ? name === needle : name.includes(needle);\n if (hit) {\n matches.push({\n profile,\n fqn: `${obj.database}.${obj.schema}.${obj.name}`,\n objectType: obj.objectType,\n });\n }\n }\n }\n }\n return matches;\n}\n\nexport function searchCommand(searchFn: SearchFn = defaultSearchFn): Command {\n const cmd = new Command('search');\n cmd\n .description('Find objects matching a name pattern across one or more connection profiles.')\n .argument('<pattern>', 'Name pattern to search for (case-insensitive substring).')\n .requiredOption(\n '--profiles <list|all>',\n 'Comma-separated profile names, or \"all\" to scan every configured profile.',\n )\n .option('--exact', 'Exact name match instead of substring.', false)\n .option('--type <objectType>', 'Filter results to a specific object type (e.g. TABLE, VIEW).')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option(\n '--profiles-dir <dir>',\n 'Directory to scan when --profiles all is used.',\n path.join(os.homedir(), '.sdt', 'connections'),\n )\n .option(\n '--root <dir>',\n 'Project / cache root containing the .sdt/cache directory. Default: cwd.',\n process.cwd(),\n )\n .option('--no-drift', 'Suppress the drift section in text output.')\n .action(async (pattern: string, opts) => {\n const profiles = await loadProfileNames(opts.profiles as string, opts.profilesDir as string);\n if (profiles.length === 0) {\n throw new Error(\n opts.profiles.toLowerCase() === 'all'\n ? `No profiles found in ${opts.profilesDir}. Run \\`sdt connection add\\` first.`\n : '--profiles must list at least one profile.',\n );\n }\n\n const results: SearchResult[] = await Promise.all(\n profiles.map(async (p) => {\n try {\n const matches = await searchFn(p, pattern, {\n exact: opts.exact as boolean,\n objectType: opts.type as string | undefined,\n root: opts.root as string,\n });\n return { profile: p, matches };\n } catch (err) {\n return {\n profile: p,\n matches: [],\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(results, null, 2) + '\\n');\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n const text = renderText(results, opts.drift !== false);\n process.stdout.write(text ? text + '\\n' : 'No results.\\n');\n });\n return cmd;\n}\n","/**\n * `sdt query-log` — AUTH.5 local query log CLI.\n *\n * Subcommands:\n * sdt query-log list [--profile <p>] [--limit N] [--format text|json]\n * sdt query-log show <id> [--format text|json|sql]\n * sdt query-log add <sql> --profile <p> [--status success|error] [--store <path>]\n * sdt query-log clear [--profile <p>] [--yes]\n *\n * The log is stored at `~/.sdt/query-log.json` (override with --store).\n * EE3 will call `appendEntry()` on the substrate directly when a query\n * is executed. This CLI surfaces it for ad-hoc review + rerun.\n *\n * Mirrors `Databricks/packages/cli/src/commands/query-log.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { queryLog } from '@sdt-tools/core';\n\nconst DEFAULT_STORE = path.join(os.homedir(), '.sdt', 'query-log.json');\n\nasync function loadStore(storePath: string): Promise<queryLog.QueryLogStore> {\n try {\n const raw = await fs.readFile(storePath, 'utf8');\n return queryLog.QueryLogStore.deserialize(JSON.parse(raw));\n } catch {\n return new queryLog.QueryLogStore();\n }\n}\n\nasync function saveStore(storePath: string, store: queryLog.QueryLogStore): Promise<void> {\n await fs.mkdir(path.dirname(storePath), { recursive: true });\n await fs.writeFile(storePath, JSON.stringify(store.serialize(), null, 2), 'utf8');\n}\n\nexport function queryLogCommand(): Command {\n const cmd = new Command('query-log');\n cmd.description('Browse and manage the local query log from the EE3 query window (AUTH.5).');\n\n cmd\n .command('list')\n .description('List recent query log entries (newest first).')\n .option('--profile <p>', 'Filter to a specific connection profile.')\n .option('--limit <n>', 'Maximum entries to show (default 100).', '100')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n const store = await loadStore(opts.store as string);\n const entries = store.listEntries({\n profile: opts.profile as string | undefined,\n limit: parseInt(String(opts.limit ?? '100'), 10),\n });\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n process.stdout.write('No query log entries.\\n');\n return;\n }\n for (const e of entries) {\n const when = e.executedAt.slice(0, 19).replace('T', ' ');\n const dur = e.durationMs !== undefined ? ` ${e.durationMs}ms` : '';\n const rows = e.rowCount !== undefined ? ` ${e.rowCount} rows` : '';\n const status = e.status === 'error' ? ' ✗' : ' ✓';\n const sql = e.sql.replace(/\\s+/g, ' ').slice(0, 80);\n process.stdout.write(`[${e.id}] ${when} [${e.profile}]${status}${dur}${rows} ${sql}\\n`);\n }\n });\n\n cmd\n .command('show <id>')\n .description('Show a single query log entry by id.')\n .option('--format <fmt>', 'text | json | sql (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (id: string, opts) => {\n const store = await loadStore(opts.store as string);\n const entry = store.getEntry(id);\n if (!entry) throw new Error(`No entry with id '${id}'.`);\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'sql') {\n process.stdout.write(entry.sql + '\\n');\n return;\n }\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`id: ${entry.id}\\n`);\n process.stdout.write(`profile: ${entry.profile}\\n`);\n process.stdout.write(`executed: ${entry.executedAt}\\n`);\n process.stdout.write(`status: ${entry.status}\\n`);\n if (entry.durationMs !== undefined) process.stdout.write(`duration: ${entry.durationMs}ms\\n`);\n if (entry.rowCount !== undefined) process.stdout.write(`rows: ${entry.rowCount}\\n`);\n if (entry.error) process.stdout.write(`error: ${entry.error}\\n`);\n process.stdout.write(`\\n${entry.sql}\\n`);\n });\n\n cmd\n .command('add <sql>')\n .description('Manually append a query to the log (used by EE3 and for testing).')\n .requiredOption('--profile <p>', 'Connection profile the query was run against.')\n .option('--status <s>', 'success | error (default success).', 'success')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (sql: string, opts) => {\n if (opts.status !== 'success' && opts.status !== 'error') {\n throw new Error(`--status must be success or error, got: ${opts.status}`);\n }\n const store = await loadStore(opts.store as string);\n const entry = store.appendEntry({\n profile: opts.profile as string,\n sql,\n executedAt: new Date().toISOString(),\n status: opts.status as 'success' | 'error',\n });\n await saveStore(opts.store as string, store);\n process.stdout.write(`Added entry ${entry.id}.\\n`);\n });\n\n cmd\n .command('clear')\n .description('Remove query log entries.')\n .option('--profile <p>', 'Remove only entries for this profile (omit for all).')\n .option('--yes', 'Skip confirmation prompt.')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n if (!opts.yes) {\n const target = opts.profile ? `profile '${opts.profile as string}'` : 'all profiles';\n throw new Error(`Pass --yes to confirm clearing the query log for ${target}.`);\n }\n const store = await loadStore(opts.store as string);\n const removed = store.clearEntries(opts.profile as string | undefined);\n await saveStore(opts.store as string, store);\n process.stdout.write(`Cleared ${removed} entries.\\n`);\n });\n\n return cmd;\n}\n"],"mappings":"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","names":["project","Command","Command","path","fs","Command","Command","path","fs","path","fs","Command","getProfile","SnowflakeConnection","wrap","fs","getProfile","SnowflakeConnection","Command","path","fs","assessment","path","fs","Command","CompareEngine","LiveSource","compileSlice","ai","safety","getProfile","SnowflakeConnection","Command","path","pac","getProfile","SnowflakeConnection","LiveSource","safety","CompareEngine","compileSlice","fs","ai","bodyReport","Command","path","readPac","CompareEngine","LiveSource","getProfile","SnowflakeConnection","loadProject","ModelSource","Command","getProfile","SnowflakeConnection","loadProject","path","pac","readPac","LiveSource","CompareEngine","fs","path","Command","catalog","Command","path","catalog","fs","report","Command","getProfile","SnowflakeConnection","Command","getProfile","SnowflakeConnection","Command","fs","path","Command","compare","project","ai","ai","Command","compare","path","fs","project","fs","path","Command","getProfile","SnowflakeConnection","Command","path","entries","fs","getProfile","SnowflakeConnection","Command","pac","fs","path","Command","fs","path","Command","CompareEngine","PacSource","ProjectSource","ScriptGenerator","colorizeMigrationScript","mergeDeployOptions","loadProject","readPac","safety","Command","CompareEngine","mergeDeployOptions","readPac","loadProject","ScriptGenerator","safety","header","path","fs","colorizeMigrationScript","PacSource","ProjectSource","fs","Command","getProfile","SnowflakeConnection","SnowflakeExecutor","fs","path","Command","getProfile","SnowflakeConnection","SnowflakeExecutor","loadProject","fs","path","Command","pac","project","fs","path","Command","model","loadModel","focus","direction","fmt","payload","pac","project","lineage","fs","path","Command","pac","project","Command","loadModel","path","fs","pac","project","fs","path","Command","ai","pac","project","Command","loadModel","safety","fs","path","ai","pac","project","fs","path","Command","pac","project","review","Command","loadModel","review","emit","pac","project","path","fs","fs","path","Command","Command","fs","path","splitStatements","fs","path","Command","CompareEngine","PacSource","ProjectSource","safety","pac","project","review","Command","CompareEngine","PacSource","ProjectSource","safety","loadModel","review","path","fs","pac","project","fs","path","Command","fs","path","Command","pac","project","loadModel","Command","Command","renderMarkdown","fs","Command","ai","Command","fs","ai","fs","Command","ai","Command","ai","fs","fs","Command","catalog","pac","project","Command","readStdin","fs","catalog","pac","project","Command","catalog","Command","catalog","Command","catalog","getProfile","SnowflakeConnection","Command","getProfile","SnowflakeConnection","catalog","Command","fs","getProfile","SnowflakeConnection","result","Command","fs","path","catalog","renderText","Command","fs","os","path"]}
|