deadbyte-mcp 0.15.25 → 0.15.27
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/DEADBYTE-MCP.cmd +4 -0
- package/MANIFEST.SHA256 +33 -23
- package/PROVENANCE.json +11 -11
- package/R49-PARENT.json +11 -0
- package/README.txt +24 -7
- package/RELEASE.json +15 -12
- package/SBOM.cdx.json +3 -3
- package/TEST-MATRIX.json +13 -10
- package/docs/R49-FULL-TOOL-CATALOG.json +13 -0
- package/docs/R49-REMOTE-CONTROL-DONORS.json +75 -0
- package/package.json +2 -2
- package/scripts/deferred-slot-operation-r46.mjs +44 -2
- package/scripts/gate-windows-r49.ps1 +54 -0
- package/scripts/gate-windows-r50.ps1 +56 -0
- package/scripts/windows-gate-evidence-r49.mjs +27 -0
- package/scripts/windows-gate-evidence-r50.mjs +80 -0
- package/src/autonomous-planner-contracts.mjs +1 -0
- package/src/autonomous-planner.mjs +11 -5
- package/src/autonomous-runtime.mjs +11 -1
- package/src/capability-ledger.mjs +1 -0
- package/src/desktop-mcp-tools-r40.mjs +23 -1
- package/src/desktop-runtime-r40.mjs +46 -2
- package/src/remote-mcp-smoke-client.mjs +7 -1
- package/src/runtime-catalog-expectation.mjs +9 -1
- package/src/version.mjs +1 -1
- package/test/autonomous-desktop-r40.test.mjs +27 -1
- package/test/desktop-mcp-tools-r40.test.mjs +19 -4
- package/test/desktop-runtime-r40.test.mjs +43 -2
- package/test/full-max-catalog-r48.test.mjs +5 -3
- package/test/package-boundary.test.mjs +6 -0
- package/test/r48-release-contract.test.mjs +44 -35
- package/test/r49-remote-control-donors.test.mjs +24 -0
- package/test/r49-windows-gate.test.mjs +36 -0
- package/test/remote-r24-catalog.test.mjs +9 -0
|
@@ -11,7 +11,7 @@ const POLICY=H('desktop-policy');
|
|
|
11
11
|
const WIN={hwnd:'0x1234',pid:77,process_image_sha256:H('desktop-app'),title_sha256:H('desktop-title')};
|
|
12
12
|
|
|
13
13
|
function fakeDesktopRuntime({armed=false,unknown=false}={}){
|
|
14
|
-
const calls={status:0,observe:0,ground:0,action:0,verify:0};
|
|
14
|
+
const calls={status:0,observe:0,wait:0,ground:0,action:0,verify:0};
|
|
15
15
|
const receipts=new Map();
|
|
16
16
|
let seq=0;
|
|
17
17
|
const issue=kind=>{
|
|
@@ -28,6 +28,9 @@ function fakeDesktopRuntime({armed=false,unknown=false}={}){
|
|
|
28
28
|
async status(){calls.status++;return {status:'ok',configured:true,armed,reason:armed?'standing-grant':'disarmed',
|
|
29
29
|
action_kinds:armed?['click_primary']:[],policy_sha256:POLICY,observer_backend:'fake'};},
|
|
30
30
|
async observe(){calls.observe++;const r=issue('desktop_observation');return {status:'ok',frame:frame(FRAME),backend:'fake',byte_length:4,...r};},
|
|
31
|
+
async wait({baselineFrameId,until}){calls.wait++;assert.equal(baselineFrameId,FRAME);assert.equal(until,'frame_changed');
|
|
32
|
+
const r=issue('desktop_wait_observation');return {status:'ok',condition:until,satisfied:true,timed_out:false,attempts:2,elapsed_ms:100,
|
|
33
|
+
baseline_frame_id:FRAME,frame:frame(GROUNDED_FRAME),match:null,...r};},
|
|
31
34
|
async ground({frameId,query}){calls.ground++;assert.equal(frameId,FRAME);assert.equal(query.kind,'root');
|
|
32
35
|
const r=issue('desktop_grounding');return {status:'ok',frame:frame(GROUNDED_FRAME),
|
|
33
36
|
target:{target_id:TARGET,frame_id:GROUNDED_FRAME,rect:{left:100,top:100,width:200,height:80},source:'uia'},
|
|
@@ -99,6 +102,29 @@ test('T7 read-only Desktop observe works while Desktop mutation authority is DIS
|
|
|
99
102
|
}finally{await f.cleanup();}
|
|
100
103
|
});
|
|
101
104
|
|
|
105
|
+
test('successor autonomous Desktop wait replaces fixed sleep and verifies signed observation evidence',async()=>{
|
|
106
|
+
const d=fakeDesktopRuntime({armed:false});
|
|
107
|
+
const f=await createR34Fixture({desktopRuntime:d});
|
|
108
|
+
try{
|
|
109
|
+
const goal=await f.runtime.submit({submissionId:'desktop-bounded-wait',rootId:'project',title:'desktop wait',goal:'wait for visual change',acceptance:'signed bounded wait'});
|
|
110
|
+
let result=await f.runtime.run({goalId:goal.goal_id,maxCycles:2});
|
|
111
|
+
result=await sendPlannerDecision(f.runtime,goal.goal_id,result,plan(['observe','wait']));
|
|
112
|
+
result=await toAct(f,goal,result);
|
|
113
|
+
result=await sendPlannerDecision(f.runtime,goal.goal_id,result,{schema:'deadbyte.autonomous-decision.v2',kind:'act',action:{kind:'desktop_observe'}});
|
|
114
|
+
result=await sendPlannerDecision(f.runtime,goal.goal_id,result,complete('observe','wait-observe-proof'));
|
|
115
|
+
result=await toAct(f,goal,result);
|
|
116
|
+
result=await sendPlannerDecision(f.runtime,goal.goal_id,result,{schema:'deadbyte.autonomous-decision.v2',kind:'act',action:{
|
|
117
|
+
kind:'desktop_wait',baseline_frame_id:FRAME,until:'frame_changed',uia_query:null,timeout_ms:1000,poll_ms:100
|
|
118
|
+
}});
|
|
119
|
+
assert.equal(result.loop.phase,'VERIFYING');
|
|
120
|
+
assert.equal(d.calls.wait,1);assert.equal(d.calls.action,0);assert.equal(d.calls.verify,2);
|
|
121
|
+
const journal=await f.runtime.events({goalId:goal.goal_id,fromSeq:1,limit:200});
|
|
122
|
+
const completed=journal.events.find(e=>e.type==='delegated_action_completed'&&e.payload?.operation?.kind==='desktop_wait');
|
|
123
|
+
assert.equal(completed.payload.capability_id,'desktop.wait');
|
|
124
|
+
assert.equal(completed.payload.evidence.receipts[0].kind,'desktop_wait_observation');
|
|
125
|
+
}finally{await f.cleanup();}
|
|
126
|
+
});
|
|
127
|
+
|
|
102
128
|
test('T7 Autonomous authority cannot substitute for missing Desktop mutation grant',async()=>{
|
|
103
129
|
const d=fakeDesktopRuntime({armed:false});
|
|
104
130
|
const f=await createR34Fixture({desktopRuntime:d});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import test from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import {
|
|
4
|
-
desktopActionInputSchema,desktopControlInputSchema,desktopTargetInputSchema,registerDesktopTools
|
|
4
|
+
desktopActionInputSchema,desktopControlInputSchema,desktopTargetInputSchema,desktopWaitInputSchema,registerDesktopTools
|
|
5
5
|
} from '../src/desktop-mcp-tools-r40.mjs';
|
|
6
6
|
|
|
7
7
|
const H=c=>c.repeat(64);
|
|
@@ -30,11 +30,26 @@ test('R40 T5 target schema supports local UIA query without arbitrary dispatch',
|
|
|
30
30
|
assert.equal(desktopControlInputSchema.safeParse({op:'target',frame_id:frame,uia_query:{kind:'control_type',value:'button',max_results:4,ordinal:0}}).success,true);
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
test('
|
|
33
|
+
test('successor desktop wait schema is bounded, semantic, and rejects action-shaped fields',()=>{
|
|
34
|
+
assert.equal(desktopWaitInputSchema.safeParse({
|
|
35
|
+
baseline_frame_id:frame,until:'frame_changed',timeout_ms:5000,poll_ms:100,preview:false
|
|
36
|
+
}).success,true);
|
|
37
|
+
assert.equal(desktopWaitInputSchema.safeParse({
|
|
38
|
+
baseline_frame_id:frame,until:'uia_present',uia_query:{kind:'name_exact',value:'Ready',max_results:8,ordinal:0},timeout_ms:5000,poll_ms:100,preview:false
|
|
39
|
+
}).success,true);
|
|
40
|
+
assert.equal(desktopWaitInputSchema.safeParse({
|
|
41
|
+
baseline_frame_id:frame,until:'uia_present',timeout_ms:5000,poll_ms:100,preview:false
|
|
42
|
+
}).success,false);
|
|
43
|
+
assert.equal(desktopControlInputSchema.safeParse({
|
|
44
|
+
op:'wait',baseline_frame_id:frame,until:'frame_changed',timeout_ms:5000,poll_ms:100,preview:false,point:{x:1,y:2}
|
|
45
|
+
}).success,false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('successor full desktop surface registers bounded semantic wait without mutation authority',()=>{
|
|
34
49
|
const server=fakeServer();
|
|
35
|
-
const runtime={status(){},observe(){},target(){},action(){}};
|
|
50
|
+
const runtime={status(){},observe(){},wait(){},target(){},action(){}};
|
|
36
51
|
registerDesktopTools(server,{runtime});
|
|
37
|
-
assert.deepEqual([...server.tools.keys()].sort(),['desktop_action','desktop_observe','desktop_status','desktop_target']);
|
|
52
|
+
assert.deepEqual([...server.tools.keys()].sort(),['desktop_action','desktop_observe','desktop_status','desktop_target','desktop_wait']);
|
|
38
53
|
});
|
|
39
54
|
|
|
40
55
|
test('R40 public desktop action output removes raw text while preserving content and action hashes',async()=>{
|
|
@@ -19,7 +19,7 @@ function F(at,image=H('same'),window=WIN){
|
|
|
19
19
|
bounds:{left:0,top:0,width:1000,height:800},activeWindow:window,imageSha256:image
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
async function fixture({grantActions=['click_primary','text_input'],captureFrames=null,times=null,inputProvider=null,grounderProvider=null}={}){
|
|
22
|
+
async function fixture({grantActions=['click_primary','text_input'],captureFrames=null,times=null,inputProvider=null,grounderProvider=null,clockMs=null,sleeper=null}={}){
|
|
23
23
|
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r40-desktop-runtime-'));
|
|
24
24
|
const grant=path.join(root,'grant.json'),evidence=path.join(root,'evidence');
|
|
25
25
|
const policy={
|
|
@@ -59,7 +59,7 @@ async function fixture({grantActions=['click_primary','text_input'],captureFrame
|
|
|
59
59
|
'2026-09-19T02:00:01.000Z'
|
|
60
60
|
])];
|
|
61
61
|
const now=()=>clock.length?clock.shift():'2026-09-19T02:00:01.000Z';
|
|
62
|
-
const runtime=createDesktopRuntime({policy,observerRuntime,inputProvider:provider,grounderProvider,privateKey,keyId:'test-key',evidenceDir:evidence,now});
|
|
62
|
+
const runtime=createDesktopRuntime({policy,observerRuntime,inputProvider:provider,grounderProvider,privateKey,keyId:'test-key',evidenceDir:evidence,now,clockMs:clockMs??undefined,sleeper:sleeper??undefined});
|
|
63
63
|
return {root,grant,evidence,policy,expected,runtime,calls,publicKey};
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -242,6 +242,47 @@ test('read-only observe works independently of desktop mutation grant',async()=>
|
|
|
242
242
|
assert.match(observed.receipt_sha256,/^[0-9a-f]{64}$/);
|
|
243
243
|
});
|
|
244
244
|
|
|
245
|
+
test('successor desktop wait observes until a frame changes and publishes signed final evidence',async()=>{
|
|
246
|
+
let tick=0;
|
|
247
|
+
const same={frame:F('2026-09-19T02:00:00.600Z'),backend:'fake',byte_length:4};
|
|
248
|
+
const changed={frame:F('2026-09-19T02:00:00.900Z',H('changed')),backend:'fake',byte_length:4};
|
|
249
|
+
const fx=await fixture({
|
|
250
|
+
captureFrames:[same,changed],clockMs:()=>tick,sleeper:async ms=>{tick+=ms;},
|
|
251
|
+
times:['2026-09-19T02:00:01.000Z']
|
|
252
|
+
});
|
|
253
|
+
await writeFile(fx.grant,'{}');
|
|
254
|
+
const result=await fx.runtime.wait({baselineFrameId:fx.expected.frame_id,until:'frame_changed',timeoutMs:1000,pollMs:100});
|
|
255
|
+
assert.equal(result.satisfied,true);
|
|
256
|
+
assert.equal(result.timed_out,false);
|
|
257
|
+
assert.equal(result.attempts,2);
|
|
258
|
+
assert.equal(result.frame.frame_id,changed.frame.frame_id);
|
|
259
|
+
assert.match(result.receipt_sha256,/^[0-9a-f]{64}$/);
|
|
260
|
+
const receipt=JSON.parse(await readFile(path.join(fx.evidence,`${result.receipt_id}.json`),'utf8'));
|
|
261
|
+
assert.equal(receipt.kind,'desktop_wait_observation');
|
|
262
|
+
assert.equal(receipt.payload.condition,'frame_changed');
|
|
263
|
+
assert.equal(receipt.payload.satisfied,true);
|
|
264
|
+
assert.equal(fx.calls.length,0);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test('successor desktop wait uses local UIA matching without leaking query text or dispatching input',async()=>{
|
|
268
|
+
let tick=0,queries=0;
|
|
269
|
+
const first={frame:F('2026-09-19T02:00:00.600Z'),backend:'fake',byte_length:4};
|
|
270
|
+
const second={frame:F('2026-09-19T02:00:00.900Z'),backend:'fake',byte_length:4};
|
|
271
|
+
const grounderProvider=async({query})=>{
|
|
272
|
+
queries++;
|
|
273
|
+
return {status:'ok',query_sha256:H('wait-query'),query_kind:query.kind,ordinal:0,visited:4,truncated:false,
|
|
274
|
+
matches:queries===1?[]:[{rect:{left:1,top:2,width:3,height:4},control_type:50000,enabled:true,offscreen:false}],
|
|
275
|
+
provider_receipt_sha256:H('wait-provider')};
|
|
276
|
+
};
|
|
277
|
+
const fx=await fixture({captureFrames:[first,second],grounderProvider,clockMs:()=>tick,sleeper:async ms=>{tick+=ms;},times:['2026-09-19T02:00:01.000Z']});
|
|
278
|
+
const result=await fx.runtime.wait({baselineFrameId:fx.expected.frame_id,until:'uia_present',query:{kind:'name_exact',value:'SECRET READY',max_results:8,ordinal:0},timeoutMs:1000,pollMs:100});
|
|
279
|
+
assert.equal(result.satisfied,true);
|
|
280
|
+
assert.equal(result.match.actionable,true);
|
|
281
|
+
assert.equal(result.match.query_sha256,H('wait-query'));
|
|
282
|
+
assert.equal(JSON.stringify(result).includes('SECRET READY'),false);
|
|
283
|
+
assert.equal(fx.calls.length,0);
|
|
284
|
+
});
|
|
285
|
+
|
|
245
286
|
|
|
246
287
|
test('desktop runtime enforces policy max_text_bytes before observation or input effect',async()=>{
|
|
247
288
|
const fx=await fixture({grantActions:['text_input']});
|
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
7
7
|
import { Client } from '@modelcontextprotocol/client';
|
|
8
8
|
import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
|
|
9
9
|
import { createR34Fixture } from './helpers/autonomous-r34-fixture.mjs';
|
|
10
|
+
import { expectedFullCatalogForEnv } from '../src/runtime-catalog-expectation.mjs';
|
|
10
11
|
|
|
11
12
|
const here=path.dirname(fileURLToPath(import.meta.url));
|
|
12
13
|
const repoRoot=path.resolve(here,'..');
|
|
@@ -15,7 +16,7 @@ const desktopPolicyPath=path.join(repoRoot,'controller','deadbyte-desktop-policy
|
|
|
15
16
|
const catalogPath=path.join(repoRoot,'docs','R48-FULL-TOOL-CATALOG.json');
|
|
16
17
|
const absent=async p=>{try{await access(p);return false;}catch(e){if(e?.code==='ENOENT')return true;throw e;}};
|
|
17
18
|
|
|
18
|
-
test('
|
|
19
|
+
test('R49 runtime full stdio catalog exactly matches sealed R48 base plus reviewed overlay',async()=>{
|
|
19
20
|
const canonical=JSON.parse(await readFile(catalogPath,'utf8'));
|
|
20
21
|
assert.equal(canonical.schema,'deadbyte.r48-full-catalog.v1');
|
|
21
22
|
assert.equal(canonical.train,'R48');
|
|
@@ -61,15 +62,16 @@ test('R48 runtime full stdio catalog exactly matches canonical registration surf
|
|
|
61
62
|
DEADBYTE_AUTONOMOUS_RUNTIME:'1',DEADBYTE_AUTONOMOUS_POLICY:path.join(f.root,'autonomous-policy.json'),
|
|
62
63
|
DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE:'external'
|
|
63
64
|
};
|
|
65
|
+
const expected=await expectedFullCatalogForEnv(env);
|
|
64
66
|
const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env,stderr:'pipe'});
|
|
65
67
|
try{
|
|
66
68
|
await client.connect(transport);
|
|
67
69
|
const listed=await client.listTools();
|
|
68
70
|
const names=listed.tools.map(t=>t.name).sort();
|
|
69
|
-
assert.deepEqual(names,
|
|
71
|
+
assert.deepEqual(names,expected);
|
|
70
72
|
assert.equal(new Set(names).size,names.length,'runtime duplicate tool names');
|
|
71
73
|
for(const tool of listed.tools) if(tool.outputSchema!==undefined) assert.equal(tool.outputSchema?.additionalProperties,false,'non-strict output '+tool.name);
|
|
72
|
-
for(const name of ['agent_task_submit','autonomous_goal_submit','coding_task_submit','process_session_start','machine_fs_write','machine_search_start','desktop_action','host_exec','native_diff_apply','skill_catalog']) assert.ok(names.includes(name),'missing
|
|
74
|
+
for(const name of ['agent_task_submit','autonomous_goal_submit','coding_task_submit','process_session_start','machine_fs_write','machine_search_start','desktop_wait','desktop_action','host_exec','native_diff_apply','skill_catalog']) assert.ok(names.includes(name),'missing R49 surface '+name);
|
|
73
75
|
} finally {
|
|
74
76
|
await client.close().catch(()=>{});
|
|
75
77
|
for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority file appeared during catalog probe: '+q);
|
|
@@ -42,3 +42,9 @@ test('publish boundary excludes live state, private keys, grants and non-example
|
|
|
42
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
|
});
|
|
45
|
+
|
|
46
|
+
test('publish boundary includes only the canonical top-level Windows launcher',()=>{
|
|
47
|
+
const files=packFiles();
|
|
48
|
+
const launchers=files.filter(rel=>/^DEADBYTE-MCP.*\.cmd$/i.test(rel));
|
|
49
|
+
assert.deepEqual(launchers,['DEADBYTE-MCP.cmd']);
|
|
50
|
+
});
|
|
@@ -3,46 +3,55 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { DEADBYTE_VERSION } from '../src/version.mjs';
|
|
5
5
|
|
|
6
|
-
const root=new URL('../',import.meta.url);
|
|
7
|
-
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
6
|
+
const root = new URL('../', import.meta.url);
|
|
7
|
+
const read = rel => readFile(new URL(rel, root), 'utf8');
|
|
8
8
|
|
|
9
|
-
test('
|
|
10
|
-
const [pkg,lock,release,provenance,matrix]=await Promise.all([
|
|
9
|
+
test('R50 0.15.27 successor binds exact published immutable 0.15.26 parent', async () => {
|
|
10
|
+
const [pkg, lock, release, provenance, matrix] = await Promise.all([
|
|
11
11
|
read('package.json').then(JSON.parse),
|
|
12
12
|
read('package-lock.json').then(JSON.parse),
|
|
13
13
|
read('RELEASE.json').then(JSON.parse),
|
|
14
14
|
read('PROVENANCE.json').then(JSON.parse),
|
|
15
15
|
read('TEST-MATRIX.json').then(JSON.parse)
|
|
16
16
|
]);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
assert.equal(
|
|
27
|
-
|
|
28
|
-
assert.equal(release.
|
|
29
|
-
assert.equal(release.
|
|
30
|
-
assert.equal(release.
|
|
31
|
-
assert.equal(release.
|
|
32
|
-
assert.equal(release.
|
|
33
|
-
|
|
34
|
-
assert.equal(release.
|
|
35
|
-
assert.equal(release.
|
|
36
|
-
assert.equal(release.
|
|
37
|
-
assert.equal(release.
|
|
38
|
-
assert.equal(release.
|
|
39
|
-
|
|
40
|
-
assert.equal(release.capabilities.
|
|
41
|
-
assert.equal(
|
|
42
|
-
assert.equal(
|
|
43
|
-
assert.equal(
|
|
44
|
-
assert.equal(
|
|
45
|
-
assert.equal(
|
|
46
|
-
assert.equal(
|
|
47
|
-
assert.equal(
|
|
17
|
+
|
|
18
|
+
for (const value of [
|
|
19
|
+
pkg.version,
|
|
20
|
+
lock.version,
|
|
21
|
+
lock.packages[''].version,
|
|
22
|
+
DEADBYTE_VERSION,
|
|
23
|
+
release.version,
|
|
24
|
+
provenance.version,
|
|
25
|
+
matrix.version
|
|
26
|
+
]) assert.equal(value, '0.15.27');
|
|
27
|
+
|
|
28
|
+
assert.equal(release.train, 'R50');
|
|
29
|
+
assert.equal(release.label, 'PUBLIC PACKAGE BOUNDARY HOTFIX');
|
|
30
|
+
assert.equal(release.parent.release_id, 'v0.15.26-669ea65d2307ee2c');
|
|
31
|
+
assert.equal(release.parent.manifest_sha256, '669ea65d2307ee2cce06be960e0a8c7243dc6135f7f129a88d99f53096433cc8');
|
|
32
|
+
assert.equal(release.parent.generation_manifest_sha256, '08364adaf1dab9730c314e29121632c6371ed76fc677e83cb7f6aa6b244eab94');
|
|
33
|
+
|
|
34
|
+
assert.equal(release.source_predecessor.version, '0.15.26');
|
|
35
|
+
assert.equal(release.source_predecessor.tarball_sha256, '3272679e3a18610d47e83dc8d3161e949d75a57da145a43c2ab50c865a83bb86');
|
|
36
|
+
assert.equal(release.source_predecessor.manifest_file_sha256, '669ea65d2307ee2cce06be960e0a8c7243dc6135f7f129a88d99f53096433cc8');
|
|
37
|
+
assert.equal(release.source_predecessor.reference_server_sha256, 'dfc303bb7dd2e8d01debac50fc43bb8644d00089bffdf2887e149497cff8b305');
|
|
38
|
+
assert.equal(release.source_predecessor.reference_schemas_sha256, 'f342345e34e48769dabaefe1b932f09d41e2e207b422f7794a15ee50ffa8f140');
|
|
39
|
+
|
|
40
|
+
assert.equal(release.capabilities.full_tool_count, 117);
|
|
41
|
+
assert.equal(release.capabilities.desktop_bounded_semantic_wait, true);
|
|
42
|
+
assert.equal(release.capabilities.commander_incremental_pdf_revisions, true);
|
|
43
|
+
assert.equal(release.capabilities.commander_docx_header_footer_search, true);
|
|
44
|
+
assert.equal(release.capabilities.commander_directory_read_fallback, true);
|
|
45
|
+
assert.equal(release.capabilities.commander_binary_detection, true);
|
|
46
|
+
assert.equal(release.capabilities.commander_protocol_adversarial, true);
|
|
47
|
+
assert.equal(release.capabilities.atomic_mutation_unknown_effect, true);
|
|
48
|
+
|
|
49
|
+
assert.equal(provenance.parent_release_id, release.parent.release_id);
|
|
50
|
+
assert.equal(provenance.parent_manifest_sha256, release.parent.manifest_sha256);
|
|
51
|
+
assert.equal(provenance.parent_generation_manifest_sha256, release.parent.generation_manifest_sha256);
|
|
52
|
+
assert.equal(provenance.source_predecessor_tarball_sha256, release.source_predecessor.tarball_sha256);
|
|
53
|
+
|
|
54
|
+
assert.equal(matrix.train, 'R50');
|
|
55
|
+
assert.equal(matrix.predecessor_r48_full_regression_partition_proof.files, 211);
|
|
56
|
+
assert.equal(matrix.predecessor_r48_full_regression_partition_proof.not_valid_as_r50_proof, true);
|
|
48
57
|
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
|
|
5
|
+
const artifact=new URL('../docs/R49-REMOTE-CONTROL-DONORS.json',import.meta.url);
|
|
6
|
+
|
|
7
|
+
test('R49 remote-control donor evidence pins all requested sources and records bounded native adoption',async()=>{
|
|
8
|
+
const value=JSON.parse(await readFile(artifact,'utf8'));
|
|
9
|
+
assert.equal(value.schema,'deadbyte.r49-remote-control-donors.v1');
|
|
10
|
+
assert.equal(value.donors.length,6);
|
|
11
|
+
assert.deepEqual(value.donors.map(item=>item.repository),[
|
|
12
|
+
'https://github.com/shahidx0x/better-remote-commander',
|
|
13
|
+
'https://github.com/Jennifer9911/open-remote-mcp',
|
|
14
|
+
'https://github.com/Razewang/secure-host-mcp',
|
|
15
|
+
'https://github.com/dddabtc/winremote-mcp',
|
|
16
|
+
'https://github.com/getremcp/remcp',
|
|
17
|
+
'https://github.com/trycua/cua'
|
|
18
|
+
]);
|
|
19
|
+
for(const donor of value.donors)assert.match(donor.commit,/^[0-9a-f]{40}$/);
|
|
20
|
+
assert.equal(value.adopted_checkpoint.capability,'desktop.wait');
|
|
21
|
+
assert.equal(value.adopted_checkpoint.authority,'none');
|
|
22
|
+
assert.ok(value.adopted_checkpoint.properties.includes('no input dispatch and no action retry'));
|
|
23
|
+
assert.ok(value.explicit_non_adoptions.includes('generic shell or caller-selected executable authority'));
|
|
24
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import test from 'node:test';
|
|
4
|
+
|
|
5
|
+
const read = path => readFile(new URL(`../${path}`, import.meta.url), 'utf8');
|
|
6
|
+
|
|
7
|
+
test('R50 canonical Windows gate is successor-bound and preserves R49/R48 historical gates', async () => {
|
|
8
|
+
const [pkgText, gate, evidence, historicalR49, historicalR48, deferred] = await Promise.all([
|
|
9
|
+
read('package.json'),
|
|
10
|
+
read('scripts/gate-windows-r50.ps1'),
|
|
11
|
+
read('scripts/windows-gate-evidence-r50.mjs'),
|
|
12
|
+
read('scripts/gate-windows-r49.ps1'),
|
|
13
|
+
read('scripts/gate-windows-r48.ps1'),
|
|
14
|
+
read('scripts/deferred-slot-operation-r46.mjs')
|
|
15
|
+
]);
|
|
16
|
+
const pkg = JSON.parse(pkgText);
|
|
17
|
+
assert.match(pkg.scripts['gate:windows'], /gate-windows-r50\.ps1$/);
|
|
18
|
+
assert.match(gate, /DEADBYTE 0\.15\.27 \/ R50 WINDOWS GATE: PASS/);
|
|
19
|
+
assert.match(gate, /r50-package-boundary/);
|
|
20
|
+
assert.match(gate, /r49-remote-control-donors\.test\.mjs/);
|
|
21
|
+
assert.match(gate, /desktop-runtime-r40\.test\.mjs/);
|
|
22
|
+
assert.match(gate, /manifest-final-verify/);
|
|
23
|
+
assert.match(evidence, /deadbyte\.r50-windows-gate\.v1/);
|
|
24
|
+
assert.match(evidence, /pkg\.version === '0\.15\.27'/);
|
|
25
|
+
assert.match(evidence, /release\.train === 'R50'/);
|
|
26
|
+
assert.match(historicalR49, /DEADBYTE 0\.15\.26 \/ R49 WINDOWS GATE: PASS/);
|
|
27
|
+
assert.match(historicalR48, /DEADBYTE 0\.15\.25 \/ R48 WINDOWS GATE: PASS/);
|
|
28
|
+
assert.match(deferred, /const expectedVersion=packageIdentity\.version/);
|
|
29
|
+
assert.match(deferred, /'--expected-version',expectedVersion/);
|
|
30
|
+
assert.match(deferred, /async function awaitHandoffCompletion/);
|
|
31
|
+
assert.match(deferred, /verifySlotUpdateEnvelope\(envelope,publicKey\)/);
|
|
32
|
+
assert.match(deferred, /active pointer does not match signed activation receipt/);
|
|
33
|
+
assert.match(deferred, /failure-receipt\.json/);
|
|
34
|
+
assert.match(deferred, /await awaitHandoffCompletion\(await runSlotUpdateCli/);
|
|
35
|
+
assert.doesNotMatch(deferred, /'--expected-version','0\.15\.5'/);
|
|
36
|
+
});
|
|
@@ -32,6 +32,15 @@ test('R29 remote gate accepts machine plane as an exact optional catalog dimensi
|
|
|
32
32
|
assert.match(source, /if \(machine\) items\.push\(\.\.\.machineTools\)/);
|
|
33
33
|
assert.match(source, /machine_runtime: machineRuntime/);
|
|
34
34
|
});
|
|
35
|
+
|
|
36
|
+
test('R49 compact remote gate independently verifies signed machine ping', async () => {
|
|
37
|
+
const source = await readFile(sourcePath, 'utf8');
|
|
38
|
+
assert.match(source, /verifyMachinePingPublic/);
|
|
39
|
+
assert.match(source, /public_key_spki_base64/);
|
|
40
|
+
assert.match(source, /machine ping public Ed25519 verification failed/);
|
|
41
|
+
assert.match(source, /ping_signature_valid: true/);
|
|
42
|
+
assert.doesNotMatch(source, /ping_signature_valid: ping\.signature_valid === true/);
|
|
43
|
+
});
|
|
35
44
|
test('R46 remote gate accepts seven-tool process supervision as one exact optional catalog dimension', async () => {
|
|
36
45
|
const source = await readFile(sourcePath, 'utf8');
|
|
37
46
|
assert.match(source, /const processTools = \[/);
|