@hawkeyexl/manni 4.0.3 → 4.1.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/cli.js CHANGED
@@ -7,16 +7,20 @@ import {
7
7
  readStdin,
8
8
  reportConfig,
9
9
  splitList
10
- } from "./chunk-DEP5AMVA.js";
10
+ } from "./chunk-JODRT4NF.js";
11
11
  import {
12
12
  CiteError,
13
+ DocevalsError,
14
+ EXECUTION_GRANTS,
13
15
  INFER_FORMATS,
14
16
  KeyError,
15
17
  LINT_JOBS,
16
18
  LintError,
19
+ REPORT_FORMATS as REPORT_FORMATS2,
17
20
  RULE_ID_PREFIX,
18
21
  SEVERITIES,
19
22
  SEVERITY_LIST,
23
+ SUMMARY_FORMATS,
20
24
  TOOLS_BY_JOB,
21
25
  asCiteError,
22
26
  codeEndAt,
@@ -26,40 +30,57 @@ import {
26
30
  isCiteRule,
27
31
  isInferFormat,
28
32
  isSeverity,
29
- loadConfig,
33
+ listReviews,
34
+ loadConfig2 as loadConfig,
30
35
  meetsSeverity,
36
+ parseFormat,
31
37
  rebaseConfig,
32
38
  render,
39
+ render2,
40
+ renderCalibration,
33
41
  renderCheckGithub,
34
42
  renderCheckJson,
35
43
  renderCheckPretty,
44
+ renderFill,
45
+ renderList,
36
46
  renderRemoveJson,
37
47
  renderRemovePretty,
48
+ renderReviews,
38
49
  renderTemplates,
39
50
  renderTools,
40
51
  renderUpdateJson,
41
52
  renderUpdatePretty,
42
53
  resolveStructureTool,
43
54
  runAdd,
55
+ runCalibrate,
44
56
  runCheck,
57
+ runFill,
58
+ runGenerate,
59
+ runInit,
45
60
  runKeyRotate,
46
61
  runKeySet,
47
62
  runLint,
63
+ runList,
64
+ runPromote,
48
65
  runRemove,
66
+ runReview,
67
+ runRun,
49
68
  runTemplates,
50
69
  runTemplatesInfer,
51
70
  runTools,
52
71
  runUpdate,
72
+ seedGoldenCases,
53
73
  shortCommit,
54
74
  shortLine,
55
75
  shortPin,
56
76
  shortSrc,
57
77
  spellSource
58
- } from "./chunk-JYRY7SKD.js";
78
+ } from "./chunk-S3NDEIOW.js";
59
79
  import {
60
80
  COMMON_FORMAT_LIST,
61
81
  CONCEPT_FIELDS,
62
82
  FAMILY_CONFIG_NAMES,
83
+ LOCAL_FLAG_HELP,
63
84
  OMITTED_WHEN_CLEAN,
64
85
  REPORT_FORMATS,
65
86
  REPORT_FORMAT_LIST,
@@ -100,10 +121,10 @@ import {
100
121
  terminalConfirm,
101
122
  valeConfigPath,
102
123
  valueAt
103
- } from "./chunk-TQG3WCJY.js";
124
+ } from "./chunk-I57KBF45.js";
104
125
 
105
126
  // src/cli.ts
106
- import { Command as Command6 } from "commander";
127
+ import { Command as Command7 } from "commander";
107
128
 
108
129
  // src/a11y/cli.ts
109
130
  import { Command } from "commander";
@@ -858,7 +879,7 @@ var A11Y_FORMAT_LIST = A11Y_FORMATS.join(" | ");
858
879
  function isA11yFormat(value) {
859
880
  return A11Y_FORMATS.includes(value);
860
881
  }
861
- function render2(format, run, opts) {
882
+ function render3(format, run, opts) {
862
883
  switch (format) {
863
884
  case "pretty":
864
885
  return renderPretty(run, opts);
@@ -1109,7 +1130,7 @@ function buildProgram2() {
1109
1130
  { analyzer: createPlaywrightAnalyzer(), onProgress: progress.listener }
1110
1131
  );
1111
1132
  const color = resolveColor(parent, process.stdout);
1112
- const text2 = render2(format, run, { color, quiet: Boolean(options.quiet) });
1133
+ const text2 = render3(format, run, { color, quiet: Boolean(options.quiet) });
1113
1134
  if (text2.length > 0 || format !== "github") {
1114
1135
  process.stdout.write(`${text2}
1115
1136
  `);
@@ -1583,8 +1604,414 @@ function buildProgram3() {
1583
1604
  return program;
1584
1605
  }
1585
1606
 
1586
- // src/key/cli.ts
1607
+ // src/docevals/cli.ts
1587
1608
  import { Command as Command3 } from "commander";
1609
+ function colorFor2(command, isTTY, env) {
1610
+ const noColor = colorOwner2(command).opts().color === false;
1611
+ return shouldColor({ noColor, isTTY, env });
1612
+ }
1613
+ function colorOwner2(command) {
1614
+ for (let c = command; c !== null; c = c.parent) {
1615
+ if (c.options.some((o) => o.long === "--no-color")) return c;
1616
+ }
1617
+ return command;
1618
+ }
1619
+ function buildProgram4() {
1620
+ const program = new Command3();
1621
+ program.name("docevals").description(
1622
+ "Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter."
1623
+ ).version(package_default.version).option("--no-color", "disable colored output").showHelpAfterError("(add --help for usage)").exitOverride();
1624
+ function collectGrant(value, previous) {
1625
+ if (!EXECUTION_GRANTS.includes(value)) {
1626
+ fail(
1627
+ new DocevalsError(
1628
+ `--allow-execution must be one of ${EXECUTION_GRANTS.join(" | ")}, got "${value}"`
1629
+ )
1630
+ );
1631
+ }
1632
+ return [...previous, value];
1633
+ }
1634
+ function parseIntArg(name) {
1635
+ return (value) => {
1636
+ const n = Number.parseInt(value, 10);
1637
+ if (Number.isNaN(n) || n < 1) {
1638
+ fail(new DocevalsError(`${name} must be a positive integer, got "${value}"`));
1639
+ }
1640
+ return n;
1641
+ };
1642
+ }
1643
+ function collectArg(value, previous) {
1644
+ return [...previous, value];
1645
+ }
1646
+ function parseFloatArg(name) {
1647
+ return (value) => {
1648
+ const n = Number.parseFloat(value);
1649
+ if (Number.isNaN(n) || n < 0) {
1650
+ fail(new DocevalsError(`${name} must be a non-negative number, got "${value}"`));
1651
+ }
1652
+ return n;
1653
+ };
1654
+ }
1655
+ function parseFormatArg(name, allowed) {
1656
+ return (value) => {
1657
+ try {
1658
+ return parseFormat(value, allowed, name);
1659
+ } catch (e) {
1660
+ fail(e);
1661
+ }
1662
+ };
1663
+ }
1664
+ function documentInputs(command, verb) {
1665
+ return command.argument(
1666
+ "[paths...]",
1667
+ `Files, directories, or globs to ${verb} (default: the configured collections)`
1668
+ ).option(
1669
+ "--collection <name>",
1670
+ "Configured collection to read (repeatable)",
1671
+ collect,
1672
+ []
1673
+ ).option("--exclude <glob>", "Glob to exclude (repeatable)", collect, []).option("-c, --config <path>", "Path to manni.config.yaml").option("--no-config", "Ignore any discovered config file");
1674
+ }
1675
+ function documentOptions(opts) {
1676
+ const { configPath, noConfig } = configOption(opts.config);
1677
+ return {
1678
+ ...configPath === void 0 ? {} : { config: configPath },
1679
+ ...noConfig === true ? { noConfig } : {},
1680
+ ...opts.collection === void 0 ? {} : { collection: opts.collection },
1681
+ ...opts.exclude === void 0 ? {} : { exclude: opts.exclude }
1682
+ };
1683
+ }
1684
+ documentInputs(
1685
+ program.command("list").description("Show the resolved eval plan per page without running anything"),
1686
+ "list"
1687
+ ).option(
1688
+ "-f, --format <format>",
1689
+ `Output format: ${SUMMARY_FORMATS.join(" | ")}`,
1690
+ parseFormatArg("--format", SUMMARY_FORMATS),
1691
+ "pretty"
1692
+ ).option("--eval <name>", "Show only this eval (repeatable)", collectArg, []).option("--suite <name>", "Show only evals in this suite").action(
1693
+ async (paths, opts, command) => {
1694
+ try {
1695
+ const run = await runList(paths, {
1696
+ ...documentOptions(opts),
1697
+ format: opts.format,
1698
+ evalNames: opts.eval,
1699
+ suite: opts.suite
1700
+ });
1701
+ console.log(
1702
+ renderList(run, opts.format, {
1703
+ color: colorFor2(command, process.stdout.isTTY)
1704
+ })
1705
+ );
1706
+ process.exitCode = run.exitCode;
1707
+ } catch (e) {
1708
+ fail(e);
1709
+ }
1710
+ }
1711
+ );
1712
+ documentInputs(
1713
+ program.command("run").description("Run evals against documentation pages"),
1714
+ "evaluate"
1715
+ ).option(
1716
+ "-f, --format <format>",
1717
+ `Output format: ${REPORT_FORMATS2.join(" | ")}`,
1718
+ parseFormatArg("--format", REPORT_FORMATS2),
1719
+ "pretty"
1720
+ ).option("--deterministic-only", "Run only command/tool graders, skip the AI judge").option("--ai-only", "Run only AI-judged evals, skip deterministic graders").option(
1721
+ // `<kind>`, not `<kind...>`: a variadic option greedily eats the
1722
+ // positional `[paths...]` that follow it, so `--allow-execution
1723
+ // frontmatter-commands docs/**` would silently swallow the glob and run
1724
+ // over the default file set instead. Repeat the flag to grant twice.
1725
+ "--allow-execution <kind>",
1726
+ "Grant content-authored execution: frontmatter-commands",
1727
+ collectGrant,
1728
+ []
1729
+ ).option("--no-execution", "Clear every execution grant for this run").option("--no-generate", "Do not generate scripts for command evals missing a command").option("--no-cache", "Bypass the judge response cache").option("--fail-on-review", "Exit 1 when any eval lands in the human-review zone").option("--provider <name>", "Judge provider: auto (default) | anthropic | openai | claude-cli | llama-cpp").option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).option("--runs <n>", "Ensemble runs per eval", parseIntArg("--runs")).option(
1730
+ "--chunk-chars <n>",
1731
+ "Characters of page per judge call; longer pages are read in parts",
1732
+ parseIntArg("--chunk-chars")
1733
+ ).option(
1734
+ "--eval <name>",
1735
+ "Run only this eval (repeatable); suite targets are not evaluated on a filtered run",
1736
+ collectArg,
1737
+ []
1738
+ ).option("--suite <name>", "Run only evals in this suite").option(
1739
+ "--since <ref>",
1740
+ "Evaluate only pages whose file or eval manifest changed between this git ref and HEAD"
1741
+ ).option(
1742
+ "--max-turns <n>",
1743
+ "Stop after this many ensemble runs (a cached ensemble costs none)",
1744
+ parseIntArg("--max-turns")
1745
+ ).option(
1746
+ "--baseline [path]",
1747
+ "Fail only on findings a recorded baseline does not already hold"
1748
+ ).option("--no-baseline", "Ignore the configured baseline for this run").option(
1749
+ "--write-baseline [path]",
1750
+ "Record this run's findings as the baseline; without a path, the configured one"
1751
+ ).action(async (paths, opts, command) => {
1752
+ try {
1753
+ const report = await runRun(paths, {
1754
+ ...documentOptions({
1755
+ config: opts.config,
1756
+ collection: opts.collection,
1757
+ exclude: opts.exclude
1758
+ }),
1759
+ // parseFormatArg validated this at parse time; the cast only re-narrows
1760
+ // from the `unknown` that the Record-typed options bag erases it to.
1761
+ format: opts.format,
1762
+ deterministicOnly: opts.deterministicOnly,
1763
+ aiOnly: opts.aiOnly,
1764
+ allowExecution: opts.allowExecution,
1765
+ execution: opts.execution,
1766
+ generate: opts.generate,
1767
+ cache: opts.cache,
1768
+ failOnReview: opts.failOnReview,
1769
+ provider: opts.provider,
1770
+ model: opts.model,
1771
+ local: opts.local,
1772
+ runs: opts.runs,
1773
+ chunkChars: opts.chunkChars,
1774
+ maxTurns: opts.maxTurns,
1775
+ evalNames: opts.eval,
1776
+ suite: opts.suite,
1777
+ since: opts.since,
1778
+ // commander collapses `--baseline` to true and `--no-baseline` to
1779
+ // false on the same key; a string is an explicit path.
1780
+ baseline: opts.baseline,
1781
+ writeBaseline: opts.writeBaseline,
1782
+ toolVersion: package_default.version
1783
+ });
1784
+ console.log(
1785
+ render(report, opts.format, {
1786
+ color: colorFor2(command, process.stdout.isTTY)
1787
+ })
1788
+ );
1789
+ process.exitCode = report.exitCode;
1790
+ } catch (e) {
1791
+ fail(e);
1792
+ }
1793
+ });
1794
+ documentInputs(
1795
+ program.command("generate").description(
1796
+ "Generate check scripts for command evals with a plain-language assertion but no command"
1797
+ ),
1798
+ "read"
1799
+ ).option("--provider <name>", "Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp").option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).action(
1800
+ async (paths, opts, command) => {
1801
+ try {
1802
+ const pc = palette(colorFor2(command, process.stdout.isTTY));
1803
+ const result = await runGenerate(paths, {
1804
+ ...documentOptions(opts),
1805
+ provider: opts.provider,
1806
+ model: opts.model,
1807
+ local: opts.local
1808
+ });
1809
+ if (result.targets === 0) {
1810
+ console.log("Nothing to generate \u2014 every command eval has a command.");
1811
+ return;
1812
+ }
1813
+ console.log(
1814
+ `Generated ${result.generatedPaths.length}/${result.targets} check script(s):`
1815
+ );
1816
+ for (const p of result.generatedPaths) console.log(` ${p}`);
1817
+ for (const r of result.refusals) console.log(pc.red(` ${r.message}`));
1818
+ if (result.generatedPaths.length < result.targets) {
1819
+ process.exitCode = 1;
1820
+ }
1821
+ } catch (e) {
1822
+ fail(e);
1823
+ }
1824
+ }
1825
+ );
1826
+ documentInputs(
1827
+ program.command("fill").description(
1828
+ "Propose frontmatter evals for pages with an LLM; writes proposals at or above the confidence threshold"
1829
+ ),
1830
+ "fill"
1831
+ ).option(
1832
+ "-f, --format <format>",
1833
+ `Output format: ${SUMMARY_FORMATS.join(" | ")}`,
1834
+ parseFormatArg("--format", SUMMARY_FORMATS),
1835
+ "pretty"
1836
+ ).option("--dry-run", "Report proposals without writing frontmatter").option(
1837
+ "--confidence <n>",
1838
+ "Minimum confidence to write (0-1, default: config fill.confidenceThreshold)",
1839
+ parseFloatArg("--confidence")
1840
+ ).option(
1841
+ "--max-turns <n>",
1842
+ "Stop after this many inference calls (a cached page costs none)",
1843
+ parseIntArg("--max-turns")
1844
+ ).option("--no-cache", "Bypass the fill proposal cache").option(
1845
+ "--chunk-chars <n>",
1846
+ "Characters of page per fill call; longer pages are proposed in parts",
1847
+ parseIntArg("--chunk-chars")
1848
+ ).option("--provider <name>", "Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp").option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).action(async (paths, opts, command) => {
1849
+ try {
1850
+ const confidence = opts.confidence;
1851
+ if (confidence !== void 0 && confidence > 1) {
1852
+ fail(new DocevalsError(`--confidence must be between 0 and 1, got ${confidence}`));
1853
+ }
1854
+ const report = await runFill(paths, {
1855
+ ...documentOptions({
1856
+ config: opts.config,
1857
+ collection: opts.collection,
1858
+ exclude: opts.exclude
1859
+ }),
1860
+ dryRun: opts.dryRun,
1861
+ confidence,
1862
+ maxTurns: opts.maxTurns,
1863
+ noCache: opts.cache === false ? true : void 0,
1864
+ provider: opts.provider,
1865
+ model: opts.model,
1866
+ local: opts.local,
1867
+ // P1 (proposal 0047): offered only on a terminal, where there is
1868
+ // someone to answer. Off one the evals go to the page and the W1
1869
+ // line says so.
1870
+ confirm: terminalConfirm(),
1871
+ onNotice: notice,
1872
+ onRelocated: (result) => {
1873
+ const manifests = result.manifests.map((m) => m.file).join(", ");
1874
+ notice(
1875
+ `moved ${String(result.summary.moved)} value(s) into ${manifests}.`
1876
+ );
1877
+ }
1878
+ });
1879
+ console.log(
1880
+ renderFill(report, opts.format, {
1881
+ color: colorFor2(command, process.stdout.isTTY)
1882
+ })
1883
+ );
1884
+ process.exitCode = report.exitCode;
1885
+ } catch (e) {
1886
+ fail(e);
1887
+ }
1888
+ });
1889
+ documentInputs(
1890
+ program.command("promote").description(
1891
+ "Find ai-graded evals expressible as deterministic checks; --write converts them"
1892
+ ),
1893
+ "read"
1894
+ ).option("--write", "Apply promotions (write scripts and rewrite evals)").option("--provider <name>", "Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp").option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).action(
1895
+ async (paths, opts, command) => {
1896
+ try {
1897
+ const pc = palette(colorFor2(command, process.stdout.isTTY));
1898
+ const proposals = await runPromote(paths, {
1899
+ ...documentOptions(opts),
1900
+ write: opts.write,
1901
+ provider: opts.provider,
1902
+ model: opts.model,
1903
+ local: opts.local
1904
+ });
1905
+ if (proposals.length === 0) {
1906
+ console.log("No ai-graded evals found.");
1907
+ return;
1908
+ }
1909
+ for (const p of proposals) {
1910
+ const tag = p.promotable ? p.applied ? pc.green("promoted") : pc.cyan("promotable") : pc.dim("keep-ai");
1911
+ const script = p.scriptPath ? pc.dim(` -> ${p.scriptPath}`) : "";
1912
+ console.log(`${tag} ${p.evalName} (${p.source}, ${p.file})${script}`);
1913
+ console.log(pc.dim(` ${p.rationale}`));
1914
+ if (p.error !== void 0) console.log(pc.red(` ${p.error}`));
1915
+ }
1916
+ if (!opts.write && proposals.some((p) => p.promotable)) {
1917
+ console.log(pc.cyan("\nRe-run with --write to apply promotions."));
1918
+ }
1919
+ } catch (e) {
1920
+ fail(e);
1921
+ }
1922
+ }
1923
+ );
1924
+ program.command("calibrate").description(
1925
+ "Measure judge agreement against a human-verified golden set (.manni/docevals/golden/*.yaml)"
1926
+ ).option("-c, --config <path>", "Path to manni.config.yaml").option("--golden <dir>", "Golden set directory", ".manni/docevals/golden").option(
1927
+ "--seed",
1928
+ "Write golden candidates from recorded reviews and exit; judges nothing, needs no provider"
1929
+ ).option("--provider <name>", "Provider: auto (default) | anthropic | openai | claude-cli | llama-cpp").option("--model <model>", "Model override; needs a named provider, from here or config").option("--local", LOCAL_FLAG_HELP).option("--runs <n>", "Ensemble runs per case", parseIntArg("--runs")).option(
1930
+ "--max-turns <n>",
1931
+ "Stop after this many ensemble runs (a cached ensemble costs none)",
1932
+ parseIntArg("--max-turns")
1933
+ ).option("--no-cache", "Bypass the judge response cache").action(
1934
+ async (opts, command) => {
1935
+ try {
1936
+ const color = colorFor2(command, process.stdout.isTTY);
1937
+ const pc = palette(color);
1938
+ if (opts.seed) {
1939
+ const seeded = seedGoldenCases({ golden: opts.golden });
1940
+ if (seeded.total === 0) {
1941
+ console.log(
1942
+ "No recorded reviews to seed from \u2014 run `manni docevals review <file> <eval> <pass|fail>` first."
1943
+ );
1944
+ return;
1945
+ }
1946
+ const changed = seeded.added + seeded.updated;
1947
+ console.log(
1948
+ changed === 0 ? `No new reviews to seed \u2014 ${seeded.total} golden case(s) already in ${seeded.path}.` : `Wrote ${changed} golden candidate(s) to ${seeded.path} (${seeded.added} new, ${seeded.updated} updated; ${seeded.total} total).`
1949
+ );
1950
+ if (seeded.unreviewed > 0) {
1951
+ console.log(
1952
+ pc.yellow(
1953
+ `${seeded.unreviewed} case(s) are \`reviewed: false\`. Read them and set \`reviewed: true\` \u2014 a golden set assembled without a human is not one.`
1954
+ )
1955
+ );
1956
+ }
1957
+ return;
1958
+ }
1959
+ const report = await runCalibrate({
1960
+ config: opts.config,
1961
+ golden: opts.golden,
1962
+ provider: opts.provider,
1963
+ model: opts.model,
1964
+ local: opts.local,
1965
+ runs: opts.runs,
1966
+ maxTurns: opts.maxTurns,
1967
+ noCache: opts.cache === false
1968
+ });
1969
+ console.log(renderCalibration(report, { color }));
1970
+ process.exitCode = report.meetsThreshold && report.unjudged === 0 && report.balanced ? 0 : 1;
1971
+ } catch (e) {
1972
+ fail(e);
1973
+ }
1974
+ }
1975
+ );
1976
+ program.command("init").description("Create a starter manni.config.yaml in the current directory").action(() => {
1977
+ try {
1978
+ console.log(`Created ${runInit()}`);
1979
+ } catch (e) {
1980
+ fail(e);
1981
+ }
1982
+ });
1983
+ program.command("review").description(
1984
+ "Record a human verdict for an eval in the human-review zone (or list recorded reviews)"
1985
+ ).argument("[file]", "Page path").argument("[eval]", "Eval name").argument("[verdict]", "pass | fail").option("--reviewer <name>", "Reviewer name recorded with the verdict").option("--note <text>", "Optional note").action(
1986
+ (file, evalName, verdict, opts, command) => {
1987
+ try {
1988
+ if (!file) {
1989
+ console.log(
1990
+ renderReviews(listReviews(), {
1991
+ color: colorFor2(command, process.stdout.isTTY)
1992
+ })
1993
+ );
1994
+ return;
1995
+ }
1996
+ if (!evalName || !verdict) {
1997
+ throw new DocevalsError(
1998
+ "Usage: manni docevals review <file> <eval> <pass|fail>"
1999
+ );
2000
+ }
2001
+ const entry = runReview(file, evalName, verdict, opts);
2002
+ console.log(
2003
+ `Recorded ${entry.verdict} for ${entry.evalName} on ${entry.file}`
2004
+ );
2005
+ } catch (e) {
2006
+ fail(e);
2007
+ }
2008
+ }
2009
+ );
2010
+ return program;
2011
+ }
2012
+
2013
+ // src/key/cli.ts
2014
+ import { Command as Command4 } from "commander";
1588
2015
 
1589
2016
  // src/key/reporters/json.ts
1590
2017
  function renderRotateJson(result) {
@@ -1681,8 +2108,8 @@ var ROTATE_FORMATS = ["pretty", "json"];
1681
2108
  function isRotateFormat(value) {
1682
2109
  return ROTATE_FORMATS.includes(value);
1683
2110
  }
1684
- function buildProgram4() {
1685
- const program = new Command3();
2111
+ function buildProgram5() {
2112
+ const program = new Command4();
1686
2113
  program.name("key").description("Set and rotate the family key that encrypted values are encrypted with.").version(package_default.version, "-V, --version").option("--no-color", "disable colored output").showHelpAfterError("(add --help for usage)").exitOverride();
1687
2114
  const color = () => shouldColor({ noColor: program.opts().color === false, isTTY: process.stdout.isTTY });
1688
2115
  program.command("set").description("Write the family encryption key to manni.config.yaml; generate one when no value is given").argument("[value]", "the key, at least 32 hex or base64url characters (default: 64 random hex)").option(
@@ -1766,7 +2193,7 @@ function buildProgram4() {
1766
2193
  }
1767
2194
 
1768
2195
  // src/lint/cli.ts
1769
- import { Command as Command4 } from "commander";
2196
+ import { Command as Command5 } from "commander";
1770
2197
  var LIST_FORMATS = /* @__PURE__ */ new Set(["pretty", "json"]);
1771
2198
  var TOOL_OPTIONS_GROUP = "Tool options:";
1772
2199
  function resolveColor2(program) {
@@ -1844,8 +2271,8 @@ function inputOptions(paths, options) {
1844
2271
  onNotice: notice
1845
2272
  };
1846
2273
  }
1847
- function buildProgram5() {
1848
- const program = new Command4();
2274
+ function buildProgram6() {
2275
+ const program = new Command5();
1849
2276
  program.name("lint").description(
1850
2277
  "Validate document structure against doctype templates. Deterministic, CI-friendly."
1851
2278
  ).version(package_default.version, "-V, --version").option("--no-color", "disable colored output").showHelpAfterError().exitOverride();
@@ -1870,7 +2297,7 @@ function buildProgram5() {
1870
2297
  });
1871
2298
  const color = resolveColor2(command.parent ?? command);
1872
2299
  const chosen = explain ? "explain" : format;
1873
- const text2 = render(run, chosen, { color });
2300
+ const text2 = render2(run, chosen, { color });
1874
2301
  if (text2.length > 0 || !omittedWhenClean(chosen)) {
1875
2302
  process.stdout.write(`${text2}
1876
2303
  `);
@@ -2044,7 +2471,7 @@ function buildProgram5() {
2044
2471
  }
2045
2472
 
2046
2473
  // src/term/cli.ts
2047
- import { Command as Command5 } from "commander";
2474
+ import { Command as Command6 } from "commander";
2048
2475
 
2049
2476
  // src/term/commands/check.ts
2050
2477
  import { existsSync as existsSync2 } from "node:fs";
@@ -4995,9 +5422,9 @@ var INTERCHANGE_LABELS = {
4995
5422
  };
4996
5423
  function rendered(writers, format, construct) {
4997
5424
  return writers.some((writer) => {
4998
- const render3 = DOCUMENT_RENDERS[writer.format];
4999
- if (render3?.input !== format) return false;
5000
- return writer.shapes.some((shape) => render3.shapes[shape] === construct);
5425
+ const render4 = DOCUMENT_RENDERS[writer.format];
5426
+ if (render4?.input !== format) return false;
5427
+ return writer.shapes.some((shape) => render4.shapes[shape] === construct);
5001
5428
  });
5002
5429
  }
5003
5430
  function listFormats(opts = {}) {
@@ -5313,7 +5740,7 @@ async function runLint2(opts) {
5313
5740
 
5314
5741
  // src/term/commands/list.ts
5315
5742
  var LIST_FORMATS2 = ["pretty", "json", "csv"];
5316
- async function runList(opts) {
5743
+ async function runList2(opts) {
5317
5744
  const { set } = await loadTerms(opts);
5318
5745
  return { terms: set.terms, set };
5319
5746
  }
@@ -5436,14 +5863,14 @@ async function runWrite(opts) {
5436
5863
  const shape = format === "vale" || /[\\/]$/.test(opts.out ?? "") || isDirectory(targetPath) ? "directory" : "file";
5437
5864
  const target = { path: targetPath, shape };
5438
5865
  const existing = await existingFor(target);
5439
- let render3;
5866
+ let render4;
5440
5867
  try {
5441
- render3 = writer.render(set.terms, target, { existing });
5868
+ render4 = writer.render(set.terms, target, { existing });
5442
5869
  } catch (error) {
5443
5870
  if (error instanceof TermError) throw relativized(error, [...existing.keys(), targetPath], cwd);
5444
5871
  throw error;
5445
5872
  }
5446
- const changes = await applyChanges(render3.files, render3.removals, existing, cwd, !check && !dryRun);
5873
+ const changes = await applyChanges(render4.files, render4.removals, existing, cwd, !check && !dryRun);
5447
5874
  const shown = format === "vale" ? displayPath(join4(targetPath, STYLE2), cwd) : opts.out ?? displayPath(targetPath, cwd);
5448
5875
  return {
5449
5876
  mode: "render",
@@ -5452,11 +5879,11 @@ async function runWrite(opts) {
5452
5879
  target: shown,
5453
5880
  terms: set.terms.length,
5454
5881
  changes,
5455
- files: render3.files.map((file) => ({ path: displayPath(file.path, cwd), content: file.content })),
5882
+ files: render4.files.map((file) => ({ path: displayPath(file.path, cwd), content: file.content })),
5456
5883
  // A Vale style holds designations only, by design; its dropped definitions are not news.
5457
- dropped: format === "vale" ? [] : render3.dropped,
5884
+ dropped: format === "vale" ? [] : render4.dropped,
5458
5885
  droppedFrom: droppedFrom(format, shape, readers),
5459
- skipped: render3.skipped,
5886
+ skipped: render4.skipped,
5460
5887
  check,
5461
5888
  dryRun,
5462
5889
  ...wiring === void 0 ? {} : { wiring }
@@ -5877,7 +6304,7 @@ async function termLabels(request) {
5877
6304
 
5878
6305
  // src/term/cli.ts
5879
6306
  registerTermLabelSource(termLabels);
5880
- function colorFor2(options) {
6307
+ function colorFor3(options) {
5881
6308
  return shouldColor({ noColor: !options.color, isTTY: process.stdout.isTTY });
5882
6309
  }
5883
6310
  async function coreOptions(paths, options) {
@@ -5905,7 +6332,7 @@ function renderFindings(report, format, options, references2) {
5905
6332
  let text2;
5906
6333
  switch (format) {
5907
6334
  case "pretty":
5908
- text2 = renderFindingsPretty(report, { color: colorFor2(options), references: references2 });
6335
+ text2 = renderFindingsPretty(report, { color: colorFor3(options), references: references2 });
5909
6336
  break;
5910
6337
  case "json":
5911
6338
  text2 = renderFindingsJson(report);
@@ -5923,8 +6350,8 @@ function renderFindings(report, format, options, references2) {
5923
6350
  if (text2.length > 0 || !OMITTED_WHEN_CLEAN.has(format)) print(text2);
5924
6351
  process.exitCode = report.summary.failed > 0 ? 1 : 0;
5925
6352
  }
5926
- function buildProgram6() {
5927
- const program = new Command5();
6353
+ function buildProgram7() {
6354
+ const program = new Command6();
5928
6355
  program.name("term").description("Check, lint and render a docset's terms and the references into them.").version(package_default.version, "-V, --version").showHelpAfterError("(add --help for usage)").exitOverride();
5929
6356
  withInputs(
5930
6357
  program.command("list").description("List the resolved entries").argument("[paths...]", "files, directories, or globs to read (use - for stdin)")
@@ -5940,7 +6367,7 @@ function buildProgram6() {
5940
6367
  ).action(async (paths, options) => {
5941
6368
  try {
5942
6369
  const format = formatChoice(options.format, LIST_FORMATS2);
5943
- const { terms } = await runList(await coreOptions(paths, options));
6370
+ const { terms } = await runList2(await coreOptions(paths, options));
5944
6371
  print(format === "json" ? renderListJson(terms) : format === "csv" ? renderListCsv(terms) : renderListPretty(terms));
5945
6372
  process.exitCode = 0;
5946
6373
  } catch (err) {
@@ -5956,7 +6383,7 @@ function buildProgram6() {
5956
6383
  try {
5957
6384
  const format = formatChoice(options.format, GET_FORMATS);
5958
6385
  const found = await runGet({ ...await coreOptions(paths, options), term });
5959
- print(format === "json" ? renderGetJson(found) : renderGetPretty(found, { color: colorFor2(options) }));
6386
+ print(format === "json" ? renderGetJson(found) : renderGetPretty(found, { color: colorFor3(options) }));
5960
6387
  process.exitCode = 0;
5961
6388
  } catch (err) {
5962
6389
  fail(err);
@@ -6042,12 +6469,12 @@ function buildProgram6() {
6042
6469
  }
6043
6470
 
6044
6471
  // src/cli.ts
6045
- function buildProgram7() {
6472
+ function buildProgram8() {
6046
6473
  const meta = buildProgram().name("meta").description(
6047
6474
  "Validate, read, query and fill document metadata against JSON Schema"
6048
6475
  );
6049
6476
  const metaCommands = new Set(meta.commands.map((c) => c.name()));
6050
- const program = new Command6();
6477
+ const program = new Command7();
6051
6478
  program.name("manni").description("Tools for documentation that is meant to be checked.").version(package_default.version, "-V, --version").showHelpAfterError("(add --help for usage)").exitOverride().configureOutput({
6052
6479
  outputError: (str, write) => {
6053
6480
  write(str);
@@ -6073,20 +6500,25 @@ function buildProgram7() {
6073
6500
  )
6074
6501
  );
6075
6502
  program.addCommand(
6076
- buildProgram5().name("lint").description(
6503
+ buildProgram6().name("lint").description(
6077
6504
  "Validate document structure against doctype templates, routed by a page's type"
6078
6505
  )
6079
6506
  );
6080
6507
  program.addCommand(
6081
- buildProgram6().name("term").description("Check, lint and render a docset's terms and the references into them")
6508
+ buildProgram4().name("docevals").description(
6509
+ "Deterministic and LLM-as-judge evals for documentation pages, driven by frontmatter"
6510
+ )
6511
+ );
6512
+ program.addCommand(
6513
+ buildProgram7().name("term").description("Check, lint and render a docset's terms and the references into them")
6082
6514
  );
6083
6515
  program.addCommand(
6084
- buildProgram4().name("key").description("Set and rotate the family key that encrypted values are encrypted with.")
6516
+ buildProgram5().name("key").description("Set and rotate the family key that encrypted values are encrypted with.")
6085
6517
  );
6086
6518
  return program;
6087
6519
  }
6088
- runIfMain(import.meta.url, buildProgram7);
6520
+ runIfMain(import.meta.url, buildProgram8);
6089
6521
  export {
6090
- buildProgram7 as buildProgram
6522
+ buildProgram8 as buildProgram
6091
6523
  };
6092
6524
  //# sourceMappingURL=cli.js.map