@hawkeyexl/manni 4.0.2 → 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/README.md +5 -4
- package/dist/{chunk-TK5PYPFU.js → chunk-I57KBF45.js} +1096 -755
- package/dist/chunk-I57KBF45.js.map +1 -0
- package/dist/{chunk-KSH7XS2R.js → chunk-JODRT4NF.js} +5 -7
- package/dist/chunk-JODRT4NF.js.map +1 -0
- package/dist/{chunk-L26XRFBJ.js → chunk-S3NDEIOW.js} +6022 -245
- package/dist/chunk-S3NDEIOW.js.map +1 -0
- package/dist/cli.js +470 -38
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +2 -2
- package/dist/index.d.ts +1815 -240
- package/dist/index.js +139 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -2
- package/dist/chunk-KSH7XS2R.js.map +0 -1
- package/dist/chunk-L26XRFBJ.js.map +0 -1
- package/dist/chunk-TK5PYPFU.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -7,16 +7,20 @@ import {
|
|
|
7
7
|
readStdin,
|
|
8
8
|
reportConfig,
|
|
9
9
|
splitList
|
|
10
|
-
} from "./chunk-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
124
|
+
} from "./chunk-I57KBF45.js";
|
|
104
125
|
|
|
105
126
|
// src/cli.ts
|
|
106
|
-
import { Command as
|
|
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
|
|
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 =
|
|
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/
|
|
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
|
|
1685
|
-
const program = new
|
|
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
|
|
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
|
|
1848
|
-
const program = new
|
|
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 =
|
|
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
|
|
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
|
|
4999
|
-
if (
|
|
5000
|
-
return writer.shapes.some((shape) =>
|
|
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
|
|
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
|
|
5866
|
+
let render4;
|
|
5440
5867
|
try {
|
|
5441
|
-
|
|
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(
|
|
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:
|
|
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" ? [] :
|
|
5884
|
+
dropped: format === "vale" ? [] : render4.dropped,
|
|
5458
5885
|
droppedFrom: droppedFrom(format, shape, readers),
|
|
5459
|
-
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
|
|
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:
|
|
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
|
|
5927
|
-
const program = new
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
6520
|
+
runIfMain(import.meta.url, buildProgram8);
|
|
6089
6521
|
export {
|
|
6090
|
-
|
|
6522
|
+
buildProgram8 as buildProgram
|
|
6091
6523
|
};
|
|
6092
6524
|
//# sourceMappingURL=cli.js.map
|