@hawkeyexl/manni 0.3.0 → 1.0.0
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/{chunk-BKJOQHWN.js → chunk-HECVSJOR.js} +36 -2
- package/dist/chunk-HECVSJOR.js.map +1 -0
- package/dist/{chunk-7M2YOXVG.js → chunk-L7HN3AWA.js} +1070 -755
- package/dist/chunk-L7HN3AWA.js.map +1 -0
- package/dist/cli.js +71 -11
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +2 -2
- package/dist/index.d.ts +275 -115
- package/dist/index.js +31 -23
- package/package.json +1 -1
- package/dist/chunk-7M2YOXVG.js.map +0 -1
- package/dist/chunk-BKJOQHWN.js.map +0 -1
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
shouldColor,
|
|
40
40
|
supportedExtensions,
|
|
41
41
|
toJsonText
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-L7HN3AWA.js";
|
|
43
43
|
|
|
44
44
|
// src/shared/run.ts
|
|
45
45
|
import { realpathSync } from "node:fs";
|
|
@@ -425,6 +425,11 @@ function buildProgram() {
|
|
|
425
425
|
"-f, --format <format>",
|
|
426
426
|
`output: ${REPORT_FORMATS.join(" | ")}`,
|
|
427
427
|
"pretty"
|
|
428
|
+
).option(
|
|
429
|
+
"--collection <name>",
|
|
430
|
+
"configured collection to run over; repeatable",
|
|
431
|
+
collect,
|
|
432
|
+
[]
|
|
428
433
|
).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("-q, --quiet", "in pretty output, hide passing files").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "check files .gitignore covers").option(
|
|
429
434
|
"--offline",
|
|
430
435
|
"never fetch a remote schema; resolve URL refs from the schema cache"
|
|
@@ -472,6 +477,11 @@ function buildProgram() {
|
|
|
472
477
|
exts,
|
|
473
478
|
exclude: options.exclude,
|
|
474
479
|
as: options.as,
|
|
480
|
+
// Straight through: commander gives `[]` when the flag was never
|
|
481
|
+
// typed, and the core reads an empty list as every declared
|
|
482
|
+
// collection. Refusing paths beside it, and refusing it with no
|
|
483
|
+
// config, is `resolveRunConfig`'s job, before the walk.
|
|
484
|
+
collections: options.collection,
|
|
475
485
|
...configOption(options.config),
|
|
476
486
|
onConfigLoaded: reportConfig(
|
|
477
487
|
!isMachineFormat(format),
|
|
@@ -528,6 +538,11 @@ function buildProgram() {
|
|
|
528
538
|
"-f, --format <format>",
|
|
529
539
|
`output: ${COMMON_FORMATS.join(" | ")}`,
|
|
530
540
|
"pretty"
|
|
541
|
+
).option(
|
|
542
|
+
"--collection <name>",
|
|
543
|
+
"configured collection to run over; repeatable",
|
|
544
|
+
collect,
|
|
545
|
+
[]
|
|
531
546
|
).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option(
|
|
532
547
|
"-q, --quiet",
|
|
533
548
|
"in pretty output, hide files where every requested field is unset"
|
|
@@ -563,6 +578,7 @@ function buildProgram() {
|
|
|
563
578
|
as: options.as,
|
|
564
579
|
exclude: options.exclude,
|
|
565
580
|
exts,
|
|
581
|
+
collections: options.collection,
|
|
566
582
|
...configOption(options.config),
|
|
567
583
|
onConfigLoaded: reportConfig(format === "pretty", process.cwd()),
|
|
568
584
|
stdinContent,
|
|
@@ -627,6 +643,11 @@ function buildProgram() {
|
|
|
627
643
|
"-f, --format <format>",
|
|
628
644
|
`output: ${QUERY_FORMATS.join(" | ")} (github, sarif, junit need --check)`,
|
|
629
645
|
"pretty"
|
|
646
|
+
).option(
|
|
647
|
+
"--collection <name>",
|
|
648
|
+
"configured collection to run over; repeatable",
|
|
649
|
+
collect,
|
|
650
|
+
[]
|
|
630
651
|
).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "load files .gitignore covers").option(
|
|
631
652
|
"--offline",
|
|
632
653
|
"accepted and ignored: query resolves schemas from disk and built-ins, never the network"
|
|
@@ -702,6 +723,7 @@ function buildProgram() {
|
|
|
702
723
|
as: options.as,
|
|
703
724
|
exclude: options.exclude,
|
|
704
725
|
exts,
|
|
726
|
+
collections: options.collection,
|
|
705
727
|
...configOption(options.config),
|
|
706
728
|
onConfigLoaded: reportConfig(format === "pretty", process.cwd()),
|
|
707
729
|
stdinContent,
|
|
@@ -793,6 +815,11 @@ function buildProgram() {
|
|
|
793
815
|
"-f, --format <format>",
|
|
794
816
|
`output: ${FILL_FORMATS.join(" | ")}`,
|
|
795
817
|
"pretty"
|
|
818
|
+
).option(
|
|
819
|
+
"--collection <name>",
|
|
820
|
+
"configured collection to run over; repeatable",
|
|
821
|
+
collect,
|
|
822
|
+
[]
|
|
796
823
|
).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option(
|
|
797
824
|
"-q, --quiet",
|
|
798
825
|
"in pretty output, hide files with nothing written and nothing required left undone"
|
|
@@ -841,6 +868,7 @@ function buildProgram() {
|
|
|
841
868
|
exts,
|
|
842
869
|
exclude: options.exclude,
|
|
843
870
|
as: options.as,
|
|
871
|
+
collections: options.collection,
|
|
844
872
|
...configOption(options.config),
|
|
845
873
|
// With `-` the filled document owns stdout, so the notice is a
|
|
846
874
|
// diagnostic there just as the report is.
|
|
@@ -934,6 +962,11 @@ function buildProgram() {
|
|
|
934
962
|
"-f, --format <format>",
|
|
935
963
|
`output: ${COMMON_FORMATS.join(" | ")}`,
|
|
936
964
|
"pretty"
|
|
965
|
+
).option(
|
|
966
|
+
"--collection <name>",
|
|
967
|
+
"configured collection to run over; repeatable",
|
|
968
|
+
collect,
|
|
969
|
+
[]
|
|
937
970
|
).option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "scan files .gitignore covers").option(
|
|
938
971
|
"--offline",
|
|
939
972
|
"accepted and ignored: infer loads no schema and no provider"
|
|
@@ -962,6 +995,7 @@ function buildProgram() {
|
|
|
962
995
|
exts,
|
|
963
996
|
exclude: options.exclude,
|
|
964
997
|
as: options.as,
|
|
998
|
+
collections: options.collection,
|
|
965
999
|
...configOption(options.config),
|
|
966
1000
|
onConfigLoaded: reportConfig(format === "pretty", process.cwd()),
|
|
967
1001
|
stdinContent,
|
|
@@ -1047,4 +1081,4 @@ export {
|
|
|
1047
1081
|
runIfMain,
|
|
1048
1082
|
buildProgram
|
|
1049
1083
|
};
|
|
1050
|
-
//# sourceMappingURL=chunk-
|
|
1084
|
+
//# sourceMappingURL=chunk-HECVSJOR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/run.ts","../src/meta/cli.ts","../src/meta/reporters/infer.ts"],"sourcesContent":["/**\n * Running a commander program as a bin.\n *\n * Every entry point (`manni`, and `docmeta` for existing scripts) is the same\n * three lines: build the program, parse, and turn what escapes into an exit\n * code. Keeping that here means the exit-code contract (0 ok, 1 findings, 2\n * operational/usage) is written once, and the stderr prefix follows the bin\n * that was actually run.\n */\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { CommanderError, type Command } from \"commander\";\nimport { ToolError } from \"./errors.js\";\nimport { programName, setProgramName } from \"./program-name.js\";\n\n/** Report an operational error on stderr and exit 2. */\nexport function fail(err: unknown): never {\n const msg =\n err instanceof ToolError\n ? err.message\n : `Unexpected error: ${(err as Error).message}`;\n process.stderr.write(`${programName()}: ${msg}\\n`);\n process.exit(2);\n}\n\nexport async function runProgram(\n program: Command,\n argv: string[] = process.argv,\n): Promise<void> {\n setProgramName(program.name());\n try {\n await program.parseAsync(argv);\n } catch (err) {\n // `exitOverride()` makes commander throw on every terminating condition,\n // including the successful ones. Branch on `err.exitCode`, not on a list of\n // code strings: `--help` is `commander.helpDisplayed`, `-V` is\n // `commander.version`, and `help get` is a third code, `commander.help` —\n // all carrying exitCode 0, and a hand-written list would eventually miss\n // one and turn a success into a usage error.\n if (err instanceof CommanderError) {\n // Say nothing. `Command.error()` has already written the message and the\n // after-error hint; `fail()` would add \"Unexpected error: …\" on top,\n // because a CommanderError is not a ToolError.\n //\n // `process.exitCode`, not `process.exit()`: Node does not flush queued\n // async stderr writes on `process.exit`, which truncates the very message\n // the user needs.\n process.exitCode = err.exitCode === 0 ? 0 : 2;\n return;\n }\n throw err;\n }\n}\n\n/**\n * Whether `moduleUrl` is the file Node was asked to run.\n *\n * Pass the entry file's own `import.meta.url`. After bundling, shared code\n * lands in a chunk whose URL is never argv[1], so this cannot read\n * `import.meta.url` itself.\n */\nexport function isMainModule(moduleUrl: string): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n return realpathSync(entry) === fileURLToPath(moduleUrl);\n } catch {\n return false;\n }\n}\n\n/** Run `build()` as a bin when `moduleUrl` is the entry, and not when imported. */\nexport function runIfMain(moduleUrl: string, build: () => Command): void {\n if (!isMainModule(moduleUrl)) return;\n runProgram(build()).catch(fail);\n}\n","/**\n * docmeta CLI. Thin commander wrapper over the command cores. Follows clig.dev:\n * primary output to stdout, diagnostics to stderr, color only on a TTY (and\n * never when NO_COLOR/--no-color), meaningful exit codes (0 ok, 1 validation\n * failures, 2 operational/usage errors).\n */\nimport { existsSync } from \"node:fs\";\nimport { basename, extname, relative, resolve as resolvePath } from \"node:path\";\nimport { Command, Option } from \"commander\";\nimport picomatch from \"picomatch\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { programName } from \"../shared/program-name.js\";\nimport { fail } from \"../shared/run.js\";\nimport {\n DocmetaError,\n type RunSummary,\n type ValidationResult,\n} from \"./types.js\";\nimport { runValidate } from \"./commands/validate.js\";\nimport { runGet } from \"./commands/get.js\";\nimport { runQuery } from \"./commands/query.js\";\nimport {\n DEFAULT_VENDOR_DIR,\n getSchemasInfo,\n runInferSchema,\n runVendorSchema,\n} from \"./commands/schemas.js\";\nimport { runFill } from \"./commands/fill.js\";\nimport { supportedExtensions } from \"./extractors/index.js\";\nimport {\n COMMON_FORMATS,\n COMMON_FORMAT_LIST,\n OMITTED_WHEN_CLEAN,\n QUERY_FORMATS,\n QUERY_FORMAT_LIST,\n REPORT_FORMATS,\n REPORT_FORMAT_LIST,\n isCommonFormat,\n isMachineFormat,\n isQueryFindingsFormat,\n isQueryFormat,\n isReportFormat,\n render,\n type CommonFormat,\n type QueryFindingsFormat,\n} from \"./reporters/index.js\";\nimport { rowsToFindings } from \"./core/checks.js\";\nimport { isParamName } from \"./core/projection.js\";\nimport type { QueryRun } from \"./commands/query.js\";\nimport {\n FILL_FORMATS,\n FILL_FORMAT_LIST,\n isFillFormat,\n renderFill,\n} from \"./reporters/fill.js\";\nimport { renderGet } from \"./reporters/get.js\";\nimport { renderQuery, renderQueryCsv } from \"./reporters/query.js\";\nimport { renderInfer } from \"./reporters/infer.js\";\nimport { shouldColor, palette } from \"./reporters/color.js\";\n\nfunction collect(value: string, prev: string[]): string[] {\n return prev.concat([value]);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n // Passed through uncoerced. `@types/node` declares `isTTY` as `boolean`, but\n // Node leaves it **undefined** on a stream that is not a terminal — it is\n // never `false` — and `shouldColor` already takes `isTTY?` and treats a\n // missing one as \"not a terminal\". A `Boolean()` here only restated that,\n // where the declared type says it restates nothing.\n return shouldColor({ noColor, isTTY: process.stdout.isTTY });\n}\n\n/**\n * The `--format` a subcommand was actually given, when its **parent** also\n * declares one.\n *\n * commander lets an option declared on a parent be written anywhere in the\n * argv, so `manni meta schemas infer -f json` binds `json` to the `schemas`\n * command — `infer`'s own `--format` keeps its default and the run answers in\n * `pretty`. Silently. That is the same false green `schemas -f github` was\n * fixed for: a request docmeta could honor, answered in a format nobody asked\n * for, with exit 0.\n *\n * `getOptionValueSource` is the public way to tell a typed value from a\n * default, so this reads both commands and prefers whichever was actually\n * typed, rather than depending on which one commander happens to bind to.\n */\nfunction formatFor(command: Command, own: unknown): unknown {\n if (command.getOptionValueSource(\"format\") === \"cli\") return own;\n const parent = command.parent;\n if (parent && parent.getOptionValueSource(\"format\") === \"cli\") {\n return parent.opts().format;\n }\n return own;\n}\n\n/** A `--format` value one of the two-format commands (`get`, `schemas`) rejects. */\nfunction assertCommonFormat(value: unknown): CommonFormat {\n const format = String(value);\n if (!isCommonFormat(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use ${COMMON_FORMAT_LIST}.`,\n );\n }\n return format;\n}\n\n/** The one input token that is neither a path nor a field: stdin. */\nconst STDIN = \"-\";\n\n/**\n * Does this token name a path rather than a field list?\n *\n * `get`'s field list is positional, so a user who forgets it has their *path*\n * bound to `[fields]`. Since the argument became optional the CLI can say so\n * outright instead of reporting the paths that are left as missing.\n *\n * The four positive tests mirror `suggestCommand`'s, `existsSync` included —\n * that leg is the one that catches a bare directory name (`manni meta get docs`),\n * which has neither a dot, a separator, nor a glob character.\n *\n * `existsSync` alone is too eager for a token with **no path shape at all**,\n * though, because field names collide with directory names constantly: `tags`,\n * `docs`, `type`, `content`. In a site repo holding a `tags/` directory,\n * `manni meta get tags docs/a.md` was refused as a path, and the remedy it\n * suggested (`manni meta get title tags`) was nonsense. So a shapeless token is\n * only read as a path when it is **alone** — nothing else was offered as one,\n * which is the shape of someone who forgot the field list. Give a path *and* a\n * bare name and the bare name is the field list: the only reading that makes\n * sense of both.\n *\n * Two negative tests matter more than any of the shape tests, because a false\n * positive rejects a legal field list:\n *\n * - a **comma** makes it a list, and a path holding one is vanishingly rare;\n * - a **leading `/`** is a JSON Pointer, the documented way to address a nested\n * or dotted key — `manni meta get /author/email page.md` is exactly the usage\n * the separator test would otherwise refuse.\n *\n * They do not run *first*, though, and the distinction is worth stating because\n * the obvious reading of the list above is that they do: a token that names a\n * file which really exists is taken as a path before either is consulted. So a\n * JSON Pointer that happens to match a real absolute path — `/author/email`, on\n * a machine where that file exists — is read as a path. `--fields` is the\n * escape, and is why the guard can afford to be wrong here.\n */\nfunction looksLikePath(token: string, cwd: string, alone: boolean): boolean {\n if (token === STDIN) return false;\n // One scan, used twice: `shaped` needs it, and so does the positive test\n // below when `existsSync` did not settle the question.\n const scan = picomatch.scan(token);\n const shaped = /[\\\\/]/.test(token) || extname(token) !== \"\" || scan.isGlob;\n // A file that really is there settles it — but only when the token looks\n // like a path, or nothing else was offered as one.\n if ((shaped || alone) && existsSync(resolvePath(cwd, token))) return true;\n if (token.includes(\",\") || token.startsWith(\"/\")) return false;\n if (scan.isGlob) return true;\n const ext = extname(token).toLowerCase();\n if (ext !== \"\" && supportedExtensions().includes(ext)) return true;\n return /[\\\\/]/.test(token);\n}\n\n/**\n * `get`'s one input rule: **if `--fields` is present, every positional is a\n * path.** Otherwise the first positional is the field list, exactly as before.\n *\n * The missing-field-list case is handled *here* rather than left to `runGet`.\n * `options.fields ?? fieldsArg` is `undefined` when neither was given, and\n * `String(undefined).split(\",\")` is `[\"undefined\"]` — a field list of length\n * one, so `runGet`'s `fields.length === 0` guard never fires and a bare\n * `manni meta get` in a repo with config `paths:` prints `undefined=(unset)` per\n * file and exits 0. A successful-looking report for a field nobody named is\n * worse than the error it replaced.\n *\n * The positional is folded in on `fieldsArg !== undefined`, not with\n * `.filter(Boolean)`: an empty-string path is a mistake worth reporting, and\n * filtering it would silently drop it instead.\n */\nexport function resolveGetInputs(\n fieldsArg: string | undefined,\n pathsArg: string[],\n fieldsOption: unknown,\n cwd: string,\n): { fields: string[]; paths: string[] } {\n const flag = typeof fieldsOption === \"string\" ? fieldsOption : undefined;\n\n if (\n flag === undefined &&\n fieldsArg !== undefined &&\n looksLikePath(fieldsArg, cwd, pathsArg.length === 0)\n ) {\n throw new DocmetaError(\n `\"${fieldsArg}\" looks like a path, not a field list. Pass fields first (manni meta get title ${fieldsArg}) or use --fields.`,\n );\n }\n\n // `-` is stdin, never a field name. Letting it become one made\n // `manni meta get - --as markdown` print `-=(unset)` for every file in the\n // config's `paths:` and exit 0 — the piped document never read, the run\n // looking entirely successful. Dropping it here leaves `fields` empty, so\n // the missing-field-list error below fires instead.\n const source = flag ?? (fieldsArg === STDIN ? undefined : fieldsArg);\n const fields = source === undefined ? [] : splitList(source);\n if (fields.length === 0) {\n throw new DocmetaError(\n \"Specify at least one field to get. Pass fields first (manni meta get title docs/a.md) or use --fields.\",\n );\n }\n\n const paths =\n fieldsArg !== undefined && (flag !== undefined || fieldsArg === STDIN)\n ? [fieldsArg, ...pathsArg]\n : pathsArg;\n return { fields, paths };\n}\n\n/**\n * `query`'s input rule is `get`'s with SQL in the fields slot: **if `--query`\n * is present, every positional is a path**; otherwise the first positional is\n * the SQL. The same three guards apply and for the same reasons — a token\n * shaped like a path in the SQL slot is a forgotten statement, `-` is stdin\n * and never SQL, and an absent statement is an error rather than a\n * plausible-looking run. Real SQL never trips `looksLikePath`: a statement\n * with a column list contains a comma, and anything else with a space cannot\n * name a file that exists.\n *\n * `--db` relaxes exactly one of those guards: exporting needs no SQL, so with\n * `sqlOptional` a path-shaped first positional is a path and an absent\n * statement means \"just write the database\".\n */\nexport function resolveQueryInputs(\n sqlArg: string | undefined,\n pathsArg: string[],\n queryOption: unknown,\n cwd: string,\n sqlOptional = false,\n): { sql: string; paths: string[] } {\n const flag = typeof queryOption === \"string\" ? queryOption : undefined;\n\n if (\n flag === undefined &&\n sqlArg !== undefined &&\n // A token with whitespace is never a path: every real statement has\n // spaces, and without this test `SELECT count(*) FROM docs` reads as a\n // *glob* — picomatch parses `(*)` as an extglob — the one SQL shape the\n // comma test inside looksLikePath does not catch.\n !/\\s/.test(sqlArg) &&\n // With SQL optional there is no \"forgot the statement\" reading to\n // protect, so a shapeless token that really exists on disk is a path\n // even when other paths follow — hence `alone` is forced on.\n looksLikePath(sqlArg, cwd, sqlOptional || pathsArg.length === 0)\n ) {\n if (sqlOptional) return { sql: \"\", paths: [sqlArg, ...pathsArg] };\n throw new DocmetaError(\n `\"${sqlArg}\" looks like a path, not SQL. Pass the SQL first (manni meta query \"SELECT _path FROM docs\" ${sqlArg}) or use --query.`,\n );\n }\n\n const source = flag ?? (sqlArg === STDIN ? undefined : sqlArg);\n const sql = source?.trim() ?? \"\";\n if (sql === \"\" && !sqlOptional) {\n throw new DocmetaError(\n 'Specify SQL to run. Pass it first (manni meta query \"SELECT _path FROM docs\" docs/) or use --query.',\n );\n }\n\n const paths =\n sqlArg !== undefined && (flag !== undefined || sqlArg === STDIN)\n ? [sqlArg, ...pathsArg]\n : pathsArg;\n return { sql, paths };\n}\n\n/**\n * `--param` values into `QueryOptions.params` (proposal 0029).\n *\n * `name=value` binds the value as a **string** — metadata is mostly strings,\n * and a projection column has no type affinity, so a bound number would\n * silently never equal a stored string. `name:=value` parses the value as\n * JSON for the deliberate typed bind (numbers, booleans, arrays, null) — the\n * httpie/jq convention. `:=` is checked before `=`, the split happens at the\n * first separator, and everything after it is the value verbatim, so values\n * containing `=` need no escaping.\n */\nexport function parseQueryParams(\n raw: readonly string[],\n): Record<string, unknown> {\n // Null prototype: `__proto__` passes the name grammar, so it must land as\n // an ordinary own key rather than silently mutating the prototype.\n const params: Record<string, unknown> = Object.create(null) as Record<\n string,\n unknown\n >;\n for (const item of raw) {\n const typed = item.indexOf(\":=\");\n const plain = item.indexOf(\"=\");\n const useTyped = typed !== -1 && (plain === -1 || typed < plain);\n const at = useTyped ? typed : plain;\n if (at <= 0) {\n throw new DocmetaError(\n `--param \"${item}\" is not name=value. Use name=value to bind a string, or name:=json for a typed value.`,\n );\n }\n const name = item.slice(0, at);\n // Exactly the token grammar `collectNamedParameters` recognizes (an\n // optional $/:/@ prefix tolerated, as the API's key handling does) —\n // `isParamName` is the scan's own predicate, so the two cannot drift.\n // Anything else — a space, a leading digit, an empty name — could never\n // be referenced from the SQL, so the engine would ignore the bind and\n // the unbound-reference guard would never fire: the false-green path\n // this flag's design closes would reopen through a typo.\n const bare = /^[$:@]/.test(name) ? name.slice(1) : name;\n if (!isParamName(bare)) {\n throw new DocmetaError(\n `--param name \"${name}\" cannot be bound: a SQL named parameter is letters, digits, and underscores, starting with a letter or underscore.`,\n );\n }\n const value = item.slice(at + (useTyped ? 2 : 1));\n if (!useTyped) {\n params[name] = value;\n continue;\n }\n try {\n params[name] = JSON.parse(value) as unknown;\n } catch {\n throw new DocmetaError(\n `--param ${name}:=${value} is not valid JSON. Quote a string — --param '${name}:=\"${value}\"' — or drop the colon (--param ${name}=${value}) to bind it as a string.`,\n );\n }\n }\n return params;\n}\n\n/**\n * Render a `query --check` run through a findings format (proposal 0026).\n *\n * The row→finding mapping is the same module `validate`'s named checks use;\n * here the check has no configured name, so its findings carry `check:query`.\n * The `RunSummary` `render()` takes is synthesized from the mapped results —\n * every file present has findings, so passed is zero by construction — and\n * JUnit ships under its own classname rather than validate's.\n *\n * Exit semantics stay `--check`'s own: rows mean findings mean exit 1.\n */\nfunction renderQueryFindings(run: QueryRun, format: QueryFindingsFormat): void {\n if (run.changes) {\n throw new DocmetaError(\n `--format ${format} renders result rows with a \\`path\\` column; this statement produced pending changes, not rows. Use pretty or json for the change preview.`,\n );\n }\n const results: ValidationResult[] = [...rowsToFindings(\n \"query\",\n run.columns,\n run.rows,\n )].map(([file, errors]) => ({\n file,\n format: \"query\",\n ok: false,\n schemas: [],\n errors,\n }));\n const summary: RunSummary = {\n files: results.length,\n passed: 0,\n failed: results.length,\n errors: results.reduce((n, r) => n + r.errors.length, 0),\n };\n const text = render(format, results, summary, {\n frame: run.frame,\n classname: \"manni.query\",\n onNotice: notice,\n });\n if (text.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) {\n process.stdout.write(`${text}\\n`);\n }\n process.exitCode = run.rows.length > 0 ? 1 : 0;\n}\n\nconst COMMAND_NAMES = [\"validate\", \"get\", \"query\", \"fill\", \"schemas\"];\n\n/** Levenshtein distance. Only used to offer a \"did you mean\" hint. */\nfunction editDistance(a: string, b: string): number {\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const row = [i];\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n row.push(\n Math.min(\n (row[j - 1] ?? 0) + 1,\n (prev[j] ?? 0) + 1,\n (prev[j - 1] ?? 0) + cost,\n ),\n );\n }\n prev = row;\n }\n return prev[b.length] ?? 0;\n}\n\n/**\n * `validate` is the default command, so an unrecognized first token is parsed as\n * a *path* rather than rejected. Since a named path that does not exist is now\n * an error, `docmeta valdiate docs/` already fails with the right exit code —\n * but it fails as `File not found: \"valdiate\"`, which does not say what went\n * wrong. Upgrade the message when the token is plainly a misspelled command.\n *\n * The guard is deliberately narrow: anything holding a separator or a dot, any\n * glob, and — crucially — anything that actually exists on disk is a path, not a\n * typo. That last check is what makes a false positive impossible.\n */\nfunction suggestCommand(token: string | undefined, cwd: string): void {\n if (token === undefined || token === \"-\") return;\n if (/[\\\\/.]/.test(token)) return;\n if (picomatch.scan(token).isGlob) return;\n if (existsSync(resolvePath(cwd, token))) return;\n\n const near = COMMAND_NAMES.map(\n (name) => [name, editDistance(token.toLowerCase(), name)] as const,\n )\n .filter(([, d]) => d > 0 && d <= 2)\n .sort((x, y) => x[1] - y[1]);\n\n const best = near[0];\n if (!best) return;\n throw new DocmetaError(\n `Unknown command \"${token}\". Did you mean \"${best[0]}\"?`,\n );\n}\n\n/**\n * Split the one commander attribute that `-c, --config <path>` and\n * `--no-config` share. Verified by experiment: `opts.config` is `undefined`\n * with neither flag, the string with `-c`, and `false` with `--no-config`.\n */\nfunction configOption(value: unknown): {\n configPath?: string;\n noConfig?: boolean;\n} {\n if (value === false) return { noConfig: true };\n return typeof value === \"string\" ? { configPath: value } : {};\n}\n\n/**\n * Say which config governed the run, and where it came from.\n *\n * Discovery now walks up to the project boundary, so the answer is no longer\n * obvious from the working directory, and an unexpected ancestor config is the\n * difference between a five-minute diagnosis and an hour of confusion. Goes to\n * stderr for anything a machine reads, so structured output stays parseable.\n */\nfunction reportConfig(\n toStdout: boolean,\n cwd: string,\n): (info: { path: string; dir: string }) => void {\n return (info) => {\n const where = (relative(cwd, info.dir) || \".\").replace(/\\\\/g, \"/\");\n const line = `Using ${basename(info.path)} (${where})\\n`;\n (toStdout ? process.stdout : process.stderr).write(line);\n };\n}\n\n/**\n * Diagnostics from a command core. Always stderr, never stdout: `json` and\n * `github` output has to stay parseable, and a note is not the report.\n */\nfunction notice(message: string): void {\n process.stderr.write(`${programName()}: ${message}\\n`);\n}\n\n/**\n * `--no-gitignore` for the core. Commander gives `true` when the flag is\n * absent, but that is its *default*, not a choice the user made — passing it\n * on would override config `respectGitignore:`. Only the explicit `false`\n * travels; absence stays `undefined` so config still decides.\n */\nfunction gitignoreFlag(value: unknown): boolean | undefined {\n return value === false ? false : undefined;\n}\n\nfunction splitList(value: string): string[] {\n return value\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Range-check a numeric flag. `parseFloat(\"abc\")` is NaN and every comparison\n * against NaN is false, so the finite check has to be explicit or garbage\n * passes silently.\n */\nfunction numeric(\n name: string,\n value: number | undefined,\n min: number,\n max: number,\n): void {\n if (value === undefined) return;\n if (!Number.isFinite(value) || value < min || value > max) {\n throw new DocmetaError(\n `${name} must be a number between ${min} and ${max}, got ${value}.`,\n );\n }\n}\n\n/**\n * Commander hands an `.action()` callback an untyped bag of option values, so\n * each subcommand declares the shape it actually reads.\n *\n * The three-state flags are the reason this is worth writing down rather than\n * coercing at each use site. `-c`/`--no-config`, `--baseline`/`--no-baseline`,\n * `--no-gitignore` and `--no-cache` are only correct while *absent*, *a value*\n * and *an explicit `false`* stay distinguishable — absence leaves config in\n * charge, `false` overrides it. A union that names all three states is the one\n * place a reader finds that out; `String(options.format)` never said anything.\n */\n\n/** The flags the parity rule keeps identical across every input-taking command. */\ninterface InputCliOptions {\n /** `--ext <list>`; the command splits it. */\n ext?: string;\n /** `--exclude <glob>`, repeatable — commander's default value is `[]`. */\n exclude: string[];\n /** `--as <format>`: force an extractor. */\n as?: string;\n /** `-f, --format <format>`. Always a string: every declaration has a default. */\n format: string;\n /**\n * `--collection <name>`, repeatable — commander's default value is `[]`, and\n * that empty array travels to the core unchanged. `selectCollections` reads\n * it as \"every declared collection\", the same as absence, so there is no\n * `undefined` dance here and must not be one: `[]` meaning \"no collections\"\n * would make a plain run validate nothing and exit 0.\n */\n collection: string[];\n /**\n * `-c, --config <path>` and `--no-config` share one commander attribute:\n * `undefined` with neither flag, the path with `-c`, `false` with\n * `--no-config`. Split by `configOption`.\n */\n config?: string | boolean;\n}\n\n/** The rest of what `validate`, `get`, and `fill` share. */\ninterface RunCliOptions extends InputCliOptions {\n quiet?: boolean;\n allowEmpty?: boolean;\n /**\n * `--no-gitignore`. Commander supplies `true` when the flag is absent, so\n * this is `boolean` and never `undefined` — which is exactly why\n * `gitignoreFlag` exists to turn that default back into \"no opinion\".\n */\n gitignore: boolean;\n offline?: boolean;\n}\n\ninterface ValidateCliOptions extends RunCliOptions {\n /** `-s, --schema <ref>`, repeatable — commander's default value is `[]`. */\n schema: string[];\n /**\n * `--baseline [path]` / `--no-baseline`, the same three-state split as\n * `config`: absent leaves the config in charge, a string names a file, `true`\n * is a bare `--baseline` (the default path), `false` is `--no-baseline`.\n */\n baseline?: string | boolean;\n /** `--write-baseline [path]`; `true` for the bare flag. See `baseline`. */\n writeBaseline?: string | boolean;\n /**\n * `--no-checks`. Commander supplies `true` when the flag is absent — its\n * default, not a choice — so only the explicit `false` travels to the core,\n * the same shape as `gitignore`.\n */\n checks: boolean;\n}\n\ninterface GetCliOptions extends RunCliOptions {\n /** `--fields <list>`; when present, every positional is a path. */\n fields?: string;\n}\n\n/**\n * Not `RunCliOptions`: `query` declares no `-q/--quiet`. `get` uses it to hide\n * files and `validate` to hide passes; a query result has no analogous noise,\n * and a flag that means nothing is what 0016 says not to declare.\n */\ninterface QueryCliOptions extends InputCliOptions {\n /** `--query <sql>`; when present, every positional is a path. */\n query?: string;\n /** `-s, --schema <ref>`, repeatable — commander's default value is `[]`. */\n schema: string[];\n /** `--check`: any row returned is a finding, so exit 1. */\n check?: boolean;\n /** `--param <name=value>`, repeatable — commander's default value is `[]`. */\n param: string[];\n /** `--db <path>`: also write the built database; SQL becomes optional. */\n db?: string;\n /** `--dry-run`: preview a mutating statement's diff; default applies. */\n dryRun?: boolean;\n allowEmpty?: boolean;\n /** `--no-gitignore`; commander's `true` default, see `gitignoreFlag`. */\n gitignore: boolean;\n offline?: boolean;\n}\n\ninterface FillCliOptions extends RunCliOptions {\n /** `-s, --schema <ref>`, repeatable — commander's default value is `[]`. */\n schema: string[];\n fields?: string;\n /** Parsed by `parseFloat`, so possibly NaN — `numeric` is the range check. */\n confidence?: number;\n dryRun?: boolean;\n provider?: string;\n model?: string;\n /**\n * `--no-cache`. Commander supplies `true` when the flag is absent; unlike\n * `gitignore` that default is passed straight through, because the core's\n * `cache` has no config counterpart for it to override.\n */\n cache: boolean;\n local?: boolean;\n maxTurns?: number;\n chunkChars?: number;\n concurrency?: number;\n}\n\ninterface SchemasCliOptions {\n format: string;\n}\n\ninterface InferCliOptions extends InputCliOptions {\n out?: string;\n /** `--min-coverage <pct>`; commander's default value is `0`. */\n minCoverage: number;\n allowEmpty?: boolean;\n /** `--no-gitignore`; commander's `true` default, see `gitignoreFlag`. */\n gitignore: boolean;\n /** `--offline`; a no-op here by construction, see `InferOptions.offline`. */\n offline?: boolean;\n}\n\ninterface VendorCliOptions {\n /** `--dir <path>`; commander's default value is `DEFAULT_VENDOR_DIR`. */\n dir: string;\n /** `-c, --config <path>`. `vendor` declares no `--no-config`, so no `false`. */\n config?: string;\n}\n\n/**\n * The metadata tool's program. Named `meta` because that is where it is\n * mounted (`manni meta …`); the `docmeta` bin renames it before running it.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"meta\")\n .description(\n \"Validate the presence and format of document metadata against JSON Schema.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n // A pointer, not the whole help screen. Commander appends this after every\n // usage error, and ~40 lines of options per typo is noise in a CI log — the\n // message that precedes it already names the offending flag.\n .showHelpAfterError(\"(add --help for usage)\")\n // MUST come before the `.command()` calls below. `copyInheritedSettings`\n // copies `_exitCallback` **by value** at subcommand-creation time, so an\n // `exitOverride()` installed afterwards (including\n // `buildProgram().exitOverride()` from main) leaves every subcommand still\n // calling `process.exit(1)` while the program-level case looks fixed.\n .exitOverride();\n\n program\n .command(\"validate\", { isDefault: true })\n .description(\"Validate metadata in the given files/dirs/globs\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to validate (use - for stdin)\",\n )\n .option(\n \"-s, --schema <ref>\",\n \"schema to validate against; repeatable; overrides $schema/config\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${REPORT_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\"-q, --quiet\", \"in pretty output, hide passing files\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"check files .gitignore covers\")\n .option(\n \"--offline\",\n \"never fetch a remote schema; resolve URL refs from the schema cache\",\n )\n // Neither flag carries `.preset()`, and neither carries a `defaultValue`.\n //\n // No `defaultValue`, because that would make the baseline active on runs\n // where the flag was never typed — semantically wrong, and it would oblige\n // the docs to carry a matching Default cell.\n //\n // No `.preset()` either, which is subtler. A preset hands the core the\n // default path as a *string*, making a bare `--baseline` indistinguishable\n // from an explicitly typed `--baseline .docmeta-baseline.json`. A typed path\n // is rightly relative to where the user is standing; an omitted one has to\n // mean \"the file this project's baseline lives in\" — `baseline:` from config\n // when there is one, resolved against the config's directory. Collapsing the\n // two made `--baseline` from a subdirectory look for the file beside the\n // user instead of beside the config, so the ratchet broke the moment anyone\n // ran from `docs/`, and a bare `--write-baseline` in a repo with a custom\n // `baseline:` recorded into a second file nothing reads.\n //\n // Commander hands the core `true` for an omitted value, which is exactly the\n // signal needed to tell the two cases apart.\n .addOption(\n new Option(\n \"--baseline [path]\",\n \"compare against a baseline; fail only on new findings\",\n ),\n )\n .addOption(\n new Option(\n \"--write-baseline [path]\",\n \"record current findings as the baseline, then exit 0 (stdin findings are not recorded and still fail)\",\n ),\n )\n .option(\"--no-baseline\", \"ignore a baseline configured by `baseline:`\")\n .option(\n \"--no-checks\",\n \"skip the corpus checks configured by `checks:` for this run\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni meta validate docs/ # walk a directory\",\n ' manni meta validate \"**/*.md\" -f github # CI annotations',\n ' manni meta validate \"**/*.md\" -f sarif > o.sarif # code scanning',\n \" manni meta validate page.md -s google:okf:0.1 -s ./my.schema.json\",\n \" cat page.md | manni meta validate - --as markdown\",\n \" manni meta validate --write-baseline # record today's backlog\",\n \" manni meta validate --baseline # fail only on new findings\",\n ].join(\"\\n\"),\n )\n .action(\n async (paths: string[], options: ValidateCliOptions, command: Command) => {\n try {\n // `validate` is the default command, so a misspelled subcommand lands\n // here as a path. Upgrade the message before it becomes \"not found\".\n suggestCommand(paths[0], process.cwd());\n const format = options.format;\n if (!isReportFormat(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use ${REPORT_FORMAT_LIST}.`,\n );\n }\n const exts: string[] | undefined = options.ext\n ? splitList(options.ext)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const { results, summary, frame } = await runValidate({\n inputs: paths,\n cliSchemas: options.schema,\n exts,\n exclude: options.exclude,\n as: options.as,\n // Straight through: commander gives `[]` when the flag was never\n // typed, and the core reads an empty list as every declared\n // collection. Refusing paths beside it, and refusing it with no\n // config, is `resolveRunConfig`'s job, before the walk.\n collections: options.collection,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(\n !isMachineFormat(format),\n process.cwd(),\n ),\n stdinContent,\n // `undefined` rather than `false` when the flag is absent, so config\n // `allowEmpty:` still wins (the cores do `opts ?? config`).\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: gitignoreFlag(options.gitignore),\n // `undefined` rather than `false` when absent, so config `offline:`\n // still decides.\n offline: options.offline ? true : undefined,\n onNotice: notice,\n // `--baseline` and `--no-baseline` share one commander attribute, the\n // same three-state `undefined | string | false` split as `-c` /\n // `--no-config`: absent leaves the config in charge, a string names a\n // file, `false` suppresses a configured one for this run.\n baseline: options.baseline,\n writeBaseline: options.writeBaseline,\n // Like `gitignore`: only the explicit `--no-checks` travels, so\n // absence stays \"run them when the corpus rule allows\".\n checks: options.checks ? undefined : false,\n });\n\n const color = resolveColor(command.parent ?? command);\n const text = render(format, results, summary, {\n color,\n quiet: Boolean(options.quiet),\n // Non-presentational: SARIF needs to know where the run stood before\n // it can name a file the way the repository does.\n frame,\n onNotice: notice,\n });\n // Only `github` may say nothing on a clean run. Every other format owes\n // its envelope even when it is empty — see `OMITTED_WHEN_CLEAN`.\n if (text.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) {\n process.stdout.write(`${text}\\n`);\n }\n process.exitCode = summary.failed > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n },\n );\n\n program\n .command(\"get\")\n .description(\"Print metadata field values from the given files/dirs/globs\")\n // Optional, and the flag below is the unambiguous spelling. A required\n // positional ate the user's *path* when the field list was forgotten, and\n // reported the paths — which were never the problem — as missing.\n .argument(\n \"[fields]\",\n \"comma-separated metadata fields to print, unless --fields is given\",\n )\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to read (use - for stdin)\",\n )\n .option(\n \"--fields <list>\",\n \"comma-separated metadata fields to print; every positional is then a path\",\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${COMMON_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\n \"-q, --quiet\",\n \"in pretty output, hide files where every requested field is unset\",\n )\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"read files .gitignore covers\")\n .option(\n \"--offline\",\n \"accepted and ignored: get loads no schema, so there is nothing to fetch\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni meta get title,type docs/intro.md\",\n \" manni meta get --fields title,type docs/intro.md\",\n \" manni meta get author.name,/author/email docs/intro.md\",\n ' manni meta get type \"**/*.md\" -f json',\n \" cat page.md | manni meta get title - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(\n async (\n fieldsArg: string | undefined,\n pathsArg: string[],\n options: GetCliOptions,\n command: Command,\n ) => {\n try {\n const format = assertCommonFormat(options.format);\n const { fields, paths } = resolveGetInputs(\n fieldsArg,\n pathsArg,\n options.fields,\n process.cwd(),\n );\n const exts: string[] | undefined = options.ext\n ? splitList(options.ext)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const results = await runGet({\n fields,\n inputs: paths,\n as: options.as,\n exclude: options.exclude,\n exts,\n collections: options.collection,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(format === \"pretty\", process.cwd()),\n stdinContent,\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: gitignoreFlag(options.gitignore),\n offline: options.offline ? true : undefined,\n onNotice: notice,\n });\n switch (format) {\n case \"json\":\n // `--quiet` is a pretty-output affordance; a filtered array would\n // be indistinguishable from an empty run to whatever parses this.\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n break;\n case \"pretty\": {\n const text = renderGet(results, fields, {\n color: resolveColor(command.parent ?? command),\n quiet: Boolean(options.quiet),\n });\n if (text.length > 0) process.stdout.write(`${text}\\n`);\n break;\n }\n default: {\n const unreachable: never = format;\n throw new DocmetaError(\n `Unknown --format ${JSON.stringify(unreachable)}. Use ${COMMON_FORMAT_LIST}.`,\n );\n }\n }\n // A document that would not parse is a finding, not an operational\n // failure: the run completed and reported on every file it was given.\n // Set after the report is written, so the values that did resolve are\n // on stdout either way.\n process.exitCode = results.some((r) => r.error !== undefined) ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n },\n );\n\n program\n .command(\"query\")\n .description(\"Run SQL over the metadata of the given files/dirs/globs\")\n // Optional for the same reason `get`'s `[fields]` is: a required\n // positional would eat the user's *path* when the SQL was forgotten.\n .argument(\"[sql]\", \"SQL to run against the `docs` table, unless --query is given\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to load (use - for stdin)\",\n )\n .option(\n \"--query <sql>\",\n \"SQL to run against the `docs` table; every positional is then a path\",\n )\n .option(\n \"-s, --schema <ref>\",\n \"schema set a DDL statement evolves; repeatable; replaces the per-file resolution for the DDL planner only\",\n collect,\n [],\n )\n .option(\n \"--check\",\n \"treat returned rows as findings: exit 1 if the query returns any\",\n )\n .option(\n \"--param <name=value>\",\n \"bind a named SQL parameter ($name/:name/@name) as a string; name:=value parses the value as JSON; repeatable\",\n collect,\n [],\n )\n // The findings formats (github, sarif, junit) are declared in the shared\n // `-f, --format` option below; they are legal only with --check and a\n // `path` result column — see the action's gates.\n .option(\n \"--db <path>\",\n \"also write the built database to this file; SQL is then optional\",\n )\n .option(\n \"--dry-run\",\n \"preview a mutating statement's diff without applying it (--check implies this)\",\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${QUERY_FORMATS.join(\" | \")} (github, sarif, junit need --check)`,\n \"pretty\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"load files .gitignore covers\")\n .option(\n \"--offline\",\n \"accepted and ignored: query resolves schemas from disk and built-ins, never the network\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"One row per file in a table named `docs`: your top-level metadata keys\",\n \"as columns, plus _path, _format, _present, and _data (all metadata as\",\n \"JSON, for json_each/->> reach into nested values).\",\n \"\",\n \"Examples:\",\n ' manni meta query \"SELECT _path, title FROM docs WHERE draft = 1\" docs/',\n ' manni meta query \"SELECT t.value tag, count(*) n FROM docs, json_each(docs.tags) t GROUP BY tag\" docs/',\n ' manni meta query --check \"SELECT slug, count(*) n FROM docs GROUP BY slug HAVING n > 1\" docs/',\n ' manni meta query -f csv \"SELECT _path, title, last_reviewed FROM docs\" docs/ > stale.csv',\n \" manni meta query --param author=\\\"O'Brien\\\" \\\"SELECT _path FROM docs WHERE author = \\\\$author\\\" docs/\",\n ' cat page.md | manni meta query \"SELECT title FROM docs\" - --as markdown',\n \" manni meta query --db docs.db docs/ # export only; open with any SQLite UI\",\n ].join(\"\\n\"),\n )\n .action(\n async (\n sqlArg: string | undefined,\n pathsArg: string[],\n options: QueryCliOptions,\n command: Command,\n ) => {\n try {\n const format = options.format;\n if (!isQueryFormat(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use ${QUERY_FORMAT_LIST}.`,\n );\n }\n // The findings formats render findings, and only `--check` produces\n // them. Gated before the run so the refusal costs nothing.\n if (isQueryFindingsFormat(format) && !options.check) {\n throw new DocmetaError(\n `--format ${format} renders findings, which only --check produces. Add --check, or use pretty, json, or csv.`,\n );\n }\n const { sql, paths } = resolveQueryInputs(\n sqlArg,\n pathsArg,\n options.query,\n process.cwd(),\n typeof options.db === \"string\",\n );\n // A `--db`-only export has no result rows to shape into CSV; its\n // summary stays with pretty/json. Refused before the run, like the\n // findings gate above.\n if (format === \"csv\" && sql === \"\") {\n throw new DocmetaError(\n \"--format csv renders result rows, and a --db export without SQL produces none. Use pretty or json for the export summary.\",\n );\n }\n // The findings formats have the same no-rows problem on an\n // export-only run — and silently printing the export summary would\n // be a --check gate that checked nothing.\n if (isQueryFindingsFormat(format) && sql === \"\") {\n throw new DocmetaError(\n `--format ${format} renders findings, which need a statement to produce rows — a --db export without SQL has none. Pass the SQL, or drop --check -f ${format}.`,\n );\n }\n // Ditto --param: with no statement there is nothing to bind into,\n // and silently ignoring the flag would hide a misspelled command.\n if (options.param.length > 0 && sql === \"\") {\n throw new DocmetaError(\n \"--param needs a statement to bind into; a --db export without SQL references no parameters. Pass the SQL, or drop --param.\",\n );\n }\n // And -s (0030): it names the schema set DDL evolves, and with no\n // SQL nothing can evolve it — the same flag-means-nothing seam,\n // refused at the same gate. Worded without naming --db: the gate\n // guards every empty-SQL arrival, not just the export spelling.\n if (options.schema.length > 0 && sql === \"\") {\n throw new DocmetaError(\n \"-s names the schema set DDL evolves; without SQL there is no statement to evolve it. Pass the SQL, or drop -s.\",\n );\n }\n const params = parseQueryParams(options.param);\n const exts: string[] | undefined = options.ext\n ? splitList(options.ext)\n : undefined;\n const stdinContent = paths.includes(STDIN)\n ? await readStdin()\n : undefined;\n\n // `--check` implies a dry run: a check judges and exits, it never\n // mutates — which keeps every CI drift gate a read-only step. So\n // does `-f csv`: csv refuses a changes-producing statement below,\n // and that refusal must land before anything is applied, not after.\n const dryRun =\n Boolean(options.dryRun) || Boolean(options.check) ||\n format === \"csv\";\n const run = await runQuery({\n sql,\n db: options.db,\n dryRun,\n ...(Object.keys(params).length > 0 ? { params } : {}),\n ...(options.schema.length > 0 ? { schemas: options.schema } : {}),\n inputs: paths,\n as: options.as,\n exclude: options.exclude,\n exts,\n collections: options.collection,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(format === \"pretty\", process.cwd()),\n stdinContent,\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: gitignoreFlag(options.gitignore),\n offline: options.offline ? true : undefined,\n onNotice: notice,\n });\n // With SQL, the rows own stdout and the export is a diagnostic;\n // export-only, the export summary IS the report.\n if (run.db && sql === \"\") {\n process.stdout.write(\n format === \"json\"\n ? `${JSON.stringify(run.db, null, 2)}\\n`\n : `Wrote ${run.db.path} (${run.db.files} files, ${run.db.columns} columns)\\n`,\n );\n process.exitCode = 0;\n return;\n }\n if (run.db) {\n notice(`wrote ${run.db.path} (${run.db.files} files)`);\n }\n // Narrowing guard: past this return, `format` is\n // `pretty | json | csv`, which is what keeps the switch below\n // compile-time exhaustive.\n if (isQueryFindingsFormat(format)) {\n renderQueryFindings(run, format);\n return;\n }\n switch (format) {\n case \"csv\":\n // CSV describes result rows. Changes are heterogeneous per-file\n // diffs (eight kinds since 0024), not a table — the refusal\n // lives here in the dispatch, where the format is known and the\n // reporter stays presentation-only (proposal 0029). The run was\n // forced dry above, so the refusal is truthful: nothing landed.\n if (run.changes) {\n throw new DocmetaError(\n \"--format csv renders result rows; this statement produced changes, which have no tabular shape — nothing was applied. Use pretty or json to preview them, and run without -f csv to apply.\",\n );\n }\n process.stdout.write(`${renderQueryCsv(run)}\\n`);\n break;\n case \"json\":\n // The bare array, mirroring `get`'s bare result array: changes\n // for a metadata edit, rows for a read. The `--check` verdict\n // travels in the exit code, not the envelope.\n process.stdout.write(\n `${JSON.stringify(run.changes ?? run.rows, null, 2)}\\n`,\n );\n break;\n case \"pretty\": {\n const text = renderQuery(run, {\n color: resolveColor(command.parent ?? command),\n check: Boolean(options.check),\n dryRun,\n });\n if (text.length > 0) process.stdout.write(`${text}\\n`);\n break;\n }\n default: {\n // Exhaustive: the findings formats returned above and narrowed\n // the union, so adding a value to QUERY_FORMATS without a case\n // here (or a findings-format branch) is a compile error. The\n // throw is the runtime half, as in `render`.\n const unreachable: never = format;\n throw new DocmetaError(\n `Unknown --format ${JSON.stringify(unreachable)}. Use ${QUERY_FORMAT_LIST}.`,\n );\n }\n }\n // Rows from a `--check` run are findings, and so are its pending\n // changes — the drift gate (`--check` never applies). An applied\n // statement is the work done, so it succeeds or fails outright.\n const findings = run.changes ? run.changes.length : run.rows.length;\n process.exitCode = options.check && findings > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n },\n );\n\n program\n .command(\"fill\")\n .description(\n \"Infer missing or invalid metadata and write values above the confidence threshold\",\n )\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to fill (use - for stdin)\",\n )\n .option(\n \"-s, --schema <ref>\",\n \"schema to fill against; repeatable; overrides $schema/config\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\"--fields <list>\", \"comma-separated fields to fill\")\n .option(\"--confidence <n>\", \"minimum confidence to write (0-1)\", parseFloat)\n .option(\"--dry-run\", \"report proposals without writing them\")\n .option(\n \"--provider <name>\",\n \"provider: auto (default), anthropic, openai, claude-cli, llama-cpp, mock\",\n )\n .option(\n \"--model <model>\",\n \"model override; needs a named provider, from here or config\",\n )\n .option(\"--no-cache\", \"bypass the proposal cache\")\n .option(\n \"--local\",\n \"run inference on this machine; refuses any hosted provider, claude-cli included\",\n )\n .option(\"--max-turns <n>\", \"stop after this many inference calls\", parseFloat)\n .option(\n \"--chunk-chars <n>\",\n \"characters of document per call (default 12000)\",\n parseFloat,\n )\n // parseFloat, not parseInt: parseInt(\"3.5\") silently yields 3, which would\n // defeat runFill's integer check and hide the mistake from the user.\n .option(\"--concurrency <n>\", \"files inferred in parallel\", parseFloat)\n .option(\n \"-f, --format <format>\",\n `output: ${FILL_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\n \"-q, --quiet\",\n \"in pretty output, hide files with nothing written and nothing required left undone\",\n )\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"fill files .gitignore covers\")\n .option(\n \"--offline\",\n \"never fetch a remote schema; resolve URL refs from the schema cache\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni meta fill docs/ --dry-run # preview proposals\",\n \" manni meta fill docs/ --confidence 0.9 # only near-certain values\",\n \" manni meta fill page.md --fields description\",\n \" manni meta fill docs/ -f github # CI annotations\",\n \" cat page.md | manni meta fill - --as markdown # filled doc to stdout\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: FillCliOptions, command: Command) => {\n try {\n const format = options.format;\n if (!isFillFormat(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use ${FILL_FORMAT_LIST}.`,\n );\n }\n // parseFloat(\"abc\") is NaN, and every comparison against NaN is false,\n // so a bare range check would silently accept garbage.\n numeric(\"--confidence\", options.confidence, 0, 1);\n numeric(\"--max-turns\", options.maxTurns, 1, Number.MAX_SAFE_INTEGER);\n numeric(\n \"--chunk-chars\",\n options.chunkChars,\n 1,\n Number.MAX_SAFE_INTEGER,\n );\n numeric(\"--concurrency\", options.concurrency, 1, 64);\n\n const exts: string[] | undefined = options.ext\n ? splitList(options.ext)\n : undefined;\n const usingStdin = paths.includes(STDIN);\n // With `-` the filled document owns stdout and the report is a\n // diagnostic on stderr — where GitHub never reads `::error`. The\n // annotations would be produced, and nothing would ever render them.\n // Refuse the combination rather than degrade to a silent no-op, which\n // is the exact false green this parity work exists to remove.\n if (usingStdin && format === \"github\") {\n throw new DocmetaError(\n 'Cannot use --format github with stdin (\"-\"): the filled document owns stdout, so the annotations would go to stderr, where GitHub ignores them. Pass file paths instead.',\n );\n }\n const stdinContent = usingStdin ? await readStdin() : undefined;\n\n const run = await runFill({\n inputs: paths,\n cliSchemas: options.schema,\n exts,\n exclude: options.exclude,\n as: options.as,\n collections: options.collection,\n ...configOption(options.config),\n // With `-` the filled document owns stdout, so the notice is a\n // diagnostic there just as the report is.\n onConfigLoaded: reportConfig(\n format === \"pretty\" && !usingStdin,\n process.cwd(),\n ),\n stdinContent,\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: gitignoreFlag(options.gitignore),\n offline: options.offline ? true : undefined,\n onNotice: notice,\n fields: options.fields ? splitList(options.fields) : undefined,\n confidence: options.confidence,\n dryRun: Boolean(options.dryRun),\n provider: options.provider,\n model: options.model,\n cache: options.cache,\n local: Boolean(options.local),\n maxTurns: options.maxTurns,\n chunkChars: options.chunkChars,\n concurrency: options.concurrency,\n includeContent: usingStdin,\n });\n\n const color = resolveColor(command.parent ?? command);\n const report = renderFill(format, run, {\n color,\n quiet: Boolean(options.quiet),\n });\n if (usingStdin) {\n // The filled document owns stdout here; the report is a diagnostic.\n const filled = run.results[0]?.content;\n if (filled != null) process.stdout.write(filled);\n if (report.length > 0) process.stderr.write(`${report}\\n`);\n } else if (report.length > 0) {\n process.stdout.write(`${report}\\n`);\n }\n\n // A field the schema requires that could not be filled confidently is\n // work left undone, so CI should see it. Optional fields are not.\n process.exitCode =\n run.summary.requiredSkipped > 0 || run.summary.errors > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n });\n\n // `-f, --format` stays on the parent rather than moving to a `list`\n // subcommand: bare `manni meta schemas` is a *default action*, not group help,\n // and both are part of the documented surface.\n const schemas = program\n .command(\"schemas\")\n .description(\"List built-in schemas and supported input formats\")\n .option(\n \"-f, --format <format>\",\n `output: ${COMMON_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .action((options: SchemasCliOptions, command: Command) => {\n try {\n // A closed set, checked like every other command's --format. This used\n // to be a bare `=== \"json\" ? json : pretty`, so `schemas -f github`\n // printed a pretty listing and exited 0 — a request docmeta cannot\n // honor, answered with success in a different format. `github` is the\n // case that matters: it is a real docmeta format, just not one this\n // command produces, so nothing about the invocation looked wrong.\n const format = assertCommonFormat(options.format);\n const info = getSchemasInfo();\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify(info, null, 2)}\\n`);\n return;\n }\n const c = palette(resolveColor(command.parent ?? command));\n const lines: string[] = [c.bold(\"Built-in schemas:\")];\n for (const b of info.builtins) {\n lines.push(` ${c.cyan(b.id)} ${c.dim(\"—\")} ${b.title}`);\n }\n lines.push(\"\", c.bold(\"Input formats:\"));\n for (const f of info.formats) {\n const tags = [\n f.implemented ? c.green(\"implemented\") : c.dim(\"planned\"),\n ];\n // Only worth surfacing on formats that can actually be read.\n if (f.implemented) {\n tags.push(f.writable ? c.green(\"writable\") : c.dim(\"read-only\"));\n }\n lines.push(\n ` ${f.name} (${f.extensions.join(\", \")}) [${tags.join(\", \")}]`,\n );\n }\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n schemas\n .command(\"infer\")\n .description(\n \"Report metadata coverage across a docset, and draft a schema from what is there\",\n )\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to scan (use - for stdin)\",\n )\n .option(\"--out <path>\", \"write the draft schema here\")\n // Default 0, and it must stay 0. A default that hid the long tail would\n // hide exactly the \"3% is one team's convention, not a standard\" signal the\n // report exists to surface.\n .option(\n \"--min-coverage <pct>\",\n \"hide keys below this coverage percentage\",\n parseFloat,\n 0,\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\n \"-f, --format <format>\",\n `output: ${COMMON_FORMATS.join(\" | \")}`,\n \"pretty\",\n )\n .option(\n \"--collection <name>\",\n \"configured collection to run over; repeatable\",\n collect,\n [],\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .option(\"--no-config\", \"ignore any discovered config file\")\n .option(\"--allow-empty\", \"treat zero matched files as success\")\n .option(\"--no-gitignore\", \"scan files .gitignore covers\")\n .option(\n \"--offline\",\n \"accepted and ignored: infer loads no schema and no provider\",\n )\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni meta schemas infer docs/ # what does this repo have?\",\n \" manni meta schemas infer docs/ --min-coverage 5 # drop the long tail\",\n \" manni meta schemas infer docs/ --out ./schemas/permissive.json\",\n \" manni meta schemas infer docs/ -f json\",\n \"\",\n \"Purely statistical and offline: no provider, no network, no model. The\",\n \"draft never marks anything `required` — coverage is your decision to\",\n \"make, not the tool's.\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options: InferCliOptions, command: Command) => {\n try {\n const format = assertCommonFormat(formatFor(command, options.format));\n numeric(\"--min-coverage\", options.minCoverage, 0, 100);\n const exts: string[] | undefined = options.ext\n ? splitList(options.ext)\n : undefined;\n const stdinContent = paths.includes(STDIN)\n ? await readStdin()\n : undefined;\n\n const result = await runInferSchema({\n inputs: paths,\n exts,\n exclude: options.exclude,\n as: options.as,\n collections: options.collection,\n ...configOption(options.config),\n onConfigLoaded: reportConfig(format === \"pretty\", process.cwd()),\n stdinContent,\n out: options.out,\n minCoverage: options.minCoverage,\n // Same shape as the other four input-taking commands: only an\n // explicit `--allow-empty` / `--no-gitignore` travels, so config\n // `allowEmpty:` and `respectGitignore:` still decide otherwise.\n allowEmpty: options.allowEmpty ? true : undefined,\n respectGitignore: gitignoreFlag(options.gitignore),\n // Accepted and ignored — `infer` never fetches. `undefined` rather\n // than `false` all the same, so this stays the same shape as the\n // other four if it ever does gain a meaning.\n offline: options.offline ? true : undefined,\n onNotice: notice,\n });\n\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n return;\n }\n const text = renderInfer(result, {\n color: resolveColor(command.parent?.parent ?? command),\n });\n process.stdout.write(`${text}\\n`);\n } catch (err) {\n fail(err);\n }\n });\n\n schemas\n .command(\"vendor\")\n .description(\n \"Download a remote schema into this repository and pin it in config\",\n )\n .argument(\"<url>\", \"http(s) URL of the schema to vendor\")\n .option(\n \"--dir <path>\",\n \"directory for the committed copy\",\n DEFAULT_VENDOR_DIR,\n )\n .option(\"-c, --config <path>\", \"path to a manni config file\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" manni meta schemas vendor https://schemas.example.com/house/2.1.json\",\n \" manni meta schemas vendor https://schemas.example.com/house/2.1.json --dir ./contracts\",\n \"\",\n \"Commit both the downloaded file and the config change: the point of\",\n \"vendoring is that CI validates against a copy in your own history.\",\n ].join(\"\\n\"),\n )\n .action(async (url: string, options: VendorCliOptions) => {\n try {\n const result = await runVendorSchema({\n url,\n dir: options.dir,\n // `typeof === \"string\"`, not `!== undefined`. `vendor` is the one\n // config-taking command with no `--no-config`, and the parity rule in\n // CLAUDE.md points straight at adding one — at which point commander\n // starts passing `false` here. The annotation on `VendorCliOptions`\n // says that cannot happen, so it would not be caught at the point the\n // flag is declared; this test is what keeps a `false` out of a field\n // that must be a path.\n ...(typeof options.config === \"string\"\n ? { configPath: options.config }\n : {}),\n onNotice: notice,\n });\n // Three states, and the operator needs to be able to tell them apart in\n // a diff: a config was created, an existing reference was replaced (the\n // re-vendor and the bare-URL migration both land here), or an entry was\n // added beside what was already there.\n const configNote = result.configCreated\n ? \"created\"\n : result.replaced\n ? \"reference updated\"\n : \"reference added\";\n process.stdout.write(\n [\n `Vendored ${result.url}`,\n ` file ${result.file} (${result.bytes} bytes${result.unchanged ? \", unchanged\" : \"\"})`,\n ` integrity ${result.integrity}`,\n ` config ${result.config} (${configNote})`,\n \"\",\n `Commit ${result.file} and ${result.config} so CI validates against this copy.`,\n ].join(\"\\n\") + \"\\n\",\n );\n } catch (err) {\n fail(err);\n }\n });\n\n return program;\n}\n\n// No entry point here. `src/cli.ts` mounts this program as `manni meta` and\n// `src/docmeta.ts` runs it under its old name; both go through `runProgram`\n// in src/shared/run.ts, which owns the exit-code contract.\n","/**\n * Reporter for `schemas infer`.\n *\n * The report **is** the product of this command, so the columns are chosen to\n * answer exactly one question each (0010 stress test 1):\n *\n * - **coverage** — require it now (~100%), require it behind a\n * `--write-baseline` ratchet (middling), or do not require it at all (low\n * single digits: one team's convention, not a standard).\n * - **types** — a distribution with counts, so a `string ×900, number ×4` split\n * reads as four data errors rather than as a union worth encoding.\n * - **sample** — what the values actually look like, which is what tells you\n * whether the key means what its name suggests.\n *\n * Files with no metadata block are on their own line rather than folded into a\n * denominator: they pass a require-nothing schema and fail the moment any key\n * becomes required, which is the surprise the report exists to prevent.\n */\nimport type { InferKeyReport, InferResult } from \"../commands/schemas.js\";\nimport { toJsonText } from \"../core/json-text.js\";\nimport { palette } from \"./color.js\";\n\nexport interface InferReportOptions {\n color?: boolean;\n}\n\n/** Outliers listed inline before the report defers to the count. */\nconst OUTLIERS_SHOWN = 5;\n\n/** Enum values listed in the sample column before it elides the rest. */\nconst ENUM_SHOWN = 3;\n\nconst SAMPLE_WIDTH = 46;\n\n/** Thousands separators, pinned to one locale so output is machine-stable. */\nfunction count(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nfunction percent(n: number): string {\n return `${n.toFixed(1)}%`;\n}\n\nfunction truncate(text: string, width: number): string {\n return text.length <= width ? text : `${text.slice(0, width - 1)}…`;\n}\n\n/** `\"Getting started\"` — JSON spelling, so a string is visibly a string. */\nexport function sampleCell(key: InferKeyReport): string {\n if (key.enumValues) {\n const shown = key.enumValues\n .slice(0, ENUM_SHOWN)\n .map((v) => (typeof v === \"string\" ? v : JSON.stringify(v)));\n if (key.enumValues.length > ENUM_SHOWN) shown.push(\"…\");\n return truncate(shown.join(\" | \"), SAMPLE_WIDTH);\n }\n if (key.sample === undefined) return \"\";\n // `toJsonText`, not `JSON.stringify`, so the `?? \"\"` stays visibly\n // reachable — see there.\n return truncate(toJsonText(key.sample) ?? \"\", SAMPLE_WIDTH);\n}\n\n/** `string`, `string (date)`, `string (7 enum)`, or `string ×900, number ×4`. */\nexport function typesCell(key: InferKeyReport): string {\n if (key.types.length > 1) {\n return key.types.map((t) => `${t.type} ×${count(t.count)}`).join(\", \");\n }\n if (key.enumValues) return `${key.dominantType} (${key.enumValues.length} enum)`;\n if (key.format) return `${key.dominantType} (${key.format})`;\n return key.dominantType;\n}\n\nexport function renderInfer(\n result: InferResult,\n opts: InferReportOptions = {},\n): string {\n const c = palette(opts.color ?? false);\n const lines: string[] = [];\n\n const headline = [\n `${count(result.filesScanned)} file${result.filesScanned === 1 ? \"\" : \"s\"} scanned`,\n ];\n headline.push(\n `${count(result.filesWithoutMetadata)} with no metadata block`,\n );\n if (result.unreadable.length > 0) {\n headline.push(`${count(result.unreadable.length)} unreadable`);\n }\n // Same reason `validate` names it on its summary line: every coverage\n // percentage below is computed over `filesScanned`, so a denominator that\n // quietly shrank moves every number in the report. A key at 100% across the\n // eight files `.gitignore` left is not the same finding as one at 100%\n // across all forty, and the headline is the only place that is visible.\n // Omitted at zero, which is every run in a clean repo.\n if (result.gitignoreSkipped > 0) {\n headline.push(`${count(result.gitignoreSkipped)} skipped by .gitignore`);\n }\n lines.push(headline.join(c.dim(\" · \")));\n\n if (result.keys.length === 0) {\n lines.push(\"\", c.dim(\"No metadata keys found.\"));\n return lines.join(\"\\n\");\n }\n\n const rows = result.keys.map((k) => ({\n key: k.key,\n coverage: percent(k.coverage),\n types: typesCell(k),\n sample: sampleCell(k),\n }));\n const width = (pick: (r: (typeof rows)[number]) => string, head: string) =>\n Math.max(head.length, ...rows.map((r) => pick(r).length));\n const wKey = width((r) => r.key, \"key\");\n const wCov = width((r) => r.coverage, \"coverage\");\n const wTypes = width((r) => r.types, \"types\");\n\n lines.push(\n \"\",\n c.dim(\n `${\"key\".padEnd(wKey)} ${\"coverage\".padStart(wCov)} ${\"types\".padEnd(wTypes)} sample`,\n ),\n );\n for (const r of rows) {\n lines.push(\n `${c.cyan(r.key.padEnd(wKey))} ${r.coverage.padStart(wCov)} ${r.types.padEnd(wTypes)} ${c.dim(r.sample)}`,\n );\n }\n\n if (result.hiddenByMinCoverage > 0) {\n lines.push(\n \"\",\n c.dim(\n `${count(result.hiddenByMinCoverage)} key(s) below --min-coverage are not shown.`,\n ),\n );\n }\n\n const withOutliers = result.keys.filter((k) => k.outlierCount > 0);\n if (withOutliers.length > 0) {\n lines.push(\n \"\",\n c.bold(\"Type outliers — these are data errors, not a union:\"),\n );\n for (const k of withOutliers) {\n for (const o of k.outliers.slice(0, OUTLIERS_SHOWN)) {\n const at = o.line === undefined ? o.file : `${o.file}:${o.line}`;\n lines.push(` ${k.key} ${at} ${o.type} (expected ${k.dominantType})`);\n }\n const rest = k.outlierCount - Math.min(k.outliers.length, OUTLIERS_SHOWN);\n if (rest > 0) lines.push(c.dim(` ${k.key} …and ${count(rest)} more`));\n }\n }\n\n for (const u of result.unreadable) {\n lines.push(\"\", `${c.yellow(\"!\")} ${u.file}: ${u.message}`);\n }\n\n if (result.out !== undefined) {\n const properties = Object.keys(result.draft.properties ?? {}).length;\n lines.push(\n \"\",\n `Wrote a draft schema to ${c.cyan(result.out)} — ${count(properties)} propert${properties === 1 ? \"y\" : \"ies\"}, nothing required.`,\n c.dim(\n \"Nothing is required on purpose: what your docset contains is not the same as what your standard should demand. Promote a key with `validate --write-baseline` behind it.\",\n ),\n );\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
|