@hawkeyexl/manni 4.4.1 → 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-HYNGXYJV.js → check-OAJWC3WD.js} +7 -5
- package/dist/{check-ASPIHA6B.js → check-PKY7KTQE.js} +13 -14
- package/dist/check-WB2QDHJQ.js +880 -0
- package/dist/check-WB2QDHJQ.js.map +1 -0
- package/dist/{chunk-MWJLZMBL.js → chunk-2JFPBZJK.js} +11 -11
- package/dist/{chunk-QQUKGCAJ.js → chunk-2KRB3EG7.js} +2 -2
- package/dist/{chunk-DXNZS72W.js → chunk-2M6DVNI5.js} +10 -6
- package/dist/{chunk-DXNZS72W.js.map → chunk-2M6DVNI5.js.map} +1 -1
- package/dist/{chunk-QZ6LRSNV.js → chunk-3NWX34ZI.js} +19 -19
- package/dist/{chunk-IDV6HJCB.js → chunk-5G53XATW.js} +4 -4
- package/dist/{chunk-M2JCK5F6.js → chunk-6KKZXB2O.js} +19 -6
- package/dist/chunk-6KKZXB2O.js.map +1 -0
- package/dist/{chunk-PNPQTHBT.js → chunk-733Y2STG.js} +2 -2
- package/dist/{chunk-WB3QM6PP.js → chunk-73TC4DYH.js} +332 -2522
- package/dist/chunk-73TC4DYH.js.map +1 -0
- package/dist/{chunk-EPH54CAY.js → chunk-7WRP5FFP.js} +4 -4
- package/dist/{chunk-NXV7WE2D.js → chunk-APKH2T6E.js} +29 -591
- package/dist/chunk-APKH2T6E.js.map +1 -0
- package/dist/{chunk-I2AH3CJJ.js → chunk-B3TS4WRM.js} +17 -15
- package/dist/{chunk-I2AH3CJJ.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-MMTSSTG7.js → chunk-C3B2VJNC.js} +2 -2
- package/dist/{chunk-PU6DFJMY.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-GCQRPUSB.js → chunk-DC5DDJVE.js} +6 -6
- package/dist/{chunk-6OYEI2VV.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-7UKO3ASZ.js → chunk-GAJIJKET.js} +3 -3
- package/dist/{chunk-6JSSEWBG.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-4IUC2MNL.js → chunk-IY7NYNPZ.js} +9 -11
- package/dist/{chunk-4IUC2MNL.js.map → chunk-IY7NYNPZ.js.map} +1 -1
- package/dist/{chunk-57NEQRVO.js → chunk-KCOFEWV5.js} +8 -6
- package/dist/{chunk-57NEQRVO.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-NLXTXE5Y.js → chunk-M6GSS72T.js} +185 -33
- package/dist/chunk-M6GSS72T.js.map +1 -0
- package/dist/{chunk-YTURO7SI.js → chunk-MHM4QEBV.js} +4 -4
- package/dist/{chunk-RL5XWQOL.js → chunk-MOWMCEOJ.js} +143 -54
- package/dist/chunk-MOWMCEOJ.js.map +1 -0
- package/dist/{chunk-C4SQM22E.js → chunk-MWBJ3KTF.js} +13 -11
- package/dist/chunk-MWBJ3KTF.js.map +1 -0
- package/dist/chunk-N7JSEDSC.js +233 -0
- package/dist/chunk-N7JSEDSC.js.map +1 -0
- package/dist/{chunk-JCDXE76J.js → chunk-NBMPHD4I.js} +2 -2
- package/dist/{chunk-37LP5HMZ.js → chunk-NHHOPZRA.js} +12 -10
- package/dist/{chunk-37LP5HMZ.js.map → chunk-NHHOPZRA.js.map} +1 -1
- package/dist/{chunk-YB4IBW3M.js → chunk-NTWW7J76.js} +2 -2
- package/dist/{chunk-UJCVAWP7.js → chunk-PCFG7E6B.js} +3 -3
- package/dist/{chunk-UJCVAWP7.js.map → chunk-PCFG7E6B.js.map} +1 -1
- package/dist/{chunk-FBEQCK47.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-PIKOVN6W.js → chunk-QW77LCOU.js} +10 -10
- package/dist/{chunk-2B7ZNTPV.js → chunk-SM6NOMJS.js} +2 -2
- package/dist/chunk-SWSTHZBI.js +2464 -0
- package/dist/chunk-SWSTHZBI.js.map +1 -0
- package/dist/{chunk-JXLTXMJ7.js → chunk-T6SYGLWR.js} +3 -3
- package/dist/{chunk-CK7SKVHR.js → chunk-TBAMBLF3.js} +3 -12
- package/dist/chunk-TBAMBLF3.js.map +1 -0
- package/dist/chunk-TH4JVQPF.js +133 -0
- package/dist/chunk-TH4JVQPF.js.map +1 -0
- package/dist/{chunk-QRWGPQKO.js → chunk-TLXE7LYK.js} +4 -4
- package/dist/{chunk-M3W7J6MU.js → chunk-TUAAR3MM.js} +3280 -283
- package/dist/chunk-TUAAR3MM.js.map +1 -0
- package/dist/{chunk-SKSDRUUK.js → chunk-UAKNZVCD.js} +4 -4
- package/dist/{chunk-YJOGUXGP.js → chunk-UJSGS2Y5.js} +8 -6
- package/dist/{chunk-YJOGUXGP.js.map → chunk-UJSGS2Y5.js.map} +1 -1
- package/dist/{chunk-UQISLDAV.js → chunk-UWQ2UVHE.js} +8 -6
- package/dist/{chunk-UQISLDAV.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-MYMBCTDE.js → chunk-XXDXIIQ4.js} +2 -2
- package/dist/chunk-YGFIQ6Y5.js +17 -0
- package/dist/chunk-YGFIQ6Y5.js.map +1 -0
- package/dist/chunk-YLK2J5YK.js +610 -0
- package/dist/chunk-YLK2J5YK.js.map +1 -0
- package/dist/{chunk-3VK37OR2.js → chunk-Z4IZGEM3.js} +16 -12
- package/dist/{chunk-3VK37OR2.js.map → chunk-Z4IZGEM3.js.map} +1 -1
- package/dist/{cli-6HIDIFVT.js → cli-6EWVMEN6.js} +5 -3
- package/dist/{cli-6HIDIFVT.js.map → cli-6EWVMEN6.js.map} +1 -1
- package/dist/{cli-VI7VHWNZ.js → cli-6H7HVDMQ.js} +113 -20
- package/dist/{cli-VI7VHWNZ.js.map → cli-6H7HVDMQ.js.map} +1 -1
- package/dist/{cli-RPM5PELX.js → cli-EPVZHAZS.js} +24 -20
- package/dist/cli-EPVZHAZS.js.map +1 -0
- package/dist/{cli-MN7PYMBI.js → cli-LUCSGTVI.js} +17 -19
- package/dist/{cli-MN7PYMBI.js.map → cli-LUCSGTVI.js.map} +1 -1
- package/dist/{cli-LFP5ZGYS.js → cli-NIG4N3XM.js} +16 -15
- package/dist/{cli-LFP5ZGYS.js.map → cli-NIG4N3XM.js.map} +1 -1
- package/dist/{cli-PYPX6O6E.js → cli-PSKNB66T.js} +225 -58
- package/dist/cli-PSKNB66T.js.map +1 -0
- package/dist/{cli-3BIBYHFK.js → cli-UO4NHIB3.js} +17 -17
- package/dist/{cli-6UB5N6CU.js → cli-UQ7A3YA2.js} +17 -18
- package/dist/{cli-6UB5N6CU.js.map → cli-UQ7A3YA2.js.map} +1 -1
- package/dist/{cli-673OTRGE.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 +102 -12
- package/dist/index.js +185 -171
- package/dist/index.js.map +1 -1
- package/dist/{json-SY7KLNC7.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-KSGV5RD4.js → page-UPSXRP75.js} +11 -12
- package/dist/prepare-6GNEWCNH.js +155 -0
- package/dist/prepare-6GNEWCNH.js.map +1 -0
- package/dist/{pretty-CXSDXNAS.js → pretty-Q6FQAOK4.js} +13 -14
- package/dist/{pretty-A5EGTN35.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-HUY7UXFS.js → reporters-45MMC2ID.js} +13 -13
- package/dist/{reporters-K2VUKSAK.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-BIQUPMOR.js → term-PCJUCWNF.js} +16 -17
- package/dist/{term-BIQUPMOR.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-GFNLTGOH.js +0 -36
- package/dist/build-COYIQ25L.js +0 -31
- package/dist/calibrate-MDBLJKEE.js +0 -31
- package/dist/capture-LRML2PKV.js +0 -32
- package/dist/check-EDLBYL5N.js +0 -27
- package/dist/chunk-6JSSEWBG.js.map +0 -1
- package/dist/chunk-A5ULMVHQ.js +0 -164
- package/dist/chunk-A5ULMVHQ.js.map +0 -1
- package/dist/chunk-C4SQM22E.js.map +0 -1
- package/dist/chunk-CK7SKVHR.js.map +0 -1
- package/dist/chunk-FBEQCK47.js.map +0 -1
- package/dist/chunk-LJ2RDH3F.js.map +0 -1
- package/dist/chunk-M2JCK5F6.js.map +0 -1
- package/dist/chunk-M3W7J6MU.js.map +0 -1
- package/dist/chunk-NLXTXE5Y.js.map +0 -1
- package/dist/chunk-NXV7WE2D.js.map +0 -1
- package/dist/chunk-Q35YIDBV.js.map +0 -1
- package/dist/chunk-RL5XWQOL.js.map +0 -1
- package/dist/chunk-TK3FC4RF.js +0 -3090
- package/dist/chunk-TK3FC4RF.js.map +0 -1
- package/dist/chunk-TU2WUBVZ.js +0 -2
- package/dist/chunk-WB3QM6PP.js.map +0 -1
- package/dist/cli-PYPX6O6E.js.map +0 -1
- package/dist/cli-RPM5PELX.js.map +0 -1
- package/dist/github-6QMYOHC3.js +0 -27
- package/dist/github-SXPGP5DB.js +0 -32
- package/dist/lint-ASMJLLPA.js +0 -28
- package/dist/list-KZNVTNVC.js +0 -31
- package/dist/list-Q57YTFUQ.js +0 -29
- package/dist/run-3DYJNRIG.js +0 -33
- package/dist/validate-53RKM2XG.js +0 -16
- /package/dist/{batch-GFNLTGOH.js.map → batch-OZOACN4G.js.map} +0 -0
- /package/dist/{build-COYIQ25L.js.map → build-Z5VOVADH.js.map} +0 -0
- /package/dist/{calibrate-MDBLJKEE.js.map → calibrate-TZYT42DR.js.map} +0 -0
- /package/dist/{capture-LRML2PKV.js.map → capture-SL4MNDDP.js.map} +0 -0
- /package/dist/{check-ASPIHA6B.js.map → check-5OMA42Y6.js.map} +0 -0
- /package/dist/{check-EDLBYL5N.js.map → check-OAJWC3WD.js.map} +0 -0
- /package/dist/{check-HYNGXYJV.js.map → check-PKY7KTQE.js.map} +0 -0
- /package/dist/{chunk-MWJLZMBL.js.map → chunk-2JFPBZJK.js.map} +0 -0
- /package/dist/{chunk-QQUKGCAJ.js.map → chunk-2KRB3EG7.js.map} +0 -0
- /package/dist/{chunk-QZ6LRSNV.js.map → chunk-3NWX34ZI.js.map} +0 -0
- /package/dist/{chunk-IDV6HJCB.js.map → chunk-5G53XATW.js.map} +0 -0
- /package/dist/{chunk-PNPQTHBT.js.map → chunk-733Y2STG.js.map} +0 -0
- /package/dist/{chunk-EPH54CAY.js.map → chunk-7WRP5FFP.js.map} +0 -0
- /package/dist/{chunk-MMTSSTG7.js.map → chunk-C3B2VJNC.js.map} +0 -0
- /package/dist/{chunk-PU6DFJMY.js.map → chunk-C73RSUIC.js.map} +0 -0
- /package/dist/{chunk-GCQRPUSB.js.map → chunk-DC5DDJVE.js.map} +0 -0
- /package/dist/{chunk-6OYEI2VV.js.map → chunk-ECVQNGTH.js.map} +0 -0
- /package/dist/{chunk-7UKO3ASZ.js.map → chunk-GAJIJKET.js.map} +0 -0
- /package/dist/{chunk-YTURO7SI.js.map → chunk-MHM4QEBV.js.map} +0 -0
- /package/dist/{chunk-JCDXE76J.js.map → chunk-NBMPHD4I.js.map} +0 -0
- /package/dist/{chunk-YB4IBW3M.js.map → chunk-NTWW7J76.js.map} +0 -0
- /package/dist/{chunk-PIKOVN6W.js.map → chunk-QW77LCOU.js.map} +0 -0
- /package/dist/{chunk-2B7ZNTPV.js.map → chunk-SM6NOMJS.js.map} +0 -0
- /package/dist/{chunk-JXLTXMJ7.js.map → chunk-T6SYGLWR.js.map} +0 -0
- /package/dist/{chunk-QRWGPQKO.js.map → chunk-TLXE7LYK.js.map} +0 -0
- /package/dist/{chunk-SKSDRUUK.js.map → chunk-UAKNZVCD.js.map} +0 -0
- /package/dist/{chunk-MYMBCTDE.js.map → chunk-XXDXIIQ4.js.map} +0 -0
- /package/dist/{cli-3BIBYHFK.js.map → cli-UO4NHIB3.js.map} +0 -0
- /package/dist/{chunk-TU2WUBVZ.js.map → cli-YHYDLQAF.js.map} +0 -0
- /package/dist/{cli-673OTRGE.js.map → config-P4HDNTYD.js.map} +0 -0
- /package/dist/{github-6QMYOHC3.js.map → conformance-ZFCMKM6M.js.map} +0 -0
- /package/dist/{github-SXPGP5DB.js.map → github-7ZCH5PSO.js.map} +0 -0
- /package/dist/{json-SY7KLNC7.js.map → github-POT6724K.js.map} +0 -0
- /package/dist/{lint-ASMJLLPA.js.map → host-6GURH5HE.js.map} +0 -0
- /package/dist/{list-KZNVTNVC.js.map → json-KT2K62L5.js.map} +0 -0
- /package/dist/{list-Q57YTFUQ.js.map → lint-5AQ5C2BV.js.map} +0 -0
- /package/dist/{page-KSGV5RD4.js.map → list-5JZKX2NK.js.map} +0 -0
- /package/dist/{pretty-A5EGTN35.js.map → list-SWPFXQMU.js.map} +0 -0
- /package/dist/{pretty-CXSDXNAS.js.map → page-UPSXRP75.js.map} +0 -0
- /package/dist/{reporters-HUY7UXFS.js.map → pretty-Q6FQAOK4.js.map} +0 -0
- /package/dist/{reporters-K2VUKSAK.js.map → pretty-SQRPFPSQ.js.map} +0 -0
- /package/dist/{run-3DYJNRIG.js.map → provider-AMGRDY6V.js.map} +0 -0
- /package/dist/{validate-53RKM2XG.js.map → reporters-45MMC2ID.js.map} +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
TracevalsError
|
|
4
|
+
} from "./chunk-UKZNLVJW.js";
|
|
5
|
+
import {
|
|
6
|
+
noticeOnce
|
|
7
|
+
} from "./chunk-HX44GB4Z.js";
|
|
8
|
+
import {
|
|
9
|
+
assertKnownProvider,
|
|
10
|
+
assertLocalFlag,
|
|
11
|
+
assertModelHasProvider,
|
|
12
|
+
localNotice,
|
|
13
|
+
providerSpecFor,
|
|
14
|
+
resolveIdentity,
|
|
15
|
+
selectProvider
|
|
16
|
+
} from "./chunk-QCHVR4ZM.js";
|
|
17
|
+
import {
|
|
18
|
+
errorMessage
|
|
19
|
+
} from "./chunk-G3T47CFV.js";
|
|
20
|
+
|
|
21
|
+
// src/tracevals/judge/provider.ts
|
|
22
|
+
import {
|
|
23
|
+
makeProvider as makeInferenceProvider,
|
|
24
|
+
mockVerdict
|
|
25
|
+
} from "@hawkeyexl/inference";
|
|
26
|
+
var JEV = "jev";
|
|
27
|
+
var JEV_OUT_OF_LOOP = "jev answers decisions only, so it cannot extract rules or write verdicts. Use it as tracevals.conformance.hook.provider.";
|
|
28
|
+
var CONFIG_KEY = "tracevals.provider";
|
|
29
|
+
var toTracevalsError = (message) => new TracevalsError(message);
|
|
30
|
+
function selectProvider2(config, flags = {}, ev = {}) {
|
|
31
|
+
assertLocalFlag(flags, toTracevalsError);
|
|
32
|
+
return selectProvider(flags, [
|
|
33
|
+
{
|
|
34
|
+
...ev.provider !== void 0 ? { provider: ev.provider } : {},
|
|
35
|
+
...ev.model !== void 0 ? { model: ev.model } : {},
|
|
36
|
+
...ev.origin !== void 0 ? { origin: ev.origin } : {}
|
|
37
|
+
},
|
|
38
|
+
...configLevels(config)
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
function selectHookProvider(config) {
|
|
42
|
+
const hook = config.conformance?.hook;
|
|
43
|
+
return selectProvider({}, [
|
|
44
|
+
{
|
|
45
|
+
...hook?.provider != null ? { provider: hook.provider } : {},
|
|
46
|
+
...hook?.model != null ? { model: hook.model } : {},
|
|
47
|
+
origin: "tracevals.conformance.hook.provider"
|
|
48
|
+
},
|
|
49
|
+
...configLevels(config)
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
function configLevels(config) {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
...config.provider !== null ? { provider: config.provider } : {},
|
|
56
|
+
...config.model !== null ? { model: config.model } : {},
|
|
57
|
+
origin: CONFIG_KEY
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
...config.providers.provider !== void 0 ? { provider: config.providers.provider } : {},
|
|
61
|
+
...config.providers.model !== void 0 ? { model: config.providers.model } : {},
|
|
62
|
+
origin: "providers.provider"
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
function announceSelection(selection) {
|
|
67
|
+
const message = localNotice(selection);
|
|
68
|
+
if (message !== void 0) noticeOnce(message);
|
|
69
|
+
}
|
|
70
|
+
function assertProviderSelection(selection) {
|
|
71
|
+
if (selection.provider === JEV) throw new TracevalsError(JEV_OUT_OF_LOOP);
|
|
72
|
+
assertKnownProvider(selection.provider, toTracevalsError);
|
|
73
|
+
assertModelHasProvider(selection.provider, selection.model, CONFIG_KEY, toTracevalsError);
|
|
74
|
+
}
|
|
75
|
+
function providerSpecFor2(config, selection, options = {}) {
|
|
76
|
+
const spec = providerSpecFor(config.providers, selection);
|
|
77
|
+
switch (selection.provider) {
|
|
78
|
+
case "anthropic":
|
|
79
|
+
return { ...spec, anthropic: { toolName: "record_verdict" } };
|
|
80
|
+
case "openai":
|
|
81
|
+
return { ...spec, openai: { schemaName: "verdict" } };
|
|
82
|
+
case "llama-cpp":
|
|
83
|
+
return {
|
|
84
|
+
...spec,
|
|
85
|
+
llamaCpp: { ...spec.llamaCpp, ...options.host ?? { host: "connect" } }
|
|
86
|
+
};
|
|
87
|
+
case "mock":
|
|
88
|
+
return {
|
|
89
|
+
...spec,
|
|
90
|
+
mockResponses: options.mockResponses ?? [mockVerdict("pass", 0.95)]
|
|
91
|
+
};
|
|
92
|
+
default:
|
|
93
|
+
return spec;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function resolveProviderIdentity(config, flags = {}, ev = {}) {
|
|
97
|
+
const selection = selectProvider2(config, flags, ev);
|
|
98
|
+
assertProviderSelection(selection);
|
|
99
|
+
return resolveSelectionIdentity(config, selection);
|
|
100
|
+
}
|
|
101
|
+
async function resolveSelectionIdentity(config, selection) {
|
|
102
|
+
const { provider, model } = selection;
|
|
103
|
+
assertKnownProvider(provider, toTracevalsError, { decisions: true });
|
|
104
|
+
assertModelHasProvider(provider, model, CONFIG_KEY, toTracevalsError);
|
|
105
|
+
announceSelection(selection);
|
|
106
|
+
return resolveIdentity(
|
|
107
|
+
providerSpecFor2(config, { provider, model: model ?? null }),
|
|
108
|
+
toTracevalsError
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
function constructProvider(config, identity, options = {}) {
|
|
112
|
+
if (identity.provider === JEV) {
|
|
113
|
+
const keyEnv = config.providers.jev?.apiKeyEnv ?? "TYPESAFE_API_KEY";
|
|
114
|
+
const key = process.env[keyEnv];
|
|
115
|
+
if (key === void 0 || key === "") {
|
|
116
|
+
throw new TracevalsError(`jev needs an API key in ${keyEnv}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return makeInferenceProvider(providerSpecFor2(config, identity, options));
|
|
121
|
+
} catch (e) {
|
|
122
|
+
throw new TracevalsError(errorMessage(e));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function makeJudgeProvider(config, flags = {}, ev = {}, options = {}) {
|
|
126
|
+
return constructProvider(
|
|
127
|
+
config,
|
|
128
|
+
await resolveProviderIdentity(config, flags, ev),
|
|
129
|
+
options
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
JEV,
|
|
135
|
+
JEV_OUT_OF_LOOP,
|
|
136
|
+
selectProvider2 as selectProvider,
|
|
137
|
+
selectHookProvider,
|
|
138
|
+
announceSelection,
|
|
139
|
+
assertProviderSelection,
|
|
140
|
+
providerSpecFor2 as providerSpecFor,
|
|
141
|
+
resolveProviderIdentity,
|
|
142
|
+
resolveSelectionIdentity,
|
|
143
|
+
constructProvider,
|
|
144
|
+
makeJudgeProvider
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=chunk-BWCWTHYS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tracevals/judge/provider.ts"],"sourcesContent":["/**\n * Choosing the provider and model, and building the shared inference\n * library's `ProviderSpec` for it.\n *\n * The providers themselves live in `@hawkeyexl/inference` (ADR 01006). The\n * names a provider may have, the two refusals, `--local`, the detection call,\n * the level-bound precedence and the mapping of the family's `providers:`\n * connection settings are `src/shared/providers.ts`, the same code\n * `manni meta fill` and `manni docevals` run. What stays here is what only\n * manni tracevals can decide: which levels it reads (a flag, an eval's own\n * `provider:`/`model:`, `tracevals.provider`/`model`, then the family's\n * `providers:`), and the judge-shaped options a verdict call wants.\n *\n * No model id is named in this file. A model the tool pinned would go stale\n * the week the provider shipped a better one, and would override the default\n * the library keeps current.\n */\nimport {\n makeProvider as makeInferenceProvider,\n mockVerdict,\n type InferenceProvider,\n type MockResponse,\n type ProviderName as ConcreteProvider,\n type ProviderSelector,\n type ProviderSpec,\n} from \"@hawkeyexl/inference\";\nimport { TracevalsError } from \"../types.js\";\nimport type { HostSetting } from \"../rules/host.js\";\nimport type { TracevalsConfig } from \"../core/config.js\";\nimport {\n assertKnownProvider,\n assertLocalFlag,\n assertModelHasProvider,\n localNotice,\n providerSpecFor as sharedProviderSpecFor,\n resolveIdentity,\n selectProvider as selectFromLevels,\n type ProviderChoice,\n type ProviderFlags,\n type ProviderSelection,\n} from \"../../shared/providers.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { noticeOnce } from \"../../shared/warn.js\";\n\nexport type { MockResponse, ProviderChoice, ProviderFlags, ProviderSelection };\n\n/** The decide-only provider (proposal 0079). */\nexport const JEV = \"jev\";\n\n/** Why jev cannot serve out of the loop, and where it goes instead. */\nexport const JEV_OUT_OF_LOOP =\n \"jev answers decisions only, so it cannot extract rules or write verdicts. Use it as tracevals.conformance.hook.provider.\";\n\n/** The key a tracevals user writes, named by the refusal a bare model gets. */\nconst CONFIG_KEY = \"tracevals.provider\";\n\nconst toTracevalsError = (message: string): Error => new TracevalsError(message);\n\n/** What a caller wants of the provider beyond which one it is. */\nexport interface JudgeProviderOptions {\n /**\n * Responses for the `mock` seam. The default is verdict-shaped, which suits\n * judging; callers with a different response schema (criteria proposals,\n * say) must supply their own. `mock` is accepted when named but never\n * offered, so nothing that lists providers mentions it.\n */\n mockResponses?: MockResponse[];\n /**\n * How a `llama-cpp` provider reaches the model host. Unset, it connects to\n * a running host and never starts one, which is every run by hand.\n */\n host?: HostSetting;\n}\n\n/**\n * The provider and model in force: a flag, then the eval's own choice, then\n * `tracevals.provider`/`model`, then the family's `providers.provider`/`model`,\n * then `auto`. A model is carried only to the provider its own level names, so\n * an eval that names a different provider takes that provider's default\n * instead of a model it cannot run (`selectProvider` in the shared module).\n *\n * `--local` runs llama-cpp over all of them. A `--provider` it contradicts is\n * refused here, so no path selects past it. `ev.origin` names the eval in the\n * notice for a provider `--local` replaced; the caller knows its artifact.\n */\nexport function selectProvider(\n config: TracevalsConfig,\n flags: ProviderFlags = {},\n ev: ProviderChoice = {},\n): ProviderSelection {\n assertLocalFlag(flags, toTracevalsError);\n return selectFromLevels(flags, [\n {\n ...(ev.provider !== undefined ? { provider: ev.provider } : {}),\n ...(ev.model !== undefined ? { model: ev.model } : {}),\n ...(ev.origin !== undefined ? { origin: ev.origin } : {}),\n },\n ...configLevels(config),\n ]);\n}\n\n/**\n * The judge inside a hook (proposal 0079, \"Two model roles\"):\n * `conformance.hook.provider`/`model`, then `tracevals.provider`/`model`, then\n * the family's `providers:`, then `auto`. No flag reaches it, because a hook\n * has no command line. A hook level naming only a model lends it to whichever\n * provider wins, as every level does.\n */\nexport function selectHookProvider(config: TracevalsConfig): ProviderSelection {\n const hook = config.conformance?.hook;\n return selectFromLevels({}, [\n {\n ...(hook?.provider != null ? { provider: hook.provider } : {}),\n ...(hook?.model != null ? { model: hook.model } : {}),\n origin: \"tracevals.conformance.hook.provider\",\n },\n ...configLevels(config),\n ]);\n}\n\n/** `tracevals.provider`/`model`, then the family's `providers:`. */\nfunction configLevels(config: TracevalsConfig): ProviderChoice[] {\n return [\n {\n ...(config.provider !== null ? { provider: config.provider } : {}),\n ...(config.model !== null ? { model: config.model } : {}),\n origin: CONFIG_KEY,\n },\n {\n ...(config.providers.provider !== undefined\n ? { provider: config.providers.provider }\n : {}),\n ...(config.providers.model !== undefined ? { model: config.providers.model } : {}),\n origin: \"providers.provider\",\n },\n ];\n}\n\n/**\n * Say what `--local` set aside, once per source. Called where a selection is\n * about to be used, never where it is only checked, so a run that sends\n * nothing to a model says nothing.\n */\nexport function announceSelection(selection: ProviderSelection): void {\n const message = localNotice(selection);\n if (message !== undefined) noticeOnce(message);\n}\n\n/**\n * Refuse a selection that cannot be right, with `manni meta fill`'s messages:\n * an unknown name, or a model under `auto`. Both are `TracevalsError`s, which\n * is what maps them to exit 2.\n */\nexport function assertProviderSelection(selection: ProviderSelection): void {\n // Every caller of this check generates: `run`'s and `calibrate`'s verdicts,\n // `fill`'s proposals, and rule extraction. Only the turn judge may decide.\n if (selection.provider === JEV) throw new TracevalsError(JEV_OUT_OF_LOOP);\n assertKnownProvider(selection.provider, toTracevalsError);\n assertModelHasProvider(selection.provider, selection.model, CONFIG_KEY, toTracevalsError);\n}\n\n/**\n * The spec for a selection, with the family's connection settings for the\n * provider it names, and under `auto` the settings detection reads.\n */\nexport function providerSpecFor(\n config: TracevalsConfig,\n selection: { provider: ProviderSelector; model: string | null },\n options: JudgeProviderOptions = {},\n): ProviderSpec {\n const spec = sharedProviderSpecFor(config.providers, selection);\n switch (selection.provider) {\n case \"anthropic\":\n // A verdict-shaped tool name steers the model better than a generic\n // one, and it is free to keep.\n return { ...spec, anthropic: { toolName: \"record_verdict\" } };\n case \"openai\":\n return { ...spec, openai: { schemaName: \"verdict\" } };\n case \"llama-cpp\":\n return {\n ...spec,\n llamaCpp: { ...spec.llamaCpp, ...(options.host ?? { host: \"connect\" }) },\n };\n case \"mock\":\n return {\n ...spec,\n mockResponses: options.mockResponses ?? [mockVerdict(\"pass\", 0.95)],\n };\n default:\n return spec;\n }\n}\n\n/**\n * The concrete provider and model, WITHOUT constructing the provider: cache\n * keys need it, and a fully cached run must not require an API key.\n *\n * Under `auto` this is where detection runs, exactly as `manni meta fill` runs\n * it, seeing the same connection settings. The model is the RESOLVED one (the\n * provider's default when none was named, a llama-cpp tier's concrete\n * weights), so a library default that changes changes every cache key built\n * from it.\n */\nexport async function resolveProviderIdentity(\n config: TracevalsConfig,\n flags: ProviderFlags = {},\n ev: ProviderChoice = {},\n): Promise<{ provider: ConcreteProvider; model: string }> {\n // Every caller of this generates, so jev is refused here as well as where\n // a command checks its selection up front.\n const selection = selectProvider(config, flags, ev);\n assertProviderSelection(selection);\n return resolveSelectionIdentity(config, selection);\n}\n\n/** `resolveProviderIdentity` for a selection already made. */\nexport async function resolveSelectionIdentity(\n config: TracevalsConfig,\n selection: ProviderSelection,\n): Promise<{ provider: ConcreteProvider; model: string }> {\n const { provider, model } = selection;\n // Generating callers refused jev in assertProviderSelection; reaching here\n // with it means the turn judge, which decides.\n assertKnownProvider(provider, toTracevalsError, { decisions: true });\n assertModelHasProvider(provider, model, CONFIG_KEY, toTracevalsError);\n announceSelection(selection);\n return resolveIdentity(\n providerSpecFor(config, { provider, model: model ?? null }),\n toTracevalsError,\n );\n}\n\n/** Construct a provider for an identity already resolved. */\nexport function constructProvider(\n config: TracevalsConfig,\n identity: { provider: ConcreteProvider; model: string },\n options: JudgeProviderOptions = {},\n): InferenceProvider {\n if (identity.provider === JEV) {\n // Checked here, so the message names the variable a user sets rather than\n // the library's wording for it.\n const keyEnv = config.providers.jev?.apiKeyEnv ?? \"TYPESAFE_API_KEY\";\n const key = process.env[keyEnv];\n if (key === undefined || key === \"\") {\n throw new TracevalsError(`jev needs an API key in ${keyEnv}`);\n }\n }\n try {\n return makeInferenceProvider(providerSpecFor(config, identity, options));\n } catch (e) {\n // The library raises its own InferenceError (a missing API key). It must\n // surface as a TracevalsError: `cli.ts`'s fail() maps only that to exit 2,\n // and letting a foreign error type through turns \"no API key configured\"\n // into an unhandled stack trace.\n throw new TracevalsError(errorMessage(e));\n }\n}\n\n/** Select, check, detect and construct: the provider a verb judges with. */\nexport async function makeJudgeProvider(\n config: TracevalsConfig,\n flags: ProviderFlags = {},\n ev: ProviderChoice = {},\n options: JudgeProviderOptions = {},\n): Promise<InferenceProvider> {\n return constructProvider(\n config,\n await resolveProviderIdentity(config, flags, ev),\n options,\n );\n}\n"],"mappings":"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","names":["selectProvider","providerSpecFor"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
displayPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-C73RSUIC.js";
|
|
5
5
|
import {
|
|
6
6
|
escapeWorkflowCommandMessage,
|
|
7
7
|
escapeWorkflowCommandProperty
|
|
@@ -20,4 +20,4 @@ function renderFindingsGithub(report) {
|
|
|
20
20
|
export {
|
|
21
21
|
renderFindingsGithub
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-C3B2VJNC.js.map
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
CONCEPT_FIELDS,
|
|
11
11
|
fieldPointer,
|
|
12
12
|
valueAt
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GREQKO6M.js";
|
|
14
14
|
import {
|
|
15
15
|
STDIN_LABEL,
|
|
16
16
|
STDIN_TOKEN,
|
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
gitignoreOptions,
|
|
21
21
|
locateFrontmatter,
|
|
22
22
|
resolveTargetSet
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KCOFEWV5.js";
|
|
24
24
|
import {
|
|
25
25
|
findConfigFile,
|
|
26
26
|
readConfigFile,
|
|
27
27
|
selectCollections,
|
|
28
28
|
valeConfigPath
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-XKBEHKWO.js";
|
|
30
30
|
import {
|
|
31
31
|
ToolError,
|
|
32
32
|
errorMessage
|
|
@@ -1972,4 +1972,4 @@ export {
|
|
|
1972
1972
|
valeConfigFor,
|
|
1973
1973
|
plural
|
|
1974
1974
|
};
|
|
1975
|
-
//# sourceMappingURL=chunk-
|
|
1975
|
+
//# sourceMappingURL=chunk-C73RSUIC.js.map
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
TracevalsError
|
|
4
|
+
} from "./chunk-UKZNLVJW.js";
|
|
5
|
+
|
|
6
|
+
// src/tracevals/judge/redact.ts
|
|
7
|
+
var SECRET_NAME = "(?:(?:[A-Za-z0-9]+[_\\-.])*(?:api[_\\-.]?key|access[_\\-.]?key|secret[_\\-.]?key|auth[_\\-.]?token|access[_\\-.]?token|refresh[_\\-.]?token|client[_\\-.]?secret|session[_\\-.]?token|key|token|secret|password|passwd|passphrase|credentials?|authorization)|AWS_[A-Za-z0-9_]+)";
|
|
8
|
+
var REDACTION_PATTERNS = [
|
|
9
|
+
{
|
|
10
|
+
label: "private-key",
|
|
11
|
+
pattern: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
|
|
12
|
+
replacement: "[redacted:private-key]"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
// `sk-`, `sk-ant-…`, `pk-`, `rk-`: the OpenAI/Anthropic/Stripe family.
|
|
16
|
+
label: "api-key",
|
|
17
|
+
pattern: /\b[sprk]k-(?:[A-Za-z0-9]+-)*[A-Za-z0-9_-]{16,}/g,
|
|
18
|
+
replacement: "[redacted:api-key]"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: "aws-access-key-id",
|
|
22
|
+
pattern: /\b(?:AKIA|ASIA|AROA|AIDA)[0-9A-Z]{16}\b/g,
|
|
23
|
+
replacement: "[redacted:aws-access-key-id]"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: "github-token",
|
|
27
|
+
pattern: /\b(?:gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})\b/g,
|
|
28
|
+
replacement: "[redacted:github-token]"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
label: "slack-token",
|
|
32
|
+
pattern: /\bxox[abeoprs]-[A-Za-z0-9-]{10,}/g,
|
|
33
|
+
replacement: "[redacted:slack-token]"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "google-api-key",
|
|
37
|
+
pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g,
|
|
38
|
+
replacement: "[redacted:google-api-key]"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: "jwt",
|
|
42
|
+
pattern: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
|
|
43
|
+
replacement: "[redacted:jwt]"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
// `Authorization: Bearer …`, `Basic …`, `Token …`. The scheme is kept so
|
|
47
|
+
// the judge can still see that authentication happened.
|
|
48
|
+
//
|
|
49
|
+
// Deliberately *not* case-insensitive as a whole: `basic` and `token` are
|
|
50
|
+
// ordinary English words, and `/i` would redact "basic configuration" as an
|
|
51
|
+
// auth header. `bearer` is not, so it gets both spellings.
|
|
52
|
+
label: "auth-token",
|
|
53
|
+
pattern: /\b([Bb]earer|Basic|Token)\s+[A-Za-z0-9\-._~+/]{12,}={0,2}/g,
|
|
54
|
+
replacement: "$1 [redacted:auth-token]"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
// JSON member — the shape a tool input renders as.
|
|
58
|
+
label: "secret-member",
|
|
59
|
+
pattern: new RegExp(`("${SECRET_NAME}"\\s*:\\s*)"[^"]*"`, "gi"),
|
|
60
|
+
replacement: '$1"[redacted:secret-value]"'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
// Shell / `.env` assignment. The variable name is kept: knowing that a
|
|
64
|
+
// secret was set, and which one, is often the adherence question.
|
|
65
|
+
label: "secret-assignment",
|
|
66
|
+
pattern: new RegExp(
|
|
67
|
+
`\\b(${SECRET_NAME})(\\s*=\\s*)(?:"[^"\\n]*"|'[^'\\n]*'|[^\\s"'\\n]+)`,
|
|
68
|
+
"gi"
|
|
69
|
+
),
|
|
70
|
+
replacement: "$1$2[redacted:secret-value]"
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
var CUSTOM_PLACEHOLDER = "[redacted]";
|
|
74
|
+
function makeRedactor(extra = []) {
|
|
75
|
+
const custom = compileRedactPatterns(extra).map(
|
|
76
|
+
(pattern) => [pattern, CUSTOM_PLACEHOLDER]
|
|
77
|
+
);
|
|
78
|
+
const all = [
|
|
79
|
+
...REDACTION_PATTERNS.map(
|
|
80
|
+
({ pattern, replacement }) => [pattern, replacement]
|
|
81
|
+
),
|
|
82
|
+
...custom
|
|
83
|
+
];
|
|
84
|
+
return (text) => {
|
|
85
|
+
let out = text;
|
|
86
|
+
for (const [pattern, replacement] of all) {
|
|
87
|
+
out = out.replace(pattern, replacement);
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function compileRedactPatterns(sources) {
|
|
93
|
+
return sources.map((source) => {
|
|
94
|
+
try {
|
|
95
|
+
return new RegExp(source, "g");
|
|
96
|
+
} catch (err) {
|
|
97
|
+
throw new TracevalsError(
|
|
98
|
+
`invalid config: judge.redact pattern ${JSON.stringify(source)} is not a valid regular expression: ${err instanceof Error ? err.message : String(err)}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/tracevals/capture/types.ts
|
|
105
|
+
var MANIFEST_VERSION = 1;
|
|
106
|
+
var DEFAULT_CAPTURE_DIR = ".manni/tracevals/sessions";
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
REDACTION_PATTERNS,
|
|
110
|
+
CUSTOM_PLACEHOLDER,
|
|
111
|
+
makeRedactor,
|
|
112
|
+
compileRedactPatterns,
|
|
113
|
+
MANIFEST_VERSION,
|
|
114
|
+
DEFAULT_CAPTURE_DIR
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=chunk-CU57HT2E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tracevals/judge/redact.ts","../src/tracevals/capture/types.ts"],"sourcesContent":["/**\n * Redaction for the judge digest (ADR 01020).\n *\n * `renderTrace` builds the only trace-derived text that leaves this machine,\n * and a session transcript routinely carries credentials: a `Bash` input with\n * an `Authorization` header, an `.env` file echoed into a message, a key pasted\n * into a prompt. Every block that enters the digest is filtered through here\n * first.\n *\n * This is **best-effort pattern matching, not a guarantee.** It recognizes\n * shapes — vendor key prefixes, auth schemes, secret-looking assignment names —\n * so it catches the common accidents and cannot catch an arbitrary secret that\n * looks like ordinary prose. `--deterministic-only` is the only setting that\n * guarantees nothing leaves the machine.\n *\n * Two properties the rest of the system leans on:\n *\n * - **Stable output.** A given input always redacts to the same text, so\n * `sha256(renderedTrace)` stays a usable judge cache key.\n * - **Idempotent.** Placeholders contain no `=`, no `:` inside quotes, and no\n * vendor prefix, so redacting redacted text is a no-op.\n */\nimport { TracevalsError } from \"../types.js\";\n\nexport interface RedactionPattern {\n /** Kebab name; appears in the placeholder so a reader knows what went. */\n label: string;\n pattern: RegExp;\n /** Replacement template; `$1`-style references into `pattern` are allowed. */\n replacement: string;\n}\n\n/**\n * Names that mark a value as secret, in the shapes they appear in shell\n * assignments and in JSON object members (tool inputs render as JSON).\n *\n * The whole name must match, which is what keeps `monkey` out of the `key`\n * alternative: the `(?:[A-Za-z0-9]+[_\\-.])*` prefix only consumes segments that\n * end in a separator. `api[_\\-.]?key` covers `apiKey` and `API_KEY` alike under\n * the `i` flag.\n */\nconst SECRET_NAME =\n \"(?:(?:[A-Za-z0-9]+[_\\\\-.])*(?:api[_\\\\-.]?key|access[_\\\\-.]?key|secret[_\\\\-.]?key|auth[_\\\\-.]?token|access[_\\\\-.]?token|refresh[_\\\\-.]?token|client[_\\\\-.]?secret|session[_\\\\-.]?token|key|token|secret|password|passwd|passphrase|credentials?|authorization)|AWS_[A-Za-z0-9_]+)\";\n\n/**\n * Applied in order. Broad structural shapes first (a private key block spans\n * lines and would otherwise be chewed up by the narrower rules), then vendor\n * prefixes, then name-driven assignment forms.\n */\nexport const REDACTION_PATTERNS: readonly RedactionPattern[] = [\n {\n label: \"private-key\",\n pattern:\n /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,\n replacement: \"[redacted:private-key]\",\n },\n {\n // `sk-`, `sk-ant-…`, `pk-`, `rk-`: the OpenAI/Anthropic/Stripe family.\n label: \"api-key\",\n pattern: /\\b[sprk]k-(?:[A-Za-z0-9]+-)*[A-Za-z0-9_-]{16,}/g,\n replacement: \"[redacted:api-key]\",\n },\n {\n label: \"aws-access-key-id\",\n pattern: /\\b(?:AKIA|ASIA|AROA|AIDA)[0-9A-Z]{16}\\b/g,\n replacement: \"[redacted:aws-access-key-id]\",\n },\n {\n label: \"github-token\",\n pattern: /\\b(?:gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})\\b/g,\n replacement: \"[redacted:github-token]\",\n },\n {\n label: \"slack-token\",\n pattern: /\\bxox[abeoprs]-[A-Za-z0-9-]{10,}/g,\n replacement: \"[redacted:slack-token]\",\n },\n {\n label: \"google-api-key\",\n pattern: /\\bAIza[0-9A-Za-z_-]{35}\\b/g,\n replacement: \"[redacted:google-api-key]\",\n },\n {\n label: \"jwt\",\n pattern: /\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}/g,\n replacement: \"[redacted:jwt]\",\n },\n {\n // `Authorization: Bearer …`, `Basic …`, `Token …`. The scheme is kept so\n // the judge can still see that authentication happened.\n //\n // Deliberately *not* case-insensitive as a whole: `basic` and `token` are\n // ordinary English words, and `/i` would redact \"basic configuration\" as an\n // auth header. `bearer` is not, so it gets both spellings.\n label: \"auth-token\",\n pattern: /\\b([Bb]earer|Basic|Token)\\s+[A-Za-z0-9\\-._~+/]{12,}={0,2}/g,\n replacement: \"$1 [redacted:auth-token]\",\n },\n {\n // JSON member — the shape a tool input renders as.\n label: \"secret-member\",\n pattern: new RegExp(`(\"${SECRET_NAME}\"\\\\s*:\\\\s*)\"[^\"]*\"`, \"gi\"),\n replacement: '$1\"[redacted:secret-value]\"',\n },\n {\n // Shell / `.env` assignment. The variable name is kept: knowing that a\n // secret was set, and which one, is often the adherence question.\n label: \"secret-assignment\",\n pattern: new RegExp(\n `\\\\b(${SECRET_NAME})(\\\\s*=\\\\s*)(?:\"[^\"\\\\n]*\"|'[^'\\\\n]*'|[^\\\\s\"'\\\\n]+)`,\n \"gi\",\n ),\n replacement: \"$1$2[redacted:secret-value]\",\n },\n];\n\n/** Placeholder used for a pattern the config supplied; it has no label. */\nexport const CUSTOM_PLACEHOLDER = \"[redacted]\";\n\nexport type Redactor = (text: string) => string;\n\n/**\n * Build the redactor for a run. Configured patterns are applied **after** the\n * built-ins and never replace them: a project adding one pattern of its own\n * must not silently lose the whole floor, which is the same reasoning that\n * makes `--require` additive (ADR 01017).\n *\n * A pattern that will not compile is an operational error raised here, not a\n * throw from inside the judge and never a silent skip — a dropped pattern is a\n * silent leak.\n */\nexport function makeRedactor(extra: readonly string[] = []): Redactor {\n // Compiled once and reused across every block of a render. Safe with a `g`\n // regex because `String.prototype.replace` sets `lastIndex` to 0 before it\n // starts and leaves it at 0 — unlike `exec`/`test`, where the shared instance\n // state would make a reused pattern skip matches.\n const custom = compileRedactPatterns(extra).map(\n (pattern) => [pattern, CUSTOM_PLACEHOLDER] as const,\n );\n const all: ReadonlyArray<readonly [RegExp, string]> = [\n ...REDACTION_PATTERNS.map(\n ({ pattern, replacement }) => [pattern, replacement] as const,\n ),\n ...custom,\n ];\n return (text) => {\n let out = text;\n for (const [pattern, replacement] of all) {\n out = out.replace(pattern, replacement);\n }\n return out;\n };\n}\n\n/**\n * Compile configured pattern sources, or say which one is unusable. Exported so\n * `parseConfig()` can reject a bad pattern at load time rather than at the\n * moment a digest is about to be sent.\n */\nexport function compileRedactPatterns(sources: readonly string[]): RegExp[] {\n return sources.map((source) => {\n try {\n return new RegExp(source, \"g\");\n } catch (err) {\n throw new TracevalsError(\n `invalid config: judge.redact pattern ${JSON.stringify(source)} is not a valid regular expression: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n });\n}\n","/**\n * The session manifest: what the project's instruction artifacts said, and\n * which commit they said it at, **when the session started** (ADR 01024).\n *\n * ADR 01016 established that the availability roster — what the session was\n * offered — is recoverable from the transcript itself, retroactively and on any\n * machine. Two things are not: the artifact **bodies** and the **git SHA**. The\n * transcript injects skill instructions into the model's context without ever\n * recording their text, so \"the SKILL.md says X now; did it say X then?\" has no\n * answer inside the trace. ADR 01021 answers it with mtime, which is a\n * heuristic that a `git checkout` defeats wholesale.\n *\n * A manifest closes that gap by recording, at session start, a sha256 per\n * instruction artifact. `run` then compares — and a mismatch is exact where\n * mtime was a guess.\n *\n * **A manifest is a claim, not proof.** It is written by the capturing device\n * and travels with the repository, so it is evidence *about that device*. It\n * never reaches an eval outcome, never moves the exit code, and never turns a\n * `skipped` into a `pass`; the only thing it may quiet is the mtime warning,\n * whose own question it answers exactly.\n *\n * Types and constants only, with no dependency of its own beyond\n * `ArtifactType` — `artifacts/resolve.ts` consumes a manifest and\n * `capture/build.ts` produces one from `artifacts/discover.ts`, so anything\n * shared has to sit below both or the two would import each other.\n */\nimport type { ArtifactType } from \"../artifacts/types.js\";\n\n/**\n * Manifest format version. Bumped when the *shape* changes incompatibly; a\n * manifest from a higher version is ignored rather than half-read, because a\n * partial read of an evidence file is worse than no evidence.\n */\nexport const MANIFEST_VERSION = 1;\n\n/** Default directory, under the state directory the judge cache already uses. */\nexport const DEFAULT_CAPTURE_DIR = \".manni/tracevals/sessions\";\n\nexport interface ManifestArtifact {\n /** Reference name, spelled as the coverage table spells it. */\n name: string;\n type: ArtifactType;\n /**\n * Path relative to `root`, with POSIX separators — never absolute, so the\n * manifest still joins after the repository is checked out somewhere else.\n */\n path: string;\n /** Lowercase hex sha256 of the file's bytes at capture time. */\n sha256: string;\n bytes: number;\n}\n\n/** What `git` could answer about the project at capture time. */\nexport interface ManifestGit {\n /** The commit the session ran against. */\n sha: string;\n branch?: string;\n /** Tracked files differed from the commit, so `sha` alone is incomplete. */\n dirty: boolean;\n}\n\nexport interface SessionManifest {\n version: number;\n sessionId: string;\n /** When `capture` ran, ISO-8601. */\n capturedAt: string;\n /** The hook that supplied the payload, or `manual` for a direct run. */\n hookEvent: string;\n /** How the session started or why it ended, when the payload said so. */\n reason?: string;\n /** Where the session file will be written. A correlation key, never read. */\n transcriptPath?: string;\n /** Project root the artifact paths are relative to. */\n root: string;\n git?: ManifestGit;\n /**\n * Which machine captured this. An opaque digest rather than the hostname:\n * the question a reader has is \"same machine or not\", and that does not need\n * the name of the machine to answer.\n */\n device: { id: string; platform: string };\n tool: { name: string; version: string };\n artifacts: ManifestArtifact[];\n /** The resolved `tracevals:` section, redacted. Recorded, not consumed. */\n config: unknown;\n}\n\nexport type ContentCheckStatus = \"match\" | \"mismatch\" | \"skipped\";\n\n/**\n * Whether an artifact still says what the manifest recorded. Three-valued on\n * purpose: `skipped` is not a shade of `match`, and collapsing them would let\n * an absent manifest read as a clean bill of health.\n */\nexport interface ContentCheck {\n status: ContentCheckStatus;\n /** Why no comparison was possible. Present only on `skipped`. */\n reason?: string;\n /** The digest recorded at capture time. */\n expected?: string;\n /** The digest of the file as it is now. */\n actual?: string;\n}\n\n/** The manifest `run` consulted, summarised for the report. */\nexport interface ManifestReport {\n /** Where it was read from. */\n path: string;\n sessionId: string;\n capturedAt: string;\n /** The commit the session ran against, when git could answer. */\n gitSha?: string;\n /** Coverage rows the manifest could speak to, and what it said. */\n matched: number;\n changed: number;\n /** Rows it had nothing to say about; those keep the mtime heuristic. */\n unrecorded: number;\n}\n"],"mappings":";;;;;;AAyCA,IAAM,cACJ;AAOK,IAAM,qBAAkD;AAAA,EAC7D;AAAA,IACE,OAAO;AAAA,IACP,SACE;AAAA,IACF,aAAa;AAAA,EACf;AAAA,EACA;AAAA;AAAA,IAEE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOE,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAAA,EACA;AAAA;AAAA,IAEE,OAAO;AAAA,IACP,SAAS,IAAI,OAAO,KAAK,WAAW,sBAAsB,IAAI;AAAA,IAC9D,aAAa;AAAA,EACf;AAAA,EACA;AAAA;AAAA;AAAA,IAGE,OAAO;AAAA,IACP,SAAS,IAAI;AAAA,MACX,OAAO,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,IACA,aAAa;AAAA,EACf;AACF;AAGO,IAAM,qBAAqB;AAc3B,SAAS,aAAa,QAA2B,CAAC,GAAa;AAKpE,QAAM,SAAS,sBAAsB,KAAK,EAAE;AAAA,IAC1C,CAAC,YAAY,CAAC,SAAS,kBAAkB;AAAA,EAC3C;AACA,QAAM,MAAgD;AAAA,IACpD,GAAG,mBAAmB;AAAA,MACpB,CAAC,EAAE,SAAS,YAAY,MAAM,CAAC,SAAS,WAAW;AAAA,IACrD;AAAA,IACA,GAAG;AAAA,EACL;AACA,SAAO,CAAC,SAAS;AACf,QAAI,MAAM;AACV,eAAW,CAAC,SAAS,WAAW,KAAK,KAAK;AACxC,YAAM,IAAI,QAAQ,SAAS,WAAW;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AACF;AAOO,SAAS,sBAAsB,SAAsC;AAC1E,SAAO,QAAQ,IAAI,CAAC,WAAW;AAC7B,QAAI;AACF,aAAO,IAAI,OAAO,QAAQ,GAAG;AAAA,IAC/B,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,wCAAwC,KAAK,UAAU,MAAM,CAAC,uCAC5D,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CACjD;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACzIO,IAAM,mBAAmB;AAGzB,IAAM,sBAAsB;","names":[]}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/tracevals/graders/util.ts
|
|
4
|
+
function finding(plan, message) {
|
|
5
|
+
return {
|
|
6
|
+
evalName: plan.evalName,
|
|
7
|
+
artifact: plan.artifact.path,
|
|
8
|
+
message,
|
|
9
|
+
severity: plan.severity
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function fail(plan, message) {
|
|
13
|
+
return { findings: [finding(plan, message)] };
|
|
14
|
+
}
|
|
15
|
+
var pass = { findings: [] };
|
|
16
|
+
function optionsError(kind, message) {
|
|
17
|
+
return { findings: [], error: `${kind}: ${message}` };
|
|
18
|
+
}
|
|
19
|
+
function firstError(...checks) {
|
|
20
|
+
return checks.find((check) => check !== void 0);
|
|
21
|
+
}
|
|
22
|
+
function requiredString(options, key) {
|
|
23
|
+
const value = options[key];
|
|
24
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
25
|
+
return `options.${key} is required`;
|
|
26
|
+
}
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
function optionalString(options, key) {
|
|
30
|
+
const value = options[key];
|
|
31
|
+
if (value === void 0) return void 0;
|
|
32
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
33
|
+
return `options.${key} must be a non-empty string`;
|
|
34
|
+
}
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
function optionalEnum(options, key, allowed) {
|
|
38
|
+
const value = options[key];
|
|
39
|
+
if (value === void 0) return void 0;
|
|
40
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
41
|
+
return `options.${key} must be one of: ${allowed.join(", ")}`;
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
function optionalNumber(options, key, bounds = {}) {
|
|
46
|
+
const value = options[key];
|
|
47
|
+
if (value === void 0) return void 0;
|
|
48
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
49
|
+
return `options.${key} must be a finite number`;
|
|
50
|
+
}
|
|
51
|
+
if (bounds.integer === true && !Number.isInteger(value)) {
|
|
52
|
+
return `options.${key} must be a whole number`;
|
|
53
|
+
}
|
|
54
|
+
if (bounds.min !== void 0 && value < bounds.min) {
|
|
55
|
+
return `options.${key} must be at least ${bounds.min}`;
|
|
56
|
+
}
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
function optionalBoolean(options, key) {
|
|
60
|
+
if (options[key] !== void 0 && typeof options[key] !== "boolean") {
|
|
61
|
+
return `options.${key} must be a boolean`;
|
|
62
|
+
}
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
function orderedBounds(options, minKey, maxKey) {
|
|
66
|
+
const min = options[minKey];
|
|
67
|
+
const max = options[maxKey];
|
|
68
|
+
if (typeof min === "number" && typeof max === "number" && min > max) {
|
|
69
|
+
return `options.${maxKey} must be greater than or equal to options.${minKey}`;
|
|
70
|
+
}
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
function requireOneOf(options, keys) {
|
|
74
|
+
if (keys.some((key) => options[key] !== void 0)) return void 0;
|
|
75
|
+
return `at least one of ${keys.map((k) => `options.${k}`).join(" or ")} is required`;
|
|
76
|
+
}
|
|
77
|
+
function windowFor(trace, plan) {
|
|
78
|
+
return windowOf(trace, plan.artifact);
|
|
79
|
+
}
|
|
80
|
+
function windowOf(trace, artifact) {
|
|
81
|
+
const { name, type } = artifact;
|
|
82
|
+
if (type === "skill") return skillWindow(trace, name);
|
|
83
|
+
if (type === "agent") return agentWindow(trace, name);
|
|
84
|
+
if (type === "slash-command") return slashCommandWindow(trace, name);
|
|
85
|
+
return {
|
|
86
|
+
scope: "session",
|
|
87
|
+
label: "whole session",
|
|
88
|
+
empty: false,
|
|
89
|
+
events: trace.events,
|
|
90
|
+
toolCalls: trace.toolCalls,
|
|
91
|
+
fileAccesses: trace.fileAccesses,
|
|
92
|
+
skillInvocations: trace.skillInvocations,
|
|
93
|
+
userMessages: trace.userMessages,
|
|
94
|
+
assistantTexts: trace.assistantTexts,
|
|
95
|
+
turnCount: trace.turnCount
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function skippedWindow(window) {
|
|
99
|
+
return { findings: [], skipped: window.reason ?? "the artifact governed no turns" };
|
|
100
|
+
}
|
|
101
|
+
function skillWindow(trace, name) {
|
|
102
|
+
return injectionWindow(trace, "skill", `skill "${name}"`, (s) => s.name === name);
|
|
103
|
+
}
|
|
104
|
+
function slashCommandWindow(trace, name) {
|
|
105
|
+
return injectionWindow(
|
|
106
|
+
trace,
|
|
107
|
+
"slash-command",
|
|
108
|
+
`slash command "/${name}"`,
|
|
109
|
+
(s) => s.name === name && s.via === "command-injection"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
function injectionWindow(trace, scope, label, opensHere) {
|
|
113
|
+
const opens = trace.skillInvocations.filter(opensHere).map((s) => s.index);
|
|
114
|
+
if (opens.length === 0) {
|
|
115
|
+
return emptyWindow(
|
|
116
|
+
scope,
|
|
117
|
+
label,
|
|
118
|
+
`${label} was never invoked in this trace, so it governed no turns`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const chainOf = (index) => trace.events[index]?.branchId;
|
|
122
|
+
const own = new Set(opens.map(chainOf));
|
|
123
|
+
const boundaries = trace.skillInvocations.filter((s) => own.has(chainOf(s.index))).map((s) => s.index).sort((a, b) => a - b);
|
|
124
|
+
const spans = opens.map((start) => ({
|
|
125
|
+
start,
|
|
126
|
+
end: boundaries.find((b) => b > start) ?? Number.POSITIVE_INFINITY
|
|
127
|
+
}));
|
|
128
|
+
return materialize(trace, scope, label, spans, void 0, own);
|
|
129
|
+
}
|
|
130
|
+
function agentWindow(trace, name) {
|
|
131
|
+
const label = `agent "${name}"`;
|
|
132
|
+
const mine = trace.subagentBranches.filter((b) => b.agentType === name);
|
|
133
|
+
if (mine.length === 0) {
|
|
134
|
+
const spawned = trace.agentSpawns.some((a) => a.subagentType === name);
|
|
135
|
+
return emptyWindow(
|
|
136
|
+
"agent",
|
|
137
|
+
label,
|
|
138
|
+
spawned ? `${label} was spawned but recorded no subagent turns (no inline sidechain records and no sidecar transcript), so it governed no turns` : `${label} was never spawned in this trace, so it governed no turns`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const branchIds = new Set(mine.map((b) => b.branchId));
|
|
142
|
+
for (const branch of trace.subagentBranches) {
|
|
143
|
+
if (branchIds.has(branch.branchId)) continue;
|
|
144
|
+
const nested = mine.some(
|
|
145
|
+
(m) => m.startIndex <= branch.startIndex && branch.endIndex <= m.endIndex
|
|
146
|
+
);
|
|
147
|
+
if (nested) branchIds.add(branch.branchId);
|
|
148
|
+
}
|
|
149
|
+
const spans = mine.map((b) => ({ start: b.startIndex, end: b.endIndex }));
|
|
150
|
+
return materialize(
|
|
151
|
+
trace,
|
|
152
|
+
"agent",
|
|
153
|
+
label,
|
|
154
|
+
spans,
|
|
155
|
+
branchIds,
|
|
156
|
+
new Set(mine.map((b) => b.branchId))
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
function emptyWindow(scope, label, reason) {
|
|
160
|
+
return {
|
|
161
|
+
scope,
|
|
162
|
+
label,
|
|
163
|
+
empty: true,
|
|
164
|
+
reason,
|
|
165
|
+
events: [],
|
|
166
|
+
toolCalls: [],
|
|
167
|
+
fileAccesses: [],
|
|
168
|
+
skillInvocations: [],
|
|
169
|
+
userMessages: [],
|
|
170
|
+
assistantTexts: [],
|
|
171
|
+
turnCount: 0
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function materialize(trace, scope, label, spans, branchIds, own) {
|
|
175
|
+
const inSpan = (index) => spans.some((s) => index >= s.start && index < s.end);
|
|
176
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
177
|
+
if (branchIds !== void 0) {
|
|
178
|
+
for (const event of trace.events) {
|
|
179
|
+
if (!inSpan(event.index)) continue;
|
|
180
|
+
if (event.branchId === void 0 || !branchIds.has(event.branchId)) {
|
|
181
|
+
excluded.add(event.index);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const inWindow = (index) => inSpan(index) && !excluded.has(index);
|
|
186
|
+
const events = trace.events.filter((e) => inWindow(e.index));
|
|
187
|
+
const textOf = (kind) => events.filter((e) => e.kind === kind && own.has(e.branchId) && e.text).map((e) => e.text);
|
|
188
|
+
const userMessages = textOf("user");
|
|
189
|
+
return {
|
|
190
|
+
scope,
|
|
191
|
+
label,
|
|
192
|
+
empty: false,
|
|
193
|
+
events,
|
|
194
|
+
toolCalls: trace.toolCalls.filter((c) => inWindow(c.index)),
|
|
195
|
+
fileAccesses: trace.fileAccesses.filter((a) => inWindow(a.index)),
|
|
196
|
+
skillInvocations: trace.skillInvocations.filter((s) => inWindow(s.index)),
|
|
197
|
+
userMessages,
|
|
198
|
+
assistantTexts: textOf("assistant"),
|
|
199
|
+
turnCount: userMessages.length
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export {
|
|
204
|
+
finding,
|
|
205
|
+
fail,
|
|
206
|
+
pass,
|
|
207
|
+
optionsError,
|
|
208
|
+
firstError,
|
|
209
|
+
requiredString,
|
|
210
|
+
optionalString,
|
|
211
|
+
optionalEnum,
|
|
212
|
+
optionalNumber,
|
|
213
|
+
optionalBoolean,
|
|
214
|
+
orderedBounds,
|
|
215
|
+
requireOneOf,
|
|
216
|
+
windowFor,
|
|
217
|
+
windowOf,
|
|
218
|
+
skippedWindow,
|
|
219
|
+
emptyWindow,
|
|
220
|
+
materialize
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=chunk-CWXZ2MRT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tracevals/graders/util.ts"],"sourcesContent":["/** Shared helpers for deterministic graders. */\nimport type { EvalPlan } from \"../core/plan.js\";\nimport type {\n FileAccess,\n SkillInvocation,\n ToolCall,\n Trace,\n TraceEvent,\n} from \"../trace/types.js\";\nimport type { Finding, GradeResult } from \"./types.js\";\n\nexport function finding(plan: EvalPlan, message: string): Finding {\n return {\n evalName: plan.evalName,\n artifact: plan.artifact.path,\n message,\n severity: plan.severity,\n };\n}\n\nexport function fail(plan: EvalPlan, message: string): GradeResult {\n return { findings: [finding(plan, message)] };\n}\n\nexport const pass: GradeResult = { findings: [] };\n\nexport function optionsError(kind: string, message: string): GradeResult {\n return { findings: [], error: `${kind}: ${message}` };\n}\n\n/** An option-validation outcome: a message when invalid, undefined when fine. */\nexport type OptionCheck = string | undefined;\n\nexport type Options = Record<string, unknown>;\n\n/** First failing check, so callers read as a flat list of constraints. */\nexport function firstError(...checks: OptionCheck[]): OptionCheck {\n return checks.find((check) => check !== undefined);\n}\n\nexport function requiredString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} is required`;\n }\n return undefined;\n}\n\nexport function optionalString(options: Options, key: string): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || value.length === 0) {\n return `options.${key} must be a non-empty string`;\n }\n return undefined;\n}\n\nexport function optionalEnum(\n options: Options,\n key: string,\n allowed: readonly string[],\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || !allowed.includes(value)) {\n return `options.${key} must be one of: ${allowed.join(\", \")}`;\n }\n return undefined;\n}\n\nexport function optionalNumber(\n options: Options,\n key: string,\n bounds: { min?: number; integer?: boolean } = {},\n): OptionCheck {\n const value = options[key];\n if (value === undefined) return undefined;\n // Number.isFinite also rejects NaN and both infinities.\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return `options.${key} must be a finite number`;\n }\n if (bounds.integer === true && !Number.isInteger(value)) {\n return `options.${key} must be a whole number`;\n }\n if (bounds.min !== undefined && value < bounds.min) {\n return `options.${key} must be at least ${bounds.min}`;\n }\n return undefined;\n}\n\nexport function optionalBoolean(options: Options, key: string): OptionCheck {\n if (options[key] !== undefined && typeof options[key] !== \"boolean\") {\n return `options.${key} must be a boolean`;\n }\n return undefined;\n}\n\n/** Rejects min > max once both are present and already known to be numbers. */\nexport function orderedBounds(\n options: Options,\n minKey: string,\n maxKey: string,\n): OptionCheck {\n const min = options[minKey];\n const max = options[maxKey];\n if (typeof min === \"number\" && typeof max === \"number\" && min > max) {\n return `options.${maxKey} must be greater than or equal to options.${minKey}`;\n }\n return undefined;\n}\n\n/**\n * Rejects a criterion that configures no bound at all. Such a criterion can\n * never fail, so it reads as coverage while asserting nothing.\n */\nexport function requireOneOf(options: Options, keys: string[]): OptionCheck {\n if (keys.some((key) => options[key] !== undefined)) return undefined;\n return `at least one of ${keys.map((k) => `options.${k}`).join(\" or \")} is required`;\n}\n\n// ── Scoped grading ───────────────────────────────────────────────\n\n/**\n * The slice of a trace an artifact was actually governing (ADR 01015). The\n * window is derived from the artifact's *type*, never declared: a skill governs\n * from its invocation until the next skill takes over, an agent governs its own\n * branch, and project rules govern the whole session.\n */\nexport interface TraceWindow {\n /**\n * Which rule produced this window. `turn` is the last turn of a session or\n * a subagent's whole run, cut by `rules/turn.ts` (proposal 0079).\n */\n scope: \"session\" | \"skill\" | \"agent\" | \"slash-command\" | \"turn\";\n /** Names the window in reasons and in the judge digest. */\n label: string;\n /**\n * True when the artifact governed no turn at all. Graders must report\n * `skipped` on an empty window — never a pass, which would be a verdict\n * about turns the artifact had no part in.\n */\n empty: boolean;\n /** Why the window is empty; set only when `empty`. */\n reason?: string;\n events: TraceEvent[];\n toolCalls: ToolCall[];\n fileAccesses: FileAccess[];\n skillInvocations: SkillInvocation[];\n /** Prompts on the window's own chain; nested subagent turns are excluded. */\n userMessages: string[];\n assistantTexts: string[];\n turnCount: number;\n}\n\n/** Half-open ordinal range over `trace.events`; `end` may be Infinity. */\nexport interface Span {\n start: number;\n end: number;\n}\n\nexport function windowFor(trace: Trace, plan: EvalPlan): TraceWindow {\n return windowOf(trace, plan.artifact);\n}\n\n/** `windowFor` keyed on the artifact alone, for callers with no eval plan. */\nexport function windowOf(\n trace: Trace,\n artifact: Pick<EvalPlan[\"artifact\"], \"name\" | \"type\">,\n): TraceWindow {\n const { name, type } = artifact;\n if (type === \"skill\") return skillWindow(trace, name);\n if (type === \"agent\") return agentWindow(trace, name);\n if (type === \"slash-command\") return slashCommandWindow(trace, name);\n // Project rules govern everything, so the window is the trace itself —\n // handed back by reference, so a session-scoped eval grades exactly what it\n // graded before scoping existed.\n return {\n scope: \"session\",\n label: \"whole session\",\n empty: false,\n events: trace.events,\n toolCalls: trace.toolCalls,\n fileAccesses: trace.fileAccesses,\n skillInvocations: trace.skillInvocations,\n userMessages: trace.userMessages,\n assistantTexts: trace.assistantTexts,\n turnCount: trace.turnCount,\n };\n}\n\n/** A grader's response to an empty window: a stated skip, never a verdict. */\nexport function skippedWindow(window: TraceWindow): GradeResult {\n return { findings: [], skipped: window.reason ?? \"the artifact governed no turns\" };\n}\n\nfunction skillWindow(trace: Trace, name: string): TraceWindow {\n // A skill loads either way: through the `Skill` tool, or by someone typing\n // its slash form.\n return injectionWindow(trace, \"skill\", `skill \"${name}\"`, (s) => s.name === name);\n}\n\n/**\n * A slash command's window is a skill's window, because the mechanism is the\n * same one: an instruction set injected at a point in the session, in force\n * until the next injection takes over (ADR 01023). Only the opening differs —\n * a `Skill` tool call is not the slash-command mechanism, so it can close a\n * command's window but never open it.\n */\nfunction slashCommandWindow(trace: Trace, name: string): TraceWindow {\n return injectionWindow(\n trace,\n \"slash-command\",\n `slash command \"/${name}\"`,\n (s) => s.name === name && s.via === \"command-injection\",\n );\n}\n\n/**\n * The window an injected instruction set governed: from each of its own\n * injections until the next injection of any kind — including another of its\n * own, which simply reopens the window — or to the end of the session.\n */\nfunction injectionWindow(\n trace: Trace,\n scope: \"skill\" | \"slash-command\",\n label: string,\n opensHere: (invocation: SkillInvocation) => boolean,\n): TraceWindow {\n const opens = trace.skillInvocations.filter(opensHere).map((s) => s.index);\n if (opens.length === 0) {\n return emptyWindow(\n scope,\n label,\n `${label} was never invoked in this trace, so it governed no turns`,\n );\n }\n // An instruction set injected inside a subagent branch governs that branch's\n // chain; one injected on the main chain governs the main chain.\n const chainOf = (index: number): string | undefined =>\n trace.events[index]?.branchId;\n const own = new Set<string | undefined>(opens.map(chainOf));\n // **Boundaries are drawn from the opening chain only** (ADR 01015: the next\n // invocation *on the same chain*). Drawn from every invocation, a subagent\n // that loaded a skill of its own closed the parent's window at the spawn —\n // so a `not-used` eval passed on turns it never saw, and the judge digest\n // stopped where the subagent started.\n const boundaries = trace.skillInvocations\n .filter((s) => own.has(chainOf(s.index)))\n .map((s) => s.index)\n .sort((a, b) => a - b);\n const spans = opens.map((start) => ({\n start,\n end: boundaries.find((b) => b > start) ?? Number.POSITIVE_INFINITY,\n }));\n return materialize(trace, scope, label, spans, undefined, own);\n}\n\nfunction agentWindow(trace: Trace, name: string): TraceWindow {\n const label = `agent \"${name}\"`;\n const mine = trace.subagentBranches.filter((b) => b.agentType === name);\n if (mine.length === 0) {\n const spawned = trace.agentSpawns.some((a) => a.subagentType === name);\n return emptyWindow(\n \"agent\",\n label,\n spawned\n ? `${label} was spawned but recorded no subagent turns (no inline ` +\n `sidechain records and no sidecar transcript), so it governed no turns`\n : `${label} was never spawned in this trace, so it governed no turns`,\n );\n }\n // A branch's span already covers everything nested under it (ADR 01014), so\n // one containment pass reaches subagents at any depth.\n const branchIds = new Set(mine.map((b) => b.branchId));\n for (const branch of trace.subagentBranches) {\n if (branchIds.has(branch.branchId)) continue;\n const nested = mine.some(\n (m) => m.startIndex <= branch.startIndex && branch.endIndex <= m.endIndex,\n );\n if (nested) branchIds.add(branch.branchId);\n }\n const spans = mine.map((b) => ({ start: b.startIndex, end: b.endIndex }));\n return materialize(\n trace,\n \"agent\",\n label,\n spans,\n branchIds,\n new Set<string | undefined>(mine.map((b) => b.branchId)),\n );\n}\n\nexport function emptyWindow(\n scope: TraceWindow[\"scope\"],\n label: string,\n reason: string,\n): TraceWindow {\n return {\n scope,\n label,\n empty: true,\n reason,\n events: [],\n toolCalls: [],\n fileAccesses: [],\n skillInvocations: [],\n userMessages: [],\n assistantTexts: [],\n turnCount: 0,\n };\n}\n\n/**\n * Cut every derived list to the spans. `branchIds`, when given, additionally\n * drops events that fall inside an *inline* branch's bounding range without\n * belonging to it — a sidecar branch is contiguous and loses nothing here, but\n * an inline one can enclose interleaved main-chain turns (ADR 01014).\n *\n * `own` names the chain the window is anchored to. Prompts and assistant text\n * are taken from that chain alone, so a subagent spawned inside the window\n * contributes tool calls and file accesses but not turns.\n */\nexport function materialize(\n trace: Trace,\n scope: TraceWindow[\"scope\"],\n label: string,\n spans: Span[],\n branchIds: Set<string> | undefined,\n own: Set<string | undefined>,\n): TraceWindow {\n const inSpan = (index: number): boolean =>\n spans.some((s) => index >= s.start && index < s.end);\n const excluded = new Set<number>();\n if (branchIds !== undefined) {\n for (const event of trace.events) {\n if (!inSpan(event.index)) continue;\n if (event.branchId === undefined || !branchIds.has(event.branchId)) {\n excluded.add(event.index);\n }\n }\n }\n const inWindow = (index: number): boolean =>\n inSpan(index) && !excluded.has(index);\n\n const events = trace.events.filter((e) => inWindow(e.index));\n const textOf = (kind: TraceEvent[\"kind\"]): string[] =>\n events\n .filter((e) => e.kind === kind && own.has(e.branchId) && e.text)\n .map((e) => e.text as string);\n const userMessages = textOf(\"user\");\n\n return {\n scope,\n label,\n empty: false,\n events,\n toolCalls: trace.toolCalls.filter((c) => inWindow(c.index)),\n fileAccesses: trace.fileAccesses.filter((a) => inWindow(a.index)),\n skillInvocations: trace.skillInvocations.filter((s) => inWindow(s.index)),\n userMessages,\n assistantTexts: textOf(\"assistant\"),\n turnCount: userMessages.length,\n };\n}\n"],"mappings":"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","names":[]}
|