chainlesschain 0.166.47 → 0.166.56
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 +22 -0
- package/package.json +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CDpT0WXV.js → AIOps-CBFnwYRX.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BNfUljWx.js → ActionButton-Sl4eXWpR.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C9323DEx.js → Analytics-DB0lD9Kb.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CRrjb2db.js → AppLayout-j77EmkRK.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-Db-DGqJS.js → Artifacts-CU3izCW9.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CJdHRJ0W.js → Audit-C44fSibb.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-_RSCnTYs.js → BackgroundAgents-pM_NnJW3.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-8GFQi-dM.js → Backup-AOHXqhxN.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C87NtgUZ.js → BaseInput-DaYc8oA_.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DcTMWS8G.js → Chat-CmlCAXxW.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-5ZDPTW_H.js → ChatBubbleRenderer-CkCSkJDJ.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DM9EmYee.js → Checkbox-DISI7iaA.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-M2YqDRNN.js → Codegen-BYpeKUpf.js} +1 -1
- package/src/assets/web-panel/assets/{Col-oB1LLxyf.js → Col-Dk6VwWGq.js} +1 -1
- package/src/assets/web-panel/assets/{Community-TcVZK5tF.js → Community-BDyTedMu.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-XKmq-3K_.js → Compact-CTNlGM9X.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-C6CBiDRy.js → Compliance-C_tw3IdT.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Dz9CGqXH.js → Cowork-cduHWEmo.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-CxJDgDVL.js → Cron-Dqotjv-s.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DMP0JsaQ.js → Crosschain-ByW7RsJQ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-I5IQeogb.js → DID-BI-lafPj.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BfLW2MXj.js → Dashboard-8m50TRZL.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BK8EjAlh.js → Dropdown-CN3hmRTc.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C3iqSv5I.js → EmailListRenderer-t0lzxsDT.js} +1 -1
- package/src/assets/web-panel/assets/EvolutionSettings-DabpA3cQ.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-T19rnqm-.js → FamilyGuardDashboard-BYN4UshY.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CozrbPMy.js → Federation-n44OtIXp.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-k1dCLNNJ.js → FormItemContext-B-WXDu_I.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DbaW_Jvt.js → GenericCardRenderer-Bm7v-mTf.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CQHRyEIt.js → Git-BMIS6sbo.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BMJYZgMy.js → Governance-B1EhHobE.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-B7mpNU7V.js → Inference-Dy_HJWHo.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Br0Blg6B.js → KnowledgeGraph-BVdfUbZy.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-HIdk0S6M.js → Logs-Dph_oLQk.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-CNHYqcxm.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Bkfq69UP.js → Marketplace-Bw4HWORj.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-dtmx0bHO.js → McpTools-Be6DPfA1.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CrRlOuEf.js → Memory-DlvLafC9.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-D4ZIZiAH.js → MobileBridge-Upc_Jwlt.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-C90Rw7GE.js → MobileProjects-I17jrUbY.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CC6k_uh4.js → Mtc-DyBzY0GH.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-T_CUIYUy.js → MtcAudit-2-7xAwEo.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-N_e0RRWk.js → Multisig-DtUZpFmZ.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Iq3VzEv0.js → NLProgramming-iInH7jBr.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-B5sKJUJt.js → Notes-BO3Z3vaS.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-K8UVp8qQ.js → NotificationSettings-ClX_0jFE.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BWNyM-6m.js → OrderTableRenderer-Czw742w4.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DMO1NJxI.js → Organization-BATEx24i.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BBY6b31Z.js → Overflow-B_PXMNia.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DmsL0y0v.js → P2P-BSiE8PqT.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-C65AX_RY.js → PdhVaultBrowser-BbklUgZY.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CWcpRtWa.js → Permissions-B7bpflT_.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub--ZNDIdsn.js → PersonalDataHub-BWZS4BLy.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DCdj5NGb.js → Pipeline-DP2YSs6H.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BRKu7Q3E.js → Privacy-DB9ptoH0.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BJ7ozIAb.js → ProjectInit-BAfePyYk.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B2cVLiXW.js → ProjectSettings-BEXn4Cm3.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Ce9r_W-p.js → Projects-BzSs0rzn.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-BDespvGZ.js → Providers-CRX9TdRO.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BUNO4fDU.js → QrScannerModal-DUWcSY5L.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D2TUqeBV.js → QuickAsk-Cgo3Z_hs.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BNNQPHBH.js → Recommend-Dcinx0IW.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-D2t1V_Cm.js → RemoteSession-BMZzTnAN.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DVK5hEqI.js → Reputation-BdZzpOp9.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BB9RTwmE.js → Row-DqM8GVcx.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DmEO7liZ.js → RssFeed-Soj_QBK3.js} +2 -2
- package/src/assets/web-panel/assets/{Search-UwEYjnDB.js → Search-Cn2es0-v.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DebqSsMp.js → Security-t7C4hz3n.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CuuPts3C.js → Services-ChF-e_Uf.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DbWpmbgf.js → Skeleton-BiPIyK-2.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BaK7SxzT.js → Skills-HgkKJenJ.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BFHv51Jb.js → Sla-BSfluv_k.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-B9b1R6uK.js → SpeechSettings-Sm0Gz9tM.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BnO0CN02.js → SyncSettings-DlhBMnfU.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Dy01Vq49.js → Tasks-C7OUvsnp.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BCy2AMHc.js → Templates-CrMtw87y.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-4Tx9y_Y1.js → Tenant-DSNSB6j5.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CPOoUH8J.js → Terminal-Cmh78FQg.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-C85GlJzu.js → TimelineRenderer-BE8b8lHR.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-_xneFBGF.js → Tokens-BrtgdIvJ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BizG4rTr.js → Trigger-HCmaoKDp.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Dh8EIn3n.js → Trust-GASQ4F-2.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C5NWoHWQ.js → UkeySign-B8kSzWGr.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-0YfrySL6.js → VideoEditing-Nn-clhv5.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BZVH8Ags.js → Wallet-DdYMKTYk.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-kNofa6vm.js → WebAuthn-xJXUr_eK.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-BNO34_j0.js → WorkflowEditor-CbSa87av.js} +1 -1
- package/src/assets/web-panel/assets/{chat-ifQ2FlwD.js → chat-CVrNLGUV.js} +1 -1
- package/src/assets/web-panel/assets/{colors-1TL8H6EH.js → colors-e2veLfIA.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DBfRjs_T.js → compact-item-CNd7nhUq.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Bs6V4iBf.js → createContext-DEudTVqv.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DW7he-SA.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Bz6LMY_0.js → hasIn-BlSAFZa3.js} +1 -1
- package/src/assets/web-panel/assets/{index--WvT2Il3.js → index-0y7tHZdT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMVktlxG.js → index-4ZT0vIJt.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6RClMZl.js → index-7-7rr4Mf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BB1Af7Fv.js → index-B1C1wS5c.js} +1 -1
- package/src/assets/web-panel/assets/{index-lUL3bD2z.js → index-BG-VNepa.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtB45Hok.js → index-BMIhGZUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOww5Qny.js → index-BRNCKg4q.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiZ7Nz5-.js → index-B_UNX_xq.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9QYxq61.js → index-BmVFeSEq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoCTDcn6.js → index-Bp4Gcn9u.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXtiLagi.js → index-BpH6T1gA.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5SJCUZ7.js → index-BptI9bLu.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cn7EIWmI.js → index-Bqeb4jnC.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvM2xBUA.js → index-Bwtt-0CQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-EK3XtMxA.js → index-C4h_Bvd2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDhy4eCS.js → index-C6zGNZ5H.js} +1 -1
- package/src/assets/web-panel/assets/{index-rGhS02f8.js → index-CHMrAZiR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQL_tldd.js → index-CK6Rb66R.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7d6QlfR.js → index-CU4Y4VVN.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cykt9BbN.js → index-CWuv47z0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXJXMaZe.js → index-CYNoXhxl.js} +1 -1
- package/src/assets/web-panel/assets/{index-f_7L9GvP.js → index-CgVwz2jD.js} +1 -1
- package/src/assets/web-panel/assets/{index-vHtnQsnV.js → index-ClROBPWd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhPDhmvN.js → index-D7yJceTZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu_V6ZJH.js → index-DFv-nsIT.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNKHoXWI.js → index-DFzvcZ3Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-vb1XIxEB.js → index-DJ5gsewX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWPp-d07.js → index-DVORJydf.js} +1 -1
- package/src/assets/web-panel/assets/{index-pOUFfRdN.js → index-D_D7lcnQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-cNwsev6n.js → index-DtrqgNBl.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBh48_Mh.js → index-DwjWRUTf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxqC3LiO.js → index-DyFZ7gDd.js} +1 -1
- package/src/assets/web-panel/assets/{index-XJIV7HEw.js → index-Ec6VBiV-.js} +1 -1
- package/src/assets/web-panel/assets/index-IkoHuWRe.js +1 -0
- package/src/assets/web-panel/assets/{index-CXVBQ82k.js → index-Jk99aZIr.js} +3 -3
- package/src/assets/web-panel/assets/{index-84mi5rsv.js → index-Lm9pm1zm.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6c0j-Ki.js → index-MuTb62K6.js} +1 -1
- package/src/assets/web-panel/assets/index-MwqsDbb1.js +1 -0
- package/src/assets/web-panel/assets/{index-DEPPzM8I.js → index-hzUfIn4u.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DpRIjwTt.js → initDefaultProps-C6fpNcA5.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CG4_9o-Z.js → motion-Bjh9Come.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dku1fXtf.js → move-DFa4ul-_.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BvAVeX-3.js → mtc-parser-KoYqA_e5.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DFu0x78D.js → omit-ByTjP-wG.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CmI-FNcK.js → pickAttrs-CG_rmTxx.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CGERYewB.js → placementArrow-LDePZ8V9.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D7G8bF5J.js → responsiveObserve-DZFzH4RR.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B2sXwWXy.js → slide-DfXQyTvD.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DI5yh0n3.js → statusUtils-CuhqsJfO.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-deGJ5dp_.js → styleChecker-qqVjJw5u.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-OqHBXEmi.js → useFlexGapSupport-BPxnCxcb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Dqgx0Qv_.js → useFs-D11NLCjV.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Be-lveh2.js → usePersonalDataHub-HbZVcaCX.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CFxB876W.js → vnode-CZHQlfTu.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BFOYrl4e.js → zoom-CV3rUknJ.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/context.js +31 -11
- package/src/commands/evolution-deployment.js +70 -0
- package/src/commands/plugin.js +36 -5
- package/src/data/changelog.json +78 -0
- package/src/gateways/ws/evolution-deployment-topic-handlers.js +20 -0
- package/src/generated/cc-agent-protocol.schema.json +44 -1
- package/src/harness/prompt-compressor.js +12 -4
- package/src/lib/background-agent-list-index.js +222 -0
- package/src/lib/background-agent-supervisor.js +38 -0
- package/src/lib/codex-app-server-adapter.js +1 -0
- package/src/lib/context-memory-kernel/provider-context.js +69 -4
- package/src/lib/deferred-question-context.js +160 -4
- package/src/lib/eval/plugin-suite.js +286 -22
- package/src/lib/evolution/evolution-deployment-config.js +16 -1
- package/src/lib/evolution/evolution-deployment-profile.js +102 -58
- package/src/lib/evolution/evolution-test-deployment.js +386 -0
- package/src/lib/model-context-window.js +3 -2
- package/src/lib/runtime-usage-ledger.js +5 -0
- package/src/lib/session-host-snapshot.js +16 -0
- package/src/repl/agent-repl.js +19 -4
- package/src/runtime/agent-core.js +13 -0
- package/src/runtime/headless-runner.js +4 -0
- package/src/runtime/headless-stream.js +171 -14
- package/src/assets/web-panel/assets/EvolutionSettings-BJmBzpW6.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-HxeocBHy.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BHnbnuYL.js +0 -1
- package/src/assets/web-panel/assets/index-CsRz9-ZH.js +0 -1
- package/src/assets/web-panel/assets/index-DnjMFf3m.js +0 -1
|
@@ -7,6 +7,8 @@ import { encodeName } from "../plugin-runtime/scopes.js";
|
|
|
7
7
|
|
|
8
8
|
export const PLUGIN_EVAL_SUITE_SCHEMA = "chainlesschain.plugin-eval-suite/v1";
|
|
9
9
|
export const PLUGIN_EVAL_REPORT_SCHEMA = "chainlesschain.plugin-eval-report/v1";
|
|
10
|
+
export const PLUGIN_EVAL_HOLDOUT_SCHEMA =
|
|
11
|
+
"chainlesschain.plugin-eval-holdout/v1";
|
|
10
12
|
|
|
11
13
|
const DEFAULT_SUITE_PATH = "evals/suite.json";
|
|
12
14
|
const MAX_SUITE_BYTES = 1024 * 1024;
|
|
@@ -22,6 +24,7 @@ const MAX_ASSERTION_FILE_BYTES = 4 * 1024 * 1024;
|
|
|
22
24
|
const MAX_RUNTIME_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
23
25
|
const MAX_RUNTIME_TOOL_CALLS = 10_000;
|
|
24
26
|
const MAX_TRIGGER_SIGNALS = 256;
|
|
27
|
+
const MAX_SAMPLE_RUNS = 20;
|
|
25
28
|
const TASK_ID = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/u;
|
|
26
29
|
const EXPECTATIONS = new Set([
|
|
27
30
|
"should_trigger",
|
|
@@ -35,6 +38,7 @@ const ASSERTION_TYPES = new Set([
|
|
|
35
38
|
"file_contains",
|
|
36
39
|
"json_equals",
|
|
37
40
|
]);
|
|
41
|
+
const ARM_ORDERS = new Set(["balanced", "control-first", "candidate-first"]);
|
|
38
42
|
|
|
39
43
|
function digest(bytes, domain) {
|
|
40
44
|
return `sha256:${crypto
|
|
@@ -122,6 +126,25 @@ function suiteRelativePath(root, suiteFile) {
|
|
|
122
126
|
return relation.split(path.sep).join("/");
|
|
123
127
|
}
|
|
124
128
|
|
|
129
|
+
function readBoundedJsonFile(file, label) {
|
|
130
|
+
const target = path.resolve(file);
|
|
131
|
+
const stat = fs.lstatSync(target);
|
|
132
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
133
|
+
throw new TypeError(`${label} must be a regular file, not a symlink`);
|
|
134
|
+
}
|
|
135
|
+
if (stat.size === 0 || stat.size > MAX_SUITE_BYTES) {
|
|
136
|
+
throw new RangeError(`${label} must be under ${MAX_SUITE_BYTES} bytes`);
|
|
137
|
+
}
|
|
138
|
+
const bytes = fs.readFileSync(target);
|
|
139
|
+
let value;
|
|
140
|
+
try {
|
|
141
|
+
value = JSON.parse(bytes.toString("utf8"));
|
|
142
|
+
} catch {
|
|
143
|
+
throw new TypeError(`${label} is not valid JSON`);
|
|
144
|
+
}
|
|
145
|
+
return { target, bytes, value: plainObject(value, label) };
|
|
146
|
+
}
|
|
147
|
+
|
|
125
148
|
function collectPluginSnapshot(root) {
|
|
126
149
|
const rootStat = fs.lstatSync(root);
|
|
127
150
|
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
|
|
@@ -214,6 +237,24 @@ function parseThreshold(value, label, { min = 0, max = 1 } = {}) {
|
|
|
214
237
|
return value;
|
|
215
238
|
}
|
|
216
239
|
|
|
240
|
+
function parseSampleRuns(value, label = "sampling.runs") {
|
|
241
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_SAMPLE_RUNS) {
|
|
242
|
+
throw new RangeError(
|
|
243
|
+
`${label} must be an integer between 1 and ${MAX_SAMPLE_RUNS}`,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return value;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function parseArmOrder(value, label = "sampling.armOrder") {
|
|
250
|
+
if (!ARM_ORDERS.has(value)) {
|
|
251
|
+
throw new TypeError(
|
|
252
|
+
`${label} must be balanced, control-first, or candidate-first`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
|
|
217
258
|
function normalizeAssertion(value, taskId, index) {
|
|
218
259
|
const assertion = plainObject(value, `task ${taskId} assertion ${index}`);
|
|
219
260
|
if (!ASSERTION_TYPES.has(assertion.type)) {
|
|
@@ -414,6 +455,8 @@ export function loadPluginEvalDefinition(pluginRoot, { suiteFile } = {}) {
|
|
|
414
455
|
}
|
|
415
456
|
const thresholds = raw.thresholds || {};
|
|
416
457
|
plainObject(thresholds, "plugin eval suite.thresholds");
|
|
458
|
+
const sampling = raw.sampling || {};
|
|
459
|
+
plainObject(sampling, "plugin eval suite.sampling");
|
|
417
460
|
const maxCandidateCostUsd = parseThreshold(
|
|
418
461
|
thresholds.maxCandidateCostUsd,
|
|
419
462
|
"thresholds.maxCandidateCostUsd",
|
|
@@ -421,6 +464,7 @@ export function loadPluginEvalDefinition(pluginRoot, { suiteFile } = {}) {
|
|
|
421
464
|
);
|
|
422
465
|
return {
|
|
423
466
|
schema: PLUGIN_EVAL_SUITE_SCHEMA,
|
|
467
|
+
pluginRoot: fs.realpathSync(root),
|
|
424
468
|
identity: {
|
|
425
469
|
name: manifest.metadata.name,
|
|
426
470
|
version: manifest.metadata.version,
|
|
@@ -433,6 +477,10 @@ export function loadPluginEvalDefinition(pluginRoot, { suiteFile } = {}) {
|
|
|
433
477
|
),
|
|
434
478
|
payload: snapshot,
|
|
435
479
|
tasks,
|
|
480
|
+
sampling: {
|
|
481
|
+
runs: parseSampleRuns(sampling.runs ?? 1),
|
|
482
|
+
armOrder: parseArmOrder(sampling.armOrder || "balanced"),
|
|
483
|
+
},
|
|
436
484
|
thresholds: {
|
|
437
485
|
minPassRateDelta:
|
|
438
486
|
parseThreshold(
|
|
@@ -450,6 +498,87 @@ export function loadPluginEvalDefinition(pluginRoot, { suiteFile } = {}) {
|
|
|
450
498
|
};
|
|
451
499
|
}
|
|
452
500
|
|
|
501
|
+
/**
|
|
502
|
+
* Attach reviewer-owned tasks from a file outside the plugin payload. The
|
|
503
|
+
* digest is reported separately so an author-controlled payload cannot mutate
|
|
504
|
+
* or silently absorb the holdout corpus.
|
|
505
|
+
*/
|
|
506
|
+
export function attachPluginEvalHoldout(definition, holdoutFile) {
|
|
507
|
+
if (!holdoutFile) return definition;
|
|
508
|
+
const { target, bytes, value } = readBoundedJsonFile(
|
|
509
|
+
holdoutFile,
|
|
510
|
+
"plugin eval holdout",
|
|
511
|
+
);
|
|
512
|
+
const holdoutReal = fs.realpathSync(target);
|
|
513
|
+
const relation = path.relative(definition.pluginRoot, holdoutReal);
|
|
514
|
+
if (
|
|
515
|
+
relation === "" ||
|
|
516
|
+
(!relation.startsWith(`..${path.sep}`) &&
|
|
517
|
+
relation !== ".." &&
|
|
518
|
+
!path.isAbsolute(relation))
|
|
519
|
+
) {
|
|
520
|
+
throw new TypeError(
|
|
521
|
+
"plugin eval holdout must be outside the plugin payload root",
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
if (value.schema !== PLUGIN_EVAL_HOLDOUT_SCHEMA) {
|
|
525
|
+
throw new TypeError(
|
|
526
|
+
`plugin eval holdout must use ${PLUGIN_EVAL_HOLDOUT_SCHEMA}`,
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
const identity = plainObject(value.plugin, "plugin eval holdout.plugin");
|
|
530
|
+
if (
|
|
531
|
+
identity.name !== definition.identity.name ||
|
|
532
|
+
identity.version !== definition.identity.version
|
|
533
|
+
) {
|
|
534
|
+
throw new TypeError(
|
|
535
|
+
"plugin eval holdout identity must match the parsed plugin manifest",
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
if (
|
|
539
|
+
!Array.isArray(value.tasks) ||
|
|
540
|
+
value.tasks.length === 0 ||
|
|
541
|
+
value.tasks.length > MAX_TASKS
|
|
542
|
+
) {
|
|
543
|
+
throw new RangeError(`plugin eval holdout requires 1-${MAX_TASKS} tasks`);
|
|
544
|
+
}
|
|
545
|
+
const holdoutTasks = value.tasks.map((task, index) => ({
|
|
546
|
+
...normalizeTask(task, index),
|
|
547
|
+
source: "holdout",
|
|
548
|
+
}));
|
|
549
|
+
if (definition.tasks.length + holdoutTasks.length > MAX_TASKS) {
|
|
550
|
+
throw new RangeError(
|
|
551
|
+
`plugin eval author and holdout tasks may not exceed ${MAX_TASKS}`,
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
const ids = new Set(definition.tasks.map((task) => task.id));
|
|
555
|
+
for (const task of holdoutTasks) {
|
|
556
|
+
if (ids.has(task.id)) {
|
|
557
|
+
throw new TypeError(`duplicate plugin eval task id: ${task.id}`);
|
|
558
|
+
}
|
|
559
|
+
ids.add(task.id);
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
...definition,
|
|
563
|
+
tasks: [
|
|
564
|
+
...definition.tasks.map((task) => ({
|
|
565
|
+
...task,
|
|
566
|
+
source: task.source || "author",
|
|
567
|
+
})),
|
|
568
|
+
...holdoutTasks,
|
|
569
|
+
],
|
|
570
|
+
holdout: {
|
|
571
|
+
schema: PLUGIN_EVAL_HOLDOUT_SCHEMA,
|
|
572
|
+
// Reports may be shared as CI artifacts; do not disclose the reviewer's
|
|
573
|
+
// absolute workstation path. The digest is the authoritative binding.
|
|
574
|
+
path: path.basename(target),
|
|
575
|
+
digest: digest(bytes, "chainlesschain.plugin-eval-holdout-bytes/v1"),
|
|
576
|
+
tasks: holdoutTasks.length,
|
|
577
|
+
independentFromPayload: true,
|
|
578
|
+
},
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
|
|
453
582
|
function materializePlugin(definition, workspace) {
|
|
454
583
|
const nameDir = path.join(
|
|
455
584
|
workspace,
|
|
@@ -555,6 +684,7 @@ function buildTasks(definition, { candidate }) {
|
|
|
555
684
|
return definition.tasks.map((task) => ({
|
|
556
685
|
id: task.id,
|
|
557
686
|
description: task.description,
|
|
687
|
+
source: task.source || "author",
|
|
558
688
|
prompt: task.prompt,
|
|
559
689
|
expectedFiles: task.expectedFiles,
|
|
560
690
|
...(task.timeoutMs === undefined ? {} : { timeoutMs: task.timeoutMs }),
|
|
@@ -708,6 +838,7 @@ function projectArm(summary, definition, { candidate }) {
|
|
|
708
838
|
metrics.pluginTriggered === false));
|
|
709
839
|
return {
|
|
710
840
|
...result,
|
|
841
|
+
source: task.source || "author",
|
|
711
842
|
expectation,
|
|
712
843
|
pluginTriggered: metrics.pluginTriggered,
|
|
713
844
|
activationEvidenceAvailable: metrics.available === true,
|
|
@@ -753,10 +884,110 @@ function reportArm(arm) {
|
|
|
753
884
|
usage: arm.usage,
|
|
754
885
|
totalCostUsd: arm.totalCostUsd,
|
|
755
886
|
ms: arm.ms,
|
|
887
|
+
sampleRuns: arm.sampleRuns,
|
|
756
888
|
results: arm.results,
|
|
757
889
|
};
|
|
758
890
|
}
|
|
759
891
|
|
|
892
|
+
function aggregateArms(arms) {
|
|
893
|
+
const results = arms.flatMap((arm, sampleIndex) =>
|
|
894
|
+
arm.results.map((result) => ({ ...result, sample: sampleIndex + 1 })),
|
|
895
|
+
);
|
|
896
|
+
const total = results.length;
|
|
897
|
+
const measured = results.filter((result) =>
|
|
898
|
+
Array.isArray(result.unrelatedChanges),
|
|
899
|
+
);
|
|
900
|
+
const tasksWithUnrelatedChanges = measured.filter(
|
|
901
|
+
(result) => result.unrelatedChanges.length > 0,
|
|
902
|
+
).length;
|
|
903
|
+
const passed = results.filter((result) => result.pass).length;
|
|
904
|
+
const effectivePassed = results.filter(
|
|
905
|
+
(result) => result.effectivePass,
|
|
906
|
+
).length;
|
|
907
|
+
const triggered = results.filter(
|
|
908
|
+
(result) => result.pluginTriggered === true,
|
|
909
|
+
).length;
|
|
910
|
+
return {
|
|
911
|
+
results,
|
|
912
|
+
passed,
|
|
913
|
+
failed: total - passed,
|
|
914
|
+
total,
|
|
915
|
+
passRate: total > 0 ? passed / total : 0,
|
|
916
|
+
effectivePassed,
|
|
917
|
+
effectiveFailed: total - effectivePassed,
|
|
918
|
+
effectivePassRate: total > 0 ? effectivePassed / total : 0,
|
|
919
|
+
artifactChecksPassed: results.filter((result) => result.artifactCheckPassed)
|
|
920
|
+
.length,
|
|
921
|
+
executionsSucceeded: results.filter((result) => result.executionSucceeded)
|
|
922
|
+
.length,
|
|
923
|
+
tasksWithUnrelatedChanges,
|
|
924
|
+
unrelatedChangeRate: measured.length
|
|
925
|
+
? tasksWithUnrelatedChanges / measured.length
|
|
926
|
+
: 0,
|
|
927
|
+
triggerRate: total > 0 ? triggered / total : 0,
|
|
928
|
+
activationEvidenceComplete: results.every(
|
|
929
|
+
(result) => result.activationEvidenceAvailable,
|
|
930
|
+
),
|
|
931
|
+
...sumUsage(results),
|
|
932
|
+
ms: arms.reduce((totalMs, arm) => totalMs + arm.ms, 0),
|
|
933
|
+
sampleRuns: arms.length,
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// Wilson score intervals stay well behaved for the small and extreme samples
|
|
938
|
+
// common in plugin author evals (unlike p +/- z*sqrt(p(1-p)/n)).
|
|
939
|
+
function wilson95(successes, total) {
|
|
940
|
+
if (!Number.isSafeInteger(total) || total <= 0) return null;
|
|
941
|
+
const z = 1.959963984540054;
|
|
942
|
+
const z2 = z * z;
|
|
943
|
+
const p = successes / total;
|
|
944
|
+
const denominator = 1 + z2 / total;
|
|
945
|
+
const center = (p + z2 / (2 * total)) / denominator;
|
|
946
|
+
const radius =
|
|
947
|
+
(z * Math.sqrt((p * (1 - p) + z2 / (4 * total)) / total)) / denominator;
|
|
948
|
+
return {
|
|
949
|
+
lower: Math.max(0, center - radius),
|
|
950
|
+
upper: Math.min(1, center + radius),
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
function confidenceComparison(control, candidate) {
|
|
955
|
+
const controlInterval = wilson95(control.effectivePassed, control.total);
|
|
956
|
+
const candidateInterval = wilson95(
|
|
957
|
+
candidate.effectivePassed,
|
|
958
|
+
candidate.total,
|
|
959
|
+
);
|
|
960
|
+
if (!controlInterval || !candidateInterval) return null;
|
|
961
|
+
return {
|
|
962
|
+
method: "wilson-95-newcombe-difference",
|
|
963
|
+
control: controlInterval,
|
|
964
|
+
candidate: candidateInterval,
|
|
965
|
+
passRateDelta: {
|
|
966
|
+
lower: candidateInterval.lower - controlInterval.upper,
|
|
967
|
+
upper: candidateInterval.upper - controlInterval.lower,
|
|
968
|
+
},
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
function sampleArmSequence(sampleRuns, armOrder, suiteDigest) {
|
|
973
|
+
if (armOrder === "control-first") {
|
|
974
|
+
return Array.from({ length: sampleRuns }, () => ["control", "candidate"]);
|
|
975
|
+
}
|
|
976
|
+
if (armOrder === "candidate-first") {
|
|
977
|
+
return Array.from({ length: sampleRuns }, () => ["candidate", "control"]);
|
|
978
|
+
}
|
|
979
|
+
// Bind the first arm to the suite digest, then alternate. This balances
|
|
980
|
+
// provider drift without introducing an unrecorded random source.
|
|
981
|
+
const startsWithCandidate =
|
|
982
|
+
Number.parseInt(String(suiteDigest).slice(-2), 16) % 2 === 1;
|
|
983
|
+
return Array.from({ length: sampleRuns }, (_, index) => {
|
|
984
|
+
const candidateFirst = startsWithCandidate
|
|
985
|
+
? index % 2 === 0
|
|
986
|
+
: index % 2 === 1;
|
|
987
|
+
return candidateFirst ? ["candidate", "control"] : ["control", "candidate"];
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
|
|
760
991
|
export async function runPluginEval(
|
|
761
992
|
definition,
|
|
762
993
|
{
|
|
@@ -768,6 +999,8 @@ export async function runPluginEval(
|
|
|
768
999
|
model = null,
|
|
769
1000
|
dryRun = false,
|
|
770
1001
|
minPassRateDelta,
|
|
1002
|
+
sampleRuns,
|
|
1003
|
+
armOrder,
|
|
771
1004
|
onResult,
|
|
772
1005
|
} = {},
|
|
773
1006
|
) {
|
|
@@ -777,30 +1010,49 @@ export async function runPluginEval(
|
|
|
777
1010
|
) {
|
|
778
1011
|
throw new TypeError("controlRunAgent and candidateRunAgent are required");
|
|
779
1012
|
}
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
keepWorkspaces,
|
|
784
|
-
onResult: onResult ? (result) => onResult({ arm, result }) : undefined,
|
|
785
|
-
});
|
|
786
|
-
const control = projectArm(
|
|
787
|
-
await runArm(
|
|
788
|
-
"control",
|
|
789
|
-
buildTasks(definition, { candidate: false }),
|
|
790
|
-
controlRunAgent,
|
|
791
|
-
),
|
|
792
|
-
definition,
|
|
793
|
-
{ candidate: false },
|
|
1013
|
+
const resolvedSampleRuns = parseSampleRuns(
|
|
1014
|
+
sampleRuns === undefined ? definition.sampling?.runs || 1 : sampleRuns,
|
|
1015
|
+
"sampleRuns",
|
|
794
1016
|
);
|
|
795
|
-
const
|
|
796
|
-
|
|
797
|
-
"
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
1017
|
+
const resolvedArmOrder = parseArmOrder(
|
|
1018
|
+
armOrder === undefined
|
|
1019
|
+
? definition.sampling?.armOrder || "balanced"
|
|
1020
|
+
: armOrder,
|
|
1021
|
+
"armOrder",
|
|
1022
|
+
);
|
|
1023
|
+
const runArm = async (arm, tasks, runAgent, sample) =>
|
|
1024
|
+
projectArm(
|
|
1025
|
+
await runSuite(tasks, {
|
|
1026
|
+
runAgent: instrumentRunAgent(runAgent, definition.identity),
|
|
1027
|
+
keepWorkspaces,
|
|
1028
|
+
onResult: onResult
|
|
1029
|
+
? (result) => onResult({ arm, sample, result })
|
|
1030
|
+
: undefined,
|
|
1031
|
+
}),
|
|
1032
|
+
definition,
|
|
1033
|
+
{ candidate: arm === "candidate" },
|
|
1034
|
+
);
|
|
1035
|
+
const armRuns = { control: [], candidate: [] };
|
|
1036
|
+
const sequence = sampleArmSequence(
|
|
1037
|
+
resolvedSampleRuns,
|
|
1038
|
+
resolvedArmOrder,
|
|
1039
|
+
definition.suiteDigest,
|
|
803
1040
|
);
|
|
1041
|
+
for (const [sampleIndex, orderedArms] of sequence.entries()) {
|
|
1042
|
+
for (const arm of orderedArms) {
|
|
1043
|
+
const candidate = arm === "candidate";
|
|
1044
|
+
armRuns[arm].push(
|
|
1045
|
+
await runArm(
|
|
1046
|
+
arm,
|
|
1047
|
+
buildTasks(definition, { candidate }),
|
|
1048
|
+
candidate ? candidateRunAgent : controlRunAgent,
|
|
1049
|
+
sampleIndex + 1,
|
|
1050
|
+
),
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
const control = aggregateArms(armRuns.control);
|
|
1055
|
+
const candidate = aggregateArms(armRuns.candidate);
|
|
804
1056
|
const requiredDelta =
|
|
805
1057
|
minPassRateDelta === undefined
|
|
806
1058
|
? definition.thresholds.minPassRateDelta
|
|
@@ -859,10 +1111,19 @@ export async function runPluginEval(
|
|
|
859
1111
|
digest: definition.suiteDigest,
|
|
860
1112
|
tasks: definition.tasks.length,
|
|
861
1113
|
},
|
|
1114
|
+
holdout: definition.holdout || null,
|
|
862
1115
|
selection: {
|
|
863
1116
|
provider,
|
|
864
1117
|
model,
|
|
865
1118
|
dryRun: dryRun === true,
|
|
1119
|
+
sampleRuns: resolvedSampleRuns,
|
|
1120
|
+
armOrder: resolvedArmOrder,
|
|
1121
|
+
},
|
|
1122
|
+
sampling: {
|
|
1123
|
+
runs: resolvedSampleRuns,
|
|
1124
|
+
armOrder: resolvedArmOrder,
|
|
1125
|
+
sequence,
|
|
1126
|
+
deterministic: true,
|
|
866
1127
|
},
|
|
867
1128
|
thresholds: {
|
|
868
1129
|
...definition.thresholds,
|
|
@@ -877,6 +1138,9 @@ export async function runPluginEval(
|
|
|
877
1138
|
? "regression"
|
|
878
1139
|
: "neutral",
|
|
879
1140
|
},
|
|
1141
|
+
statistics: {
|
|
1142
|
+
confidence95: confidenceComparison(control, candidate),
|
|
1143
|
+
},
|
|
880
1144
|
arms: {
|
|
881
1145
|
control: reportArm(control),
|
|
882
1146
|
candidate: reportArm(candidate),
|
|
@@ -80,7 +80,7 @@ export function assessEvolutionDeploymentReadiness(
|
|
|
80
80
|
: "no enabled signed Evolution deployment",
|
|
81
81
|
disabled
|
|
82
82
|
? "review the saved signed deployment, then run cc evolution deployment enable"
|
|
83
|
-
: "
|
|
83
|
+
: "before production, run cc evolution deployment init-test --module <absolute-path>; otherwise configure a signed descriptor and trust root",
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
if (missingCommands.length > 0) {
|
|
@@ -126,6 +126,10 @@ export async function getEvolutionDeploymentStatus(options = {}) {
|
|
|
126
126
|
fromEnvironment || (saved.profile?.enabled ? saved.profile : null);
|
|
127
127
|
const base = {
|
|
128
128
|
source,
|
|
129
|
+
deploymentMode:
|
|
130
|
+
source === "environment"
|
|
131
|
+
? "external"
|
|
132
|
+
: saved.profile?.deploymentMode || "none",
|
|
129
133
|
effectiveEnabled: source !== "none",
|
|
130
134
|
profileEnabled: saved.profile?.enabled === true,
|
|
131
135
|
profilePath: saved.filePath,
|
|
@@ -183,6 +187,8 @@ export async function configureEvolutionDeployment(
|
|
|
183
187
|
rootRotationPath = null,
|
|
184
188
|
revocationPath = null,
|
|
185
189
|
enabled = true,
|
|
190
|
+
deploymentMode,
|
|
191
|
+
testPrivateKeyPath,
|
|
186
192
|
},
|
|
187
193
|
options = {},
|
|
188
194
|
) {
|
|
@@ -239,6 +245,11 @@ export async function configureEvolutionDeployment(
|
|
|
239
245
|
verified.descriptor.revision,
|
|
240
246
|
),
|
|
241
247
|
};
|
|
248
|
+
const preserveTestMode =
|
|
249
|
+
deploymentMode === undefined &&
|
|
250
|
+
current?.deploymentMode === "test" &&
|
|
251
|
+
current.descriptorPath === verified.descriptorPath &&
|
|
252
|
+
current.trustRootPath === verified.trustRootPath;
|
|
242
253
|
return {
|
|
243
254
|
enabled: enabled === true,
|
|
244
255
|
descriptorPath: verified.descriptorPath,
|
|
@@ -246,6 +257,10 @@ export async function configureEvolutionDeployment(
|
|
|
246
257
|
revisionFloors,
|
|
247
258
|
activeTrustRootDigest: verified.descriptor.trustRootDigest,
|
|
248
259
|
revokedDescriptorRevisions,
|
|
260
|
+
deploymentMode: preserveTestMode ? "test" : deploymentMode || "managed",
|
|
261
|
+
testPrivateKeyPath: preserveTestMode
|
|
262
|
+
? current.testPrivateKeyPath
|
|
263
|
+
: testPrivateKeyPath || null,
|
|
249
264
|
};
|
|
250
265
|
}, options);
|
|
251
266
|
return getEvolutionDeploymentStatus(options);
|