chainlesschain 0.166.86 → 0.166.88
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 +26 -15
- package/package.json +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DZwiXAIh.js → AIOps-QzeGep9J.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-aNzXoIJP.js → ActionButton-Dfc5bx7S.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-ETQk4ZXt.js → Analytics-tn-_ZG2E.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-D5oEbeEC.js → AppLayout-Deg3WAK8.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-ja48FAne.js → Artifacts-KU05t0a6.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DlN0YnDt.js → Audit-CkSZf54T.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CzvyNsRg.js → BackgroundAgents-i7ivfXF0.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DXgEC2MQ.js → Backup-QcVUKtf0.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-D9XqejLx.js → BaseInput-B3h5ZJ0g.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BTwuYUlN.js → Chat-D7AVz0xi.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-0anIC2Wn.js → ChatBubbleRenderer-B0-euPW7.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-CLuaQbDt.js → Checkbox-H0p0TMlD.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-KwQUZs8A.js → Codegen-B6HOmAY3.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BCmROkzc.js → Col-n_64Fog2.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CXlUEHR4.js → Community-CX0JGgj0.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Dzx-lWI2.js → Compact-C4JWUZlx.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CfXW82FF.js → Compliance-DKyTZakB.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DIISTRm2.js → Cowork-C0joBMci.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-nyJ-KcFE.js → Cron-D6VkYpxK.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Dtv1E4cV.js → Crosschain-7b6Uu8jc.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BCTpektS.js → DID-C8YPKqzY.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C1Q_m0So.js → Dashboard-DJsOiEry.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BrQ5_PPL.js → Dropdown-CyStFY-4.js} +1 -1
- package/src/assets/web-panel/assets/EmailListRenderer-COrIx2Rg.js +1 -0
- package/src/assets/web-panel/assets/{EvolutionSettings-DaGaE6bX.js → EvolutionSettings-DpxORusH.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-nJDWBECt.js → FamilyGuardDashboard-5BYZdMG0.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DhMUY_wG.js → Federation-s1kS0ekU.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CbONJPuc.js → FormItemContext-CmgoH9HV.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CDdX4dX-.js → GenericCardRenderer-DSRWrvcL.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DXbDVJdR.js → Git-Cz3EgnS1.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DbAfAvs1.js → Governance-De4atTe7.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dy-fGea2.js → Inference-DoitBBxJ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DAxRpGUF.js → KnowledgeGraph-CIdmJ1pH.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-5L1UCR8X.js → Logs-Coa_qNhU.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-u0FPafvT.js → MarkdownRenderer-CeT_RocE.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DUk_McDG.js → Marketplace-C6kbAQoM.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-B6PNsZ_p.js → McpTools-C2TZn8D-.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BUUs8j5F.js → Memory-DYdEKDuB.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-pXRsgyuO.js → MobileBridge-pKLeVviZ.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-D4bWcHA_.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-Deaj4faB.js → Mtc-IEoVRV29.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-wUV0VUH1.js → MtcAudit-Cov-yYTY.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-C67IIkts.js → Multisig--Jr7OCmp.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BCA_CWrW.js → NLProgramming-D2gXnYAA.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-D9eu14hQ.js → Notes-hk8pMyve.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Cnd-J4LM.js → NotificationSettings-D26Nc7MU.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C4pHUuyZ.js → OrderTableRenderer-DmzHMEOa.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-4YExAbnp.js → Organization-Cn-o6mHT.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BF-wFuZz.js → Overflow-DP6xpDak.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CdiajqCT.js → P2P-C9WAjG-I.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-DxZb0Ux8.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-DrZ4D78_.js → Permissions-BFBN4-IL.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-lDc6OXjz.js → PersonalDataHub-BEDvoAiz.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-DqDS9ON1.js → Pipeline-Co2Ze_rR.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-BMekZRZu.js → Privacy-BOTn1EId.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-LYS7NFvJ.js → ProjectInit-CObyrZYm.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CcJNHk9A.js → ProjectSettings-DVTN31rd.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DrfAHgdF.js → Projects-DQSEaVjE.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-aqsly9SR.js → Providers-BRIKWIdQ.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-ZWvR3zqg.js → QrScannerModal-3nxaEXxN.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BT5CgsvW.js → QuickAsk-iwZJEE9z.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cz8Dz2RN.js → Recommend-D2_EEbvc.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BlxPVbtQ.js → RemoteSession-S4w2mUfq.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-B3VGBE-1.js → Reputation-CstUvfTC.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Bwv7vSEA.js → Row-DEGHFpxz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DHI085r_.js → RssFeed-DGdZtJQl.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DBler5T0.js → Search-DhfXi99U.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BZdw43NW.js → Security-BbzISrgX.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Cslk5lUj.js → Services-CFjP2sQ3.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bur-C-25.js → Skeleton-CFn5wbvm.js} +1 -1
- package/src/assets/web-panel/assets/Skills-fVbT8RcW.js +1 -0
- package/src/assets/web-panel/assets/{Sla-B1OWgQ51.js → Sla-D6OtC0MT.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CaBcEaV4.js → SpeechSettings-D0kteBjU.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CBbG8L6J.js → SyncSettings-BGEWCtPh.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-B1xZUG4D.js +1 -0
- package/src/assets/web-panel/assets/{Templates-VBBOZ1H5.js → Templates-COlorjqb.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CtQTj7IF.js → Tenant-yLkwfuo3.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DXVTQjnl.js → Terminal-CAmkq1wf.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BRIno0aN.js → TimelineRenderer-CcKYq1Ue.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-uiiAfkYN.js → Tokens-9hIqn_LE.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CPApN8o6.js → Trigger-Dsdkb74C.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-T2jKVwCE.js → Trust-DC4GuE3C.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C2U_gbzP.js → UkeySign-CSlh00wf.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BCdlr3Kj.js → VideoEditing-QEWLo3QY.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CWnjoSc1.js → Wallet-BkPNQgmg.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CqSbYqHq.js → WebAuthn-7---jCBl.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-Dr_I3jcr.js → WorkflowEditor-Dq6Yiu8E.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Cg21FKdE.js → chat-CTYIMpWD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CK85tY9e.js → colors-C8JtYlDN.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-m-XYPC7W.js → compact-item-spXpnsNC.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BmiEeNvs.js → createContext-D04ewPuL.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-3-s4adfp.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CCw4KAoc.js → hasIn-DZblOKXx.js} +1 -1
- package/src/assets/web-panel/assets/{index-Br9t_I1X.js → index-749P1pkM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvjC3t35.js → index-B-cKXztT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiVPFsat.js → index-B57W1RB6.js} +1 -1
- package/src/assets/web-panel/assets/{index-8KzhlvJ9.js → index-B7RA974g.js} +1 -1
- package/src/assets/web-panel/assets/{index-OIbfsi-o.js → index-BKfR2eSQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGb1j2z9.js → index-BLv-KSGc.js} +1 -1
- package/src/assets/web-panel/assets/{index-yYmjkf38.js → index-BOuUUW2U.js} +3 -3
- package/src/assets/web-panel/assets/{index-J81uvUMN.js → index-BSO33_O2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DI9GJFcn.js → index-B_65aY6c.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHsiSoGY.js → index-BjMY3Y_L.js} +1 -1
- package/src/assets/web-panel/assets/{index-6jXf-Lln.js → index-Bm0z1M6s.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGUYgc96.js → index-Bw-3CtK2.js} +1 -1
- package/src/assets/web-panel/assets/{index-sWUmvT8H.js → index-CE3TYhl0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CN2xbLGz.js → index-CHtwoTKX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7gS_TJl.js → index-CLkua5sJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BStyjmLG.js → index-COvZnoIg.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmSgfXuz.js → index-CZmBlh5P.js} +1 -1
- package/src/assets/web-panel/assets/{index-lhoexBDH.js → index-Cfk4o9eI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMbrl43d.js → index-Cgztj1JO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxRhnsEC.js → index-Cz0gkRz_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAlGVix-.js → index-DHOV24VR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIlGxS2W.js → index-DLUHbPl3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYEzWoyZ.js → index-DSoyEHi2.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBcgIWOe.js → index-D_Md0Jhp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1sU5-XA.js → index-Dcd-qZ68.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8IC9ZeZ.js → index-DcjouIsi.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByVvAXdl.js → index-DdC0OsNh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtvVupUL.js → index-DruABY-g.js} +1 -1
- package/src/assets/web-panel/assets/{index-IskAKXhx.js → index-Dssnz_1x.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpIy2HzE.js → index-DtSzmzFF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIOTRzaF.js → index-DwIEfKo7.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7xJkhtJ.js → index-EM4_wLPi.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bv90WEWa.js → index-IFEbaISP.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf5arJie.js → index-KIoJ2eCK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUYyhYP6.js → index-Mxj-qi1G.js} +1 -1
- package/src/assets/web-panel/assets/index-ZMf_BGlO.js +1 -0
- package/src/assets/web-panel/assets/index-jvp8bJBF.js +1 -0
- package/src/assets/web-panel/assets/{index-Br0ZNdu1.js → index-rU6_An6N.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcfVHmFK.js → index-rVEqWa0_.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Cc1XOmNe.js → initDefaultProps-Dl0wiMxn.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BehsX88u.js → motion-BFmZYrGO.js} +1 -1
- package/src/assets/web-panel/assets/{move-BPx2YsqY.js → move-Cjs64yWq.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BSFJgFQA.js → mtc-parser-NeQsnBuP.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DBN5KUeo.js → omit-4Rs-rfs9.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BDK1yZ-9.js → pickAttrs-CUhx2rDY.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C4rMmKNJ.js → placementArrow-DbIM_OB2.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BoeoOnxX.js → responsiveObserve-B_TGx9AN.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BKlr1bl9.js → slide-C46cEP5t.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Ky1apWPI.js → statusUtils-DqeksICX.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DxxR7uXk.js → styleChecker-2rrypo5u.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DmsUqVe9.js → useFlexGapSupport-RRe1Edsg.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CwkG7sOg.js → useFs-CB0oxU1U.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CddgeEfF.js → usePersonalDataHub-B98WdlUE.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-C_-H8i4Y.js → vnode-CY8AoD95.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-aAsHUMNE.js → zoom-BnT-0MbP.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/eval.js +116 -67
- package/src/commands/memory.js +34 -15
- package/src/commands/sandbox.js +9 -0
- package/src/data/changelog.json +26 -0
- package/src/lib/causal-observability.js +6 -45
- package/src/lib/context-memory-kernel/durable-memory-port.js +49 -10
- package/src/lib/context-memory-kernel/memory-query-index.js +278 -0
- package/src/lib/context-memory-kernel/memory-service.js +17 -2
- package/src/lib/context-memory-kernel/segmented-memory-port.js +277 -9
- package/src/lib/eval/outcomes.js +20 -10
- package/src/lib/eval/runner.js +49 -5
- package/src/lib/eval/stream-terminal.js +51 -0
- package/src/lib/eval/tasks.js +8 -3
- package/src/lib/eval/verify01-contracts.js +349 -0
- package/src/lib/eval/verify01-execution.js +611 -0
- package/src/lib/eval/verify01-host-evidence.js +604 -0
- package/src/lib/execution-support.js +58 -0
- package/src/lib/llm-pricing.js +98 -11
- package/src/lib/model-catalog-review.js +116 -0
- package/src/lib/model-context-catalog.js +23 -1
- package/src/lib/openai-responses.js +39 -0
- package/src/lib/process-execution-broker/index.js +8 -0
- package/src/lib/process-execution-broker/linux-subreaper-process.js +24 -2
- package/src/lib/process-execution-broker/process-ownership-journal.js +168 -7
- package/src/lib/process-execution-broker/process-ownership-quarantine.js +56 -1
- package/src/lib/process-execution-broker/process-recovery-cgroup.js +272 -0
- package/src/runtime/agent-core.js +9 -24
- package/src/runtime/permission-authority-host.js +14 -0
- package/src/assets/web-panel/assets/EmailListRenderer-DjoNlONP.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-D7v-2Hwm.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-BkjfS6Th.js +0 -7
- package/src/assets/web-panel/assets/Skills-v0zgLy0X.js +0 -1
- package/src/assets/web-panel/assets/Tasks-C7EjXrnN.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CkMEODFC.js +0 -1
- package/src/assets/web-panel/assets/index-BjE5qaKn.js +0 -1
- package/src/assets/web-panel/assets/index-CsFH-2Zk.js +0 -1
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createEvalHistoryRecord,
|
|
3
|
+
evalDigest,
|
|
4
|
+
EVAL_EXECUTION_PROTOCOL,
|
|
5
|
+
} from "./evidence.js";
|
|
6
|
+
import { outcomeDigest } from "./outcomes.js";
|
|
7
|
+
import { verifyAgentTerminal } from "./stream-terminal.js";
|
|
8
|
+
import {
|
|
9
|
+
relativeFile,
|
|
10
|
+
requireValue,
|
|
11
|
+
validateVerify01Review,
|
|
12
|
+
validateVerify01Collection,
|
|
13
|
+
} from "./verify01-contracts.js";
|
|
14
|
+
|
|
15
|
+
const HOST_SCHEMA = "chainlesschain.verify01-host-capture/v1";
|
|
16
|
+
const RECORD_SCHEMA = "chainlesschain.ide-protocol-record/v1";
|
|
17
|
+
const STAGES = ["install", "configure", "authenticate", "tool", "artifact"];
|
|
18
|
+
const epoch = (value) => Date.parse(value);
|
|
19
|
+
const count = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
20
|
+
|
|
21
|
+
function artifact(descriptor, readArtifact) {
|
|
22
|
+
relativeFile(descriptor?.path);
|
|
23
|
+
const bytes = readArtifact(descriptor.path);
|
|
24
|
+
requireValue(
|
|
25
|
+
Buffer.isBuffer(bytes) &&
|
|
26
|
+
bytes.length <= 16 * 1024 * 1024 &&
|
|
27
|
+
evalDigest(bytes) === descriptor.digest,
|
|
28
|
+
"host artifact digest mismatch or size limit exceeded",
|
|
29
|
+
);
|
|
30
|
+
return bytes;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One freshly started IDE session per task. Sequence gaps, interleaved user
|
|
34
|
+
* turns, stale receipts and undrained exits remain unverified, never replayed.
|
|
35
|
+
*/
|
|
36
|
+
export function inspectIdeProtocol(records, { prompt, comparison } = {}) {
|
|
37
|
+
requireValue(
|
|
38
|
+
Array.isArray(records) && records.length >= 4,
|
|
39
|
+
"IDE protocol capture is incomplete",
|
|
40
|
+
);
|
|
41
|
+
const generation = records[0]?.generation;
|
|
42
|
+
let previousTime = -Infinity;
|
|
43
|
+
for (const [index, record] of records.entries()) {
|
|
44
|
+
const at = epoch(record?.at);
|
|
45
|
+
requireValue(
|
|
46
|
+
record?.schema === RECORD_SCHEMA &&
|
|
47
|
+
typeof generation === "string" &&
|
|
48
|
+
generation.length > 0 &&
|
|
49
|
+
record.generation === generation &&
|
|
50
|
+
record.sequence === index + 1 &&
|
|
51
|
+
Number.isFinite(at) &&
|
|
52
|
+
at >= previousTime &&
|
|
53
|
+
["input", "output", "exit"].includes(record.direction) &&
|
|
54
|
+
record.event &&
|
|
55
|
+
typeof record.event === "object",
|
|
56
|
+
"IDE protocol generation, sequence or timestamp is inconsistent",
|
|
57
|
+
);
|
|
58
|
+
previousTime = at;
|
|
59
|
+
}
|
|
60
|
+
const exits = records.filter((record) => record.direction === "exit");
|
|
61
|
+
requireValue(
|
|
62
|
+
exits.length === 1 &&
|
|
63
|
+
records.at(-1) === exits[0] &&
|
|
64
|
+
exits[0].event.stdoutDrained === true &&
|
|
65
|
+
Number.isInteger(exits[0].event.code),
|
|
66
|
+
"IDE capture lacks a drained process exit",
|
|
67
|
+
);
|
|
68
|
+
const inputs = records.filter((record) => record.direction === "input");
|
|
69
|
+
// Control or second-turn input makes correlation ambiguous because older
|
|
70
|
+
// result envelopes do not echo client_message_id. Use a fresh session.
|
|
71
|
+
requireValue(
|
|
72
|
+
inputs.length === 1 &&
|
|
73
|
+
inputs[0].event.type === "user" &&
|
|
74
|
+
inputs[0].event.text === prompt &&
|
|
75
|
+
typeof inputs[0].event.client_message_id === "string" &&
|
|
76
|
+
inputs[0].event.client_message_id.length > 0,
|
|
77
|
+
"IDE sample requires exactly its frozen user prompt and client identity",
|
|
78
|
+
);
|
|
79
|
+
requireValue(
|
|
80
|
+
inputs[0].event.llm == null &&
|
|
81
|
+
inputs[0].event.worklog_session_id == null &&
|
|
82
|
+
(inputs[0].event.images === undefined ||
|
|
83
|
+
(Array.isArray(inputs[0].event.images) &&
|
|
84
|
+
inputs[0].event.images.length === 0)),
|
|
85
|
+
"frozen IDE sample cannot add per-turn model overrides, historical context or attachments",
|
|
86
|
+
);
|
|
87
|
+
const outputs = records.filter((record) => record.direction === "output");
|
|
88
|
+
const initializations = outputs.filter(
|
|
89
|
+
(record) =>
|
|
90
|
+
record.event.type === "system" && record.event.subtype === "init",
|
|
91
|
+
);
|
|
92
|
+
requireValue(
|
|
93
|
+
initializations.length === 1,
|
|
94
|
+
"IDE sample requires one actual initialization",
|
|
95
|
+
);
|
|
96
|
+
const init = initializations[0];
|
|
97
|
+
requireValue(
|
|
98
|
+
init.sequence < inputs[0].sequence &&
|
|
99
|
+
init.event.model === comparison.model &&
|
|
100
|
+
init.event.provider === comparison.provider &&
|
|
101
|
+
init.event.permission_mode === comparison.permissionMode &&
|
|
102
|
+
typeof init.event.session_id === "string" &&
|
|
103
|
+
init.event.session_id.length > 0,
|
|
104
|
+
"actual IDE initialization differs from the frozen provider/model/mode",
|
|
105
|
+
);
|
|
106
|
+
const sessionId = init.event.session_id;
|
|
107
|
+
requireValue(
|
|
108
|
+
outputs.every(
|
|
109
|
+
(record) =>
|
|
110
|
+
!record.event.session_id || record.event.session_id === sessionId,
|
|
111
|
+
),
|
|
112
|
+
"IDE capture contains a foreign session",
|
|
113
|
+
);
|
|
114
|
+
const accepted = outputs.filter(
|
|
115
|
+
(record) =>
|
|
116
|
+
record.event.type === "system" &&
|
|
117
|
+
record.event.subtype === "input_accepted",
|
|
118
|
+
);
|
|
119
|
+
requireValue(
|
|
120
|
+
init.event.input_receipts?.version === 1 &&
|
|
121
|
+
accepted.length === 1 &&
|
|
122
|
+
accepted[0].sequence > inputs[0].sequence &&
|
|
123
|
+
accepted[0].event.client_message_id ===
|
|
124
|
+
inputs[0].event.client_message_id &&
|
|
125
|
+
accepted[0].event.receipt?.duplicate === false &&
|
|
126
|
+
accepted[0].event.receipt?.sessionId === sessionId &&
|
|
127
|
+
accepted[0].event.receipt?.clientMessageId ===
|
|
128
|
+
inputs[0].event.client_message_id &&
|
|
129
|
+
/^[a-f0-9]{64}$/u.test(accepted[0].event.receipt?.eventHash || "") &&
|
|
130
|
+
accepted[0].event.receipt?.inputDigest ===
|
|
131
|
+
evalDigest(
|
|
132
|
+
Buffer.from(
|
|
133
|
+
JSON.stringify({
|
|
134
|
+
text: prompt,
|
|
135
|
+
images: [],
|
|
136
|
+
llm: null,
|
|
137
|
+
worklogSessionId: null,
|
|
138
|
+
}),
|
|
139
|
+
),
|
|
140
|
+
).slice(7),
|
|
141
|
+
"IDE input acceptance is missing, stale or duplicated",
|
|
142
|
+
);
|
|
143
|
+
const resultRecords = outputs.filter(
|
|
144
|
+
(record) => record.event.type === "result",
|
|
145
|
+
);
|
|
146
|
+
requireValue(
|
|
147
|
+
resultRecords.length === 1 &&
|
|
148
|
+
resultRecords[0].sequence > accepted[0].sequence &&
|
|
149
|
+
resultRecords[0].event.session_id === sessionId,
|
|
150
|
+
"IDE terminal is missing or ambiguous",
|
|
151
|
+
);
|
|
152
|
+
const parsed = verifyAgentTerminal(
|
|
153
|
+
outputs.map((record) => JSON.stringify(record.event)).join("\n"),
|
|
154
|
+
);
|
|
155
|
+
const terminal = resultRecords[0].event;
|
|
156
|
+
// A complete explicit failure is an observation. It never becomes success.
|
|
157
|
+
const knownFailure =
|
|
158
|
+
outputs.at(-1) === resultRecords[0] &&
|
|
159
|
+
terminal.is_error === true &&
|
|
160
|
+
typeof terminal.subtype === "string" &&
|
|
161
|
+
terminal.subtype.length > 0 &&
|
|
162
|
+
terminal.subtype !== "success";
|
|
163
|
+
const exit = exits[0].event;
|
|
164
|
+
const succeeded =
|
|
165
|
+
parsed.terminalVerified &&
|
|
166
|
+
exit.code === 0 &&
|
|
167
|
+
(exit.signal ?? null) === null;
|
|
168
|
+
return {
|
|
169
|
+
...parsed,
|
|
170
|
+
generation,
|
|
171
|
+
sessionId,
|
|
172
|
+
result:
|
|
173
|
+
knownFailure && typeof terminal.error === "string"
|
|
174
|
+
? terminal.error
|
|
175
|
+
: terminal.result,
|
|
176
|
+
terminalFailure: knownFailure,
|
|
177
|
+
startedAt: records[0].at,
|
|
178
|
+
inputAt: inputs[0].at,
|
|
179
|
+
terminalAt: resultRecords[0].at,
|
|
180
|
+
finishedAt: exits[0].at,
|
|
181
|
+
elapsedMs: epoch(exits[0].at) - epoch(records[0].at),
|
|
182
|
+
executionSucceeded: succeeded,
|
|
183
|
+
executionEvidence: {
|
|
184
|
+
protocol: EVAL_EXECUTION_PROTOCOL,
|
|
185
|
+
exitCode: exit.code,
|
|
186
|
+
signal: exit.signal ?? null,
|
|
187
|
+
terminalVerified: parsed.terminalVerified || knownFailure,
|
|
188
|
+
observedFallback: parsed.observedFallback,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function capturedDiff(changes, allowed, declaredChangedFiles) {
|
|
194
|
+
requireValue(Array.isArray(changes), "captured full diff must be an array");
|
|
195
|
+
const paths = new Set();
|
|
196
|
+
for (const change of changes) {
|
|
197
|
+
const file = relativeFile(change?.path);
|
|
198
|
+
requireValue(
|
|
199
|
+
!paths.has(file) && allowed.includes(file),
|
|
200
|
+
"full diff has a duplicate or unreviewed path",
|
|
201
|
+
);
|
|
202
|
+
paths.add(file);
|
|
203
|
+
requireValue(
|
|
204
|
+
change.before || change.after,
|
|
205
|
+
"full diff cannot contain an empty change",
|
|
206
|
+
);
|
|
207
|
+
for (const side of [change.before, change.after]) {
|
|
208
|
+
if (side === null) continue;
|
|
209
|
+
requireValue(
|
|
210
|
+
side?.type === "file" &&
|
|
211
|
+
side.dependency === false &&
|
|
212
|
+
count(side.mode) &&
|
|
213
|
+
side.mode <= 0o777 &&
|
|
214
|
+
count(side.bytes) &&
|
|
215
|
+
typeof side.bytesBase64 === "string",
|
|
216
|
+
"full diff is incomplete or contains a link/dependency",
|
|
217
|
+
);
|
|
218
|
+
const bytes = Buffer.from(side.bytesBase64, "base64");
|
|
219
|
+
requireValue(
|
|
220
|
+
bytes.toString("base64") === side.bytesBase64 &&
|
|
221
|
+
bytes.length === side.bytes &&
|
|
222
|
+
evalDigest(bytes) === side.digest,
|
|
223
|
+
"captured diff body, byte length or digest differs",
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
requireValue(
|
|
227
|
+
change.before?.digest !== change.after?.digest ||
|
|
228
|
+
change.before?.mode !== change.after?.mode,
|
|
229
|
+
"full diff falsely declares an unchanged file",
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
requireValue(
|
|
233
|
+
paths.size === declaredChangedFiles.length &&
|
|
234
|
+
declaredChangedFiles.every((file) => paths.has(file)),
|
|
235
|
+
"full diff differs from the declared changed-file inventory",
|
|
236
|
+
);
|
|
237
|
+
return changes;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function validateUi(actions, protocol, sampleId, observedAt, elapsedMs) {
|
|
241
|
+
const required = [
|
|
242
|
+
"submit",
|
|
243
|
+
"background-tab",
|
|
244
|
+
"return-tab",
|
|
245
|
+
"final-result",
|
|
246
|
+
"reload",
|
|
247
|
+
"restored-result",
|
|
248
|
+
];
|
|
249
|
+
requireValue(
|
|
250
|
+
Array.isArray(actions) &&
|
|
251
|
+
(protocol.terminalFailure
|
|
252
|
+
? actions.length > 0 && actions.length <= required.length
|
|
253
|
+
: actions.length === required.length),
|
|
254
|
+
"actual IDE tab/reload journey is incomplete",
|
|
255
|
+
);
|
|
256
|
+
// Submission may be what starts a cold session, before its first init event.
|
|
257
|
+
let previous = epoch(observedAt) - elapsedMs;
|
|
258
|
+
for (const [index, action] of actions.entries()) {
|
|
259
|
+
const at = epoch(action.at);
|
|
260
|
+
requireValue(
|
|
261
|
+
action.action === required[index] &&
|
|
262
|
+
action.sampleId === sampleId &&
|
|
263
|
+
action.sessionId === protocol.sessionId &&
|
|
264
|
+
Number.isFinite(at) &&
|
|
265
|
+
at >= previous &&
|
|
266
|
+
at <= epoch(observedAt),
|
|
267
|
+
"IDE UI action order, session or time differs",
|
|
268
|
+
);
|
|
269
|
+
previous = at;
|
|
270
|
+
if (action.action === "submit")
|
|
271
|
+
requireValue(
|
|
272
|
+
at <= epoch(protocol.inputAt),
|
|
273
|
+
"UI submission follows the protocol input",
|
|
274
|
+
);
|
|
275
|
+
if (["final-result", "restored-result"].includes(action.action))
|
|
276
|
+
requireValue(
|
|
277
|
+
at >= epoch(protocol.terminalAt) &&
|
|
278
|
+
typeof protocol.result === "string" &&
|
|
279
|
+
action.resultDigest === evalDigest(Buffer.from(protocol.result)),
|
|
280
|
+
"IDE visible/restored result differs from the actual terminal",
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** Import existing captured artifacts into the established Eval/outcome schema.
|
|
286
|
+
* Byte bindings and raw terminals are checked, but local declarations cannot
|
|
287
|
+
* attest a marketplace install, machine identity, provider account or billing.
|
|
288
|
+
*/
|
|
289
|
+
export function importVerify01HostCapture(
|
|
290
|
+
bundle,
|
|
291
|
+
preparation,
|
|
292
|
+
{
|
|
293
|
+
manifest,
|
|
294
|
+
expectedManifestDigest,
|
|
295
|
+
readArtifact,
|
|
296
|
+
sourceCommit,
|
|
297
|
+
now = Date.now(),
|
|
298
|
+
},
|
|
299
|
+
) {
|
|
300
|
+
const { samples, tasks, reviewed } = validateVerify01Review(
|
|
301
|
+
bundle,
|
|
302
|
+
preparation,
|
|
303
|
+
);
|
|
304
|
+
requireValue(
|
|
305
|
+
manifest?.schema === HOST_SCHEMA &&
|
|
306
|
+
outcomeDigest(manifest) === expectedManifestDigest,
|
|
307
|
+
"externally pinned host capture digest mismatch",
|
|
308
|
+
);
|
|
309
|
+
const sample = samples.get(manifest.sampleId);
|
|
310
|
+
requireValue(
|
|
311
|
+
sample &&
|
|
312
|
+
manifest.planDigest === bundle.expectedPlanDigest &&
|
|
313
|
+
manifest.reviewDigest === preparation.expectedReviewDigest &&
|
|
314
|
+
manifest.projectCommit === bundle.catalog.projectCommit &&
|
|
315
|
+
manifest.sourceCommit === sourceCommit,
|
|
316
|
+
"host capture frozen/source/review identity differs",
|
|
317
|
+
);
|
|
318
|
+
const target = bundle.bindings.matrix.find((entry) =>
|
|
319
|
+
sample.stratum.startsWith(`${entry.id}-`),
|
|
320
|
+
);
|
|
321
|
+
requireValue(
|
|
322
|
+
target &&
|
|
323
|
+
manifest.entry === target.entry &&
|
|
324
|
+
manifest.platform === target.platform &&
|
|
325
|
+
manifest.arch === target.arch &&
|
|
326
|
+
manifest.node === target.node &&
|
|
327
|
+
manifest.host === target.host &&
|
|
328
|
+
manifest.os === target.os,
|
|
329
|
+
"actual host/runtime declaration differs from frozen matrix; CLI cannot impersonate an IDE",
|
|
330
|
+
);
|
|
331
|
+
requireValue(
|
|
332
|
+
sample.kind === "first-run" ||
|
|
333
|
+
["vscode", "jetbrains"].includes(manifest.entry),
|
|
334
|
+
"ordinary CLI tasks use the frozen CLI executor",
|
|
335
|
+
);
|
|
336
|
+
requireValue(
|
|
337
|
+
count(manifest.retries) &&
|
|
338
|
+
manifest.retries <= 1 &&
|
|
339
|
+
count(manifest.manualRepairs),
|
|
340
|
+
"invalid retry or repair count",
|
|
341
|
+
);
|
|
342
|
+
const comparison = bundle.bindings.comparisons[sample.stratum];
|
|
343
|
+
const task = tasks.get(sample.taskId);
|
|
344
|
+
const observation = {
|
|
345
|
+
sampleId: sample.id,
|
|
346
|
+
runId: null,
|
|
347
|
+
observedAt: manifest.observedAt,
|
|
348
|
+
cost: null,
|
|
349
|
+
elapsedMs: manifest.elapsedMs,
|
|
350
|
+
retries: manifest.retries,
|
|
351
|
+
manualRepairs: manifest.manualRepairs,
|
|
352
|
+
failureCause: manifest.failureCause ?? "unknown",
|
|
353
|
+
};
|
|
354
|
+
const receiptDigests = [];
|
|
355
|
+
if (sample.kind === "first-run") {
|
|
356
|
+
requireValue(
|
|
357
|
+
typeof manifest.firstRun?.cleanEnvironment === "boolean",
|
|
358
|
+
"fresh profile evidence declaration is required",
|
|
359
|
+
);
|
|
360
|
+
observation.firstRun = {
|
|
361
|
+
cleanEnvironment: manifest.firstRun.cleanEnvironment,
|
|
362
|
+
stages: {},
|
|
363
|
+
};
|
|
364
|
+
let stopped = false;
|
|
365
|
+
for (const stage of STAGES) {
|
|
366
|
+
const entry = manifest.firstRun.stages?.[stage];
|
|
367
|
+
requireValue(
|
|
368
|
+
typeof entry?.passed === "boolean" &&
|
|
369
|
+
(!stopped || entry.passed === false),
|
|
370
|
+
"first-install stages cannot succeed after a failed prerequisite",
|
|
371
|
+
);
|
|
372
|
+
const bytes = artifact(entry.receipt, readArtifact);
|
|
373
|
+
requireValue(
|
|
374
|
+
bytes.length > 0,
|
|
375
|
+
"first-install stage receipt cannot be empty",
|
|
376
|
+
);
|
|
377
|
+
observation.firstRun.stages[stage] = {
|
|
378
|
+
passed: entry.passed,
|
|
379
|
+
receipt: entry.receipt.digest,
|
|
380
|
+
};
|
|
381
|
+
receiptDigests.push(entry.receipt.digest);
|
|
382
|
+
stopped ||= !entry.passed;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const earlyStop =
|
|
386
|
+
sample.kind === "first-run" &&
|
|
387
|
+
observation.firstRun.stages.tool.passed === false;
|
|
388
|
+
let run = null;
|
|
389
|
+
if (earlyStop) {
|
|
390
|
+
requireValue(
|
|
391
|
+
!manifest.protocol &&
|
|
392
|
+
!manifest.stream &&
|
|
393
|
+
!manifest.check &&
|
|
394
|
+
!manifest.ui &&
|
|
395
|
+
!manifest.exit &&
|
|
396
|
+
!manifest.diff &&
|
|
397
|
+
!manifest.invocation,
|
|
398
|
+
"first-install early stop cannot claim a task terminal or artifact check",
|
|
399
|
+
);
|
|
400
|
+
requireValue(
|
|
401
|
+
manifest.cost === null ||
|
|
402
|
+
(Number.isFinite(manifest.cost) && manifest.cost >= 0),
|
|
403
|
+
"invalid early-stop cost declaration",
|
|
404
|
+
);
|
|
405
|
+
observation.cost = manifest.cost;
|
|
406
|
+
} else {
|
|
407
|
+
requireValue(
|
|
408
|
+
typeof manifest.runId === "string" && manifest.runId.trim().length > 0,
|
|
409
|
+
"completed host capture requires its actual run identity",
|
|
410
|
+
);
|
|
411
|
+
let protocol;
|
|
412
|
+
if (manifest.entry === "cli") {
|
|
413
|
+
const raw = artifact(manifest.stream, readArtifact).toString("utf8");
|
|
414
|
+
const parsed = verifyAgentTerminal(raw);
|
|
415
|
+
const exit = JSON.parse(
|
|
416
|
+
artifact(manifest.exit, readArtifact).toString("utf8"),
|
|
417
|
+
);
|
|
418
|
+
requireValue(
|
|
419
|
+
Number.isInteger(exit.code) &&
|
|
420
|
+
(exit.signal === null || typeof exit.signal === "string"),
|
|
421
|
+
"invalid CLI exit capture",
|
|
422
|
+
);
|
|
423
|
+
const invocation = JSON.parse(
|
|
424
|
+
artifact(manifest.invocation, readArtifact).toString("utf8"),
|
|
425
|
+
);
|
|
426
|
+
requireValue(
|
|
427
|
+
invocation.taskId === task.id &&
|
|
428
|
+
invocation.prompt === task.prompt &&
|
|
429
|
+
invocation.provider === comparison.provider &&
|
|
430
|
+
invocation.model === comparison.model &&
|
|
431
|
+
invocation.permissionMode === comparison.permissionMode &&
|
|
432
|
+
invocation.projectCommit === bundle.catalog.projectCommit &&
|
|
433
|
+
invocation.sourceCommit === sourceCommit &&
|
|
434
|
+
Number.isFinite(epoch(invocation.startedAt)) &&
|
|
435
|
+
Number.isFinite(epoch(exit.finishedAt)) &&
|
|
436
|
+
epoch(exit.finishedAt) >= epoch(invocation.startedAt),
|
|
437
|
+
"CLI first-run invocation differs from the frozen task or runtime identity",
|
|
438
|
+
);
|
|
439
|
+
// CLI first-run capture still needs the actual init identity.
|
|
440
|
+
const events = raw
|
|
441
|
+
.split(/\r?\n/u)
|
|
442
|
+
.filter((line) => line.trim())
|
|
443
|
+
.map((line) => JSON.parse(line));
|
|
444
|
+
const inits = events.filter(
|
|
445
|
+
(event) => event.type === "system" && event.subtype === "init",
|
|
446
|
+
);
|
|
447
|
+
const init = inits[0];
|
|
448
|
+
requireValue(
|
|
449
|
+
inits.length === 1 &&
|
|
450
|
+
typeof init.session_id === "string" &&
|
|
451
|
+
init.session_id.length > 0 &&
|
|
452
|
+
init?.provider === comparison.provider &&
|
|
453
|
+
init?.model === comparison.model &&
|
|
454
|
+
init?.permission_mode === comparison.permissionMode &&
|
|
455
|
+
events.every(
|
|
456
|
+
(event) =>
|
|
457
|
+
!event.session_id || event.session_id === init.session_id,
|
|
458
|
+
),
|
|
459
|
+
"CLI first-run initialized a different model, mode or session",
|
|
460
|
+
);
|
|
461
|
+
const terminals = events.filter((event) => event.type === "result");
|
|
462
|
+
const terminal = terminals[0];
|
|
463
|
+
const knownFailure =
|
|
464
|
+
terminals.length === 1 &&
|
|
465
|
+
events.at(-1) === terminal &&
|
|
466
|
+
terminal.is_error === true &&
|
|
467
|
+
typeof terminal.subtype === "string" &&
|
|
468
|
+
terminal.subtype.length > 0 &&
|
|
469
|
+
terminal.subtype !== "success";
|
|
470
|
+
protocol = {
|
|
471
|
+
...parsed,
|
|
472
|
+
executionSucceeded:
|
|
473
|
+
parsed.terminalVerified && exit.code === 0 && exit.signal === null,
|
|
474
|
+
executionEvidence: {
|
|
475
|
+
protocol: EVAL_EXECUTION_PROTOCOL,
|
|
476
|
+
exitCode: exit.code,
|
|
477
|
+
signal: exit.signal,
|
|
478
|
+
terminalVerified: parsed.terminalVerified || knownFailure,
|
|
479
|
+
observedFallback: parsed.observedFallback,
|
|
480
|
+
},
|
|
481
|
+
startedAt: invocation.startedAt,
|
|
482
|
+
elapsedMs: epoch(exit.finishedAt) - epoch(invocation.startedAt),
|
|
483
|
+
};
|
|
484
|
+
} else {
|
|
485
|
+
protocol = inspectIdeProtocol(
|
|
486
|
+
JSON.parse(artifact(manifest.protocol, readArtifact).toString("utf8")),
|
|
487
|
+
{
|
|
488
|
+
prompt: task.prompt,
|
|
489
|
+
comparison,
|
|
490
|
+
},
|
|
491
|
+
);
|
|
492
|
+
validateUi(
|
|
493
|
+
JSON.parse(artifact(manifest.ui, readArtifact).toString("utf8")),
|
|
494
|
+
protocol,
|
|
495
|
+
sample.id,
|
|
496
|
+
manifest.observedAt,
|
|
497
|
+
manifest.elapsedMs,
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
const check = JSON.parse(
|
|
501
|
+
artifact(manifest.check, readArtifact).toString("utf8"),
|
|
502
|
+
);
|
|
503
|
+
requireValue(
|
|
504
|
+
check.taskId === task.id &&
|
|
505
|
+
check.reviewDigest === preparation.expectedReviewDigest &&
|
|
506
|
+
typeof check.pass === "boolean" &&
|
|
507
|
+
Array.isArray(check.changedFiles) &&
|
|
508
|
+
Array.isArray(check.unrelatedChanges) &&
|
|
509
|
+
check.unrelatedChanges.length === 0 &&
|
|
510
|
+
check.changedFiles.every((file) =>
|
|
511
|
+
reviewed
|
|
512
|
+
.get(task.id)
|
|
513
|
+
.allowedChangedPaths.includes(relativeFile(file)),
|
|
514
|
+
),
|
|
515
|
+
"independent artifact check is unbound or contains unreviewed edits",
|
|
516
|
+
);
|
|
517
|
+
requireValue(
|
|
518
|
+
!check.pass ||
|
|
519
|
+
task.expectedFiles.every((file) => check.changedFiles.includes(file)),
|
|
520
|
+
"independent check omits required deliverables",
|
|
521
|
+
);
|
|
522
|
+
requireValue(
|
|
523
|
+
check.process?.sourceDigest === reviewed.get(task.id).check.digest &&
|
|
524
|
+
check.process.exitCode === 0 &&
|
|
525
|
+
check.process.signal === null &&
|
|
526
|
+
check.process.error === null,
|
|
527
|
+
"independent artifact check lacks its pinned process receipt",
|
|
528
|
+
);
|
|
529
|
+
const verdict = JSON.parse(check.process.stdout);
|
|
530
|
+
requireValue(
|
|
531
|
+
verdict.pass === check.pass && typeof verdict.detail === "string",
|
|
532
|
+
"check verdict differs from raw process output",
|
|
533
|
+
);
|
|
534
|
+
capturedDiff(
|
|
535
|
+
JSON.parse(artifact(manifest.diff, readArtifact).toString("utf8")),
|
|
536
|
+
reviewed.get(task.id).allowedChangedPaths,
|
|
537
|
+
check.changedFiles,
|
|
538
|
+
);
|
|
539
|
+
requireValue(
|
|
540
|
+
manifest.elapsedMs >= protocol.elapsedMs &&
|
|
541
|
+
epoch(manifest.observedAt) >=
|
|
542
|
+
epoch(protocol.startedAt) + protocol.elapsedMs,
|
|
543
|
+
"host observation precedes protocol completion",
|
|
544
|
+
);
|
|
545
|
+
const result = {
|
|
546
|
+
id: task.id,
|
|
547
|
+
artifactCheckPassed: check.pass,
|
|
548
|
+
executionSucceeded: protocol.executionSucceeded,
|
|
549
|
+
agentOk: protocol.executionSucceeded,
|
|
550
|
+
pass: check.pass && protocol.executionSucceeded,
|
|
551
|
+
error: protocol.executionSucceeded
|
|
552
|
+
? null
|
|
553
|
+
: "captured agent execution did not succeed",
|
|
554
|
+
detail: String(
|
|
555
|
+
check.detail || "Captured independent artifact acceptance",
|
|
556
|
+
),
|
|
557
|
+
ms: protocol.elapsedMs,
|
|
558
|
+
usage: protocol.usage,
|
|
559
|
+
totalCostUsd: protocol.totalCostUsd,
|
|
560
|
+
executionEvidence: protocol.executionEvidence,
|
|
561
|
+
changedFiles: check.changedFiles,
|
|
562
|
+
unrelatedChanges: check.unrelatedChanges,
|
|
563
|
+
};
|
|
564
|
+
run = createEvalHistoryRecord(
|
|
565
|
+
{
|
|
566
|
+
results: [result],
|
|
567
|
+
passed: result.pass ? 1 : 0,
|
|
568
|
+
failed: result.pass ? 0 : 1,
|
|
569
|
+
total: 1,
|
|
570
|
+
passRate: result.pass ? 1 : 0,
|
|
571
|
+
unrelatedChangeRate: 0,
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
comparison,
|
|
575
|
+
runId: manifest.runId,
|
|
576
|
+
ranAt: protocol.startedAt,
|
|
577
|
+
label: sourceCommit,
|
|
578
|
+
},
|
|
579
|
+
);
|
|
580
|
+
observation.runId = run.runId;
|
|
581
|
+
observation.cost = protocol.totalCostUsd;
|
|
582
|
+
}
|
|
583
|
+
const history = { runs: run ? [run] : [], issues: [] };
|
|
584
|
+
const observations = [observation];
|
|
585
|
+
const report = validateVerify01Collection(bundle, preparation, {
|
|
586
|
+
sampleIds: [sample.id],
|
|
587
|
+
history,
|
|
588
|
+
observations,
|
|
589
|
+
sourceCommit,
|
|
590
|
+
now,
|
|
591
|
+
});
|
|
592
|
+
return {
|
|
593
|
+
scope: "verify01-existing-host-evidence-import",
|
|
594
|
+
productionAttested: false,
|
|
595
|
+
identityVerified: false,
|
|
596
|
+
installationVerified: false,
|
|
597
|
+
billingVerified: false,
|
|
598
|
+
captureDigest: expectedManifestDigest,
|
|
599
|
+
stageReceiptDigests: receiptDigests,
|
|
600
|
+
history,
|
|
601
|
+
observations,
|
|
602
|
+
report,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { permissionRulesProviderAuthority } from "./permission-authority.js";
|
|
2
|
+
|
|
3
|
+
/** Diagnostic projection only. Admission remains with the broker and authority. */
|
|
4
|
+
export function describeExecutionSupport({
|
|
5
|
+
capabilityReport,
|
|
6
|
+
permissionRulesProvider,
|
|
7
|
+
} = {}) {
|
|
8
|
+
const report = capabilityReport;
|
|
9
|
+
if (!report?.host || !report?.backend)
|
|
10
|
+
throw new TypeError("sandbox capability report is required");
|
|
11
|
+
let authority = "process-local",
|
|
12
|
+
authorityAvailable = true;
|
|
13
|
+
try {
|
|
14
|
+
const bound = permissionRulesProviderAuthority(permissionRulesProvider);
|
|
15
|
+
if (bound?.getSnapshot()?.durable) authority = "durable-controlled-host";
|
|
16
|
+
else if (permissionRulesProvider && !bound) authority = "sampled-callback";
|
|
17
|
+
} catch {
|
|
18
|
+
authority = "unavailable";
|
|
19
|
+
authorityAvailable = false;
|
|
20
|
+
}
|
|
21
|
+
const supportedHost =
|
|
22
|
+
report.host.platform === "linux" &&
|
|
23
|
+
["x64", "arm64"].includes(report.host.arch);
|
|
24
|
+
const domainRoute =
|
|
25
|
+
report.backend.engine === "docker-egress" &&
|
|
26
|
+
report.unsupported.length === 0;
|
|
27
|
+
const durable =
|
|
28
|
+
supportedHost && domainRoute && authority === "durable-controlled-host";
|
|
29
|
+
return {
|
|
30
|
+
schema: "chainlesschain.execution-support/v1",
|
|
31
|
+
platform: report.host.platform,
|
|
32
|
+
arch: report.host.arch,
|
|
33
|
+
engine: report.backend.engine,
|
|
34
|
+
entrypoint: "agent-shell",
|
|
35
|
+
io: {
|
|
36
|
+
stdin: "noninteractive",
|
|
37
|
+
stdout: "captured",
|
|
38
|
+
stderr: "captured",
|
|
39
|
+
interactiveTerminal: false,
|
|
40
|
+
},
|
|
41
|
+
permissionSource: authority,
|
|
42
|
+
permissionSourceAvailable: authorityAvailable,
|
|
43
|
+
persistentNetworkRevocation: {
|
|
44
|
+
status: durable ? "configured" : "unavailable",
|
|
45
|
+
reason: !supportedHost
|
|
46
|
+
? "requires-linux-x64-or-arm64-controlled-host"
|
|
47
|
+
: !domainRoute
|
|
48
|
+
? "requires-docker-egress-domain-policy"
|
|
49
|
+
: authority !== "durable-controlled-host"
|
|
50
|
+
? "requires-explicit-durable-authority-binding"
|
|
51
|
+
: null,
|
|
52
|
+
executionObserved: durable && report.execution.started === true,
|
|
53
|
+
backendAvailable: report.backend.available,
|
|
54
|
+
modelRequestGovernance: "not-established-by-shell-capabilities",
|
|
55
|
+
},
|
|
56
|
+
nativeReleaseValidation: "not-established-by-this-probe",
|
|
57
|
+
};
|
|
58
|
+
}
|