pi-mega-compact 0.18.0 → 0.19.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/assets/vector-cortex/encoder-v1/manifest.json +1 -0
- package/assets/vector-cortex/encoder-v1/model-card.json +1 -0
- package/assets/vector-cortex/encoder-v1/model.onnx +0 -0
- package/assets/vector-cortex/encoder-v1/tokenizer.json +1 -0
- package/dist/config/vector-cortex.js +18 -0
- package/dist/config.js +117 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +4 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex.js +89 -1
- package/dist/log.js +47 -0
- package/dist/src/config/vector-cortex.js +18 -0
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/encoder/calibrate.js +174 -0
- package/dist/src/vector-cortex/encoder/emit-vc2b.js +63 -0
- package/dist/src/vector-cortex/encoder/emit-vc2c.js +59 -0
- package/dist/src/vector-cortex/encoder/fallback.js +62 -0
- package/dist/src/vector-cortex/encoder/heads.js +113 -0
- package/dist/src/vector-cortex/encoder/lexical.js +104 -0
- package/dist/src/vector-cortex/encoder/router.js +115 -0
- package/dist/src/vector-cortex/encoder/select.js +172 -0
- package/dist/src/vector-cortex/encoder/trigram.js +75 -0
- package/dist/src/vector-cortex/encoder/types.js +84 -0
- package/dist/vector-cortex/encoder/calibrate.js +174 -0
- package/dist/vector-cortex/encoder/emit-vc2b.js +63 -0
- package/dist/vector-cortex/encoder/emit-vc2c.js +59 -0
- package/dist/vector-cortex/encoder/fallback.js +62 -0
- package/dist/vector-cortex/encoder/heads.js +113 -0
- package/dist/vector-cortex/encoder/lexical.js +104 -0
- package/dist/vector-cortex/encoder/router.js +115 -0
- package/dist/vector-cortex/encoder/select.js +172 -0
- package/dist/vector-cortex/encoder/trigram.js +75 -0
- package/dist/vector-cortex/encoder/types.js +84 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-BQXFF7UI.js → AreaChart-DywU5SSt.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BQXFF7UI.js.map → AreaChart-DywU5SSt.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-BVtoz9Eg.js → BarChart-But7WN6K.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-BVtoz9Eg.js.map → BarChart-But7WN6K.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-trI2TIGy.js → CacheTab-7aZWa1DR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-trI2TIGy.js.map → CacheTab-7aZWa1DR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-CNUbk9__.js → EventsTab-Bf_boNG2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-CNUbk9__.js.map → EventsTab-Bf_boNG2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-K-bd_CM-.js → HealthTab-AbGc1nXP.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-K-bd_CM-.js.map → HealthTab-AbGc1nXP.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CoEioKzx.js → MaintenanceTab-BfHHhn5F.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CoEioKzx.js.map → MaintenanceTab-BfHHhn5F.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CJo24ulv.js → MemoryMapTab-DrcWti0-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CJo24ulv.js.map → MemoryMapTab-DrcWti0-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DCNlQWWP.js → MetricsTab-ALiglXQq.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DCNlQWWP.js.map → MetricsTab-ALiglXQq.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-CQQlyIQ6.js → OverviewTab-nnaJdNyR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-CQQlyIQ6.js.map → OverviewTab-nnaJdNyR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-Cqm82_yn.js → ReposTab-BTK0nofM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-Cqm82_yn.js.map → ReposTab-BTK0nofM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-A8xTAdET.js → SessionsTab-RXPNqO6x.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-A8xTAdET.js.map → SessionsTab-RXPNqO6x.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-CqaSgaZl.js → SetupTab-Dab0AVfs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-CqaSgaZl.js.map → SetupTab-Dab0AVfs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C_f3q8GR.js → TimeSavedCard-DIVG8hdt.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C_f3q8GR.js.map → TimeSavedCard-DIVG8hdt.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BEsafACo.js → TurnsTab-9uz2fBwx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BEsafACo.js.map → TurnsTab-9uz2fBwx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-DD1CMK80.js → VectorCortexTab-DnKY61EJ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DnKY61EJ.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-Bf01M2_Z.js → WikiTab-CpcgaggS.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-Bf01M2_Z.js.map → WikiTab-CpcgaggS.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-BEJPTk_E.js → button-B0Q2fuKY.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-BEJPTk_E.js.map → button-B0Q2fuKY.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-DK1V382s.js → card-Cnik3TFr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-DK1V382s.js.map → card-Cnik3TFr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CRtaPphL.js → generateCategoricalChart-DrSwgn1V.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CRtaPphL.js.map → generateCategoricalChart-DrSwgn1V.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-CB6BslE4.js → index-DraytcOY.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-CB6BslE4.js.map → index-DraytcOY.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-C4FV6B9k.js → switch-DVQ1aB9b.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-C4FV6B9k.js.map → switch-DVQ1aB9b.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-GBmeENMd.js → toggle-Dkppx-49.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-GBmeENMd.js.map → toggle-Dkppx-49.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-BOKZGSn1.js → useSSE-CPkjU4Gx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BOKZGSn1.js.map → useSSE-CPkjU4Gx.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +2 -0
- package/extensions/dashboard-client/src/types/vector-cortex.ts +11 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex.ts +11 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +14 -0
- package/extensions/dashboard-server/routes-vector-cortex.ts +108 -1
- package/package.json +2 -1
- package/src/config/vector-cortex.ts +20 -0
- package/src/config.ts +2 -0
- package/src/vector-cortex/encoder/calibrate.ts +225 -0
- package/src/vector-cortex/encoder/emit-vc2b.ts +82 -0
- package/src/vector-cortex/encoder/emit-vc2c.ts +70 -0
- package/src/vector-cortex/encoder/fallback.ts +99 -0
- package/src/vector-cortex/encoder/heads.ts +142 -0
- package/src/vector-cortex/encoder/lexical.ts +123 -0
- package/src/vector-cortex/encoder/router.ts +163 -0
- package/src/vector-cortex/encoder/select.ts +237 -0
- package/src/vector-cortex/encoder/trigram.ts +85 -0
- package/src/vector-cortex/encoder/types.ts +226 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DD1CMK80.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"batch":1,"heads":{"cacheStability":64,"contradiction":128,"dependency":128,"payloadRouting":32,"semantic":384},"hiddenWidth":384,"maxTokens":512,"modelVersion":"encoder-v1-placeholder","onnx":{"bytes":42,"path":"model.onnx","sha256":"01cbed8b0b301609542ff8c392c3e7d927b0d848ac53a768dfffd33bfe6005ff"},"opset":17,"platform":"linux-x64","schema":"model-manifest-v1","semanticWidth":384,"tokenizer":{"bytes":8518,"path":"tokenizer.json","sha256":"ada18e5c4dfcb5c369c05f4ffc10bc40298ce707e78f16135c6d33019f6db8cd"},"totalBytes":8560,"trainingManifestDigest":"e9b2550dbb79141af84440dda65ca21d3509904b2c09a89316145137a5b5e3de"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"accepted":"local offline deterministic projection over verified asset (V1); trained weights + evaluation land in VC2B/VC2C","comparison":[{"candidate":"MiniLM-class transformer","latencyMs":8,"license":"permissive","offlineNode":"no (native addon)","quality":"high","sizeMB":120},{"candidate":"small BERT","latencyMs":10,"license":"permissive","offlineNode":"partial","quality":"high","sizeMB":110},{"candidate":"bag/subword baseline","latencyMs":1,"license":"permissive","offlineNode":"yes","quality":"medium","sizeMB":4}],"note":"placeholder asset — replaced by the VC2C export pipeline","reprintPermission":true,"schema":"model-card-v1"}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"maxTokens":512,"schema":"wordpiece-tokenizer-v1","specialTokens":{"cls":2,"mask":4,"pad":0,"sep":3,"unk":1},"truncation":{"keepFirst":128,"keepLast":384},"vocab":[["[PAD]",0],["[UNK]",1],["[CLS]",2],["[SEP]",3],["[MASK]",4],["##tok0",5],["##tok1",6],["##tok2",7],["##tok3",8],["##tok4",9],["##tok5",10],["##tok6",11],["##tok7",12],["##tok8",13],["##tok9",14],["##tok10",15],["##tok11",16],["##tok12",17],["##tok13",18],["##tok14",19],["##tok15",20],["##tok16",21],["##tok17",22],["##tok18",23],["##tok19",24],["##tok20",25],["##tok21",26],["##tok22",27],["##tok23",28],["##tok24",29],["##tok25",30],["##tok26",31],["##tok27",32],["##tok28",33],["##tok29",34],["##tok30",35],["##tok31",36],["##tok32",37],["##tok33",38],["##tok34",39],["##tok35",40],["##tok36",41],["##tok37",42],["##tok38",43],["##tok39",44],["##tok40",45],["##tok41",46],["##tok42",47],["##tok43",48],["##tok44",49],["##tok45",50],["##tok46",51],["##tok47",52],["##tok48",53],["##tok49",54],["##tok50",55],["##tok51",56],["##tok52",57],["##tok53",58],["##tok54",59],["##tok55",60],["##tok56",61],["##tok57",62],["##tok58",63],["##tok59",64],["##tok60",65],["##tok61",66],["##tok62",67],["##tok63",68],["##tok64",69],["##tok65",70],["##tok66",71],["##tok67",72],["##tok68",73],["##tok69",74],["##tok70",75],["##tok71",76],["##tok72",77],["##tok73",78],["##tok74",79],["##tok75",80],["##tok76",81],["##tok77",82],["##tok78",83],["##tok79",84],["##tok80",85],["##tok81",86],["##tok82",87],["##tok83",88],["##tok84",89],["##tok85",90],["##tok86",91],["##tok87",92],["##tok88",93],["##tok89",94],["##tok90",95],["##tok91",96],["##tok92",97],["##tok93",98],["##tok94",99],["##tok95",100],["##tok96",101],["##tok97",102],["##tok98",103],["##tok99",104],["##tok100",105],["##tok101",106],["##tok102",107],["##tok103",108],["##tok104",109],["##tok105",110],["##tok106",111],["##tok107",112],["##tok108",113],["##tok109",114],["##tok110",115],["##tok111",116],["##tok112",117],["##tok113",118],["##tok114",119],["##tok115",120],["##tok116",121],["##tok117",122],["##tok118",123],["##tok119",124],["##tok120",125],["##tok121",126],["##tok122",127],["##tok123",128],["##tok124",129],["##tok125",130],["##tok126",131],["##tok127",132],["##tok128",133],["##tok129",134],["##tok130",135],["##tok131",136],["##tok132",137],["##tok133",138],["##tok134",139],["##tok135",140],["##tok136",141],["##tok137",142],["##tok138",143],["##tok139",144],["##tok140",145],["##tok141",146],["##tok142",147],["##tok143",148],["##tok144",149],["##tok145",150],["##tok146",151],["##tok147",152],["##tok148",153],["##tok149",154],["##tok150",155],["##tok151",156],["##tok152",157],["##tok153",158],["##tok154",159],["##tok155",160],["##tok156",161],["##tok157",162],["##tok158",163],["##tok159",164],["##tok160",165],["##tok161",166],["##tok162",167],["##tok163",168],["##tok164",169],["##tok165",170],["##tok166",171],["##tok167",172],["##tok168",173],["##tok169",174],["##tok170",175],["##tok171",176],["##tok172",177],["##tok173",178],["##tok174",179],["##tok175",180],["##tok176",181],["##tok177",182],["##tok178",183],["##tok179",184],["##tok180",185],["##tok181",186],["##tok182",187],["##tok183",188],["##tok184",189],["##tok185",190],["##tok186",191],["##tok187",192],["##tok188",193],["##tok189",194],["##tok190",195],["##tok191",196],["##tok192",197],["##tok193",198],["##tok194",199],["##tok195",200],["##tok196",201],["##tok197",202],["##tok198",203],["##tok199",204],["##tok200",205],["##tok201",206],["##tok202",207],["##tok203",208],["##tok204",209],["##tok205",210],["##tok206",211],["##tok207",212],["##tok208",213],["##tok209",214],["##tok210",215],["##tok211",216],["##tok212",217],["##tok213",218],["##tok214",219],["##tok215",220],["##tok216",221],["##tok217",222],["##tok218",223],["##tok219",224],["##tok220",225],["##tok221",226],["##tok222",227],["##tok223",228],["##tok224",229],["##tok225",230],["##tok226",231],["##tok227",232],["##tok228",233],["##tok229",234],["##tok230",235],["##tok231",236],["##tok232",237],["##tok233",238],["##tok234",239],["##tok235",240],["##tok236",241],["##tok237",242],["##tok238",243],["##tok239",244],["##tok240",245],["##tok241",246],["##tok242",247],["##tok243",248],["##tok244",249],["##tok245",250],["##tok246",251],["##tok247",252],["##tok248",253],["##tok249",254],["##tok250",255],["##tok251",256],["##tok252",257],["##tok253",258],["##tok254",259],["##tok255",260],["##tok256",261],["##tok257",262],["##tok258",263],["##tok259",264],["##tok260",265],["##tok261",266],["##tok262",267],["##tok263",268],["##tok264",269],["##tok265",270],["##tok266",271],["##tok267",272],["##tok268",273],["##tok269",274],["##tok270",275],["##tok271",276],["##tok272",277],["##tok273",278],["##tok274",279],["##tok275",280],["##tok276",281],["##tok277",282],["##tok278",283],["##tok279",284],["##tok280",285],["##tok281",286],["##tok282",287],["##tok283",288],["##tok284",289],["##tok285",290],["##tok286",291],["##tok287",292],["##tok288",293],["##tok289",294],["##tok290",295],["##tok291",296],["##tok292",297],["##tok293",298],["##tok294",299],["##tok295",300],["##tok296",301],["##tok297",302],["##tok298",303],["##tok299",304],["##tok300",305],["##tok301",306],["##tok302",307],["##tok303",308],["##tok304",309],["##tok305",310],["##tok306",311],["##tok307",312],["##tok308",313],["##tok309",314],["##tok310",315],["##tok311",316],["##tok312",317],["##tok313",318],["##tok314",319],["##tok315",320],["##tok316",321],["##tok317",322],["##tok318",323],["##tok319",324],["##tok320",325],["##tok321",326],["##tok322",327],["##tok323",328],["##tok324",329],["##tok325",330],["##tok326",331],["##tok327",332],["##tok328",333],["##tok329",334],["##tok330",335],["##tok331",336],["##tok332",337],["##tok333",338],["##tok334",339],["##tok335",340],["##tok336",341],["##tok337",342],["##tok338",343],["##tok339",344],["##tok340",345],["##tok341",346],["##tok342",347],["##tok343",348],["##tok344",349],["##tok345",350],["##tok346",351],["##tok347",352],["##tok348",353],["##tok349",354],["##tok350",355],["##tok351",356],["##tok352",357],["##tok353",358],["##tok354",359],["##tok355",360],["##tok356",361],["##tok357",362],["##tok358",363],["##tok359",364],["##tok360",365],["##tok361",366],["##tok362",367],["##tok363",368],["##tok364",369],["##tok365",370],["##tok366",371],["##tok367",372],["##tok368",373],["##tok369",374],["##tok370",375],["##tok371",376],["##tok372",377],["##tok373",378],["##tok374",379],["##tok375",380],["##tok376",381],["##tok377",382],["##tok378",383],["##tok379",384],["##tok380",385],["##tok381",386],["##tok382",387],["##tok383",388],["##tok384",389],["##tok385",390],["##tok386",391],["##tok387",392],["##tok388",393],["##tok389",394],["##tok390",395],["##tok391",396],["##tok392",397],["##tok393",398],["##tok394",399],["##tok395",400],["##tok396",401],["##tok397",402],["##tok398",403],["##tok399",404],["##tok400",405],["##tok401",406],["##tok402",407],["##tok403",408],["##tok404",409],["##tok405",410],["##tok406",411],["##tok407",412],["##tok408",413],["##tok409",414],["##tok410",415],["##tok411",416],["##tok412",417],["##tok413",418],["##tok414",419],["##tok415",420],["##tok416",421],["##tok417",422],["##tok418",423],["##tok419",424],["##tok420",425],["##tok421",426],["##tok422",427],["##tok423",428],["##tok424",429],["##tok425",430],["##tok426",431],["##tok427",432],["##tok428",433],["##tok429",434],["##tok430",435],["##tok431",436],["##tok432",437],["##tok433",438],["##tok434",439],["##tok435",440],["##tok436",441],["##tok437",442],["##tok438",443],["##tok439",444],["##tok440",445],["##tok441",446],["##tok442",447],["##tok443",448],["##tok444",449],["##tok445",450],["##tok446",451],["##tok447",452],["##tok448",453],["##tok449",454],["##tok450",455],["##tok451",456],["##tok452",457],["##tok453",458],["##tok454",459],["##tok455",460],["##tok456",461],["##tok457",462],["##tok458",463],["##tok459",464],["##tok460",465],["##tok461",466],["##tok462",467],["##tok463",468],["##tok464",469],["##tok465",470],["##tok466",471],["##tok467",472],["##tok468",473],["##tok469",474],["##tok470",475],["##tok471",476],["##tok472",477],["##tok473",478],["##tok474",479],["##tok475",480],["##tok476",481],["##tok477",482],["##tok478",483],["##tok479",484],["##tok480",485],["##tok481",486],["##tok482",487],["##tok483",488],["##tok484",489],["##tok485",490],["##tok486",491],["##tok487",492],["##tok488",493],["##tok489",494],["##tok490",495],["##tok491",496],["##tok492",497],["##tok493",498],["##tok494",499],["##tok495",500],["##tok496",501],["##tok497",502],["##tok498",503],["##tok499",504]]}
|
|
@@ -73,6 +73,24 @@ export const VC1C_ENABLED = () => sprintFlag("MEGACOMPACT_VC1C");
|
|
|
73
73
|
* encoder runtime's A/B/C selection.
|
|
74
74
|
*/
|
|
75
75
|
export const VC2A_ENABLED = () => sprintFlag("MEGACOMPACT_VC2A");
|
|
76
|
+
/**
|
|
77
|
+
* VC2B — multi-head encoder (VectorSetV1 / HeadCalibrationDraft).
|
|
78
|
+
* Default ON. `MEGACOMPACT_VC2B=0` disables and is byte-identical to the
|
|
79
|
+
* predecessor (the encoder emits no per-head vectors and no fallback-selected
|
|
80
|
+
* event; the trigram/lexical paths themselves are unchanged and are the
|
|
81
|
+
* predecessor's mode-B/C producers). The real consumers are the encoder-heads
|
|
82
|
+
* emit seam and the multi-head encoder producers (heads/trigram/lexical).
|
|
83
|
+
*/
|
|
84
|
+
export const VC2B_ENABLED = () => sprintFlag("MEGACOMPACT_VC2B");
|
|
85
|
+
/**
|
|
86
|
+
* VC2C — encoder qualification + calibration (QualifiedEncoderV1 / CalibrationV1).
|
|
87
|
+
* Default ON. `MEGACOMPACT_VC2C=0` disables and is byte-identical to the
|
|
88
|
+
* predecessor (mode C: no qualification manifest is read or selected, the
|
|
89
|
+
* calibrate/select/fallback seams are idle, zero `vector_cortex_encoder_qualification_*`
|
|
90
|
+
* emissions; the trigram/lexical paths are unchanged). The real consumers are
|
|
91
|
+
* the encoder-qualification emit seam and the calibrate/select seams.
|
|
92
|
+
*/
|
|
93
|
+
export const VC2C_ENABLED = () => sprintFlag("MEGACOMPACT_VC2C");
|
|
76
94
|
// ---------------------------------------------------------------------------
|
|
77
95
|
// Breaker state machine constants (TRIAD_RESILIENCE.md §breaker).
|
|
78
96
|
// Rolled numbers for one 60s window; VC0C consumes these at its breaker seam.
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config.ts — shared default paths/constants for the mega-compact engine.
|
|
3
|
+
*
|
|
4
|
+
* Kept tiny and dependency-free so both the extension entry and unit tests can
|
|
5
|
+
* import it without pulling in pi runtime types.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
/** Default on-disk location for checkpoints + session state. */
|
|
10
|
+
export const STATE_DIR_DEFAULT = join(homedir(), ".pi", "agent", "extensions", "pi-mega-compact");
|
|
11
|
+
/** Pi custom message / entry type used as the dedup sentinel. */
|
|
12
|
+
export const MARKER_TYPE = "mega-compact-marker";
|
|
13
|
+
/**
|
|
14
|
+
* Derive context-window pressure (0–1) from a usage percentage. Used to scale
|
|
15
|
+
* compression strength + keepFrom depth (Fix E): low pct = room to spare,
|
|
16
|
+
* high pct = near the limit. Deterministic; clamps to [0,1].
|
|
17
|
+
*/
|
|
18
|
+
export function pressureFromPct(pct) {
|
|
19
|
+
if (pct == null || Number.isNaN(pct))
|
|
20
|
+
return 0;
|
|
21
|
+
return pct < 0 ? 0 : pct > 100 ? 1 : pct / 100;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Map pressure → how many recent messages to preserve verbatim. Under low
|
|
25
|
+
* pressure we keep `preserveRecent`; under high pressure we compact deeper,
|
|
26
|
+
* down to `preserveRecentMin`. Never splits a tool pair / anchor floor — the
|
|
27
|
+
* boundary guard (computeDropRange) enforces that downstream.
|
|
28
|
+
*/
|
|
29
|
+
export function preserveRecentForPressure(pressure, preserveRecent, preserveRecentMin) {
|
|
30
|
+
const p = pressure < 0 ? 0 : pressure > 1 ? 1 : pressure;
|
|
31
|
+
const v = Math.round(preserveRecent - (preserveRecent - preserveRecentMin) * p);
|
|
32
|
+
// Floor of 1: even with preserveRecentMin=0 at full pressure, never compact
|
|
33
|
+
// ALL messages — the boundary guard (computeDropRange) needs ≥1 to anchor on.
|
|
34
|
+
return Math.max(1, preserveRecentMin, Math.min(preserveRecent, v));
|
|
35
|
+
}
|
|
36
|
+
/** Clamp a pressure ratio into [0, 1]. */
|
|
37
|
+
function clamp01(p) {
|
|
38
|
+
if (!Number.isFinite(p))
|
|
39
|
+
return 0;
|
|
40
|
+
return p < 0 ? 0 : p > 1 ? 1 : p;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Pressure as a 0–1 ratio from live token usage relative to the compaction
|
|
44
|
+
* threshold. Cheaper + more direct than deriving from a usage percentage when
|
|
45
|
+
* we already have both numbers (the context handler does). Re-exports
|
|
46
|
+
* `pressureFromPct` covers the percentage-only path. (S24.)
|
|
47
|
+
*/
|
|
48
|
+
export function pressureRatio(currentTokens, thresholdTokens) {
|
|
49
|
+
if (!Number.isFinite(currentTokens) || currentTokens <= 0)
|
|
50
|
+
return 0;
|
|
51
|
+
const t = Number.isFinite(thresholdTokens) && thresholdTokens > 0 ? thresholdTokens : 0;
|
|
52
|
+
return clamp01(t > 0 ? currentTokens / t : 0);
|
|
53
|
+
}
|
|
54
|
+
/** Map a 0–1 pressure ratio to a discrete band. (S24.) */
|
|
55
|
+
export function pressureBand(pressure) {
|
|
56
|
+
const p = clamp01(pressure);
|
|
57
|
+
if (p >= 1.0)
|
|
58
|
+
return "mega";
|
|
59
|
+
if (p >= 0.9)
|
|
60
|
+
return "ultra";
|
|
61
|
+
if (p >= 0.75)
|
|
62
|
+
return "high";
|
|
63
|
+
if (p >= 0.5)
|
|
64
|
+
return "medium";
|
|
65
|
+
return "low";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Memory auto-review cadence (in turns) for a given pressure band. As pressure
|
|
69
|
+
* climbs, the conversation is reviewed more often so durable memories keep pace
|
|
70
|
+
* with the faster context churn. Returns a divisor used as
|
|
71
|
+
* `turn % cadence === 0`. Always >= 1. (S24 — memory cadence tie-in.)
|
|
72
|
+
*/
|
|
73
|
+
export function memoryReviewCadence(band, baseInterval) {
|
|
74
|
+
const base = baseInterval >= 1 ? baseInterval : 1;
|
|
75
|
+
switch (band) {
|
|
76
|
+
case "mega": return Math.max(1, Math.round(base / 5));
|
|
77
|
+
case "ultra": return Math.max(1, Math.round(base / 3));
|
|
78
|
+
case "high": return Math.max(1, Math.round(base / 2));
|
|
79
|
+
case "medium": return Math.max(1, Math.round((base * 2) / 3));
|
|
80
|
+
case "low":
|
|
81
|
+
default: return base;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// S57 RAG Suite feature flags — all default ON with graceful fallback; opt OUT
|
|
86
|
+
// via MEGACOMPACT_<NAME>_DISABLED=true. Every feature degrades to existing
|
|
87
|
+
// behavior on error (non-fatal, best-effort).
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
function ragFlag(name) {
|
|
90
|
+
const v = process.env[name];
|
|
91
|
+
if (v === undefined)
|
|
92
|
+
return false;
|
|
93
|
+
return v === "true" || v === "1";
|
|
94
|
+
}
|
|
95
|
+
function ragEnabled(name) {
|
|
96
|
+
return !ragFlag(name + "_DISABLED");
|
|
97
|
+
}
|
|
98
|
+
/** B1: Query reformulation (keyword expansion via embedding neighbors). */
|
|
99
|
+
export const RAG_QUERY_REFORMULATION = () => ragEnabled("MEGACOMPACT_QUERY_REFORMULATION");
|
|
100
|
+
/** B2: Tiered recall router (L0 cache → L1 FTS5 → L2 HNSW). */
|
|
101
|
+
export const RAG_TIERED_ROUTER = () => ragEnabled("MEGACOMPACT_TIERED_ROUTER");
|
|
102
|
+
/** B3: Recall quality metrics (precision/recall scoring + logging). */
|
|
103
|
+
export const RAG_RECALL_METRICS = () => ragEnabled("MEGACOMPACT_RECALL_METRICS");
|
|
104
|
+
/** B4: Memory graph traversal (dashboard-oriented). */
|
|
105
|
+
export const RAG_MEMORY_GRAPH = () => ragEnabled("MEGACOMPACT_MEMORY_GRAPH");
|
|
106
|
+
/** B5: HyDE — generate a hypothetical answer doc via LLM. Auto-ON when an
|
|
107
|
+
* HttpEmbedder is active (the LLM is configured for indexing); opt OUT with
|
|
108
|
+
* MEGACOMPACT_HYDE_DISABLED=true. TrigramEmbedder path is unaffected. */
|
|
109
|
+
export const RAG_HYDE_ENABLED = () => ragEnabled("MEGACOMPACT_HYDE");
|
|
110
|
+
/** Spec 1: vbrainstorm visual design migration for the dashboard. */
|
|
111
|
+
export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Vector-cortex flags + breaker constants (VC0A+). Positive sprint flags,
|
|
114
|
+
// default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
|
|
115
|
+
// so root consumers share one source of truth.
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
@@ -127,6 +127,8 @@ export const SETTINGS = [
|
|
|
127
127
|
str("MEGACOMPACT_RAPTOR_MODEL", "RAPTOR Summary Model", "Ollama model for cluster summarization (empty = extractive)", ""),
|
|
128
128
|
str("MEGACOMPACT_RAPTOR_URL", "RAPTOR Ollama URL", "Ollama endpoint for RAPTOR summarization", "http://127.0.0.1:11434"),
|
|
129
129
|
num("MEGACOMPACT_EMBED_CACHE", "Embed Cache Size", "Embedding cache entries (0 = disabled)", 256, 0, 10000),
|
|
130
|
+
num("MEGACOMPACT_EMBEDDING_BATCH_TOKENS", "Embedding Batch Tokens", "Oversized-prompt chunking limit (tokens) for the BYO localhost embedder; text above this is chunked + mean-pooled", 2048, 64, 8192),
|
|
131
|
+
num("MEGACOMPACT_EMBEDDING_CHARS_PER_TOKEN", "Embedding Chars per Token", "Estimated characters per token used for embedder chunking size", 4, 1, 32),
|
|
130
132
|
],
|
|
131
133
|
},
|
|
132
134
|
{
|
|
@@ -139,6 +141,8 @@ export const SETTINGS = [
|
|
|
139
141
|
boolDirect("MEGACOMPACT_VC0C", "VC0C Live Safety Envelope", "TriadResult/Breaker live circuit breaker (60s window, 20 attempts, 30s cooldown, 3 probes, 5min healthy residence) + durable spool before provider invocation; manual reset clears cooldown but never evidence. OFF = mode C, unchanged transcript, byte-identical.", true),
|
|
140
142
|
boolDirect("MEGACOMPACT_VC1C", "VC1C Cross-Language Conformance v2", "FixtureManifestV2 canonical manifest validator + DowngradeReport deterministic downgrade export + MinHashV2 exact big-integer signatures and the M4 copy/validate/switch minhash-v2 migration (seed table frozen, cross-language byte-exact). OFF = mode C, v1 sync dedup scan unchanged, byte-identical.", true),
|
|
141
143
|
boolDirect("MEGACOMPACT_VC2A", "VC2A Offline Model Runtime", "ModelManifestV1 digest-before-load ONNX runtime (opset17/batch1/max512) + asset-free trigram demotion. Asset path assets/vector-cortex/encoder-v1 is immutable/digest-pinned. OFF = mode C, byte-identical to predecessor.", true),
|
|
144
|
+
boolDirect("MEGACOMPACT_VC2B", "VC2B Multi-Head Encoder", "VectorSetV1 five L2-normalized heads (384/128/128/64/32) with head-calibration draft + asset-free trigram B (512d) and lexical C fallbacks, plus the per-head emit seam. OFF = mode C, no per-head vectors emitted, byte-identical predecessor.", true),
|
|
145
|
+
boolDirect("MEGACOMPACT_VC2C", "VC2C Encoder Qualification + Calibration", "QualifiedEncoderV1/CalibrationV1: calibration fit on the calibration split only (held-out labels prohibited) + atomic selection across MODEL_ASSET and per-head EVALUATION thresholds (any field failure demotes all of A). OFF = mode C, no qualification/calibration selection, byte-identical predecessor.", true),
|
|
142
146
|
],
|
|
143
147
|
},
|
|
144
148
|
{
|
|
@@ -14,11 +14,16 @@
|
|
|
14
14
|
* Guardrails: PREVENT-PI-004 (local filesystem read only), PREVENT-011 (no
|
|
15
15
|
* `any`), reader-only aggregate (never payloads/prompts/ledger — EVAL-REDACT-002).
|
|
16
16
|
*/
|
|
17
|
-
import {
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
18
|
+
import { readFileSync, statSync } from "node:fs";
|
|
19
|
+
import { join, dirname } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { VC0A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC2C_ENABLED } from "../../src/config.js";
|
|
18
22
|
import { readEvalRows } from "../../src/vector-cortex/eval/persist.js";
|
|
19
23
|
import { summarizeEvalRows } from "../../src/vector-cortex/eval/reader.js";
|
|
20
24
|
import { createVectorCortexSafety } from "../mega-runtime/vector-cortex-safety.js";
|
|
21
25
|
import { createLedgerStore } from "../../src/vector-cortex/ledger/store.js";
|
|
26
|
+
import { readEncoderManifest, verifyEncoderAsset, detectPlatform } from "../../src/vector-cortex/encoder/asset.js";
|
|
22
27
|
/** Admin capability: an actor-supplied subsystem selector for breaker reset. */
|
|
23
28
|
function readJsonBody(req, cb) {
|
|
24
29
|
let body = "";
|
|
@@ -50,6 +55,84 @@ function sendJson(res, status, body) {
|
|
|
50
55
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
51
56
|
res.end(JSON.stringify(body));
|
|
52
57
|
}
|
|
58
|
+
/** Resolve the committed encoder-v1 asset dir by walking up to the repo root. */
|
|
59
|
+
function encoderAssetDir() {
|
|
60
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
61
|
+
const rel = join("assets", "vector-cortex", "encoder-v1");
|
|
62
|
+
for (let i = 0; i < 8; i++) {
|
|
63
|
+
const candidate = join(dir, rel);
|
|
64
|
+
try {
|
|
65
|
+
// guardrails-allow PREVENT-PI-004: local asset filesystem read (loopback)
|
|
66
|
+
readFileSync(join(candidate, "manifest.json"));
|
|
67
|
+
return candidate;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
/* keep walking */
|
|
71
|
+
}
|
|
72
|
+
const next = dirname(dir);
|
|
73
|
+
if (next === dir)
|
|
74
|
+
break;
|
|
75
|
+
dir = next;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
let healthCache = null;
|
|
80
|
+
/** Stable cache key: manifest bytes + (size,mtime) of the asset files + platform. */
|
|
81
|
+
function healthFactCacheKey(dir, manifestPath) {
|
|
82
|
+
const platform = detectPlatform();
|
|
83
|
+
if (!platform)
|
|
84
|
+
return null;
|
|
85
|
+
const parts = [platform];
|
|
86
|
+
try {
|
|
87
|
+
for (const p of [manifestPath, join(dir, "model.onnx"), join(dir, "tokenizer.json")]) {
|
|
88
|
+
const s = statSync(p);
|
|
89
|
+
parts.push(`${s.size}:${s.mtimeMs}`);
|
|
90
|
+
}
|
|
91
|
+
// guardrails-allow PREVENT-PI-004: local manifest filesystem read (loopback)
|
|
92
|
+
parts.push(createHash("sha256").update(readFileSync(manifestPath)).digest("hex"));
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return parts.join("|");
|
|
98
|
+
}
|
|
99
|
+
function computeEncoderHealthFacts(dir) {
|
|
100
|
+
const manifest = readEncoderManifest(dir);
|
|
101
|
+
if (manifest === null)
|
|
102
|
+
return { assetDigest: null, mode: "C" };
|
|
103
|
+
const manifestPath = join(dir, "manifest.json");
|
|
104
|
+
const key = healthFactCacheKey(dir, manifestPath);
|
|
105
|
+
if (key === null)
|
|
106
|
+
return null;
|
|
107
|
+
if (healthCache !== null && healthCache.key === key)
|
|
108
|
+
return healthCache.facts;
|
|
109
|
+
let digest;
|
|
110
|
+
try {
|
|
111
|
+
// guardrails-allow PREVENT-PI-004: local manifest filesystem read (loopback)
|
|
112
|
+
digest = createHash("sha256").update(readFileSync(manifestPath)).digest("hex");
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return { assetDigest: null, mode: "B" };
|
|
116
|
+
}
|
|
117
|
+
const verify = verifyEncoderAsset(dir, manifest, detectPlatform());
|
|
118
|
+
const facts = { assetDigest: digest, mode: verify.ok ? "A" : "B" };
|
|
119
|
+
healthCache = { key, facts };
|
|
120
|
+
return facts;
|
|
121
|
+
}
|
|
122
|
+
function encoderHealthFacts() {
|
|
123
|
+
if (!VC2C_ENABLED()) {
|
|
124
|
+
// Rollback: MEGACOMPACT_VC2C=0 selects C — report the inactive (flag-gated)
|
|
125
|
+
// mode with no asset digest rather than an on-disk-computed A/B.
|
|
126
|
+
return { assetDigest: null, mode: "C" };
|
|
127
|
+
}
|
|
128
|
+
const dir = encoderAssetDir();
|
|
129
|
+
if (dir === null)
|
|
130
|
+
return { assetDigest: null, mode: "C" };
|
|
131
|
+
const facts = computeEncoderHealthFacts(dir);
|
|
132
|
+
if (facts === null)
|
|
133
|
+
return { assetDigest: null, mode: "C" };
|
|
134
|
+
return facts;
|
|
135
|
+
}
|
|
53
136
|
/** Reader-only aggregate GET /api/vector-cortex/evaluation. */
|
|
54
137
|
export function handleVectorCortexEvaluation(req, res, ctx) {
|
|
55
138
|
const url = req.url ?? "";
|
|
@@ -107,6 +190,7 @@ export function handleVectorCortexHealth(req, res, ctx) {
|
|
|
107
190
|
const enabled = VC0C_ENABLED();
|
|
108
191
|
const safety = enabled ? createVectorCortexSafety({ stateDir: ctx.stateDir }) : null;
|
|
109
192
|
const card = safety ? safety.health() : null;
|
|
193
|
+
const enc = encoderHealthFacts();
|
|
110
194
|
const fallback = {
|
|
111
195
|
enabled: false,
|
|
112
196
|
mode: "C",
|
|
@@ -126,6 +210,8 @@ export function handleVectorCortexHealth(req, res, ctx) {
|
|
|
126
210
|
updatedAt: new Date().toISOString(),
|
|
127
211
|
aggregate: "CLOSED_A",
|
|
128
212
|
stateSource: "ephemeral",
|
|
213
|
+
encoderAssetDigest: enc.assetDigest,
|
|
214
|
+
encoderMode: enc.mode,
|
|
129
215
|
};
|
|
130
216
|
if (!card) {
|
|
131
217
|
sendJson(res, 200, fallback);
|
|
@@ -161,6 +247,8 @@ export function handleVectorCortexHealth(req, res, ctx) {
|
|
|
161
247
|
updatedAt: new Date().toISOString(),
|
|
162
248
|
aggregate,
|
|
163
249
|
stateSource: card.stateSource,
|
|
250
|
+
encoderAssetDigest: enc.assetDigest,
|
|
251
|
+
encoderMode: enc.mode,
|
|
164
252
|
};
|
|
165
253
|
sendJson(res, 200, body);
|
|
166
254
|
return true;
|
package/dist/log.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log.ts — tiny append-only structured logger.
|
|
3
|
+
*
|
|
4
|
+
* Writes one JSON object per line to a log file (default:
|
|
5
|
+
* ~/.pi/agent/extensions/mega-compact.log). Best-effort: logging never throws
|
|
6
|
+
* into the extension. Pi-agnostic and dependency-free so it can be unit-tested.
|
|
7
|
+
*/
|
|
8
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { STATE_DIR_DEFAULT } from "./config.js";
|
|
11
|
+
/** Default log path lives alongside the state dir. */
|
|
12
|
+
export function defaultLogPath() {
|
|
13
|
+
return join(STATE_DIR_DEFAULT, "mega-compact.log");
|
|
14
|
+
}
|
|
15
|
+
export class Logger {
|
|
16
|
+
path;
|
|
17
|
+
enabled;
|
|
18
|
+
/** Monotonic clock injected by the caller so the module stays deterministic. */
|
|
19
|
+
now;
|
|
20
|
+
constructor(opts = {}) {
|
|
21
|
+
this.path = opts.path ?? defaultLogPath();
|
|
22
|
+
this.enabled = opts.enabled ?? true;
|
|
23
|
+
this.now = opts.now ?? (() => Date.now());
|
|
24
|
+
}
|
|
25
|
+
/** Append one structured line. Swallows all I/O errors. */
|
|
26
|
+
log(level, event, fields = {}) {
|
|
27
|
+
if (!this.enabled)
|
|
28
|
+
return;
|
|
29
|
+
const entry = { ts: this.now(), level, event, ...fields };
|
|
30
|
+
try {
|
|
31
|
+
mkdirSync(dirname(this.path), { recursive: true });
|
|
32
|
+
appendFileSync(this.path, `${JSON.stringify(entry)}\n`);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
/* best-effort: never break the extension on a log failure */
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
info(event, fields) {
|
|
39
|
+
this.log("info", event, fields);
|
|
40
|
+
}
|
|
41
|
+
warn(event, fields) {
|
|
42
|
+
this.log("warn", event, fields);
|
|
43
|
+
}
|
|
44
|
+
error(event, fields) {
|
|
45
|
+
this.log("error", event, fields);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -73,6 +73,24 @@ export const VC1C_ENABLED = () => sprintFlag("MEGACOMPACT_VC1C");
|
|
|
73
73
|
* encoder runtime's A/B/C selection.
|
|
74
74
|
*/
|
|
75
75
|
export const VC2A_ENABLED = () => sprintFlag("MEGACOMPACT_VC2A");
|
|
76
|
+
/**
|
|
77
|
+
* VC2B — multi-head encoder (VectorSetV1 / HeadCalibrationDraft).
|
|
78
|
+
* Default ON. `MEGACOMPACT_VC2B=0` disables and is byte-identical to the
|
|
79
|
+
* predecessor (the encoder emits no per-head vectors and no fallback-selected
|
|
80
|
+
* event; the trigram/lexical paths themselves are unchanged and are the
|
|
81
|
+
* predecessor's mode-B/C producers). The real consumers are the encoder-heads
|
|
82
|
+
* emit seam and the multi-head encoder producers (heads/trigram/lexical).
|
|
83
|
+
*/
|
|
84
|
+
export const VC2B_ENABLED = () => sprintFlag("MEGACOMPACT_VC2B");
|
|
85
|
+
/**
|
|
86
|
+
* VC2C — encoder qualification + calibration (QualifiedEncoderV1 / CalibrationV1).
|
|
87
|
+
* Default ON. `MEGACOMPACT_VC2C=0` disables and is byte-identical to the
|
|
88
|
+
* predecessor (mode C: no qualification manifest is read or selected, the
|
|
89
|
+
* calibrate/select/fallback seams are idle, zero `vector_cortex_encoder_qualification_*`
|
|
90
|
+
* emissions; the trigram/lexical paths are unchanged). The real consumers are
|
|
91
|
+
* the encoder-qualification emit seam and the calibrate/select seams.
|
|
92
|
+
*/
|
|
93
|
+
export const VC2C_ENABLED = () => sprintFlag("MEGACOMPACT_VC2C");
|
|
76
94
|
// ---------------------------------------------------------------------------
|
|
77
95
|
// Breaker state machine constants (TRIAD_RESILIENCE.md §breaker).
|
|
78
96
|
// Rolled numbers for one 60s window; VC0C consumes these at its breaker seam.
|
package/dist/src/config.js
CHANGED
|
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
|
|
|
114
114
|
// default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
|
|
115
115
|
// so root consumers share one source of truth.
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
117
|
-
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
117
|
+
export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/encoder/calibrate.ts — VC2C calibration fit (task 2).
|
|
3
|
+
*
|
|
4
|
+
* Fits a `CalibrationV1` using ONLY the calibration split. Held-out
|
|
5
|
+
* (test/eval) labels are STRICTLY PROHIBITED from the fit inputs: the fit
|
|
6
|
+
* function rejects (ENC_QUALIFICATION_HELD_OUT_IN_FIT) any example whose
|
|
7
|
+
* `itemId` appears in the caller's held-out set. Ties in example score are
|
|
8
|
+
* broken deterministically by item ID (stable score/id ties), never by arrival
|
|
9
|
+
* order, so the fit is invariant to row order.
|
|
10
|
+
*
|
|
11
|
+
* The calibration split assignment is grouped by repository+session
|
|
12
|
+
* (EVALUATION.md §corpus): every label-bearing item carries a `repository` +
|
|
13
|
+
* `session` group, and the split digest is the canonical SHA-256 over the
|
|
14
|
+
* sorted group list. A single repo/session group NEVER crosses split boundaries
|
|
15
|
+
* (the caller seeds a group wholly into the calibration split or not at all).
|
|
16
|
+
*
|
|
17
|
+
* The fit itself is a deterministic seeded per-head temperature + threshold
|
|
18
|
+
* calibration over the calibration-only examples (real isotonic/Platt weights
|
|
19
|
+
* land with trained weights; the contract, split isolation, held-out
|
|
20
|
+
* prohibition, stable ties, and frozen-temperature/threshold surface are all
|
|
21
|
+
* normative here). Pi-agnostic, zero network (PREVENT-PI-004), no `any`
|
|
22
|
+
* (PREVENT-011).
|
|
23
|
+
*/
|
|
24
|
+
import { createHash } from "node:crypto";
|
|
25
|
+
import { ENCODER_HEAD_ORDER, ENCODER_SEED, ENC_QUALIFICATION_FAIL, } from "./types.js";
|
|
26
|
+
/** Canonical digests of a sorted stable representation (order-invariant). */
|
|
27
|
+
function digestStrings(values) {
|
|
28
|
+
const sorted = [...values].sort();
|
|
29
|
+
return createHash("sha256").update(sorted.join("\n")).digest("hex");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Compute the calibration split digest for a set of (repository, session) groups
|
|
33
|
+
* present in the fit. The group list is canonicalized (sorted, deduped) so the
|
|
34
|
+
* digest is invariant to row order within the input. A caller that seeds WHOLE
|
|
35
|
+
* groups into the calibration split guarantees no group crosses a boundary.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Render one (repository, session) group as an injective canonical string.
|
|
39
|
+
* Each field is length-prefixed (`<len>:<value>`), so two distinct pairs can
|
|
40
|
+
* never collide to the same rendering — e.g. `{r:"a", s:"b::c"}` renders as
|
|
41
|
+
* `1:a3:b::c` while `{r:"a::b", s:"c"}` renders as `4:a::b1:c`. A plain
|
|
42
|
+
* `repository::session` join would conflate those when identifiers happen to
|
|
43
|
+
* contain "::"; length-prefixing makes the split digest sound for arbitrary
|
|
44
|
+
* repository/session identifiers.
|
|
45
|
+
*/
|
|
46
|
+
function renderGroup(g) {
|
|
47
|
+
return `${g.repository.length}:${g.repository}${g.session.length}:${g.session}`;
|
|
48
|
+
}
|
|
49
|
+
export function calibrationSplitDigest(groups) {
|
|
50
|
+
const rendered = new Set();
|
|
51
|
+
for (const g of groups)
|
|
52
|
+
rendered.add(renderGroup(g));
|
|
53
|
+
return digestStrings([...rendered]);
|
|
54
|
+
}
|
|
55
|
+
/** A deterministic 32-bit LCG step (matches the heads/runtime projectors). */
|
|
56
|
+
function nextState(state) {
|
|
57
|
+
return (state * 1664525 + 1013904223) >>> 0;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Deterministic per-head temperature in a stable, healthy range (e.g. 0.8..1.5).
|
|
61
|
+
*
|
|
62
|
+
* The caller-supplied `seed` is mixed into the LCG state through independent
|
|
63
|
+
* steps so it ALWAYS affects the temperature — even when it equals ENCODER_SEED.
|
|
64
|
+
* (A naive `ENCODER_SEED ^ head.length ^ seed` cancels the two seed terms when
|
|
65
|
+
* `seed === ENCODER_SEED`, leaving a pure function of the head — the default
|
|
66
|
+
* path would make the seed option inert. Here the seed seeds the PRNG first,
|
|
67
|
+
* then the head name is folded in, so both vary the fit independently.) The fit
|
|
68
|
+
* stays deterministic for a fixed (seed, head) across processes.
|
|
69
|
+
*/
|
|
70
|
+
function fitTemperature(head, seed) {
|
|
71
|
+
let state = (seed >>> 0) ^ 0x9e3779b9;
|
|
72
|
+
state = nextState(state);
|
|
73
|
+
state = (state ^ (head.length >>> 0)) >>> 0;
|
|
74
|
+
state = nextState(state);
|
|
75
|
+
state = (state ^ 0x85ebca6b) >>> 0;
|
|
76
|
+
state = nextState(state);
|
|
77
|
+
const r = (state / 4294967296) % 1;
|
|
78
|
+
return 0.8 + r * 0.7; // 0.8 .. 1.5
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Deterministic per-head decision threshold derived from the calibration
|
|
82
|
+
* distribution. For a head with BOTH classes present the threshold is the
|
|
83
|
+
* midpoint between the highest-scoring negative (label 0) and the lowest-scoring
|
|
84
|
+
* positive (label 1) — a true between-class balance point that NEVER lands on a
|
|
85
|
+
* negative example's own score (code-review Q03): a future inference at the
|
|
86
|
+
* highest calibration negative is still classified negative, and one at the
|
|
87
|
+
* lowest calibration positive is still classified positive. Degenerate heads with
|
|
88
|
+
* a single class fall back conservatively (no positives -> just above the top
|
|
89
|
+
* observed score; no negatives -> just below the lowest observed positive) and an
|
|
90
|
+
* empty head defaults to 0.5. Scoring is order-invariant: ties in score resolve by
|
|
91
|
+
* item ID bytewise (stable score/id ties), never by arrival order, so the fit is
|
|
92
|
+
* invariant to row order. This frozen threshold is a normative placeholder (real
|
|
93
|
+
* trained weights land later).
|
|
94
|
+
*/
|
|
95
|
+
function fitThreshold(head, examples) {
|
|
96
|
+
const headEx = examples
|
|
97
|
+
.filter((e) => e.head === head)
|
|
98
|
+
.slice()
|
|
99
|
+
.sort((a, b) => (a.score - b.score) || (a.itemId < b.itemId ? -1 : a.itemId > b.itemId ? 1 : 0));
|
|
100
|
+
if (headEx.length === 0)
|
|
101
|
+
return 0.5;
|
|
102
|
+
let highestNeg = -Infinity;
|
|
103
|
+
let lowestPos = Infinity;
|
|
104
|
+
for (const e of headEx) {
|
|
105
|
+
if (e.label === 0)
|
|
106
|
+
highestNeg = Math.max(highestNeg, e.score);
|
|
107
|
+
else
|
|
108
|
+
lowestPos = Math.min(lowestPos, e.score);
|
|
109
|
+
}
|
|
110
|
+
if (lowestPos === Infinity) {
|
|
111
|
+
// Only negatives observed — no positive class to balance against. Set the
|
|
112
|
+
// threshold just above the top observed score so no observed negative is
|
|
113
|
+
// re-admitted (a genuine future positive must exceed all calibration negatives).
|
|
114
|
+
return Math.max(0.5, highestNeg + 0.05);
|
|
115
|
+
}
|
|
116
|
+
if (highestNeg === -Infinity) {
|
|
117
|
+
// Only positives observed — set the threshold just below the lowest observed
|
|
118
|
+
// positive so every observed positive is admitted.
|
|
119
|
+
return Math.max(0, lowestPos - 0.05);
|
|
120
|
+
}
|
|
121
|
+
// Both classes present: the midpoint strictly between the highest negative and
|
|
122
|
+
// the lowest positive is the between-class balance point (Q03).
|
|
123
|
+
return (highestNeg + lowestPos) / 2;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Fit `CalibrationV1` over the calibration split only (task 2).
|
|
127
|
+
*
|
|
128
|
+
* - rejects any item whose `itemId` is in `heldOutIds` (held-out labels are
|
|
129
|
+
* prohibited from fit inputs).
|
|
130
|
+
* - treats `groups` as the calibration split units; the emitted split digest
|
|
131
|
+
* covers only the groups ACTUALLY present in the fit examples (plus the
|
|
132
|
+
* declared `groups`, when supplied — see below).
|
|
133
|
+
* - stable score/id ties (never arrival order).
|
|
134
|
+
*
|
|
135
|
+
* Held-out labels are prohibited by construction: the caller passes the full set
|
|
136
|
+
* of held-out item IDs, and the fit fails loudly if any calibration input is
|
|
137
|
+
* actually a held-out item — the fit can never silently learn from review labels.
|
|
138
|
+
*/
|
|
139
|
+
export function fitCalibration(examples, options = {}) {
|
|
140
|
+
const seed = options.seed ?? ENCODER_SEED;
|
|
141
|
+
const heldOut = new Set(options.heldOutIds ?? []);
|
|
142
|
+
for (const e of examples) {
|
|
143
|
+
if (heldOut.has(e.itemId)) {
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
code: ENC_QUALIFICATION_FAIL.HELD_OUT_IN_FIT,
|
|
147
|
+
reason: `held-out item ${e.itemId} leaked into calibration fit`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Stable order by (score, itemId) — arrival order never affects the digest or
|
|
152
|
+
// the fit; ties resolve by item ID bytewise (stable score/id ties).
|
|
153
|
+
const stable = examples
|
|
154
|
+
.slice()
|
|
155
|
+
.sort((a, b) => (a.score - b.score) || (a.itemId < b.itemId ? -1 : a.itemId > b.itemId ? 1 : 0));
|
|
156
|
+
const usedGroups = options.groups ?? stable.map((e) => ({ repository: e.repository, session: e.session }));
|
|
157
|
+
const splitDigest = calibrationSplitDigest(usedGroups);
|
|
158
|
+
const temperatures = {};
|
|
159
|
+
const thresholds = {};
|
|
160
|
+
for (const head of ENCODER_HEAD_ORDER) {
|
|
161
|
+
temperatures[head] = fitTemperature(head, seed);
|
|
162
|
+
thresholds[head] = fitThreshold(head, stable);
|
|
163
|
+
}
|
|
164
|
+
const calibration = {
|
|
165
|
+
schema: "calibration-v1",
|
|
166
|
+
headOrder: [...ENCODER_HEAD_ORDER],
|
|
167
|
+
calibrationSplitDigest: splitDigest,
|
|
168
|
+
fittedOnCalibrationOnly: true,
|
|
169
|
+
temperatures,
|
|
170
|
+
thresholds,
|
|
171
|
+
seed,
|
|
172
|
+
};
|
|
173
|
+
return { ok: true, calibration };
|
|
174
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/encoder/emit-vc2b.ts — VC2B observability seam.
|
|
3
|
+
*
|
|
4
|
+
* Owns the two VC2B events (task 5), gated on `MEGACOMPACT_VC2B` so the
|
|
5
|
+
* flag-OFF path emits zero events (mode C parity, byte-identical predecessor):
|
|
6
|
+
*
|
|
7
|
+
* vector_cortex_encoder_heads_emitted — a multi-head VectorSetV1 produced
|
|
8
|
+
* vector_cortex_encoder_fallback_selected — a mode B/C fallback selected
|
|
9
|
+
*
|
|
10
|
+
* No dashboard or API change is necessary for this internal sprint (task 5).
|
|
11
|
+
* Every event is a JSON line with `ts` + `event` (ENGINEERING_PRACTICES §8); the
|
|
12
|
+
* emitters are non-fatal (never break the agent loop). Pi-agnostic, zero network
|
|
13
|
+
* (PREVENT-PI-004), no `any` (PREVENT-011).
|
|
14
|
+
*/
|
|
15
|
+
import { VC2B_ENABLED } from "../../config/vector-cortex.js";
|
|
16
|
+
import { Logger } from "../../log.js";
|
|
17
|
+
/** A flag-gated no-op reporter (zero emissions, structural no-op). */
|
|
18
|
+
export const NOOP_VC2B_REPORTER = {
|
|
19
|
+
headsEmitted: () => { },
|
|
20
|
+
fallbackSelected: () => { },
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The default emitter: routes both VC2B events into the append-only structured
|
|
24
|
+
* logger (`src/log.ts`) as JSON lines with `ts` + `event`. Supplying `emit:` to
|
|
25
|
+
* `createEncoderHeadsReporter` replaces this with a caller-provided sink (used
|
|
26
|
+
* by tests and downstream consumers). Making the default a REAL producer means a
|
|
27
|
+
* caller that just invokes the producer seam (`encodeOrFallback`, `encodeVectorSet`,
|
|
28
|
+
* `selectTrigramBFallback`, `selectLexicalC`) without injecting an emitter still
|
|
29
|
+
* yields structured telemetry instead of silently dropping every event (task 5,
|
|
30
|
+
* code-review Q01). Best-effort: the logger swallows all I/O errors.
|
|
31
|
+
*/
|
|
32
|
+
function defaultEmitFor(logPath) {
|
|
33
|
+
const logger = new Logger(logPath === undefined ? {} : { path: logPath });
|
|
34
|
+
return (event, fields) => {
|
|
35
|
+
logger.info(event, fields);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Flag-gated emit, defaulting to a real logger-backed sink. The returned
|
|
40
|
+
* reporter is itself flag-gated (`VC2B_ENABLED`), so wiring it into a producer
|
|
41
|
+
* seam yields zero emissions when `MEGACOMPACT_VC2B=0` (byte-identical to the
|
|
42
|
+
* predecessor). Pass an explicit `emit` to route elsewhere (tests, downstream
|
|
43
|
+
* consumers); omit it to emit real structured log lines (Q01: the default is a
|
|
44
|
+
* live producer, not a silent no-op). `opts.logPath` only redirects the default
|
|
45
|
+
* sink and is ignored when `emit` is supplied.
|
|
46
|
+
*/
|
|
47
|
+
export function createEncoderHeadsReporter(emit, opts = {}) {
|
|
48
|
+
const sink = emit ?? defaultEmitFor(opts.logPath);
|
|
49
|
+
const fire = (event, fields) => {
|
|
50
|
+
if (!VC2B_ENABLED())
|
|
51
|
+
return;
|
|
52
|
+
try {
|
|
53
|
+
sink(event, { ...fields, ts: new Date().toISOString() });
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
/* non-fatal observability */
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
headsEmitted: (fields) => fire("vector_cortex_encoder_heads_emitted", fields),
|
|
61
|
+
fallbackSelected: (fields) => fire("vector_cortex_encoder_fallback_selected", fields),
|
|
62
|
+
};
|
|
63
|
+
}
|