@hawkeyexl/manni 4.5.0 → 4.6.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 +1 -1
- package/dist/batch-OZOACN4G.js +41 -0
- package/dist/build-Z5VOVADH.js +32 -0
- package/dist/calibrate-TZYT42DR.js +36 -0
- package/dist/capture-SL4MNDDP.js +34 -0
- package/dist/check-5OMA42Y6.js +26 -0
- package/dist/{check-ESNS7ZBC.js → check-OAJWC3WD.js} +7 -5
- package/dist/{check-RQIIIURI.js → check-PKY7KTQE.js} +13 -14
- package/dist/check-WB2QDHJQ.js +880 -0
- package/dist/check-WB2QDHJQ.js.map +1 -0
- package/dist/{chunk-F2OVHJNC.js → chunk-2JFPBZJK.js} +11 -11
- package/dist/{chunk-CP4ZM43V.js → chunk-2KRB3EG7.js} +2 -2
- package/dist/{chunk-QLUMKWQQ.js → chunk-2M6DVNI5.js} +10 -6
- package/dist/{chunk-QLUMKWQQ.js.map → chunk-2M6DVNI5.js.map} +1 -1
- package/dist/{chunk-HQFVJDEN.js → chunk-3NWX34ZI.js} +19 -19
- package/dist/{chunk-TCC737IS.js → chunk-5G53XATW.js} +4 -4
- package/dist/{chunk-B7XUEQF3.js → chunk-6KKZXB2O.js} +7 -5
- package/dist/{chunk-B7XUEQF3.js.map → chunk-6KKZXB2O.js.map} +1 -1
- package/dist/{chunk-SNEHX4VE.js → chunk-733Y2STG.js} +2 -2
- package/dist/{chunk-ELZ2IIOF.js → chunk-73TC4DYH.js} +2 -2
- package/dist/{chunk-QY3DOZMS.js → chunk-7WRP5FFP.js} +4 -4
- package/dist/{chunk-3R5Y3XOL.js → chunk-APKH2T6E.js} +29 -591
- package/dist/chunk-APKH2T6E.js.map +1 -0
- package/dist/{chunk-FLF6AECQ.js → chunk-B3TS4WRM.js} +17 -15
- package/dist/{chunk-FLF6AECQ.js.map → chunk-B3TS4WRM.js.map} +1 -1
- package/dist/chunk-BWCWTHYS.js +146 -0
- package/dist/chunk-BWCWTHYS.js.map +1 -0
- package/dist/{chunk-C6HZ6C5T.js → chunk-C3B2VJNC.js} +2 -2
- package/dist/{chunk-NN4ASVTY.js → chunk-C73RSUIC.js} +4 -4
- package/dist/chunk-CU57HT2E.js +116 -0
- package/dist/chunk-CU57HT2E.js.map +1 -0
- package/dist/chunk-CWXZ2MRT.js +222 -0
- package/dist/chunk-CWXZ2MRT.js.map +1 -0
- package/dist/{chunk-GAZFKZHM.js → chunk-DC5DDJVE.js} +6 -6
- package/dist/{chunk-52PDIZKV.js → chunk-ECVQNGTH.js} +3 -3
- package/dist/chunk-FLAO4ZS3.js +502 -0
- package/dist/chunk-FLAO4ZS3.js.map +1 -0
- package/dist/chunk-FQGLRJGX.js +174 -0
- package/dist/chunk-FQGLRJGX.js.map +1 -0
- package/dist/{chunk-XWFNO5PO.js → chunk-GAJIJKET.js} +3 -3
- package/dist/{chunk-QCBICNKC.js → chunk-GREQKO6M.js} +202 -54
- package/dist/chunk-GREQKO6M.js.map +1 -0
- package/dist/chunk-HX44GB4Z.js +30 -0
- package/dist/chunk-HX44GB4Z.js.map +1 -0
- package/dist/{chunk-7ZUCEMCY.js → chunk-IY7NYNPZ.js} +9 -11
- package/dist/{chunk-7ZUCEMCY.js.map → chunk-IY7NYNPZ.js.map} +1 -1
- package/dist/{chunk-527HHQPS.js → chunk-KCOFEWV5.js} +6 -4
- package/dist/{chunk-527HHQPS.js.map → chunk-KCOFEWV5.js.map} +1 -1
- package/dist/chunk-M2RLHZ4J.js +849 -0
- package/dist/chunk-M2RLHZ4J.js.map +1 -0
- package/dist/{chunk-K3U5F2QT.js → chunk-M6GSS72T.js} +12 -12
- package/dist/{chunk-UK2I3ACY.js → chunk-MHM4QEBV.js} +4 -4
- package/dist/{chunk-EL2BZTDL.js → chunk-MOWMCEOJ.js} +13 -11
- package/dist/{chunk-EL2BZTDL.js.map → chunk-MOWMCEOJ.js.map} +1 -1
- package/dist/{chunk-OIZ3XMKB.js → chunk-MWBJ3KTF.js} +4 -4
- package/dist/chunk-N7JSEDSC.js +233 -0
- package/dist/chunk-N7JSEDSC.js.map +1 -0
- package/dist/{chunk-MZC62HPZ.js → chunk-NBMPHD4I.js} +2 -2
- package/dist/{chunk-YA63PVWI.js → chunk-NHHOPZRA.js} +12 -10
- package/dist/{chunk-YA63PVWI.js.map → chunk-NHHOPZRA.js.map} +1 -1
- package/dist/{chunk-DX32P2DT.js → chunk-NTWW7J76.js} +2 -2
- package/dist/{chunk-6XTQDFGP.js → chunk-PCFG7E6B.js} +3 -3
- package/dist/{chunk-6XTQDFGP.js.map → chunk-PCFG7E6B.js.map} +1 -1
- package/dist/{chunk-SJO2FTPG.js → chunk-PL4UAF4S.js} +73 -1304
- package/dist/chunk-PL4UAF4S.js.map +1 -0
- package/dist/chunk-QCHVR4ZM.js +286 -0
- package/dist/chunk-QCHVR4ZM.js.map +1 -0
- package/dist/{chunk-JQU7FHYH.js → chunk-QW77LCOU.js} +10 -10
- package/dist/{chunk-IA7BMIPE.js → chunk-SM6NOMJS.js} +2 -2
- package/dist/{chunk-DE7JSWXV.js → chunk-SWSTHZBI.js} +8 -6
- package/dist/{chunk-DE7JSWXV.js.map → chunk-SWSTHZBI.js.map} +1 -1
- package/dist/{chunk-NGK3N6F2.js → chunk-T6SYGLWR.js} +3 -3
- package/dist/chunk-TH4JVQPF.js +133 -0
- package/dist/chunk-TH4JVQPF.js.map +1 -0
- package/dist/{chunk-TVIX653Q.js → chunk-TLXE7LYK.js} +4 -4
- package/dist/{chunk-HVFR66GQ.js → chunk-TUAAR3MM.js} +3280 -283
- package/dist/chunk-TUAAR3MM.js.map +1 -0
- package/dist/{chunk-TA42STP7.js → chunk-UAKNZVCD.js} +4 -4
- package/dist/{chunk-C3KI45RF.js → chunk-UJSGS2Y5.js} +4 -4
- package/dist/{chunk-ZX43SRZR.js → chunk-UWQ2UVHE.js} +8 -6
- package/dist/{chunk-ZX43SRZR.js.map → chunk-UWQ2UVHE.js.map} +1 -1
- package/dist/chunk-WQWKYAAK.js +86 -0
- package/dist/chunk-WQWKYAAK.js.map +1 -0
- package/dist/{chunk-LJ2RDH3F.js → chunk-XG6PVB5S.js} +1 -23
- package/dist/chunk-XG6PVB5S.js.map +1 -0
- package/dist/{chunk-Q35YIDBV.js → chunk-XKBEHKWO.js} +29 -264
- package/dist/chunk-XKBEHKWO.js.map +1 -0
- package/dist/chunk-XPEWUK7J.js +532 -0
- package/dist/chunk-XPEWUK7J.js.map +1 -0
- package/dist/{chunk-BOIF2XGG.js → chunk-XXDXIIQ4.js} +2 -2
- package/dist/chunk-YLK2J5YK.js +610 -0
- package/dist/chunk-YLK2J5YK.js.map +1 -0
- package/dist/{chunk-7OQAU4EA.js → chunk-Z4IZGEM3.js} +16 -12
- package/dist/{chunk-7OQAU4EA.js.map → chunk-Z4IZGEM3.js.map} +1 -1
- package/dist/{cli-E3H6ZP4I.js → cli-6EWVMEN6.js} +5 -3
- package/dist/{cli-E3H6ZP4I.js.map → cli-6EWVMEN6.js.map} +1 -1
- package/dist/{cli-MHTYPVOD.js → cli-6H7HVDMQ.js} +113 -20
- package/dist/{cli-MHTYPVOD.js.map → cli-6H7HVDMQ.js.map} +1 -1
- package/dist/{cli-HUIMNJT6.js → cli-EPVZHAZS.js} +19 -20
- package/dist/{cli-HUIMNJT6.js.map → cli-EPVZHAZS.js.map} +1 -1
- package/dist/{cli-6PGVHP7Y.js → cli-LUCSGTVI.js} +17 -19
- package/dist/{cli-6PGVHP7Y.js.map → cli-LUCSGTVI.js.map} +1 -1
- package/dist/{cli-PRZHQ3QB.js → cli-NIG4N3XM.js} +14 -15
- package/dist/{cli-PRZHQ3QB.js.map → cli-NIG4N3XM.js.map} +1 -1
- package/dist/{cli-TYGOHJOJ.js → cli-PSKNB66T.js} +225 -58
- package/dist/cli-PSKNB66T.js.map +1 -0
- package/dist/{cli-QKIJOXGW.js → cli-UO4NHIB3.js} +17 -17
- package/dist/{cli-AAG3N4NB.js → cli-UQ7A3YA2.js} +17 -18
- package/dist/{cli-AAG3N4NB.js.map → cli-UQ7A3YA2.js.map} +1 -1
- package/dist/{cli-YW6VWBHX.js → cli-YHYDLQAF.js} +10 -10
- package/dist/cli.js +11 -11
- package/dist/config-P4HDNTYD.js +26 -0
- package/dist/conformance-ZFCMKM6M.js +18 -0
- package/dist/docmeta.js +9 -9
- package/dist/github-7ZCH5PSO.js +26 -0
- package/dist/github-POT6724K.js +31 -0
- package/dist/host-6GURH5HE.js +23 -0
- package/dist/index.d.ts +72 -4
- package/dist/index.js +176 -166
- package/dist/index.js.map +1 -1
- package/dist/{json-4DCKDGUV.js → json-KT2K62L5.js} +12 -13
- package/dist/lint-5AQ5C2BV.js +29 -0
- package/dist/list-5JZKX2NK.js +28 -0
- package/dist/list-SWPFXQMU.js +30 -0
- package/dist/{page-QEDB7EVU.js → page-UPSXRP75.js} +11 -12
- package/dist/prepare-6GNEWCNH.js +155 -0
- package/dist/prepare-6GNEWCNH.js.map +1 -0
- package/dist/{pretty-SQX33UM2.js → pretty-Q6FQAOK4.js} +13 -14
- package/dist/{pretty-5DGEBZSV.js → pretty-SQRPFPSQ.js} +12 -13
- package/dist/provider-AMGRDY6V.js +34 -0
- package/dist/release-IECYCLTD.js +36 -0
- package/dist/release-IECYCLTD.js.map +1 -0
- package/dist/{reporters-OHSI3RMV.js → reporters-45MMC2ID.js} +11 -12
- package/dist/{reporters-YELDDYJD.js → reporters-XUV4MM64.js} +7 -5
- package/dist/reporters-XUV4MM64.js.map +1 -0
- package/dist/run-KMWY2IAN.js +32 -0
- package/dist/run-KMWY2IAN.js.map +1 -0
- package/dist/{term-2WMDZ4PY.js → term-PCJUCWNF.js} +16 -17
- package/dist/{term-2WMDZ4PY.js.map → term-PCJUCWNF.js.map} +1 -1
- package/dist/validate-IMNCZNWG.js +17 -0
- package/dist/validate-IMNCZNWG.js.map +1 -0
- package/package.json +2 -2
- package/plugin/manni/.claude-plugin/plugin.json +1 -1
- package/plugin/manni/hooks/hooks.json +47 -0
- package/dist/batch-GOE3UXOD.js +0 -36
- package/dist/build-M7BMEHL2.js +0 -33
- package/dist/calibrate-6RRAILUY.js +0 -31
- package/dist/capture-RJPQ6B4N.js +0 -32
- package/dist/check-BQD64X3N.js +0 -27
- package/dist/chunk-3R5Y3XOL.js.map +0 -1
- package/dist/chunk-3YHAYXBC.js +0 -164
- package/dist/chunk-3YHAYXBC.js.map +0 -1
- package/dist/chunk-HVFR66GQ.js.map +0 -1
- package/dist/chunk-LJ2RDH3F.js.map +0 -1
- package/dist/chunk-NAZRLJAK.js +0 -3090
- package/dist/chunk-NAZRLJAK.js.map +0 -1
- package/dist/chunk-Q35YIDBV.js.map +0 -1
- package/dist/chunk-QCBICNKC.js.map +0 -1
- package/dist/chunk-SJO2FTPG.js.map +0 -1
- package/dist/chunk-TU2WUBVZ.js +0 -2
- package/dist/cli-TYGOHJOJ.js.map +0 -1
- package/dist/github-3WMSTNTK.js +0 -32
- package/dist/github-OXSJQ4PS.js +0 -27
- package/dist/lint-YDHVVZHT.js +0 -30
- package/dist/list-3ZO2NIYO.js +0 -31
- package/dist/list-EJH6VAOW.js +0 -29
- package/dist/run-IP6NZHAG.js +0 -33
- package/dist/validate-G6HH3YXL.js +0 -16
- /package/dist/{batch-GOE3UXOD.js.map → batch-OZOACN4G.js.map} +0 -0
- /package/dist/{build-M7BMEHL2.js.map → build-Z5VOVADH.js.map} +0 -0
- /package/dist/{calibrate-6RRAILUY.js.map → calibrate-TZYT42DR.js.map} +0 -0
- /package/dist/{capture-RJPQ6B4N.js.map → capture-SL4MNDDP.js.map} +0 -0
- /package/dist/{check-BQD64X3N.js.map → check-5OMA42Y6.js.map} +0 -0
- /package/dist/{check-ESNS7ZBC.js.map → check-OAJWC3WD.js.map} +0 -0
- /package/dist/{check-RQIIIURI.js.map → check-PKY7KTQE.js.map} +0 -0
- /package/dist/{chunk-F2OVHJNC.js.map → chunk-2JFPBZJK.js.map} +0 -0
- /package/dist/{chunk-CP4ZM43V.js.map → chunk-2KRB3EG7.js.map} +0 -0
- /package/dist/{chunk-HQFVJDEN.js.map → chunk-3NWX34ZI.js.map} +0 -0
- /package/dist/{chunk-TCC737IS.js.map → chunk-5G53XATW.js.map} +0 -0
- /package/dist/{chunk-SNEHX4VE.js.map → chunk-733Y2STG.js.map} +0 -0
- /package/dist/{chunk-ELZ2IIOF.js.map → chunk-73TC4DYH.js.map} +0 -0
- /package/dist/{chunk-QY3DOZMS.js.map → chunk-7WRP5FFP.js.map} +0 -0
- /package/dist/{chunk-C6HZ6C5T.js.map → chunk-C3B2VJNC.js.map} +0 -0
- /package/dist/{chunk-NN4ASVTY.js.map → chunk-C73RSUIC.js.map} +0 -0
- /package/dist/{chunk-GAZFKZHM.js.map → chunk-DC5DDJVE.js.map} +0 -0
- /package/dist/{chunk-52PDIZKV.js.map → chunk-ECVQNGTH.js.map} +0 -0
- /package/dist/{chunk-XWFNO5PO.js.map → chunk-GAJIJKET.js.map} +0 -0
- /package/dist/{chunk-K3U5F2QT.js.map → chunk-M6GSS72T.js.map} +0 -0
- /package/dist/{chunk-UK2I3ACY.js.map → chunk-MHM4QEBV.js.map} +0 -0
- /package/dist/{chunk-OIZ3XMKB.js.map → chunk-MWBJ3KTF.js.map} +0 -0
- /package/dist/{chunk-MZC62HPZ.js.map → chunk-NBMPHD4I.js.map} +0 -0
- /package/dist/{chunk-DX32P2DT.js.map → chunk-NTWW7J76.js.map} +0 -0
- /package/dist/{chunk-JQU7FHYH.js.map → chunk-QW77LCOU.js.map} +0 -0
- /package/dist/{chunk-IA7BMIPE.js.map → chunk-SM6NOMJS.js.map} +0 -0
- /package/dist/{chunk-NGK3N6F2.js.map → chunk-T6SYGLWR.js.map} +0 -0
- /package/dist/{chunk-TVIX653Q.js.map → chunk-TLXE7LYK.js.map} +0 -0
- /package/dist/{chunk-TA42STP7.js.map → chunk-UAKNZVCD.js.map} +0 -0
- /package/dist/{chunk-C3KI45RF.js.map → chunk-UJSGS2Y5.js.map} +0 -0
- /package/dist/{chunk-BOIF2XGG.js.map → chunk-XXDXIIQ4.js.map} +0 -0
- /package/dist/{cli-QKIJOXGW.js.map → cli-UO4NHIB3.js.map} +0 -0
- /package/dist/{chunk-TU2WUBVZ.js.map → cli-YHYDLQAF.js.map} +0 -0
- /package/dist/{cli-YW6VWBHX.js.map → config-P4HDNTYD.js.map} +0 -0
- /package/dist/{github-3WMSTNTK.js.map → conformance-ZFCMKM6M.js.map} +0 -0
- /package/dist/{github-OXSJQ4PS.js.map → github-7ZCH5PSO.js.map} +0 -0
- /package/dist/{json-4DCKDGUV.js.map → github-POT6724K.js.map} +0 -0
- /package/dist/{lint-YDHVVZHT.js.map → host-6GURH5HE.js.map} +0 -0
- /package/dist/{list-3ZO2NIYO.js.map → json-KT2K62L5.js.map} +0 -0
- /package/dist/{list-EJH6VAOW.js.map → lint-5AQ5C2BV.js.map} +0 -0
- /package/dist/{page-QEDB7EVU.js.map → list-5JZKX2NK.js.map} +0 -0
- /package/dist/{pretty-5DGEBZSV.js.map → list-SWPFXQMU.js.map} +0 -0
- /package/dist/{pretty-SQX33UM2.js.map → page-UPSXRP75.js.map} +0 -0
- /package/dist/{reporters-OHSI3RMV.js.map → pretty-Q6FQAOK4.js.map} +0 -0
- /package/dist/{reporters-YELDDYJD.js.map → pretty-SQRPFPSQ.js.map} +0 -0
- /package/dist/{run-IP6NZHAG.js.map → provider-AMGRDY6V.js.map} +0 -0
- /package/dist/{validate-G6HH3YXL.js.map → reporters-45MMC2ID.js.map} +0 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_CAPTURE_DIR,
|
|
4
|
+
compileRedactPatterns
|
|
5
|
+
} from "./chunk-CU57HT2E.js";
|
|
6
|
+
import {
|
|
7
|
+
JEV,
|
|
8
|
+
JEV_OUT_OF_LOOP
|
|
9
|
+
} from "./chunk-BWCWTHYS.js";
|
|
10
|
+
import {
|
|
11
|
+
TracevalsError
|
|
12
|
+
} from "./chunk-UKZNLVJW.js";
|
|
13
|
+
import {
|
|
14
|
+
EXECUTION_GRANTS,
|
|
15
|
+
configuredGrants,
|
|
16
|
+
isExecutionGrant,
|
|
17
|
+
unknownGrantsMessage
|
|
18
|
+
} from "./chunk-YNHZHSSM.js";
|
|
19
|
+
import {
|
|
20
|
+
FAMILY_CONFIG_NAMES,
|
|
21
|
+
findConfigFileSync,
|
|
22
|
+
readConfigFileSync
|
|
23
|
+
} from "./chunk-XKBEHKWO.js";
|
|
24
|
+
import {
|
|
25
|
+
assertKnownProvider
|
|
26
|
+
} from "./chunk-QCHVR4ZM.js";
|
|
27
|
+
import {
|
|
28
|
+
errorMessage
|
|
29
|
+
} from "./chunk-G3T47CFV.js";
|
|
30
|
+
|
|
31
|
+
// src/tracevals/core/config.ts
|
|
32
|
+
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
33
|
+
|
|
34
|
+
// src/tracevals/core/config-schema.json
|
|
35
|
+
var config_schema_default = {
|
|
36
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
37
|
+
$id: "manni:tracevals:config",
|
|
38
|
+
title: "tracevals section of manni.config.yaml",
|
|
39
|
+
description: "Settings for manni tracevals, held under the `tracevals` key of the config file shared by the manni family of tools. Sibling keys belong to other tools and are not validated here.",
|
|
40
|
+
type: "object",
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
properties: {
|
|
43
|
+
provider: {
|
|
44
|
+
type: "string",
|
|
45
|
+
minLength: 1,
|
|
46
|
+
description: "Which provider judges out of the loop, and extracts rules: auto, anthropic, openai, claude-cli, or llama-cpp. jev only decides, so it is refused here; name it as conformance.hook.provider. Overrides the family's top-level `providers.provider` for tracevals only. Connection settings \u2014 an endpoint, an API key's environment variable, the Claude CLI command \u2014 live in that top-level `providers:` map, never here."
|
|
47
|
+
},
|
|
48
|
+
model: {
|
|
49
|
+
type: "string",
|
|
50
|
+
minLength: 1,
|
|
51
|
+
description: "The model within `provider`, which must be named at this level. Unset, the inference library's default for the winning provider is used; manni pins no model id of its own."
|
|
52
|
+
},
|
|
53
|
+
judge: {
|
|
54
|
+
type: "object",
|
|
55
|
+
additionalProperties: false,
|
|
56
|
+
properties: {
|
|
57
|
+
ensembleRuns: { type: "integer", minimum: 1 },
|
|
58
|
+
temperature: { type: "number", minimum: 0, maximum: 2 },
|
|
59
|
+
zones: {
|
|
60
|
+
type: "object",
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
properties: {
|
|
63
|
+
autoPass: { type: "number", minimum: 0, maximum: 1 },
|
|
64
|
+
autoFail: { type: "number", minimum: 0, maximum: 1 }
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
cacheDir: { type: "string" },
|
|
68
|
+
maxTurns: { type: "integer", minimum: 1, description: "Stop after this many ensemble runs. A cached ensemble spends none. Unset means unbounded; the remaining evals report `skipped` with the reason `turn budget` rather than aborting the run." },
|
|
69
|
+
redact: {
|
|
70
|
+
type: "array",
|
|
71
|
+
description: "Extra regular expressions scrubbed from the session digest before it is sent to a judge provider. Applied on top of the built-in secret shapes, never instead of them; each source is compiled with the `g` flag, and a match is replaced with `[redacted]`. Pattern matching is best-effort \u2014 --deterministic-only is the only setting that guarantees nothing leaves the machine.",
|
|
72
|
+
items: { type: "string", minLength: 1 }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
execution: {
|
|
77
|
+
type: "object",
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
description: "Operator grant for executing content-authored code.",
|
|
80
|
+
properties: {
|
|
81
|
+
allow: {
|
|
82
|
+
type: "array",
|
|
83
|
+
items: { enum: ["frontmatter-commands"] },
|
|
84
|
+
default: ["frontmatter-commands"],
|
|
85
|
+
description: "Which content-authored code a run may execute. Absent, every grant holds; list fewer to narrow it, or write [] to run none. frontmatter-commands lets `command` evals declared in an artifact's front matter run; without it they report `skipped` with a reason, never `pass`."
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
render: {
|
|
90
|
+
type: "object",
|
|
91
|
+
additionalProperties: false,
|
|
92
|
+
properties: {
|
|
93
|
+
maxBlockChars: { type: "integer", minimum: 100 },
|
|
94
|
+
maxTotalChars: {
|
|
95
|
+
type: "integer",
|
|
96
|
+
minimum: 1e3,
|
|
97
|
+
description: "Upper bound on the rendered digest, in characters. The timeline always keeps at least 200 characters, so a very long header can push the digest past this bound by up to 200."
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
history: {
|
|
102
|
+
type: "object",
|
|
103
|
+
additionalProperties: false,
|
|
104
|
+
properties: {
|
|
105
|
+
file: { type: "string" }
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
capture: {
|
|
109
|
+
type: "object",
|
|
110
|
+
additionalProperties: false,
|
|
111
|
+
description: "Session manifests \u2014 sha256 of every instruction artifact plus the git SHA, recorded at session start by `manni tracevals capture` and read back by `run` to make staleness exact instead of an mtime guess. See ADR 01024.",
|
|
112
|
+
properties: {
|
|
113
|
+
dir: {
|
|
114
|
+
type: "string",
|
|
115
|
+
minLength: 1,
|
|
116
|
+
description: "Directory manifests are written to and looked for, resolved against the project root. `run` also accepts one placed beside the trace as `<trace>.manifest.json`, and --manifest names one outright."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
fill: {
|
|
121
|
+
type: "object",
|
|
122
|
+
additionalProperties: false,
|
|
123
|
+
properties: {
|
|
124
|
+
confidenceThreshold: { type: "number", minimum: 0, maximum: 1 },
|
|
125
|
+
maxEvalsPerArtifact: { type: "integer", minimum: 1 },
|
|
126
|
+
temperature: { type: "number", minimum: 0, maximum: 2 },
|
|
127
|
+
cacheDir: { type: "string" },
|
|
128
|
+
maxTurns: { type: "integer", minimum: 1, description: "Stop after this many inference calls, one per artifact filled. A cached artifact spends none. Unset means unbounded." }
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
calibrate: {
|
|
132
|
+
type: "object",
|
|
133
|
+
additionalProperties: false,
|
|
134
|
+
description: "Settings for `manni tracevals calibrate` \u2014 measuring the tool's verdicts against a human's answers. See ADR 01022.",
|
|
135
|
+
properties: {
|
|
136
|
+
labels: {
|
|
137
|
+
type: "string",
|
|
138
|
+
minLength: 1,
|
|
139
|
+
description: "Default labels sidecar, resolved against this config file's directory. Overridden by --labels."
|
|
140
|
+
},
|
|
141
|
+
maxFalsePass: {
|
|
142
|
+
type: "integer",
|
|
143
|
+
minimum: 0,
|
|
144
|
+
description: "Fail the calibration run (exit 1) above this many false passes \u2014 labelled fail, judged pass. Unset by default: a calibration run is a measurement, not a gate."
|
|
145
|
+
},
|
|
146
|
+
maxFalseFail: {
|
|
147
|
+
type: "integer",
|
|
148
|
+
minimum: 0,
|
|
149
|
+
description: "Fail the calibration run above this many false fails \u2014 labelled pass, judged fail."
|
|
150
|
+
},
|
|
151
|
+
maxReview: {
|
|
152
|
+
type: "integer",
|
|
153
|
+
minimum: 0,
|
|
154
|
+
description: "Fail the calibration run above this many needs-review outcomes across the whole corpus."
|
|
155
|
+
},
|
|
156
|
+
sweep: {
|
|
157
|
+
type: "object",
|
|
158
|
+
additionalProperties: false,
|
|
159
|
+
description: "Values --sweep tries on each axis, one axis at a time with the others held at their configured value. The corpus is judged once at the largest ensembleRuns here and every cell is re-scored from those cached runs, so the grid costs nothing beyond that one run.",
|
|
160
|
+
properties: {
|
|
161
|
+
ensembleRuns: {
|
|
162
|
+
type: "array",
|
|
163
|
+
minItems: 1,
|
|
164
|
+
items: { type: "integer", minimum: 1 }
|
|
165
|
+
},
|
|
166
|
+
autoPass: {
|
|
167
|
+
type: "array",
|
|
168
|
+
minItems: 1,
|
|
169
|
+
items: { type: "number", minimum: 0, maximum: 1 }
|
|
170
|
+
},
|
|
171
|
+
autoFail: {
|
|
172
|
+
type: "array",
|
|
173
|
+
minItems: 1,
|
|
174
|
+
items: { type: "number", minimum: 0, maximum: 1 }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
conformance: {
|
|
181
|
+
type: "object",
|
|
182
|
+
additionalProperties: false,
|
|
183
|
+
description: "Checking each turn against the rules the files that govern the agent declare. Present, even as {}, it puts tracevals in play under Claude Code hooks; absent, tracevals stays out of them.",
|
|
184
|
+
properties: {
|
|
185
|
+
hook: {
|
|
186
|
+
type: "object",
|
|
187
|
+
additionalProperties: false,
|
|
188
|
+
description: "The judge inside a Stop or SubagentStop hook. Each key falls back to the top-level one of the same name.",
|
|
189
|
+
properties: {
|
|
190
|
+
provider: {
|
|
191
|
+
type: "string",
|
|
192
|
+
minLength: 1,
|
|
193
|
+
description: "The provider that judges inside a hook. Default: tracevals.provider. jev is accepted here, and only here."
|
|
194
|
+
},
|
|
195
|
+
model: {
|
|
196
|
+
type: "string",
|
|
197
|
+
minLength: 1,
|
|
198
|
+
description: "The model that judges inside a hook. Default: tracevals.model."
|
|
199
|
+
},
|
|
200
|
+
runs: {
|
|
201
|
+
type: "integer",
|
|
202
|
+
minimum: 1,
|
|
203
|
+
description: "Judge calls per rule inside a hook. A rule blocks only when every run scores it not followed at the bar. jev makes one call and ignores it. Default 1."
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
include: {
|
|
208
|
+
type: "array",
|
|
209
|
+
description: "Globs, relative to the project root, naming files that govern agents beyond the known formats. Each applies to every turn.",
|
|
210
|
+
items: { type: "string", minLength: 1 }
|
|
211
|
+
},
|
|
212
|
+
exclude: {
|
|
213
|
+
type: "array",
|
|
214
|
+
description: "Globs, relative to the project root, naming files never treated as rule sources, in any format. It removes plan and spec files too.",
|
|
215
|
+
items: { type: "string", minLength: 1 }
|
|
216
|
+
},
|
|
217
|
+
plans: {
|
|
218
|
+
type: "array",
|
|
219
|
+
default: [],
|
|
220
|
+
description: "Globs, relative to the project root, naming files that say what to build, beyond the known spec formats. Each is a rule source once the session touches it.",
|
|
221
|
+
items: { type: "string", minLength: 1 }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
failOnReview: { type: "boolean" },
|
|
226
|
+
plugins: {
|
|
227
|
+
type: "array",
|
|
228
|
+
description: "Modules imported before evals are planned, so one calling registerGrader() can add a grader kind the built-ins do not cover. A relative or absolute path resolves against this file's directory, not the working directory; a bare package name resolves the way an import from this file's directory would. Load order is significant: a later entry wins a colliding kind.",
|
|
229
|
+
items: { type: "string", minLength: 1 }
|
|
230
|
+
},
|
|
231
|
+
reportUnusedArtifacts: {
|
|
232
|
+
type: "boolean",
|
|
233
|
+
description: "List every skill and agent the session was offered and never used, rather than only counting them. Off by default: a real roster runs to hundreds of skills."
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/tracevals/calibrate/labels.ts
|
|
239
|
+
import { readFile } from "node:fs/promises";
|
|
240
|
+
import { dirname, resolve } from "node:path";
|
|
241
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
242
|
+
import { parse as parseYaml } from "yaml";
|
|
243
|
+
|
|
244
|
+
// src/tracevals/calibrate/labels-schema.json
|
|
245
|
+
var labels_schema_default = {
|
|
246
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
247
|
+
$id: "manni:tracevals:calibration-labels",
|
|
248
|
+
title: "manni tracevals calibration labels",
|
|
249
|
+
description: "Ground truth for `manni tracevals calibrate`: what a human decided a given eval should have produced on a given trace. A sidecar rather than an eval field, because a label belongs to a corpus and a reviewer, not to the artifact \u2014 and because the eval vocabulary is docmeta's, vendored byte-identical, with `inlineEval` closed to additions (ADR 01010).",
|
|
250
|
+
type: "object",
|
|
251
|
+
additionalProperties: false,
|
|
252
|
+
required: ["version", "labels"],
|
|
253
|
+
properties: {
|
|
254
|
+
version: {
|
|
255
|
+
const: 1,
|
|
256
|
+
description: "Format version. Pinned so a future shape change is an explicit migration rather than a silently-reinterpreted file."
|
|
257
|
+
},
|
|
258
|
+
labels: {
|
|
259
|
+
type: "array",
|
|
260
|
+
minItems: 1,
|
|
261
|
+
description: "One entry per (trace, artifact, eval) you have judged by hand.",
|
|
262
|
+
items: {
|
|
263
|
+
type: "object",
|
|
264
|
+
additionalProperties: false,
|
|
265
|
+
required: ["trace", "artifact", "eval", "expected"],
|
|
266
|
+
properties: {
|
|
267
|
+
trace: {
|
|
268
|
+
type: "string",
|
|
269
|
+
minLength: 1,
|
|
270
|
+
description: "Path to the trace file, resolved against this file's own directory \u2014 not the working directory."
|
|
271
|
+
},
|
|
272
|
+
artifact: {
|
|
273
|
+
type: "string",
|
|
274
|
+
minLength: 1,
|
|
275
|
+
description: "Artifact name as the report shows it: a skill name, a subagent_type, or a project-rules filename such as CLAUDE.md."
|
|
276
|
+
},
|
|
277
|
+
type: {
|
|
278
|
+
enum: ["skill", "agent", "project-rules", "slash-command"],
|
|
279
|
+
description: "Optional disambiguator, needed when one name resolves to two kinds of artifact \u2014 a skill and an agent, or a skill and the slash command that types it. Every `ArtifactType` the resolver can produce belongs here: a label whose type this rejects has no way to name the artifact it means."
|
|
280
|
+
},
|
|
281
|
+
eval: {
|
|
282
|
+
type: "string",
|
|
283
|
+
minLength: 1,
|
|
284
|
+
description: "The eval's id. Shorthand entries with no declared id get a positional one (eval-1, eval-2, ...), so labelling those is only as stable as the order they are written in."
|
|
285
|
+
},
|
|
286
|
+
expected: {
|
|
287
|
+
enum: ["pass", "fail", "needs-review"],
|
|
288
|
+
description: "What you decided. `needs-review` means you found it genuinely ambiguous and want the tool to defer too."
|
|
289
|
+
},
|
|
290
|
+
note: {
|
|
291
|
+
type: "string",
|
|
292
|
+
description: "Why you decided that. Carried into the disagreement report, where it is the whole reason a disagreement is actionable."
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/tracevals/calibrate/labels.ts
|
|
301
|
+
var labelsSchema = labels_schema_default;
|
|
302
|
+
var DEFAULT_LABELS_FILE = "tracevals/labels.yaml";
|
|
303
|
+
var ajv = new Ajv2020({ allErrors: true });
|
|
304
|
+
var validate = ajv.compile(labelsSchema);
|
|
305
|
+
var labelKey = (traceFile, artifact, evalName, type) => `${traceFile}\0${type ?? ""}\0${artifact}\0${evalName}`;
|
|
306
|
+
function parseLabels(text, file) {
|
|
307
|
+
let raw;
|
|
308
|
+
try {
|
|
309
|
+
raw = parseYaml(text);
|
|
310
|
+
} catch (err) {
|
|
311
|
+
throw new TracevalsError(
|
|
312
|
+
`could not parse ${file}: ${errorMessage(err)}`
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
if (raw === null || raw === void 0) {
|
|
316
|
+
throw new TracevalsError(`invalid labels file ${file}: it is empty`);
|
|
317
|
+
}
|
|
318
|
+
if (!validate(raw)) {
|
|
319
|
+
const detail = (validate.errors ?? []).map((e) => `${e.instancePath || "/"} ${e.message ?? "invalid"}`).join("; ");
|
|
320
|
+
const empty = (validate.errors ?? []).some(
|
|
321
|
+
(e) => e.instancePath === "/labels" && e.keyword === "minItems"
|
|
322
|
+
);
|
|
323
|
+
throw new TracevalsError(
|
|
324
|
+
empty ? `invalid labels file ${file}: it must carry at least one label \u2014 an empty one measures nothing` : `invalid labels file ${file}: ${detail}`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
const base = dirname(resolve(file));
|
|
328
|
+
const labels = [];
|
|
329
|
+
const seen = /* @__PURE__ */ new Set();
|
|
330
|
+
for (const entry of raw.labels) {
|
|
331
|
+
const traceFile = resolve(base, entry.trace);
|
|
332
|
+
const type = entry.type;
|
|
333
|
+
const key = labelKey(
|
|
334
|
+
traceFile,
|
|
335
|
+
entry.artifact,
|
|
336
|
+
entry.eval,
|
|
337
|
+
type
|
|
338
|
+
);
|
|
339
|
+
if (seen.has(key)) {
|
|
340
|
+
throw new TracevalsError(
|
|
341
|
+
`invalid labels file ${file}: duplicate label for ${entry.artifact ?? "?"} \u203A ${entry.eval ?? "?"} on ${entry.trace ?? "?"}`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
seen.add(key);
|
|
345
|
+
labels.push({
|
|
346
|
+
trace: entry.trace,
|
|
347
|
+
traceFile,
|
|
348
|
+
artifact: entry.artifact,
|
|
349
|
+
...type !== void 0 ? { type } : {},
|
|
350
|
+
eval: entry.eval,
|
|
351
|
+
expected: entry.expected,
|
|
352
|
+
...entry.note !== void 0 ? { note: entry.note } : {}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return labels;
|
|
356
|
+
}
|
|
357
|
+
async function loadLabels(file) {
|
|
358
|
+
let text;
|
|
359
|
+
try {
|
|
360
|
+
text = await readFile(file, "utf-8");
|
|
361
|
+
} catch (err) {
|
|
362
|
+
throw new TracevalsError(
|
|
363
|
+
`could not read labels file ${file}: ${errorMessage(err)}`
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
return parseLabels(text, file);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// src/tracevals/core/config.ts
|
|
370
|
+
var configSchema = config_schema_default;
|
|
371
|
+
var DEFAULT_CONFIG_FILENAME = FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml";
|
|
372
|
+
var CONFIG_SECTION_KEY = "tracevals";
|
|
373
|
+
var CONFIG_SECTION_KEY_PATH = `/${CONFIG_SECTION_KEY}`;
|
|
374
|
+
var CONFIG_FILE = {
|
|
375
|
+
section: CONFIG_SECTION_KEY,
|
|
376
|
+
legacyNames: [],
|
|
377
|
+
toError: (message) => new TracevalsError(message)
|
|
378
|
+
};
|
|
379
|
+
var ajv2 = new Ajv20202({ allErrors: true, verbose: true });
|
|
380
|
+
var validate2 = ajv2.compile(configSchema);
|
|
381
|
+
function camelCaseHint(key, parentSchema) {
|
|
382
|
+
const camel = key.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
383
|
+
if (camel === key || parentSchema === null || typeof parentSchema !== "object") {
|
|
384
|
+
return "";
|
|
385
|
+
}
|
|
386
|
+
const properties = parentSchema.properties;
|
|
387
|
+
return properties !== null && typeof properties === "object" && Object.hasOwn(properties, camel) ? `; did you mean "${camel}"?` : "";
|
|
388
|
+
}
|
|
389
|
+
function movedProviderHint(instancePath, keyword) {
|
|
390
|
+
return instancePath === "/provider" && keyword === "type" ? `; "provider" is now a provider name; per-provider settings moved to the top-level providers: map` : "";
|
|
391
|
+
}
|
|
392
|
+
function parseConfig(raw, file = {}) {
|
|
393
|
+
const source = file.source ?? DEFAULT_CONFIG_FILENAME;
|
|
394
|
+
const unknownGrants = configuredGrants(raw).filter((g) => !isExecutionGrant(g));
|
|
395
|
+
if (unknownGrants.length > 0) {
|
|
396
|
+
throw new TracevalsError(`${source}: ${unknownGrantsMessage(unknownGrants)}`);
|
|
397
|
+
}
|
|
398
|
+
if (!validate2(raw)) {
|
|
399
|
+
const detail = (validate2.errors ?? []).map((e) => {
|
|
400
|
+
const extra = e.keyword === "additionalProperties" ? e.params.additionalProperty : void 0;
|
|
401
|
+
return extra !== void 0 ? `unknown key "${extra}"${camelCaseHint(extra, e.parentSchema)}` : `${CONFIG_SECTION_KEY_PATH}${e.instancePath} ${e.message ?? "is invalid"}` + movedProviderHint(e.instancePath, e.keyword);
|
|
402
|
+
}).join("; ");
|
|
403
|
+
throw new TracevalsError(`${source}: ${detail}`);
|
|
404
|
+
}
|
|
405
|
+
const r = raw;
|
|
406
|
+
const provider = r.provider ?? null;
|
|
407
|
+
if (provider !== null) {
|
|
408
|
+
if (provider === JEV) throw new TracevalsError(JEV_OUT_OF_LOOP);
|
|
409
|
+
assertKnownProvider(provider, (message) => new TracevalsError(message));
|
|
410
|
+
}
|
|
411
|
+
const hookProvider = r.conformance?.hook?.provider ?? null;
|
|
412
|
+
if (hookProvider !== null) {
|
|
413
|
+
assertKnownProvider(hookProvider, (message) => new TracevalsError(message), { decisions: true });
|
|
414
|
+
}
|
|
415
|
+
const config = {
|
|
416
|
+
provider,
|
|
417
|
+
model: r.model ?? null,
|
|
418
|
+
providers: file.providers ?? {},
|
|
419
|
+
configSource: source,
|
|
420
|
+
judge: {
|
|
421
|
+
ensembleRuns: r.judge?.ensembleRuns ?? 3,
|
|
422
|
+
temperature: r.judge?.temperature ?? 0,
|
|
423
|
+
zones: {
|
|
424
|
+
autoPass: r.judge?.zones?.autoPass ?? 0.8,
|
|
425
|
+
autoFail: r.judge?.zones?.autoFail ?? 0.8
|
|
426
|
+
},
|
|
427
|
+
cacheDir: r.judge?.cacheDir ?? ".manni/tracevals/cache",
|
|
428
|
+
// `null`, not a number: unbounded is a state, and any number here would
|
|
429
|
+
// be a ceiling nobody asked for.
|
|
430
|
+
maxTurns: r.judge?.maxTurns ?? null,
|
|
431
|
+
// Always a list: the render site concatenates nothing onto it, but a
|
|
432
|
+
// hole here would be a special case in every consumer.
|
|
433
|
+
redact: [...r.judge?.redact ?? []]
|
|
434
|
+
},
|
|
435
|
+
render: {
|
|
436
|
+
maxBlockChars: r.render?.maxBlockChars ?? 2e3,
|
|
437
|
+
maxTotalChars: r.render?.maxTotalChars ?? 15e4
|
|
438
|
+
},
|
|
439
|
+
execution: { allow: [...r.execution?.allow ?? EXECUTION_GRANTS] },
|
|
440
|
+
history: {
|
|
441
|
+
file: r.history?.file ?? ".manni/tracevals/history.jsonl"
|
|
442
|
+
},
|
|
443
|
+
capture: {
|
|
444
|
+
// Beside the judge cache, under the state directory that already travels
|
|
445
|
+
// with the project — which is what puts a manifest next to its trace in
|
|
446
|
+
// the CI patterns the docs describe.
|
|
447
|
+
dir: r.capture?.dir ?? DEFAULT_CAPTURE_DIR
|
|
448
|
+
},
|
|
449
|
+
fill: {
|
|
450
|
+
// 0.7 matches the manuscript's calibration bar for judged agreement.
|
|
451
|
+
confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,
|
|
452
|
+
maxEvalsPerArtifact: r.fill?.maxEvalsPerArtifact ?? 8,
|
|
453
|
+
temperature: r.fill?.temperature ?? 0,
|
|
454
|
+
// Separate from the judge cache: different key scheme and value shape.
|
|
455
|
+
cacheDir: r.fill?.cacheDir ?? ".manni/tracevals/cache/fill",
|
|
456
|
+
maxTurns: r.fill?.maxTurns ?? null
|
|
457
|
+
},
|
|
458
|
+
calibrate: {
|
|
459
|
+
labels: r.calibrate?.labels ?? DEFAULT_LABELS_FILE,
|
|
460
|
+
sweep: {
|
|
461
|
+
// Spans the range rather than filling it: the first sweep judges the
|
|
462
|
+
// corpus at the largest value here, so a wide grid is the one part of
|
|
463
|
+
// calibration that does cost money.
|
|
464
|
+
ensembleRuns: [...r.calibrate?.sweep?.ensembleRuns ?? [1, 3, 5]],
|
|
465
|
+
autoPass: [
|
|
466
|
+
...r.calibrate?.sweep?.autoPass ?? [0.5, 0.6, 0.7, 0.8, 0.9, 0.95]
|
|
467
|
+
],
|
|
468
|
+
autoFail: [
|
|
469
|
+
...r.calibrate?.sweep?.autoFail ?? [0.5, 0.6, 0.7, 0.8, 0.9, 0.95]
|
|
470
|
+
]
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
failOnReview: r.failOnReview ?? true,
|
|
474
|
+
// Always a list, never undefined: the read site concatenates `--require`
|
|
475
|
+
// onto it, and a hole there would be a special case in every caller.
|
|
476
|
+
plugins: [...r.plugins ?? []],
|
|
477
|
+
// An observation, not a gate: listing it is opt-in because a real roster
|
|
478
|
+
// runs to hundreds of skills (ADR 01016).
|
|
479
|
+
reportUnusedArtifacts: r.reportUnusedArtifacts ?? false,
|
|
480
|
+
conformance: r.conformance === void 0 ? null : {
|
|
481
|
+
hook: {
|
|
482
|
+
provider: hookProvider,
|
|
483
|
+
model: r.conformance.hook?.model ?? null,
|
|
484
|
+
runs: r.conformance.hook?.runs ?? 1
|
|
485
|
+
},
|
|
486
|
+
include: [...r.conformance.include ?? []],
|
|
487
|
+
exclude: [...r.conformance.exclude ?? []],
|
|
488
|
+
plans: [...r.conformance.plans ?? []]
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
compileRedactPatterns(config.judge.redact);
|
|
492
|
+
for (const key of ["maxFalsePass", "maxFalseFail", "maxReview"]) {
|
|
493
|
+
if (typeof r.calibrate?.[key] === "number") {
|
|
494
|
+
config.calibrate[key] = r.calibrate[key];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return config;
|
|
498
|
+
}
|
|
499
|
+
async function discoverConfig(dir = process.cwd(), lookup = {}) {
|
|
500
|
+
if (lookup.noConfig === true) {
|
|
501
|
+
return { config: parseConfig({}), dir, collections: [] };
|
|
502
|
+
}
|
|
503
|
+
const file = await Promise.resolve().then(
|
|
504
|
+
() => lookup.configPath === void 0 ? findConfigFileSync(dir, CONFIG_FILE) : readConfigFileSync(lookup.configPath, dir, CONFIG_FILE)
|
|
505
|
+
);
|
|
506
|
+
if (file === null) return { config: parseConfig({}), dir, collections: [] };
|
|
507
|
+
return {
|
|
508
|
+
config: parseConfig(file.value ?? {}, {
|
|
509
|
+
source: file.source,
|
|
510
|
+
...file.providers !== void 0 ? { providers: file.providers } : {}
|
|
511
|
+
}),
|
|
512
|
+
dir: file.dir,
|
|
513
|
+
collections: file.collections,
|
|
514
|
+
path: file.path
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
async function loadConfig(dir = process.cwd(), lookup = {}) {
|
|
518
|
+
return (await discoverConfig(dir, lookup)).config;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export {
|
|
522
|
+
DEFAULT_LABELS_FILE,
|
|
523
|
+
labelKey,
|
|
524
|
+
parseLabels,
|
|
525
|
+
loadLabels,
|
|
526
|
+
DEFAULT_CONFIG_FILENAME,
|
|
527
|
+
CONFIG_SECTION_KEY,
|
|
528
|
+
parseConfig,
|
|
529
|
+
discoverConfig,
|
|
530
|
+
loadConfig
|
|
531
|
+
};
|
|
532
|
+
//# sourceMappingURL=chunk-XPEWUK7J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tracevals/core/config.ts","../src/tracevals/core/config-schema.json","../src/tracevals/calibrate/labels.ts","../src/tracevals/calibrate/labels-schema.json"],"sourcesContent":["/**\n * Config loading. Every knob flows config → Ajv validate → defaults → CLI\n * override (`??` at the read site) → runtime; parseConfig() fills every\n * default so downstream code never re-applies one.\n *\n * Settings live under a `tracevals:` key in `manni.config.yaml`, one file\n * shared by the whole manni family. Sibling keys belong to other tools and are\n * ignored here, so parseConfig() validates the section — never the file root.\n * Finding the file is the shared loader's job (`src/shared/config-file.ts`).\n */\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport configSchemaJson from \"./config-schema.json\" with { type: \"json\" };\nimport {\n FAMILY_CONFIG_NAMES,\n findConfigFileSync,\n readConfigFileSync,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport type { CollectionConfig } from \"../../shared/collections.js\";\nimport {\n assertKnownProvider,\n type ProvidersConfig,\n} from \"../../shared/providers.js\";\nimport { compileRedactPatterns } from \"../judge/redact.js\";\nimport { JEV, JEV_OUT_OF_LOOP } from \"../judge/provider.js\";\nimport { DEFAULT_CAPTURE_DIR } from \"../capture/types.js\";\nimport { DEFAULT_LABELS_FILE } from \"../calibrate/labels.js\";\nimport { TracevalsError } from \"../types.js\";\nimport {\n configuredGrants,\n EXECUTION_GRANTS,\n isExecutionGrant,\n unknownGrantsMessage,\n type ExecutionGrant,\n} from \"../../shared/execution.js\";\n\nconst configSchema = configSchemaJson as Record<string, unknown>;\n\nexport const DEFAULT_CONFIG_FILENAME =\n FAMILY_CONFIG_NAMES[0] ?? \"manni.config.yaml\";\n\n/**\n * Top-level key holding this tool's settings inside the shared family config.\n * Sibling tools (meta, docevals) own their own keys in the same file.\n */\nexport const CONFIG_SECTION_KEY = \"tracevals\";\n\n/**\n * The section key as an error's instance path spells it. The schema describes\n * the section rather than the file, so Ajv's own paths start below it; a\n * message that said `/provider` would name a key nobody writes at the root.\n */\nconst CONFIG_SECTION_KEY_PATH = `/${CONFIG_SECTION_KEY}`;\n\n/**\n * No legacy filename. The family file is the only one read, so a file named\n * for the tool is not config however it is spelled, and nothing warns about\n * one because nothing looks for it.\n */\nconst CONFIG_FILE: ConfigFileOptions = {\n section: CONFIG_SECTION_KEY,\n legacyNames: [],\n toError: (message) => new TracevalsError(message),\n};\n\nexport interface TracevalsConfig {\n /**\n * Which provider judges, as `tracevals.provider` names it. `null` when the\n * key is absent, which defers to the family's `providers.provider`. The\n * connection settings are never here: they are `providers` below.\n */\n provider: string | null;\n /** The model within `provider`; `null` when unset. manni pins none. */\n model: string | null;\n /** The family's top-level `providers:` map, parsed by the shared loader. */\n providers: ProvidersConfig;\n /** The file as the user would name it, for messages. */\n configSource: string;\n judge: {\n ensembleRuns: number;\n temperature: number;\n zones: { autoPass: number; autoFail: number };\n cacheDir: string;\n /**\n * Ensemble runs this invocation may spend, or `null` for unbounded. A\n * cached ensemble spends none, and an eval the budget cannot cover is\n * `skipped` with the `turn budget` reason rather than dropped.\n */\n maxTurns: number | null;\n /**\n * Extra patterns scrubbed from the session digest before it reaches a\n * provider, applied *on top of* the built-in secret shapes (ADR 01020).\n * Always a list; validated for compilability at load time.\n */\n redact: string[];\n };\n render: {\n maxBlockChars: number;\n maxTotalChars: number;\n };\n /**\n * What content-authored code a run may execute: the grants it holds, every\n * one unless the operator narrows it (proposal 0075). A `command` eval runs\n * only under `frontmatter-commands`; `[]` runs none and reports them\n * `skipped`.\n */\n execution: { allow: ExecutionGrant[] };\n history: {\n file: string;\n };\n /**\n * Session manifests (ADR 01024). `capture` writes one here; `run` looks here\n * for the trace's own, and reports a `skipped` hash check when there is none.\n */\n capture: {\n /** Resolved against the project root, not the working directory. */\n dir: string;\n };\n fill: {\n /** Minimum self-reported confidence a proposal needs to be written. */\n confidenceThreshold: number;\n maxEvalsPerArtifact: number;\n temperature: number;\n cacheDir: string;\n /** Inference calls this invocation may spend, or `null` for unbounded. */\n maxTurns: number | null;\n };\n /**\n * `calibrate` — measuring the judge against a human's answers (ADR 01022).\n * The sweep grid lives here rather than behind flags because the useful\n * range is a property of a corpus, and a corpus outlives an invocation.\n */\n calibrate: {\n /** Labels sidecar, resolved against the config file's directory. */\n labels: string;\n /** Thresholds. Unset means the run measures without gating. */\n maxFalsePass?: number;\n maxFalseFail?: number;\n maxReview?: number;\n sweep: {\n ensembleRuns: number[];\n autoPass: number[];\n autoFail: number[];\n };\n };\n failOnReview: boolean;\n /**\n * Module specifiers imported before evals are planned, so a `registerGrader`\n * call from outside this package lands in time (ADR 01017). Resolved against\n * the config file's directory, in order — a later entry wins a colliding\n * kind. `--require` appends to this list rather than replacing it.\n */\n plugins: string[];\n /** List offered-but-unused artifacts in coverage, not just count them. */\n reportUnusedArtifacts: boolean;\n /**\n * Checking each turn against its rule sources (proposal 0079). `null` when\n * the section is absent, which keeps tracevals out of every hook; `{}` puts\n * it in play with these defaults.\n */\n conformance: ConformanceConfig | null;\n}\n\nexport interface ConformanceConfig {\n /** The in-loop judge. `null` falls back to `tracevals.provider` / `model`. */\n hook: { provider: string | null; model: string | null; runs: number };\n /** Globs of designated rule sources, in scope once read. */\n include: string[];\n /** Globs never treated as rule sources. */\n exclude: string[];\n /** Globs of files that say what to build, in scope once touched (proposal 0080). */\n plans: string[];\n}\n\n// `verbose` puts the parent schema on each error, so an unknown key can be\n// checked against the keys its section does have.\nconst ajv = new Ajv2020({ allErrors: true, verbose: true });\nconst validate = ajv.compile(configSchema);\n\n/**\n * `; did you mean \"ensembleRuns\"?` when `key` is the kebab spelling of a key\n * its section has. Only the exact counterpart: a guess at a near miss is\n * advice that can be wrong, and the kebab spelling is the one mistake a\n * reader of the frontmatter vocabulary is likely to make here.\n */\nfunction camelCaseHint(key: string, parentSchema: unknown): string {\n const camel = key.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n if (camel === key || parentSchema === null || typeof parentSchema !== \"object\") {\n return \"\";\n }\n const properties = (parentSchema as { properties?: unknown }).properties;\n return properties !== null &&\n typeof properties === \"object\" &&\n Object.hasOwn(properties, camel)\n ? `; did you mean \"${camel}\"?`\n : \"\";\n}\n\n/**\n * The hint on an old `provider:` object. The key used to hold a `default` and\n * a section per provider; it is now the provider's name, as `docevals.provider`\n * and `fill.provider` are, and the connection settings moved to the family's\n * top-level `providers:` map, which every tool reads. Ajv's own message says\n * it must be a string, which is true and leaves the reader to find out where\n * the settings went.\n */\nfunction movedProviderHint(instancePath: string, keyword: string): string {\n return instancePath === \"/provider\" && keyword === \"type\"\n ? `; \"provider\" is now a provider name; per-provider settings moved to the top-level providers: map`\n : \"\";\n}\n\n/**\n * The section as the schema admits it: every key optional, because\n * `parseConfig` supplies the defaults. Ajv has checked the document against\n * `config-schema.json` before it is read as this, so the one cast below is\n * where the validated document becomes a typed one.\n */\ninterface RawConfig {\n provider?: string;\n model?: string;\n judge?: {\n ensembleRuns?: number;\n temperature?: number;\n zones?: { autoPass?: number; autoFail?: number };\n cacheDir?: string;\n maxTurns?: number;\n redact?: string[];\n };\n render?: { maxBlockChars?: number; maxTotalChars?: number };\n execution?: { allow?: ExecutionGrant[] };\n history?: { file?: string };\n capture?: { dir?: string };\n fill?: {\n confidenceThreshold?: number;\n maxEvalsPerArtifact?: number;\n temperature?: number;\n cacheDir?: string;\n maxTurns?: number;\n };\n calibrate?: {\n labels?: string;\n maxFalsePass?: number;\n maxFalseFail?: number;\n maxReview?: number;\n sweep?: { ensembleRuns?: number[]; autoPass?: number[]; autoFail?: number[] };\n };\n failOnReview?: boolean;\n plugins?: string[];\n reportUnusedArtifacts?: boolean;\n conformance?: {\n hook?: { provider?: string; model?: string; runs?: number };\n include?: string[];\n exclude?: string[];\n plans?: string[];\n };\n}\n\n/** What the file the section came from carries beside it. */\nexport interface ConfigFileContext {\n /** The file as the user would name it, for messages. */\n source?: string;\n /** The file's top-level `providers:`; `{}` when it declares none. */\n providers?: ProvidersConfig;\n}\n\nexport function parseConfig(\n raw: unknown,\n file: ConfigFileContext = {},\n): TracevalsConfig {\n const source = file.source ?? DEFAULT_CONFIG_FILENAME;\n // Before the schema: Ajv's enum error names neither the value nor the\n // grants that exist, and a grant is the key where a misreading costs most.\n const unknownGrants = configuredGrants(raw).filter((g) => !isExecutionGrant(g));\n if (unknownGrants.length > 0) {\n throw new TracevalsError(`${source}: ${unknownGrantsMessage(unknownGrants)}`);\n }\n if (!validate(raw)) {\n const detail = (validate.errors ?? [])\n .map((e) => {\n // Ajv reports an unknown key against the *parent* object, so the bare\n // message (\"must NOT have additional properties\") leaves the reader to\n // diff their file against the schema to find which key it meant. Name\n // it: the common case is a removed key in an unmigrated config —\n // `judge.maxCostUsd` after the turn budget landed, say — and a\n // migration error that makes you guess is one people work around.\n const extra =\n e.keyword === \"additionalProperties\"\n ? (e.params as { additionalProperty?: string }).additionalProperty\n : undefined;\n return extra !== undefined\n ? `unknown key \"${extra}\"${camelCaseHint(extra, e.parentSchema)}`\n : `${CONFIG_SECTION_KEY_PATH}${e.instancePath} ${e.message ?? \"is invalid\"}` +\n movedProviderHint(e.instancePath, e.keyword);\n })\n .join(\"; \");\n throw new TracevalsError(`${source}: ${detail}`);\n }\n const r = raw as RawConfig;\n // Checked here, with the message every other tool in the family gives, so a\n // typo is caught by every verb and not only the ones that reach a model.\n // Whether a model has a provider to own it waits for the flags: a\n // `--provider`, or the family's `providers.provider`, can supply the\n // provider a configured model needs.\n const provider = r.provider ?? null;\n if (provider !== null) {\n // jev only decides. Out of the loop a provider extracts rules and writes\n // verdicts, which are generations.\n if (provider === JEV) throw new TracevalsError(JEV_OUT_OF_LOOP);\n assertKnownProvider(provider, (message) => new TracevalsError(message));\n }\n const hookProvider = r.conformance?.hook?.provider ?? null;\n if (hookProvider !== null) {\n assertKnownProvider(hookProvider, (message) => new TracevalsError(message), { decisions: true });\n }\n const config: TracevalsConfig = {\n provider,\n model: r.model ?? null,\n providers: file.providers ?? {},\n configSource: source,\n judge: {\n ensembleRuns: r.judge?.ensembleRuns ?? 3,\n temperature: r.judge?.temperature ?? 0,\n zones: {\n autoPass: r.judge?.zones?.autoPass ?? 0.8,\n autoFail: r.judge?.zones?.autoFail ?? 0.8,\n },\n cacheDir: r.judge?.cacheDir ?? \".manni/tracevals/cache\",\n // `null`, not a number: unbounded is a state, and any number here would\n // be a ceiling nobody asked for.\n maxTurns: r.judge?.maxTurns ?? null,\n // Always a list: the render site concatenates nothing onto it, but a\n // hole here would be a special case in every consumer.\n redact: [...(r.judge?.redact ?? [])],\n },\n render: {\n maxBlockChars: r.render?.maxBlockChars ?? 2000,\n maxTotalChars: r.render?.maxTotalChars ?? 150000,\n },\n execution: { allow: [...(r.execution?.allow ?? EXECUTION_GRANTS)] },\n history: {\n file: r.history?.file ?? \".manni/tracevals/history.jsonl\",\n },\n capture: {\n // Beside the judge cache, under the state directory that already travels\n // with the project — which is what puts a manifest next to its trace in\n // the CI patterns the docs describe.\n dir: r.capture?.dir ?? DEFAULT_CAPTURE_DIR,\n },\n fill: {\n // 0.7 matches the manuscript's calibration bar for judged agreement.\n confidenceThreshold: r.fill?.confidenceThreshold ?? 0.7,\n maxEvalsPerArtifact: r.fill?.maxEvalsPerArtifact ?? 8,\n temperature: r.fill?.temperature ?? 0,\n // Separate from the judge cache: different key scheme and value shape.\n cacheDir: r.fill?.cacheDir ?? \".manni/tracevals/cache/fill\",\n maxTurns: r.fill?.maxTurns ?? null,\n },\n calibrate: {\n labels: r.calibrate?.labels ?? DEFAULT_LABELS_FILE,\n sweep: {\n // Spans the range rather than filling it: the first sweep judges the\n // corpus at the largest value here, so a wide grid is the one part of\n // calibration that does cost money.\n ensembleRuns: [...(r.calibrate?.sweep?.ensembleRuns ?? [1, 3, 5])],\n autoPass: [\n ...(r.calibrate?.sweep?.autoPass ?? [0.5, 0.6, 0.7, 0.8, 0.9, 0.95]),\n ],\n autoFail: [\n ...(r.calibrate?.sweep?.autoFail ?? [0.5, 0.6, 0.7, 0.8, 0.9, 0.95]),\n ],\n },\n },\n failOnReview: r.failOnReview ?? true,\n // Always a list, never undefined: the read site concatenates `--require`\n // onto it, and a hole there would be a special case in every caller.\n plugins: [...(r.plugins ?? [])],\n // An observation, not a gate: listing it is opt-in because a real roster\n // runs to hundreds of skills (ADR 01016).\n reportUnusedArtifacts: r.reportUnusedArtifacts ?? false,\n conformance:\n r.conformance === undefined\n ? null\n : {\n hook: {\n provider: hookProvider,\n model: r.conformance.hook?.model ?? null,\n runs: r.conformance.hook?.runs ?? 1,\n },\n include: [...(r.conformance.include ?? [])],\n exclude: [...(r.conformance.exclude ?? [])],\n plans: [...(r.conformance.plans ?? [])],\n },\n };\n // Compilability is not expressible in JSON Schema, and a pattern that cannot\n // compile must fail here rather than at the moment a digest is about to be\n // sent — a dropped redaction pattern is a silent leak.\n compileRedactPatterns(config.judge.redact);\n // Left absent rather than defaulted to a number: `0` is a meaningful limit\n // (\"no false pass at all\"), so it cannot double as \"unset\".\n for (const key of [\"maxFalsePass\", \"maxFalseFail\", \"maxReview\"] as const) {\n if (typeof r.calibrate?.[key] === \"number\") {\n config.calibrate[key] = r.calibrate[key];\n }\n }\n return config;\n}\n\n/** This tool's config, and the directory its relative paths resolve from. */\nexport interface LoadedConfig {\n config: TracevalsConfig;\n /**\n * The directory holding the config file, or `dir` when none was found.\n * Plugin specifiers and the labels default resolve against it, so a\n * committed config means the same thing from any working directory.\n */\n dir: string;\n /**\n * The file's top-level `collections:` (proposal 0041); `[]` with no config.\n *\n * Collections never choose tracevals' inputs — `run` and `calibrate` take\n * traces, `fill` detects artifacts under `--project` — and there is no\n * `--collection`. What they say is *where a relocated `metadata` block\n * lives*, so a declared manifest is read for the evals an artifact no longer\n * carries inline (proposals 0047 and 0049 §1).\n */\n collections: CollectionConfig[];\n /**\n * The config file's absolute path; absent when there is none. A keyless\n * manifest owns what an artifact's schemas mark external (proposal 0068),\n * and those schemas are read from meta's section of this same file.\n */\n path?: string;\n}\n\n/** How a command was told to find its config: `-c` and `--no-config`. */\nexport interface ConfigLookup {\n /** `-c/--config`: read this file instead of discovering one. */\n configPath?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n}\n\n/**\n * Discover the family config from `dir` (cwd by default) upward to the\n * repository root and return this tool's section (`src/shared/config-file.ts`:\n * `manni.config.yaml` read at its `tracevals:` key, with the family's\n * top-level `providers:` beside it). An absent file — or one that carries only\n * other tools' sections — yields defaults.\n *\n * `-c` names a file and skips the walk; `--no-config` skips the file\n * altogether and runs on the built-in defaults, with `dir` still anchoring\n * whatever the config would otherwise have anchored.\n */\nexport async function discoverConfig(\n dir = process.cwd(),\n lookup: ConfigLookup = {},\n): Promise<LoadedConfig> {\n if (lookup.noConfig === true) {\n // No config means no collections, so no manifest owns anything and every\n // artifact's evals are its own front matter's — the same rule cite states.\n return { config: parseConfig({}), dir, collections: [] };\n }\n const file = await Promise.resolve().then(() =>\n lookup.configPath === undefined\n ? findConfigFileSync(dir, CONFIG_FILE)\n : readConfigFileSync(lookup.configPath, dir, CONFIG_FILE),\n );\n if (file === null) return { config: parseConfig({}), dir, collections: [] };\n return {\n config: parseConfig(file.value ?? {}, {\n source: file.source,\n ...(file.providers !== undefined ? { providers: file.providers } : {}),\n }),\n dir: file.dir,\n collections: file.collections,\n path: file.path,\n };\n}\n\n/** `discoverConfig`, for callers that only want the settings. */\nexport async function loadConfig(\n dir = process.cwd(),\n lookup: ConfigLookup = {},\n): Promise<TracevalsConfig> {\n return (await discoverConfig(dir, lookup)).config;\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:tracevals:config\",\n \"title\": \"tracevals section of manni.config.yaml\",\n \"description\": \"Settings for manni tracevals, held under the `tracevals` key of the config file shared by the manni family of tools. Sibling keys belong to other tools and are not validated here.\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Which provider judges out of the loop, and extracts rules: auto, anthropic, openai, claude-cli, or llama-cpp. jev only decides, so it is refused here; name it as conformance.hook.provider. Overrides the family's top-level `providers.provider` for tracevals only. Connection settings — an endpoint, an API key's environment variable, the Claude CLI command — live in that top-level `providers:` map, never here.\"\n },\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The model within `provider`, which must be named at this level. Unset, the inference library's default for the winning provider is used; manni pins no model id of its own.\"\n },\n \"judge\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"ensembleRuns\": { \"type\": \"integer\", \"minimum\": 1 },\n \"temperature\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 2 },\n \"zones\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"autoPass\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 },\n \"autoFail\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 }\n }\n },\n \"cacheDir\": { \"type\": \"string\" },\n \"maxTurns\": { \"type\": \"integer\", \"minimum\": 1, \"description\": \"Stop after this many ensemble runs. A cached ensemble spends none. Unset means unbounded; the remaining evals report `skipped` with the reason `turn budget` rather than aborting the run.\" },\n \"redact\": {\n \"type\": \"array\",\n \"description\": \"Extra regular expressions scrubbed from the session digest before it is sent to a judge provider. Applied on top of the built-in secret shapes, never instead of them; each source is compiled with the `g` flag, and a match is replaced with `[redacted]`. Pattern matching is best-effort — --deterministic-only is the only setting that guarantees nothing leaves the machine.\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n }\n }\n },\n \"execution\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Operator grant for executing content-authored code.\",\n \"properties\": {\n \"allow\": {\n \"type\": \"array\",\n \"items\": { \"enum\": [\"frontmatter-commands\"] },\n \"default\": [\"frontmatter-commands\"],\n \"description\": \"Which content-authored code a run may execute. Absent, every grant holds; list fewer to narrow it, or write [] to run none. frontmatter-commands lets `command` evals declared in an artifact's front matter run; without it they report `skipped` with a reason, never `pass`.\"\n }\n }\n },\n \"render\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"maxBlockChars\": { \"type\": \"integer\", \"minimum\": 100 },\n \"maxTotalChars\": {\n \"type\": \"integer\",\n \"minimum\": 1000,\n \"description\": \"Upper bound on the rendered digest, in characters. The timeline always keeps at least 200 characters, so a very long header can push the digest past this bound by up to 200.\"\n }\n }\n },\n \"history\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"file\": { \"type\": \"string\" }\n }\n },\n \"capture\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Session manifests — sha256 of every instruction artifact plus the git SHA, recorded at session start by `manni tracevals capture` and read back by `run` to make staleness exact instead of an mtime guess. See ADR 01024.\",\n \"properties\": {\n \"dir\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Directory manifests are written to and looked for, resolved against the project root. `run` also accepts one placed beside the trace as `<trace>.manifest.json`, and --manifest names one outright.\"\n }\n }\n },\n \"fill\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"confidenceThreshold\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 },\n \"maxEvalsPerArtifact\": { \"type\": \"integer\", \"minimum\": 1 },\n \"temperature\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 2 },\n \"cacheDir\": { \"type\": \"string\" },\n \"maxTurns\": { \"type\": \"integer\", \"minimum\": 1, \"description\": \"Stop after this many inference calls, one per artifact filled. A cached artifact spends none. Unset means unbounded.\" }\n }\n },\n \"calibrate\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Settings for `manni tracevals calibrate` — measuring the tool's verdicts against a human's answers. See ADR 01022.\",\n \"properties\": {\n \"labels\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Default labels sidecar, resolved against this config file's directory. Overridden by --labels.\"\n },\n \"maxFalsePass\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Fail the calibration run (exit 1) above this many false passes — labelled fail, judged pass. Unset by default: a calibration run is a measurement, not a gate.\"\n },\n \"maxFalseFail\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Fail the calibration run above this many false fails — labelled pass, judged fail.\"\n },\n \"maxReview\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"description\": \"Fail the calibration run above this many needs-review outcomes across the whole corpus.\"\n },\n \"sweep\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Values --sweep tries on each axis, one axis at a time with the others held at their configured value. The corpus is judged once at the largest ensembleRuns here and every cell is re-scored from those cached runs, so the grid costs nothing beyond that one run.\",\n \"properties\": {\n \"ensembleRuns\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"integer\", \"minimum\": 1 }\n },\n \"autoPass\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 }\n },\n \"autoFail\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 }\n }\n }\n }\n }\n },\n \"conformance\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"Checking each turn against the rules the files that govern the agent declare. Present, even as {}, it puts tracevals in play under Claude Code hooks; absent, tracevals stays out of them.\",\n \"properties\": {\n \"hook\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"description\": \"The judge inside a Stop or SubagentStop hook. Each key falls back to the top-level one of the same name.\",\n \"properties\": {\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The provider that judges inside a hook. Default: tracevals.provider. jev is accepted here, and only here.\"\n },\n \"model\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The model that judges inside a hook. Default: tracevals.model.\"\n },\n \"runs\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"description\": \"Judge calls per rule inside a hook. A rule blocks only when every run scores it not followed at the bar. jev makes one call and ignores it. Default 1.\"\n }\n }\n },\n \"include\": {\n \"type\": \"array\",\n \"description\": \"Globs, relative to the project root, naming files that govern agents beyond the known formats. Each applies to every turn.\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"exclude\": {\n \"type\": \"array\",\n \"description\": \"Globs, relative to the project root, naming files never treated as rule sources, in any format. It removes plan and spec files too.\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"plans\": {\n \"type\": \"array\",\n \"default\": [],\n \"description\": \"Globs, relative to the project root, naming files that say what to build, beyond the known spec formats. Each is a rule source once the session touches it.\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n }\n }\n },\n \"failOnReview\": { \"type\": \"boolean\" },\n \"plugins\": {\n \"type\": \"array\",\n \"description\": \"Modules imported before evals are planned, so one calling registerGrader() can add a grader kind the built-ins do not cover. A relative or absolute path resolves against this file's directory, not the working directory; a bare package name resolves the way an import from this file's directory would. Load order is significant: a later entry wins a colliding kind.\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"reportUnusedArtifacts\": {\n \"type\": \"boolean\",\n \"description\": \"List every skill and agent the session was offered and never used, rather than only counting them. Off by default: a real roster runs to hundreds of skills.\"\n }\n }\n}\n","/**\n * The calibration labels sidecar (ADR 01022).\n *\n * A label is a human's answer for one `(trace, artifact, eval)`. It lives in\n * its own file rather than in the eval entry for two reasons: the vendored\n * `artifact-evals` vocabulary is docmeta's and `inlineEval` is closed to\n * additions (ADR 01010), and — more importantly — a label is a property of a\n * *corpus and a reviewer*, not of the artifact. Two teams calibrating the same\n * skill against different sessions hold different ground truth, and neither\n * belongs in the SKILL.md.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { Ajv2020 } from \"ajv/dist/2020.js\";\nimport { parse as parseYaml } from \"yaml\";\nimport labelsSchemaJson from \"./labels-schema.json\" with { type: \"json\" };\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { TracevalsError } from \"../types.js\";\nimport type { ArtifactType } from \"../artifacts/types.js\";\n\nconst labelsSchema = labelsSchemaJson as Record<string, unknown>;\n\n/** Conventional location inside a project; overridable with `--labels`. */\nexport const DEFAULT_LABELS_FILE = \"tracevals/labels.yaml\";\n\n/**\n * What a human decided. `needs-review` is a legitimate label, not a cop-out:\n * an eval you found genuinely ambiguous is the one that tells you whether the\n * review band is set sensibly, and the docs have always asked for a couple.\n */\nexport type LabelOutcome = \"pass\" | \"fail\" | \"needs-review\";\n\nexport interface EvalLabel {\n /** Path exactly as written in the file, for error messages. */\n trace: string;\n /** Resolved absolute path — the join key against the batch corpus. */\n traceFile: string;\n artifact: string;\n /** Only when the file disambiguates a name shared by two artifact kinds. */\n type?: ArtifactType;\n eval: string;\n expected: LabelOutcome;\n note?: string;\n}\n\nconst ajv = new Ajv2020({ allErrors: true });\nconst validate = ajv.compile(labelsSchema);\n\n/**\n * Stable identity for one label, and the duplicate-detection key.\n *\n * The separator is written as a backslash-u escape, never as a literal NUL:\n * the runtime value is identical, but a literal one makes git call the file\n * binary — its diff renders as `Bin 0 -> N bytes` and cannot be reviewed or\n * three-way merged, and `grep` answers `Binary file … matches` and stops.\n * `test/unit/source-text-safety.test.ts` holds the whole tree to this.\n */\nexport const labelKey = (\n traceFile: string,\n artifact: string,\n evalName: string,\n type?: ArtifactType,\n): string => `${traceFile}\\u0000${type ?? \"\"}\\u0000${artifact}\\u0000${evalName}`;\n\n/**\n * Validate a labels document and resolve its trace paths.\n *\n * `file` is the path the text came from; trace paths resolve against **its**\n * directory rather than the working directory, matching how `plugins` resolves\n * against the config file that names them. A labels file travels with its\n * corpus, so it must mean the same thing from any cwd.\n */\nexport function parseLabels(text: string, file: string): EvalLabel[] {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (err) {\n throw new TracevalsError(\n `could not parse ${file}: ${errorMessage(err)}`,\n );\n }\n if (raw === null || raw === undefined) {\n throw new TracevalsError(`invalid labels file ${file}: it is empty`);\n }\n if (!validate(raw)) {\n const detail = (validate.errors ?? [])\n .map((e) => `${e.instancePath || \"/\"} ${e.message ?? \"invalid\"}`)\n .join(\"; \");\n // The empty-list case gets its own wording: \"must NOT have fewer than 1\n // items\" describes the schema, not the mistake.\n const empty = (validate.errors ?? []).some(\n (e) => e.instancePath === \"/labels\" && e.keyword === \"minItems\",\n );\n throw new TracevalsError(\n empty\n ? `invalid labels file ${file}: it must carry at least one label — an empty one measures nothing`\n : `invalid labels file ${file}: ${detail}`,\n );\n }\n\n const base = dirname(resolve(file));\n const labels: EvalLabel[] = [];\n const seen = new Set<string>();\n for (const entry of (raw as { labels: Record<string, string>[] }).labels) {\n const traceFile = resolve(base, entry.trace as string);\n const type = entry.type as ArtifactType | undefined;\n const key = labelKey(\n traceFile,\n entry.artifact as string,\n entry.eval as string,\n type,\n );\n if (seen.has(key)) {\n // Two answers for one question is not a merge problem to resolve at run\n // time — whichever won would silently decide the measurement.\n throw new TracevalsError(\n `invalid labels file ${file}: duplicate label for ${entry.artifact ?? \"?\"} › ${entry.eval ?? \"?\"} on ${entry.trace ?? \"?\"}`,\n );\n }\n seen.add(key);\n labels.push({\n trace: entry.trace as string,\n traceFile,\n artifact: entry.artifact as string,\n ...(type !== undefined ? { type } : {}),\n eval: entry.eval as string,\n expected: entry.expected as LabelOutcome,\n ...(entry.note !== undefined ? { note: entry.note } : {}),\n });\n }\n return labels;\n}\n\nexport async function loadLabels(file: string): Promise<EvalLabel[]> {\n let text: string;\n try {\n text = await readFile(file, \"utf-8\");\n } catch (err) {\n throw new TracevalsError(\n `could not read labels file ${file}: ${errorMessage(err)}`,\n );\n }\n return parseLabels(text, file);\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:tracevals:calibration-labels\",\n \"title\": \"manni tracevals calibration labels\",\n \"description\": \"Ground truth for `manni tracevals calibrate`: what a human decided a given eval should have produced on a given trace. A sidecar rather than an eval field, because a label belongs to a corpus and a reviewer, not to the artifact — and because the eval vocabulary is docmeta's, vendored byte-identical, with `inlineEval` closed to additions (ADR 01010).\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"version\", \"labels\"],\n \"properties\": {\n \"version\": {\n \"const\": 1,\n \"description\": \"Format version. Pinned so a future shape change is an explicit migration rather than a silently-reinterpreted file.\"\n },\n \"labels\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"description\": \"One entry per (trace, artifact, eval) you have judged by hand.\",\n \"items\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"trace\", \"artifact\", \"eval\", \"expected\"],\n \"properties\": {\n \"trace\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Path to the trace file, resolved against this file's own directory — not the working directory.\"\n },\n \"artifact\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Artifact name as the report shows it: a skill name, a subagent_type, or a project-rules filename such as CLAUDE.md.\"\n },\n \"type\": {\n \"enum\": [\"skill\", \"agent\", \"project-rules\", \"slash-command\"],\n \"description\": \"Optional disambiguator, needed when one name resolves to two kinds of artifact — a skill and an agent, or a skill and the slash command that types it. Every `ArtifactType` the resolver can produce belongs here: a label whose type this rejects has no way to name the artifact it means.\"\n },\n \"eval\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"The eval's id. Shorthand entries with no declared id get a positional one (eval-1, eval-2, ...), so labelling those is only as stable as the order they are written in.\"\n },\n \"expected\": {\n \"enum\": [\"pass\", \"fail\", \"needs-review\"],\n \"description\": \"What you decided. `needs-review` means you found it genuinely ambiguous and want the tool to defer too.\"\n },\n \"note\": {\n \"type\": \"string\",\n \"description\": \"Why you decided that. Carried into the disagreement report, where it is the whole reason a disagreement is actionable.\"\n }\n }\n }\n }\n }\n}\n"],"mappings":"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","names":["Ajv2020","ajv","Ajv2020","validate"]}
|