deadbyte-mcp 0.14.0 → 0.15.1
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/AGENTS.md +11 -18
- package/CONTEXT.md +3 -3
- package/MANIFEST.SHA256 +156 -70
- package/PROVENANCE.json +10 -0
- package/R43-PARENT.json +20 -0
- package/R44-DONORS.json +99 -0
- package/R44-PARENT.json +18 -0
- package/R45-PARENT.json +18 -0
- package/README.txt +19 -14
- package/RELEASE.json +37 -0
- package/SBOM.cdx.json +46 -0
- package/TEST-MATRIX.json +31 -0
- package/bin/deadbyte-hardware-observer-r45.exe +0 -0
- package/bin/deadbyte-hardware-observer-r45.obj +0 -0
- package/controller/README.TXT +5 -6
- package/controller/deadbyte-controller.ps1 +2 -2
- package/docs/ARCHITECTURE.md +8 -1
- package/docs/R44-ARCHITECTURE.md +37 -0
- package/native/deadbyte-hardware-observer.cpp +308 -0
- package/package.json +18 -8
- package/scripts/autonomous-tests.ps1 +2 -2
- package/scripts/build-hardware-r45.ps1 +71 -0
- package/scripts/deferred-slot-operation-r43.mjs +126 -0
- package/scripts/deferred-slot-operation-r44.mjs +126 -0
- package/scripts/deferred-slot-operation-r45.mjs +126 -0
- package/scripts/derive-r45-parent.mjs +24 -0
- package/scripts/derive-r45-release.mjs +72 -0
- package/scripts/derive-r45-tests.mjs +20 -0
- package/scripts/final-closure-r43.mjs +115 -0
- package/scripts/final-closure-r44.mjs +121 -0
- package/scripts/final-closure-r45.mjs +121 -0
- package/scripts/final-closure-verify-r43.mjs +213 -0
- package/scripts/final-closure-verify-r44.mjs +220 -0
- package/scripts/final-closure-verify-r45.mjs +220 -0
- package/scripts/finalize-r43.mjs +217 -0
- package/scripts/finalize-r44.mjs +217 -0
- package/scripts/finalize-r45.mjs +219 -0
- package/scripts/full-regression-r43.mjs +20 -0
- package/scripts/full-regression-r44.mjs +20 -0
- package/scripts/full-regression-r45.mjs +20 -0
- package/scripts/full-regression-summary-r45.mjs +14 -0
- package/scripts/gate-windows-r43.ps1 +36 -0
- package/scripts/gate-windows-r44.ps1 +36 -0
- package/scripts/gate-windows-r45.ps1 +44 -0
- package/scripts/init-host-policy.ps1 +39 -1
- package/scripts/inspect-active-release-r45.mjs +20 -0
- package/scripts/release-manifest.mjs +3 -1
- package/scripts/release-parity-r43.mjs +218 -0
- package/scripts/release-parity-r44.mjs +242 -0
- package/scripts/release-parity-r45.mjs +253 -0
- package/scripts/release-parity-tests-r43.ps1 +8 -0
- package/scripts/release-parity-tests-r44.ps1 +8 -0
- package/scripts/release-parity-tests-r45.ps1 +8 -0
- package/scripts/verify-r43-parent.mjs +126 -0
- package/scripts/verify-r44-parent.mjs +142 -0
- package/scripts/verify-r45-parent.mjs +142 -0
- package/scripts/windows-gate-evidence-r43.mjs +55 -0
- package/scripts/windows-gate-evidence-r44.mjs +55 -0
- package/scripts/windows-gate-evidence-r45.mjs +60 -0
- package/src/agent-backend-r44.mjs +254 -0
- package/src/autonomous-output-contracts.mjs +1 -1
- package/src/autonomous-policy.mjs +41 -4
- package/src/autonomous-runtime.mjs +37 -19
- package/src/autonomous-supervisor-host.mjs +12 -2
- package/src/capability-ledger.mjs +3 -1
- package/src/codex-app-server-r44.mjs +154 -0
- package/src/coding-plane.mjs +66 -19
- package/src/compact-gateway-mcp-tools.mjs +4 -2
- package/src/deadbyte-cli.mjs +17 -9
- package/src/doctor-r45.mjs +65 -0
- package/src/durable-job-r44.mjs +145 -0
- package/src/external-job-provider-r44.mjs +126 -0
- package/src/host-plane.mjs +156 -87
- package/src/job-supervisor-host-r44.mjs +112 -0
- package/src/machine-fs-smoke-client.mjs +1 -1
- package/src/machine-fs.mjs +21 -10
- package/src/mcp-host-smoke-client.mjs +1 -1
- package/src/mcp-server.mjs +84 -26
- package/src/mcp-smoke-client.mjs +1 -1
- package/src/native-diff-v2.mjs +12 -7
- package/src/native-diff.mjs +32 -9
- package/src/observation-mcp-tools.mjs +5 -1
- package/src/observation-output-contracts.mjs +8 -0
- package/src/observation-runtime.mjs +33 -2
- package/src/observation-smoke-client.mjs +7 -3
- package/src/operator-surface.mjs +2 -2
- package/src/output-contracts.mjs +27 -11
- package/src/process-policy.mjs +19 -0
- package/src/process-runtime.mjs +5 -2
- package/src/process-smoke-client.mjs +2 -2
- package/src/provider-circuit.mjs +8 -2
- package/src/r44-compact-disarmed-probe.mjs +74 -0
- package/src/r44-full-surface-probe.mjs +34 -0
- package/src/r45-compact-disarmed-probe.mjs +74 -0
- package/src/r45-full-surface-probe.mjs +34 -0
- package/src/release-generation.mjs +1 -0
- package/src/remote-device-r44.mjs +205 -0
- package/src/remote-mcp-autonomous-smoke-client.mjs +4 -4
- package/src/remote-mcp-r44-parity-client.mjs +203 -0
- package/src/remote-mcp-r45-parity-client.mjs +206 -0
- package/src/remote-mcp-smoke-client.mjs +7 -4
- package/src/runtime-update.mjs +100 -39
- package/src/skill-mcp-tools-r44.mjs +37 -0
- package/src/skill-plane-r44.mjs +203 -0
- package/src/tunnel-stdio-compat-smoke.mjs +1 -1
- package/src/version.mjs +1 -1
- package/test/agent-backend-r44.test.mjs +115 -0
- package/test/agent-runtime.test.mjs +4 -3
- package/test/autonomous-loop.test.mjs +121 -11
- package/test/autonomous-runtime.test.mjs +3 -2
- package/test/capability-ledger-r36.test.mjs +3 -3
- package/test/cli-entrypoint.test.mjs +4 -4
- package/test/codex-app-server-r44.test.mjs +115 -0
- package/test/codex-autonomous-r44.test.mjs +87 -0
- package/test/coding-plane.test.mjs +3 -2
- package/test/coding-runtime.test.mjs +36 -1
- package/test/compact-catalog-r36.test.mjs +3 -3
- package/test/compact-max-catalog-r40.test.mjs +4 -2
- package/test/compact-max-catalog-r44.test.mjs +97 -0
- package/test/compact-max-catalog-r45.test.mjs +99 -0
- package/test/contained.test.mjs +23 -11
- package/test/controller.test.mjs +5 -1
- package/test/core.test.mjs +1 -1
- package/test/durable-job-r44.test.mjs +75 -0
- package/test/external-job-provider-r44.test.mjs +46 -0
- package/test/full-max-catalog-r40.test.mjs +5 -3
- package/test/full-max-catalog-r44.test.mjs +91 -0
- package/test/full-max-catalog-r45.test.mjs +91 -0
- package/test/hardware-observation-r45.test.mjs +44 -0
- package/test/host-inline-r45.test.mjs +67 -0
- package/test/host-plane.test.mjs +15 -1
- package/test/machine-mcp-integration.test.mjs +1 -0
- package/test/native-diff.test.mjs +28 -0
- package/test/observation-mcp-tools.test.mjs +4 -3
- package/test/output-schema.test.mjs +3 -2
- package/test/package-boundary.test.mjs +1 -1
- package/test/process-policy.test.mjs +22 -1
- package/test/production-docs.test.mjs +3 -3
- package/test/prompts-resources.test.mjs +1 -1
- package/test/r33-closeout-regression.test.mjs +20 -36
- package/test/r33-finalization.test.mjs +7 -7
- package/test/r43-finalization.test.mjs +31 -0
- package/test/r43-finalizer.test.mjs +34 -0
- package/test/r43-parent.test.mjs +29 -0
- package/test/r44-finalization.test.mjs +58 -0
- package/test/r44-finalizer.test.mjs +48 -0
- package/test/r44-parent.test.mjs +25 -0
- package/test/r45-autonomous-quick-test.test.mjs +10 -0
- package/test/r45-finalization.test.mjs +84 -0
- package/test/release-generation.test.mjs +1 -0
- package/test/release-version.test.mjs +65 -20
- package/test/remote-device-r44.test.mjs +104 -0
- package/test/runtime-host-bootstrap-r45.test.mjs +46 -0
- package/test/runtime-self-update.test.mjs +42 -0
- package/test/skill-mcp-r44.test.mjs +38 -0
- package/test/skill-plane-r44.test.mjs +93 -0
- package/test/standing-grants.test.mjs +5 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { Client } from '@modelcontextprotocol/client';
|
|
8
|
+
import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
|
|
9
|
+
import { createR34Fixture } from './helpers/autonomous-r34-fixture.mjs';
|
|
10
|
+
|
|
11
|
+
const here=path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const repoRoot=path.resolve(here,'..');
|
|
13
|
+
const serverPath=path.join(repoRoot,'src','mcp-server.mjs');
|
|
14
|
+
const desktopPolicyPath=path.join(repoRoot,'controller','deadbyte-desktop-policy.json');
|
|
15
|
+
const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
16
|
+
const absent=async p=>{try{await access(p);return false;}catch(e){if(e?.code==='ENOENT')return true;throw e;}};
|
|
17
|
+
|
|
18
|
+
test('R45 real max-runtime full stdio catalog is exactly 82 with skill and four Desktop primitives while authority remains disarmed',async()=>{
|
|
19
|
+
const f=await createR34Fixture({authority:'disarmed'});
|
|
20
|
+
const processPolicyPath=path.join(f.root,'process-policy.json');
|
|
21
|
+
const processGrant=path.join(f.root,'process-grant.json');
|
|
22
|
+
const processState=path.join(f.root,'process-state');
|
|
23
|
+
const hostPolicyPath=path.join(f.root,'host-policy.json');
|
|
24
|
+
const hostArm=path.join(f.root,'host-arm.json');
|
|
25
|
+
const nodeSha=sha(await readFile(process.execPath));
|
|
26
|
+
await mkdir(processState,{recursive:true});
|
|
27
|
+
await writeFile(processPolicyPath,JSON.stringify({
|
|
28
|
+
schema:'deadbyte.process-policy.v1',enabled:true,grant_file:processGrant,state_dir:processState,
|
|
29
|
+
native_host:{path:process.execPath,sha256:nodeSha},
|
|
30
|
+
roots:{core:{path:f.project,deny_paths:[]}},
|
|
31
|
+
profiles:{node:{executable:process.execPath,executable_sha256:nodeSha,root_ids:['core'],
|
|
32
|
+
prefix_args:[],transport:'pipe',max_args:8,max_arg_bytes:1024,max_sessions:2,
|
|
33
|
+
max_input_bytes:65536,max_retained_output_bytes:262144,env_allow:['PATH','TEMP','TMP'],
|
|
34
|
+
input_actions:{ping:'PING\r\n'}}}
|
|
35
|
+
},null,2));
|
|
36
|
+
await writeFile(hostPolicyPath,JSON.stringify({
|
|
37
|
+
schema:'deadbyte.host-policy.v1',enabled:true,arm_file:hostArm,max_read_bytes:262144,max_write_bytes:1048576,
|
|
38
|
+
roots:{core:{path:f.project,read:true,write:true,exec:true}},
|
|
39
|
+
commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:nodeSha,
|
|
40
|
+
root_ids:['core'],prefix_args:[],extensions:['.mjs'],timeout_ms:5000,max_output_bytes:65536}}
|
|
41
|
+
},null,2));
|
|
42
|
+
|
|
43
|
+
const desktopRaw=JSON.parse(await readFile(desktopPolicyPath,'utf8'));
|
|
44
|
+
const desktopGrant=desktopRaw.grant_file;
|
|
45
|
+
const codingLease=f.codingPolicy.lease_file;
|
|
46
|
+
const autonomousLease=f.policy.lease_file;
|
|
47
|
+
for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority unexpectedly armed before start: '+q);
|
|
48
|
+
|
|
49
|
+
const client=new Client({name:'deadbyte-r45-full-catalog',version:'0.15.1'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
|
|
50
|
+
const env={
|
|
51
|
+
...getDefaultEnvironment(),
|
|
52
|
+
DEADBYTE_CAPABILITY_PROFILE:'full',
|
|
53
|
+
DEADBYTE_AUDIT_RUNTIME:'0',
|
|
54
|
+
DEADBYTE_STATE_ROOT:path.join(f.root,'state'),
|
|
55
|
+
DEADBYTE_WORKSPACE_ROOT:f.root,
|
|
56
|
+
DEADBYTE_SIGNING_KEY:f.keys.privateKeyPath,
|
|
57
|
+
DEADBYTE_VERIFY_KEY:f.keys.publicKeyPath,
|
|
58
|
+
DEADBYTE_PRIVILEGED_POLICY:hostPolicyPath,
|
|
59
|
+
DEADBYTE_MACHINE_RUNTIME:'1',
|
|
60
|
+
DEADBYTE_AGENT_RUNTIME:'1',
|
|
61
|
+
DEADBYTE_PROCESS_RUNTIME:'1',
|
|
62
|
+
DEADBYTE_PROCESS_POLICY:processPolicyPath,
|
|
63
|
+
DEADBYTE_CODING_RUNTIME:'1',
|
|
64
|
+
DEADBYTE_CODING_POLICY:path.join(f.root,'coding-policy.json'),
|
|
65
|
+
DEADBYTE_MACHINE_FS_RUNTIME:'1',
|
|
66
|
+
DEADBYTE_OBSERVATION_RUNTIME:'1',
|
|
67
|
+
DEADBYTE_DESKTOP_RUNTIME:'1',
|
|
68
|
+
DEADBYTE_DESKTOP_POLICY:desktopPolicyPath,
|
|
69
|
+
DEADBYTE_AUTONOMOUS_RUNTIME:'1',
|
|
70
|
+
DEADBYTE_AUTONOMOUS_POLICY:path.join(f.root,'autonomous-policy.json'),
|
|
71
|
+
DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE:'external'
|
|
72
|
+
};
|
|
73
|
+
const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env,stderr:'pipe'});
|
|
74
|
+
try{
|
|
75
|
+
await client.connect(transport);
|
|
76
|
+
const listed=await client.listTools();
|
|
77
|
+
const names=listed.tools.map(t=>t.name).sort();
|
|
78
|
+
const {R45_EXPECTED_TOOLS}=await import('../src/remote-mcp-r45-parity-client.mjs');
|
|
79
|
+
assert.equal(names.length,82,'expected exact full R45 catalog 82, got '+names.length+': '+names.join(','));
|
|
80
|
+
assert.deepEqual(names,R45_EXPECTED_TOOLS);
|
|
81
|
+
for(const name of ['machine_hardware_query','desktop_status','desktop_observe','desktop_target','desktop_action',
|
|
82
|
+
'host_file_read','host_file_write','host_exec','skill_catalog']) assert.ok(names.includes(name),'missing '+name);
|
|
83
|
+
for(const tool of listed.tools) assert.equal(tool.outputSchema?.additionalProperties,false,'non-strict output '+tool.name);
|
|
84
|
+
const catalog_sha256=sha(Buffer.from(JSON.stringify(names),'utf8'));
|
|
85
|
+
console.log(JSON.stringify({tool_count:names.length,catalog_sha256,desktop_tools:4,skill:true,authority:'DISARMED'}));
|
|
86
|
+
} finally {
|
|
87
|
+
await client.close().catch(()=>{});
|
|
88
|
+
for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority file appeared during catalog probe: '+q);
|
|
89
|
+
await f.cleanup();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, mkdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { generateTrustKeypair } from '../src/trust.mjs';
|
|
7
|
+
import { loadCodingPolicy } from '../src/coding-plane.mjs';
|
|
8
|
+
import { createObservationRuntime, verifyObservationReceiptFile } from '../src/observation-runtime.mjs';
|
|
9
|
+
|
|
10
|
+
async function fixture(){
|
|
11
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-hardware-query-r45-'));
|
|
12
|
+
const project=path.join(root,'project');await mkdir(project);
|
|
13
|
+
const policyPath=path.join(root,'coding-policy.json');
|
|
14
|
+
await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,
|
|
15
|
+
lease_file:path.join(root,'coding-grant.json'),evidence_dir:path.join(root,'evidence'),
|
|
16
|
+
roots:{project:{path:project,read:true,write:false,exec:false,deny_paths:[]}},commands:{},
|
|
17
|
+
max_read_bytes:65536,max_write_bytes:65536}));
|
|
18
|
+
const policy=await loadCodingPolicy(policyPath);
|
|
19
|
+
const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
|
|
20
|
+
const calls=[];
|
|
21
|
+
const hardwareSnapshotProvider=async query=>{calls.push(query);return {schema:'deadbyte.hardware-query.v1',query,
|
|
22
|
+
data:query==='cpu'?{brand:'TEST CPU',logical_processors:16}:{fixture:true}};};
|
|
23
|
+
const runtime=createObservationRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath,
|
|
24
|
+
stateRoot:root,processSnapshotProvider:async()=>[],systemSnapshotProvider:async()=>({hostname:'x',platform:'win32',architecture:'x64',
|
|
25
|
+
uptime_seconds:1,total_memory_bytes:1,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0]}),
|
|
26
|
+
ownedRuntimePidProvider:async()=>new Set(),hardwareSnapshotProvider});
|
|
27
|
+
return {root,policy,keys,runtime,calls};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
test('R45 hardware query is typed read-only observation with signed evidence and no host authority',async()=>{
|
|
31
|
+
const f=await fixture();
|
|
32
|
+
const out=await f.runtime.hardwareQuery({query:'cpu'});
|
|
33
|
+
assert.equal(out.query,'cpu');assert.equal(out.data.brand,'TEST CPU');assert.deepEqual(f.calls,['cpu']);
|
|
34
|
+
assert.match(out.request_sha256,/^[0-9a-f]{64}$/);assert.match(out.result_head_sha256,/^[0-9a-f]{64}$/);
|
|
35
|
+
assert.match(out.receipt_id,/^[0-9a-f]{24}$/);assert.match(out.receipt_sha256,/^[0-9a-f]{64}$/);
|
|
36
|
+
const verified=await verifyObservationReceiptFile({policy:f.policy,verifyKeyPath:f.keys.publicKeyPath,receiptId:out.receipt_id});
|
|
37
|
+
assert.equal(verified.ok,true);assert.equal(verified.signature_valid,true);assert.equal(verified.kind,'machine_hardware_query');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('R45 hardware query rejects untyped arbitrary query names before provider dispatch',async()=>{
|
|
41
|
+
const f=await fixture();
|
|
42
|
+
await assert.rejects(()=>f.runtime.hardwareQuery({query:'run_powershell'}),/hardware query/i);
|
|
43
|
+
assert.deepEqual(f.calls,[]);
|
|
44
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
4
|
+
import { mkdtemp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import {
|
|
8
|
+
HOST_GRANT_SCHEMA, HOST_POLICY_SCHEMA_V2, hostExecInline, hostExecNative, loadHostPolicy
|
|
9
|
+
} from '../src/host-plane.mjs';
|
|
10
|
+
|
|
11
|
+
const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
12
|
+
|
|
13
|
+
async function fixture(){
|
|
14
|
+
const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-host-inline-r45-'));
|
|
15
|
+
const root=path.join(dir,'root');await mkdir(root);
|
|
16
|
+
const arm=path.join(dir,'arm.json'), policyPath=path.join(dir,'policy.json');
|
|
17
|
+
const exeSha=sha(await readFile(process.execPath));
|
|
18
|
+
const raw={
|
|
19
|
+
schema:HOST_POLICY_SCHEMA_V2,enabled:true,arm_file:arm,
|
|
20
|
+
roots:{core:{path:root,read:true,write:true,exec:true}},
|
|
21
|
+
commands:{
|
|
22
|
+
node_inline:{kind:'inline',executable:process.execPath,executable_sha256:exeSha,root_ids:['core'],
|
|
23
|
+
prefix_args:['-e'],timeout_ms:5000,max_output_bytes:65536,max_command_chars:32768}
|
|
24
|
+
},
|
|
25
|
+
native_exec:{enabled:true,root_ids:['core'],timeout_ms:5000,max_output_bytes:65536,max_args:64,max_arg_chars:8192},
|
|
26
|
+
max_read_bytes:262144,max_write_bytes:1048576
|
|
27
|
+
};
|
|
28
|
+
await writeFile(policyPath,JSON.stringify(raw,null,2));
|
|
29
|
+
const policy=await loadHostPolicy(policyPath);
|
|
30
|
+
await writeFile(arm,JSON.stringify({schema:HOST_GRANT_SCHEMA,policy_sha256:policy.policy_sha256,
|
|
31
|
+
instance_nonce:randomBytes(32).toString('hex'),armed_at_utc:new Date().toISOString()},null,2));
|
|
32
|
+
return {dir,root,arm,policy,exeSha};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test('R45 host inline executes in argv memory with zero staging artifact and hashes command/output',async t=>{
|
|
36
|
+
const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
|
|
37
|
+
const before=(await readdir(f.root)).sort();
|
|
38
|
+
const command='process.stdout.write("INLINE_OK")';
|
|
39
|
+
const out=await hostExecInline(f.policy,{commandId:'node_inline',rootId:'core',command,cwd:'.',timeoutMs:2000});
|
|
40
|
+
const after=(await readdir(f.root)).sort();
|
|
41
|
+
assert.deepEqual(after,before,'inline execution must not stage a script file');
|
|
42
|
+
assert.equal(out.exit_code,0);assert.equal(out.stdout,'INLINE_OK');assert.equal(out.stderr,'');
|
|
43
|
+
assert.equal(out.command_sha256,sha(Buffer.from(command,'utf8')));
|
|
44
|
+
assert.equal(out.stdout_sha256,sha(Buffer.from('INLINE_OK','utf8')));
|
|
45
|
+
assert.equal(out.stderr_sha256,sha(Buffer.alloc(0)));
|
|
46
|
+
assert.match(out.argv_sha256,/^[0-9a-f]{64}$/);assert.equal(out.executable_sha256,f.exeSha);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('R45 native argv execution accepts arbitrary absolute hash-pinned executable only while Host is armed',async t=>{
|
|
50
|
+
const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
|
|
51
|
+
const before=(await readdir(f.root)).sort();
|
|
52
|
+
const out=await hostExecNative(f.policy,{rootId:'core',executable:process.execPath,executableSha256:f.exeSha,
|
|
53
|
+
args:['-e','process.stdout.write("NATIVE_OK")'],cwd:'.',timeoutMs:2000});
|
|
54
|
+
assert.equal(out.exit_code,0);assert.equal(out.stdout,'NATIVE_OK');
|
|
55
|
+
assert.deepEqual((await readdir(f.root)).sort(),before,'native argv execution must not create staging files');
|
|
56
|
+
await assert.rejects(()=>hostExecNative(f.policy,{rootId:'core',executable:process.execPath,executableSha256:'f'.repeat(64),
|
|
57
|
+
args:['--version'],cwd:'.'}),/executable hash mismatch/i);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('R45 inline execution observes authority revocation during a live child and fails closed',async t=>{
|
|
61
|
+
const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
|
|
62
|
+
const running=hostExecInline(f.policy,{commandId:'node_inline',rootId:'core',
|
|
63
|
+
command:'setTimeout(()=>process.stdout.write("SHOULD_NOT_COMPLETE"),1500)',cwd:'.',timeoutMs:4000,authorityPollMs:50});
|
|
64
|
+
await new Promise(r=>setTimeout(r,150));
|
|
65
|
+
await rm(f.arm,{force:true});
|
|
66
|
+
await assert.rejects(()=>running,/host authority changed during operation/i);
|
|
67
|
+
});
|
package/test/host-plane.test.mjs
CHANGED
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
hostExec,
|
|
12
12
|
hostFileRead,
|
|
13
13
|
hostFileWrite,
|
|
14
|
-
loadHostPolicy
|
|
14
|
+
loadHostPolicy,
|
|
15
|
+
recheckHostAuthority
|
|
15
16
|
} from '../src/host-plane.mjs';
|
|
16
17
|
|
|
17
18
|
const sha = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
@@ -66,6 +67,19 @@ test('privileged host plane requires a live policy-bound arm lease', async () =>
|
|
|
66
67
|
await assert.rejects(() => assertHostArmed(expired.policy), /arm expired/);
|
|
67
68
|
});
|
|
68
69
|
|
|
70
|
+
test('host authority recheck rejects arm generation or expiry drift before side effects', async () => {
|
|
71
|
+
const f = await fixture();
|
|
72
|
+
const initial = await assertHostArmed(f.policy);
|
|
73
|
+
const arm = JSON.parse(await readFile(f.arm, 'utf8'));
|
|
74
|
+
await writeFile(f.arm, JSON.stringify({ ...arm, instance_nonce: 'b'.repeat(64) }));
|
|
75
|
+
await assert.rejects(() => recheckHostAuthority(f.policy, initial), /host authority changed during operation/);
|
|
76
|
+
await writeFile(f.arm, JSON.stringify({
|
|
77
|
+
...arm,
|
|
78
|
+
expires_at_utc: new Date(Date.parse(arm.expires_at_utc) + 60000).toISOString()
|
|
79
|
+
}));
|
|
80
|
+
await assert.rejects(() => recheckHostAuthority(f.policy, initial), /host authority changed during operation/);
|
|
81
|
+
});
|
|
82
|
+
|
|
69
83
|
test('host_file_write is root-scoped hash-precondition and host_file_read returns a verified digest', async () => {
|
|
70
84
|
const f = await fixture();
|
|
71
85
|
const first = await hostFileWrite(f.policy, {
|
|
@@ -51,6 +51,7 @@ async function fixture() {
|
|
|
51
51
|
env: {
|
|
52
52
|
...getDefaultEnvironment(), DEADBYTE_STATE_ROOT: root, DEADBYTE_MACHINE_RUNTIME: '1',
|
|
53
53
|
DEADBYTE_SIGNING_KEY: keys.privateKeyPath, DEADBYTE_VERIFY_KEY: keys.publicKeyPath,
|
|
54
|
+
DEADBYTE_PRIVILEGED_POLICY: '',
|
|
54
55
|
DEADBYTE_AGENT_RUNTIME: '0', DEADBYTE_CODING_RUNTIME: '0', DEADBYTE_AUTONOMOUS_RUNTIME: '0'
|
|
55
56
|
}, stderr: 'pipe'
|
|
56
57
|
});
|
|
@@ -79,6 +79,34 @@ test('native diff rolls back earlier operations when a later operation fails', a
|
|
|
79
79
|
} finally { await rm(f.root,{recursive:true,force:true}); }
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
test('native diff revocation between operations rolls back to preimage without autonomous rollback authority', async () => {
|
|
83
|
+
const f = await fixture();
|
|
84
|
+
try {
|
|
85
|
+
let writes = 0;
|
|
86
|
+
const revokingCoding = Object.freeze({
|
|
87
|
+
...f.codingRuntime,
|
|
88
|
+
fileWrite: async args => {
|
|
89
|
+
const result = await f.codingRuntime.fileWrite(args);
|
|
90
|
+
writes += 1;
|
|
91
|
+
if (writes === 1) {
|
|
92
|
+
const lease = JSON.parse(await readFile(f.policy.lease_file, 'utf8'));
|
|
93
|
+
await writeFile(f.policy.lease_file, JSON.stringify({ ...lease, instance_nonce:'e'.repeat(64) }));
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
const runtime = createNativeDiffRuntime({ policy:f.policy, codingRuntime:revokingCoding,
|
|
99
|
+
signingKeyPath:f.keys.privateKeyPath, verifyKeyPath:f.keys.publicKeyPath });
|
|
100
|
+
const preview = await runtime.preview({ rootId:'project', title:'revoke mid transaction', operations:[
|
|
101
|
+
{ kind:'write', path:'first.txt', expected_sha256:'absent', encoding:'utf8', content:'first\n' },
|
|
102
|
+
{ kind:'write', path:'second.txt', expected_sha256:'absent', encoding:'utf8', content:'second\n' }
|
|
103
|
+
] });
|
|
104
|
+
await assert.rejects(runtime.apply({ diffId:preview.diff_id }), /rolled back.*autonomous authority changed/i);
|
|
105
|
+
assert.equal(await exists(path.join(f.project,'first.txt')), false);
|
|
106
|
+
assert.equal(await exists(path.join(f.project,'second.txt')), false);
|
|
107
|
+
} finally { await rm(f.root,{recursive:true,force:true}); }
|
|
108
|
+
});
|
|
109
|
+
|
|
82
110
|
test('autonomous application scope isolates repeated identical native diffs across goals', async () => {
|
|
83
111
|
const f = await fixture();
|
|
84
112
|
try {
|
|
@@ -15,14 +15,15 @@ function runtime(){
|
|
|
15
15
|
searchStatus:async()=>({status:'ok',search_id:hex('a'),state:'completed',result_count:0,files_scanned:0,bytes_scanned:0,truncated:false,request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d'),error:null}),
|
|
16
16
|
searchCancel:async()=>({status:'ok',search_id:hex('a'),state:'cancelled',cancel_requested:true}),
|
|
17
17
|
processList:async()=>({status:'ok',snapshot_id:hex('e'),observed_at_utc:new Date(0).toISOString(),processes:[],next_cursor:null,request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')}),
|
|
18
|
-
systemStatus:async()=>({status:'ok',observed_at_utc:new Date(0).toISOString(),hostname:'x',platform:'win32',architecture:'x64',uptime_seconds:1,total_memory_bytes:2,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0],request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')})
|
|
18
|
+
systemStatus:async()=>({status:'ok',observed_at_utc:new Date(0).toISOString(),hostname:'x',platform:'win32',architecture:'x64',uptime_seconds:1,total_memory_bytes:2,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0],request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')}),
|
|
19
|
+
hardwareQuery:async({query})=>({status:'ok',query,observed_at_utc:new Date(0).toISOString(),observer_sha256:hex('e'),data:{vendor:'x'},request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')})
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
test('
|
|
23
|
+
test('R45 registers exactly seven bounded observation tools including typed native hardware',()=>{
|
|
23
24
|
const server=new FakeServer(); registerObservationTools(server,{runtime:runtime()});
|
|
24
25
|
assert.deepEqual([...server.tools.keys()].sort(),[
|
|
25
|
-
'machine_process_list','machine_search_cancel','machine_search_page','machine_search_start','machine_search_status','machine_system_status'
|
|
26
|
+
'machine_hardware_query','machine_process_list','machine_search_cancel','machine_search_page','machine_search_start','machine_search_status','machine_system_status'
|
|
26
27
|
]);
|
|
27
28
|
for(const [name,tool] of server.tools){ assert.ok(tool.spec.inputSchema,`${name} input`); assert.ok(tool.spec.outputSchema,`${name} output`); }
|
|
28
29
|
});
|
|
@@ -19,7 +19,7 @@ const EXPECTED_TOOLS = [
|
|
|
19
19
|
'agent_task_run', 'agent_task_status', 'agent_task_submit',
|
|
20
20
|
'agent_task_verify', 'contained_transform', 'evidence_verify',
|
|
21
21
|
'file_read',
|
|
22
|
-
'proof_execute', 'workspace_open'
|
|
22
|
+
'proof_execute', 'skill_catalog', 'workspace_open'
|
|
23
23
|
];
|
|
24
24
|
|
|
25
25
|
async function fixture() {
|
|
@@ -40,6 +40,7 @@ async function fixture() {
|
|
|
40
40
|
DEADBYTE_WORKSPACE_ROOT: workspaceRoot,
|
|
41
41
|
DEADBYTE_SIGNING_KEY: keys.privateKeyPath,
|
|
42
42
|
DEADBYTE_VERIFY_KEY: keys.publicKeyPath,
|
|
43
|
+
DEADBYTE_PRIVILEGED_POLICY: '',
|
|
43
44
|
DEADBYTE_AGENT_RUNTIME: '1'
|
|
44
45
|
},
|
|
45
46
|
stderr: 'pipe'
|
|
@@ -47,7 +48,7 @@ async function fixture() {
|
|
|
47
48
|
return { trust, client, transport };
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
test('
|
|
51
|
+
test('R44 hermetic base-plus-agent catalog advertises 13 strict output schemas', async () => {
|
|
51
52
|
const f = await fixture();
|
|
52
53
|
try {
|
|
53
54
|
await f.client.connect(f.transport);
|
|
@@ -39,6 +39,6 @@ test('R28 package boundary contains only immutable workspace seed files', () =>
|
|
|
39
39
|
|
|
40
40
|
test('publish boundary excludes live state, private keys, grants and non-example controller secrets',()=>{
|
|
41
41
|
const files=packFiles();
|
|
42
|
-
const forbidden=files.filter(rel
|
|
42
|
+
const forbidden=files.filter(rel=>rel.startsWith('tmp/')||rel.startsWith('.deadbyte-machine-fs-recovery/')||/(^|\/)(active-release\.json|runtime\/|audit\/|evidence\/)|\.pem$|(^|\/)deadbyte-controller\.config\.psd1$|(^|\/)deadbyte-host-policy\.json$|(^|\/)[^/]*(?:grant|arm)\.json$/i.test(rel));
|
|
43
43
|
assert.deepEqual(forbidden,[]);
|
|
44
44
|
});
|
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
PROCESS_POLICY_SCHEMA,
|
|
10
10
|
assertProcessArmed,
|
|
11
11
|
loadProcessPolicy,
|
|
12
|
-
processSessionStatus
|
|
12
|
+
processSessionStatus,
|
|
13
|
+
recheckProcessAuthority
|
|
13
14
|
} from '../src/process-policy.mjs';
|
|
14
15
|
|
|
15
16
|
const sha = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
@@ -69,6 +70,26 @@ test('process policy loads pinned native host, profile and root while grant is a
|
|
|
69
70
|
await assert.rejects(() => assertProcessArmed(policy, 'other', 'core'), /profile 'other' is not included/);
|
|
70
71
|
});
|
|
71
72
|
|
|
73
|
+
test('process authority recheck rejects grant generation or scope drift before side effects', async () => {
|
|
74
|
+
const f = await fixture();
|
|
75
|
+
const policy = await loadProcessPolicy(f.policyPath);
|
|
76
|
+
const grant = {
|
|
77
|
+
schema: PROCESS_GRANT_SCHEMA,
|
|
78
|
+
policy_sha256: policy.policy_sha256,
|
|
79
|
+
instance_nonce: 'a'.repeat(64),
|
|
80
|
+
profile_ids: ['node'],
|
|
81
|
+
root_ids: ['core'],
|
|
82
|
+
granted_at_utc: '2026-09-14T00:00:00Z'
|
|
83
|
+
};
|
|
84
|
+
await writeFile(f.grantFile, JSON.stringify(grant));
|
|
85
|
+
const initial = await assertProcessArmed(policy, 'node', 'core');
|
|
86
|
+
await writeFile(f.grantFile, JSON.stringify({ ...grant, instance_nonce: 'b'.repeat(64) }));
|
|
87
|
+
await assert.rejects(() => recheckProcessAuthority(policy, initial, 'node', 'core'), /process authority changed during operation/);
|
|
88
|
+
await writeFile(f.grantFile, JSON.stringify({ ...grant, profile_ids: ['node', 'node'] }));
|
|
89
|
+
const deduped = await recheckProcessAuthority(policy, initial, 'node', 'core');
|
|
90
|
+
assert.equal(deduped.instance_nonce, initial.instance_nonce);
|
|
91
|
+
});
|
|
92
|
+
|
|
72
93
|
test('process grant with wrong policy digest is disarmed', async () => {
|
|
73
94
|
const f = await fixture();
|
|
74
95
|
const policy = await loadProcessPolicy(f.policyPath);
|
|
@@ -9,9 +9,9 @@ const readme=()=>readFile(path.join(root,'README.txt'),'utf8');
|
|
|
9
9
|
|
|
10
10
|
test('production README documents one-command stdio configs for major MCP clients',async()=>{
|
|
11
11
|
const text=await readme();
|
|
12
|
-
assert.match(text,/npx -y deadbyte-mcp@0\.
|
|
12
|
+
assert.match(text,/npx -y deadbyte-mcp@0\.15\.1 mcp/);
|
|
13
13
|
assert.match(text,/CLAUDE DESKTOP/);
|
|
14
|
-
assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.
|
|
14
|
+
assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.15\.1"[\s\S]*?"mcp"/);
|
|
15
15
|
assert.match(text,/CURSOR/);
|
|
16
16
|
assert.match(text,/\.cursor\/mcp\.json/);
|
|
17
17
|
assert.match(text,/VS CODE/);
|
|
@@ -20,7 +20,7 @@ test('production README documents one-command stdio configs for major MCP client
|
|
|
20
20
|
assert.match(text,/CODEX/);
|
|
21
21
|
assert.match(text,/\[mcp_servers\.deadbyte\]/);
|
|
22
22
|
assert.match(text,/command\s*=\s*"npx"/);
|
|
23
|
-
assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.
|
|
23
|
+
assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.15\.1",\s*"mcp"\]/);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
test('production README records tracer bullet, semantic scope, remote UX, safety and document extension',async()=>{
|
|
@@ -30,7 +30,7 @@ test('MCP exposes compact workflow prompts and source-of-truth context resources
|
|
|
30
30
|
const surfaceState=JSON.parse(surfaceText);
|
|
31
31
|
assert.equal(surfaceState.schema,'deadbyte.surface-profile.v1');
|
|
32
32
|
assert.equal(surfaceState.profile,'full');
|
|
33
|
-
assert.equal(surfaceState.compact_tool_limit,
|
|
33
|
+
assert.equal(surfaceState.compact_tool_limit,43);
|
|
34
34
|
const context=await client.readResource({uri:'deadbyte://context'});
|
|
35
35
|
const contextText=context.contents.map(c=>'text' in c?c.text:'').join('\n');
|
|
36
36
|
assert.match(contextText,/Machine truth/i); assert.match(contextText,/Authority plane/i); assert.match(contextText,/Loop Supervisor/i);
|
|
@@ -86,40 +86,24 @@ test('audit restart reconciles an orphan request with an explicit interrupted re
|
|
|
86
86
|
}finally{await rm(stateRoot,{recursive:true,force:true});}
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
test('Windows current
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
assert.equal(evaluation.payload.status,'passed');
|
|
111
|
-
|
|
112
|
-
const summary=await writeWindowsGateEvidence({candidateRoot:root,stateRoot,clock:()=>new Date('2026-09-20T02:01:00.000Z')});
|
|
113
|
-
assert.equal(summary.status,'written');
|
|
114
|
-
const evidence=JSON.parse(await readFile(summary.path,'utf8'));
|
|
115
|
-
assert.equal(evidence.schema,'deadbyte.r42-windows-gate.v1');
|
|
116
|
-
assert.equal(evidence.status,'passed');
|
|
117
|
-
assert.equal(evidence.exit_code,0);
|
|
118
|
-
assert.equal(evidence.version,'0.14.0');
|
|
119
|
-
assert.equal(evidence.manifest_sha256,manifestSha);
|
|
120
|
-
assert.equal(evidence.marker,'DEADBYTE V0.14.0 / R42 WINDOWS BATCH GATE: PASS');
|
|
121
|
-
assert.equal(evidence.model_eval.evidence_sha256,evaluation.publication.evidence_sha256);
|
|
122
|
-
assert.equal(evidence.model_eval.case_count,suite.cases.length);
|
|
123
|
-
assert.ok(summary.path.startsWith(path.join(stateRoot,'evidence','release')));
|
|
124
|
-
}finally{await rm(stateRoot,{recursive:true,force:true});}
|
|
89
|
+
test('Windows current R45 gate binds exact sealed R44 parent and machine-freedom evidence contract', async()=>{
|
|
90
|
+
const gate=await readFile(path.join(root,'scripts','gate-windows-r45.ps1'),'utf8');
|
|
91
|
+
const evidenceSource=await readFile(path.join(root,'scripts','windows-gate-evidence-r45.mjs'),'utf8');
|
|
92
|
+
const parent=JSON.parse(await readFile(path.join(root,'R45-PARENT.json'),'utf8'));
|
|
93
|
+
assert.match(gate,/windows-gate-evidence-r45\.mjs/);
|
|
94
|
+
assert.match(gate,/r45-parent-verify/);
|
|
95
|
+
assert.match(gate,/host-policy-refresh/);
|
|
96
|
+
assert.match(gate,/hardware-build/);
|
|
97
|
+
assert.match(gate,/doctor/);
|
|
98
|
+
assert.match(evidenceSource,/deadbyte\.r45-windows-gate\.v1/);
|
|
99
|
+
assert.match(evidenceSource,/version:'0\.15\.1'/);
|
|
100
|
+
assert.match(evidenceSource,/DEADBYTE V0\.15\.1 \/ R45 MACHINE FREEDOM WINDOWS BATCH GATE: PASS/);
|
|
101
|
+
for(const key of ['host_inline_native','native_hardware_observation','doctor_release_truth']) assert.match(evidenceSource,new RegExp(key+':true'));
|
|
102
|
+
assert.equal(parent.parent_release_id,'v0.15.0-c15fa41719be61b3');
|
|
103
|
+
assert.equal(parent.parent_manifest_sha256,'c15fa41719be61b3186e49b2367a5f4c057365cfb465102dbefb7d7355f45483');
|
|
104
|
+
assert.equal(parent.parent_generation_manifest_sha256,'6d7429c050b7fe893492e102f00282019116e0c9e54e4f25a5791defa1661d30');
|
|
105
|
+
assert.equal(parent.parent_final_closure_sha256,'533b7e0ff9ded04086dd90ed34e3b87bc427acc3c55c25bb9f4ec66cb448e667');
|
|
106
|
+
const historical=await readFile(path.join(root,'scripts','windows-gate-evidence-r44.mjs'),'utf8');
|
|
107
|
+
assert.match(historical,/version:'0\.15\.0'/);
|
|
108
|
+
assert.match(historical,/deadbyte\.r44-windows-gate\.v1/);
|
|
125
109
|
});
|
|
@@ -19,9 +19,9 @@ test('R34 public parity catalog is exact, unique, and includes production coding
|
|
|
19
19
|
|
|
20
20
|
test('release parity and final verifier are package entry points', async () => {
|
|
21
21
|
const pkg = JSON.parse(await text('package.json'));
|
|
22
|
-
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-
|
|
23
|
-
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-
|
|
24
|
-
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-
|
|
22
|
+
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-r45.mjs');
|
|
23
|
+
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-r45.mjs');
|
|
24
|
+
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-r45.mjs');
|
|
25
25
|
assert.equal(typeof validateParityEvidence, 'function');
|
|
26
26
|
assert.equal(typeof verifyFinalClosureObject, 'function');
|
|
27
27
|
});
|
|
@@ -45,11 +45,11 @@ test('final closure verifier canonicalizes traversal order before exact-tree com
|
|
|
45
45
|
assert.match(verifier, /const expected=\[\.\.\.entries\.keys\(\)\]\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
test('
|
|
48
|
+
test('R44 autonomous live gate binds the current compact gateway contract instead of the historical 73-tool public catalog', async () => {
|
|
49
49
|
const autonomous = await text('src/remote-mcp-autonomous-smoke-client.mjs');
|
|
50
|
-
assert.match(autonomous, /
|
|
51
|
-
assert.match(autonomous, /
|
|
52
|
-
assert.match(autonomous, /names\.length >
|
|
50
|
+
assert.match(autonomous, /R44_COMPACT_GATEWAYS/);
|
|
51
|
+
assert.match(autonomous, /R44_COMPACT_TOOL_LIMIT/);
|
|
52
|
+
assert.match(autonomous, /names\.length > R44_COMPACT_TOOL_LIMIT/);
|
|
53
53
|
for (const name of ['autonomous_goal_submit','autonomous_goal_run','autonomous_goal_verify','autonomous_release_gate','native_diff_apply','native_diff_verify']) {
|
|
54
54
|
assert.match(autonomous,new RegExp(name));
|
|
55
55
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { validateParityEvidence,R43_PREDECESSOR_RELEASE_ID,R43_PREDECESSOR_MANIFEST } from '../scripts/release-parity-r43.mjs';
|
|
5
|
+
import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r43.mjs';
|
|
6
|
+
|
|
7
|
+
const root=new URL('../',import.meta.url);const text=rel=>readFile(new URL(rel,root),'utf8');
|
|
8
|
+
function parity(){const manifest='a'.repeat(64);return {schema:'deadbyte.r43-parity.v1',status:'passed',execution_provider:'deadbyte_mcp',rdc_operation_count:0,
|
|
9
|
+
candidate:{release_id:`v0.14.1-${manifest.slice(0,16)}`,version:'0.14.1',manifest_sha256:manifest},
|
|
10
|
+
immutable_slot:{protected:true,release_root:'C:/immutable/r43',development_root:'D:/Projects/deadbyte-mcp/development/deadbyte-mcp-r42-agentic-dev'},
|
|
11
|
+
local_full:{status:'passed',tool_count:80,strict_output_schemas:true},
|
|
12
|
+
public_compact:{status:'passed',tool_count:42,capability_closure:true,gateway_count:6,desktop_armed:false,desktop_observation_receipt_verified:true,desktop_grounding_receipt_verified:true},
|
|
13
|
+
autonomous:{status:'passed',signed_release_verified:true},desktop_guarded:{status:'passed',native_injected:true,replay_performed:false,predispatch_retry_count:0,observation_receipts_verified:1,action_receipts_verified:3},
|
|
14
|
+
deterministic_memory:{status:'passed',goal_count:1,snapshot_count:1,index_count:1},
|
|
15
|
+
before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false,desktop_armed:false},rollback:{state:'completed'},restore:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},
|
|
16
|
+
predecessor:{release_id:R43_PREDECESSOR_RELEASE_ID,version:'0.14.0',manifest_sha256:R43_PREDECESSOR_MANIFEST},predecessor_disarmed:{status:'passed',tool_count:42,capability_closure:true},
|
|
17
|
+
successor:{release_id:`v0.14.1-${manifest.slice(0,16)}`,version:'0.14.1',manifest_sha256:manifest},successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false,desktop_armed:false},
|
|
18
|
+
requirements:Object.fromEntries(['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface','desktop_readonly','desktop_guarded_input','deterministic_memory'].map(key=>[key,true]))};}
|
|
19
|
+
|
|
20
|
+
test('R43 parity requires exact R42 predecessor and immutable R43 slot',()=>{const value=parity();assert.equal(validateParityEvidence(value),true);
|
|
21
|
+
assert.throws(()=>validateParityEvidence({...value,predecessor:{...value.predecessor,manifest_sha256:'b'.repeat(64)}}),/predecessor/i);
|
|
22
|
+
assert.throws(()=>validateParityEvidence({...value,immutable_slot:{...value.immutable_slot,development_root:value.immutable_slot.release_root}}),/immutable-slot/i);});
|
|
23
|
+
|
|
24
|
+
test('R43 release machinery binds 0.14.1 exact R42 predecessor and no fresh model credential dependency',async()=>{const [gate,deferred,paritySource,writer,verifier,evidence,suite,finalizer]=await Promise.all([
|
|
25
|
+
text('scripts/gate-windows-r43.ps1'),text('scripts/deferred-slot-operation-r43.mjs'),text('scripts/release-parity-r43.mjs'),text('scripts/final-closure-r43.mjs'),text('scripts/final-closure-verify-r43.mjs'),text('scripts/windows-gate-evidence-r43.mjs'),text('scripts/release-parity-tests-r43.ps1'),text('scripts/finalize-r43.mjs')]);
|
|
26
|
+
assert.equal(R43_PREDECESSOR_RELEASE_ID,'v0.14.0-08cd8f3b98c90e0e');assert.equal(R43_PREDECESSOR_MANIFEST,'08cd8f3b98c90e0e250cf506ff396515065ff5457909f850b75b0b6e8ecc2dd1');
|
|
27
|
+
assert.match(gate,/r43-parent-verify/);assert.doesNotMatch(gate,/model-backed-eval|OPENAI_API_KEY/);assert.match(gate,/full-regression/);assert.match(gate,/r43:full:test/);assert.match(gate,/DEADBYTE V0\.14\.1 \/ R43 AUTHORITY HARDENING WINDOWS BATCH GATE: PASS/);
|
|
28
|
+
assert.match(deferred,/--expected-version','0\.14\.1'/);assert.match(paritySource,/deadbyte\.r43-parity\.v1/);assert.doesNotMatch(paritySource,/verifyR42ModelEval|model_eval/);
|
|
29
|
+
for(const source of [writer,verifier]){assert.match(source,/DEADBYTE-R43-FINAL-CLOSURE-V1/);assert.match(source,/deadbyte\.r43-final-closure\.v1/);assert.match(source,/R43 AUTHORITY HARDENING PATCH/);assert.doesNotMatch(source,/model_eval/);}
|
|
30
|
+
assert.equal(typeof verifyFinalClosureObject,'function');assert.match(evidence,/deadbyte\.r43-windows-gate\.v1/);assert.match(evidence,/parent_activation_receipt_sha256/);assert.match(suite,/autonomous-loop\.test\.mjs/);assert.match(suite,/runtime-self-update\.test\.mjs/);assert.match(suite,/r43-finalizer\.test\.mjs/);assert.match(finalizer,/--restore-standing-grants/);assert.match(finalizer,/final_authority\?\.process_armed===true/);assert.match(finalizer,/requires Process standing grant/);assert.match(finalizer,/runReleaseParity/);assert.match(finalizer,/writeFinalClosure/);assert.match(finalizer,/verifyFinalClosureObject/);assert.match(finalizer,/--rollback-receipt/);assert.match(finalizer,/parity_scratch/);
|
|
31
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { validateFinalizerAuthorityStatus, validateWindowsGateEvidence } from '../scripts/finalize-r43.mjs';
|
|
4
|
+
|
|
5
|
+
const manifest='a'.repeat(64);
|
|
6
|
+
const parent={parent_release_id:'v0.14.0-08cd8f3b98c90e0e',
|
|
7
|
+
parent_manifest_sha256:'08cd8f3b98c90e0e250cf506ff396515065ff5457909f850b75b0b6e8ecc2dd1',
|
|
8
|
+
parent_generation_manifest_sha256:'df8ca9894a3e2ca9a9f145cfa3e4e23fd71f42c1988266a1591fc16261ab18a5'};
|
|
9
|
+
const valid=()=>({schema:'deadbyte.r43-windows-gate.v1',status:'passed',exit_code:0,version:'0.14.1',
|
|
10
|
+
marker:'DEADBYTE V0.14.1 / R43 AUTHORITY HARDENING WINDOWS BATCH GATE: PASS',manifest_sha256:manifest,
|
|
11
|
+
parent:{release_id:parent.parent_release_id,manifest_sha256:parent.parent_manifest_sha256,
|
|
12
|
+
generation_manifest_sha256:parent.parent_generation_manifest_sha256,
|
|
13
|
+
activation_receipt_sha256:'074140ad8b94501e0a095a7fa132dc5d6e2c57102c9eeaaa2ac9e4ea93b9b187'},
|
|
14
|
+
hardening:{authority_toctou:true,absolute_execution_deadline:true,pre_spawn_authority_recheck:true,
|
|
15
|
+
full_regression_required:true,model_path_changed:false}});
|
|
16
|
+
|
|
17
|
+
test('R43 detached finalizer requires explicit Process+Coding+Autonomous grants and keeps Desktop+Host disarmed',()=>{
|
|
18
|
+
assert.equal(validateFinalizerAuthorityStatus({
|
|
19
|
+
process_armed:true,coding_armed:true,autonomous_armed:true,desktop_armed:false,host_armed:false
|
|
20
|
+
}),true);
|
|
21
|
+
assert.throws(()=>validateFinalizerAuthorityStatus({
|
|
22
|
+
process_armed:false,coding_armed:true,autonomous_armed:true,desktop_armed:false,host_armed:false
|
|
23
|
+
}),/Process standing grant/);
|
|
24
|
+
assert.throws(()=>validateFinalizerAuthorityStatus({
|
|
25
|
+
process_armed:true,coding_armed:true,autonomous_armed:true,desktop_armed:false,host_armed:true
|
|
26
|
+
}),/Host DISARMED/);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('R43 detached finalizer accepts only exact parent-bound hardening gate evidence',()=>{
|
|
30
|
+
assert.equal(validateWindowsGateEvidence(valid(),manifest,parent),true);
|
|
31
|
+
assert.throws(()=>validateWindowsGateEvidence({...valid(),manifest_sha256:'b'.repeat(64)},manifest,parent),/candidate mismatch/);
|
|
32
|
+
assert.throws(()=>validateWindowsGateEvidence({...valid(),hardening:{...valid().hardening,authority_toctou:false}},manifest,parent),/hardening contract/);
|
|
33
|
+
assert.throws(()=>validateWindowsGateEvidence({...valid(),parent:{...valid().parent,release_id:'v0.14.0-bad'}},manifest,parent),/parent mismatch/);
|
|
34
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { verifyR43Parent } from '../scripts/verify-r43-parent.mjs';
|
|
5
|
+
|
|
6
|
+
const root=new URL('../',import.meta.url);
|
|
7
|
+
|
|
8
|
+
test('R43 parent contract binds exact immutable R42 release and signed activation evidence', async()=>{
|
|
9
|
+
const record=JSON.parse(await readFile(new URL('../R43-PARENT.json',import.meta.url),'utf8'));
|
|
10
|
+
assert.equal(record.schema,'deadbyte.r43-parent.v1');
|
|
11
|
+
assert.equal(record.parent_release_id,'v0.14.0-08cd8f3b98c90e0e');
|
|
12
|
+
assert.equal(record.parent_version,'0.14.0');
|
|
13
|
+
assert.equal(record.parent_manifest_sha256,'08cd8f3b98c90e0e250cf506ff396515065ff5457909f850b75b0b6e8ecc2dd1');
|
|
14
|
+
assert.equal(record.parent_generation_manifest_sha256,'df8ca9894a3e2ca9a9f145cfa3e4e23fd71f42c1988266a1591fc16261ab18a5');
|
|
15
|
+
assert.equal(record.parent_manifest_file_count,1820);
|
|
16
|
+
assert.equal(record.parent_generation_file_count,7);
|
|
17
|
+
assert.equal(record.parent_final_closure_present,false);
|
|
18
|
+
const verified=await verifyR43Parent(new URL('../R43-PARENT.json',import.meta.url));
|
|
19
|
+
assert.equal(verified.status,'passed');
|
|
20
|
+
assert.equal(verified.release_files,1820);
|
|
21
|
+
assert.equal(verified.generation_files,7);
|
|
22
|
+
assert.equal(verified.parent_activation_receipt_sha256,'074140ad8b94501e0a095a7fa132dc5d6e2c57102c9eeaaa2ac9e4ea93b9b187');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('R43 parent record explicitly refuses to invent missing R42 final closure evidence', async()=>{
|
|
26
|
+
const record=JSON.parse(await readFile(new URL('../R43-PARENT.json',import.meta.url),'utf8'));
|
|
27
|
+
assert.equal(record.parent_final_closure_present,false);
|
|
28
|
+
assert.equal(Object.prototype.hasOwnProperty.call(record,'parent_final_closure_path'),false);
|
|
29
|
+
});
|