deadbyte-mcp 0.15.33 → 0.15.35

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.
Files changed (72) hide show
  1. package/MANIFEST.SHA256 +71 -22
  2. package/PROVENANCE.json +57 -28
  3. package/README.txt +22 -14
  4. package/RELEASE.json +41 -29
  5. package/SBOM.cdx.json +25 -3
  6. package/TEST-MATRIX.json +135 -43
  7. package/bridge/package.json +11 -0
  8. package/bridge/src/bridge.mjs +412 -0
  9. package/bridge/src/node-http-adapter.mjs +56 -0
  10. package/bridge/src/public-tool-definitions.mjs +14 -0
  11. package/bridge/src/r40-governor.mjs +160 -0
  12. package/controller/deadbyte-controller.ps1 +84 -8
  13. package/controller/deadbyte-process-policy.json +4 -4
  14. package/package.json +6 -3
  15. package/scripts/bridge-benchmark-r58.mjs +67 -0
  16. package/scripts/deploy-r48.mjs +2 -3
  17. package/scripts/gate-windows-r57.ps1 +27 -0
  18. package/scripts/gate-windows-r58.ps1 +33 -0
  19. package/scripts/owner-probe-r58.mjs +31 -0
  20. package/scripts/performance-r58.mjs +57 -0
  21. package/scripts/public-baseline-r58.mjs +72 -0
  22. package/scripts/public-surface-r58.mjs +84 -0
  23. package/scripts/r58-cross-plane.ps1 +6 -0
  24. package/scripts/r58-focused.ps1 +6 -0
  25. package/scripts/windows-gate-evidence-r57.mjs +81 -0
  26. package/scripts/windows-gate-evidence-r58.mjs +93 -0
  27. package/src/deadbyte-cli.mjs +40 -12
  28. package/src/doctor-foreground-r58.mjs +44 -0
  29. package/src/doctor-installation-r58.mjs +63 -0
  30. package/src/doctor-r45.mjs +21 -4
  31. package/src/doctor-runtime-r58.mjs +82 -0
  32. package/src/doctor-transactions-r58.mjs +40 -0
  33. package/src/foreground-process-identity.mjs +27 -0
  34. package/src/foreground-session-lock.mjs +20 -0
  35. package/src/foreground-session-lock.ps1 +15 -0
  36. package/src/release-generation.mjs +1 -0
  37. package/src/release-slot.mjs +2 -1
  38. package/src/remote-session-guardian.mjs +8 -1
  39. package/src/runtime-update.mjs +117 -3
  40. package/src/version.mjs +1 -1
  41. package/test/controller-r211.test.mjs +4 -1
  42. package/test/controller.test.mjs +2 -1
  43. package/test/helpers/r58-doctor-fixture.mjs +26 -0
  44. package/test/r49-windows-gate.test.mjs +14 -10
  45. package/test/r56-release-contract.test.mjs +5 -3
  46. package/test/r57-core-startup-race.test.mjs +85 -0
  47. package/test/r57-release-contract.test.mjs +67 -0
  48. package/test/r58-bridge-dependency-binding.test.mjs +62 -0
  49. package/test/r58-bundled-bridge.test.mjs +22 -0
  50. package/test/r58-cleanup-retention.test.mjs +45 -0
  51. package/test/r58-completed-update-receipt.test.mjs +76 -0
  52. package/test/r58-concurrent-recovery.test.mjs +54 -0
  53. package/test/r58-controller-core-observation.test.mjs +36 -0
  54. package/test/r58-controller-json.test.mjs +48 -0
  55. package/test/r58-controller-live-local.test.mjs +85 -0
  56. package/test/r58-controller-readonly.test.mjs +23 -0
  57. package/test/r58-controller-state-coherence.test.mjs +45 -0
  58. package/test/r58-doctor-cli.test.mjs +20 -0
  59. package/test/r58-doctor-foreground.test.mjs +50 -0
  60. package/test/r58-doctor-installation.test.mjs +55 -0
  61. package/test/r58-doctor-pointer.test.mjs +41 -0
  62. package/test/r58-doctor-runtime.test.mjs +45 -0
  63. package/test/r58-doctor-transactions.test.mjs +21 -0
  64. package/test/r58-guardian-channel.test.mjs +26 -0
  65. package/test/r58-launcher-shell.test.mjs +28 -0
  66. package/test/r58-owner-identity.test.mjs +20 -0
  67. package/test/r58-release-contract.test.mjs +49 -0
  68. package/test/r58-session-lock.test.mjs +26 -0
  69. package/test/r58-stale-owner.test.mjs +71 -0
  70. package/test/r58-windows-gate.test.mjs +31 -0
  71. package/test/release-generation.test.mjs +4 -1
  72. package/test/remote-session-cli.test.mjs +55 -2
@@ -0,0 +1,56 @@
1
+ import {once} from 'node:events';
2
+
3
+ function requestHeaders(headers){
4
+ const out=new Headers();
5
+ for(const [name,value] of Object.entries(headers??{})){
6
+ if(value===undefined) continue;
7
+ if(Array.isArray(value)){for(const item of value) out.append(name,String(item));}
8
+ else out.append(name,String(value));
9
+ }
10
+ return out;
11
+ }
12
+ async function requestBody(req,maxBodyBytes){
13
+ const method=String(req.method??'GET').toUpperCase();
14
+ if(method==='GET'||method==='HEAD') return undefined;
15
+ const chunks=[];let total=0;
16
+ for await(const chunk of req){
17
+ const bytes=Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk);
18
+ total+=bytes.length;
19
+ if(total>maxBodyBytes) throw new Error(`bridge request body exceeds ${maxBodyBytes} bytes`);
20
+ chunks.push(bytes);
21
+ }
22
+ return Buffer.concat(chunks,total);
23
+ }
24
+ async function writeResponse(res,response){
25
+ const headers={};
26
+ for(const [name,value] of response.headers.entries()) headers[name]=value;
27
+ res.writeHead(response.status,headers);
28
+ if(!response.body){res.end();return;}
29
+ const reader=response.body.getReader();
30
+ try{
31
+ while(true){
32
+ const {done,value}=await reader.read();
33
+ if(done) break;
34
+ if(res.destroyed){await reader.cancel().catch(()=>{});return;}
35
+ if(!res.write(value)) await once(res,'drain');
36
+ }
37
+ }finally{reader.releaseLock();}
38
+ if(!res.destroyed) res.end();
39
+ }
40
+
41
+ export function createDeadbyteNodeHandler(handler,{maxBodyBytes=1024*1024}={}){
42
+ if(!handler||typeof handler.fetch!=='function') throw new Error('bridge node adapter requires fetch-shaped MCP handler');
43
+ if(!Number.isInteger(maxBodyBytes)||maxBodyBytes<1024||maxBodyBytes>4*1024*1024) throw new Error('bridge node adapter maxBodyBytes invalid');
44
+ return async function nodeHandler(req,res){
45
+ const method=String(req.method??'GET').toUpperCase();
46
+ const url=new URL(String(req.url??'/'),'http://127.0.0.1');
47
+ const body=await requestBody(req,maxBodyBytes);
48
+ const init={method,headers:requestHeaders(req.headers)};
49
+ if(body!==undefined) init.body=body;
50
+ const request=new Request(url,init);
51
+ const options=req.auth?{authInfo:req.auth}:undefined;
52
+ const response=await handler.fetch(request,options);
53
+ if(!(response instanceof Response)) throw new Error('bridge MCP handler returned non-Response');
54
+ await writeResponse(res,response);
55
+ };
56
+ }
@@ -0,0 +1,14 @@
1
+ import {fromJsonSchema} from '@modelcontextprotocol/server';
2
+
3
+ // Catalog is fixed by the existing downstream startup attestation. Only schema
4
+ // definitions/validators are shared; servers, callbacks and requestState aren't.
5
+ export function preparePublicToolDefinitions(tools){
6
+ return Object.freeze(tools.map(tool=>{
7
+ const input=structuredClone(tool.inputSchema??{type:'object',properties:{},additionalProperties:false});
8
+ if(tool.name==='autonomous_goal_run'){
9
+ if(input.properties&&typeof input.properties==='object')delete input.properties.planner_response;
10
+ if(Array.isArray(input.required))input.required=input.required.filter(name=>name!=='planner_response');
11
+ }
12
+ return Object.freeze({...tool,inputSchema:fromJsonSchema(input),outputSchema:tool.outputSchema?fromJsonSchema(tool.outputSchema):undefined});
13
+ }));
14
+ }
@@ -0,0 +1,160 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ const DESKTOP_RAW_KEYS=new Set([
4
+ 'pixels','pixel_bytes','frame_bytes','raw_bgra','raw_rgba','raw_image','screenshot_bytes','bitmap_bytes'
5
+ ]);
6
+ const DEFAULT_LIMITS=Object.freeze({
7
+ normal:Object.freeze({max_active:8,max_queue:32,queue_timeout_ms:30000}),
8
+ autonomous:Object.freeze({max_active:2,max_queue:8,queue_timeout_ms:60000}),
9
+ desktop_observe:Object.freeze({max_active:2,max_queue:4,queue_timeout_ms:10000}),
10
+ desktop_action:Object.freeze({max_active:1,max_queue:2,queue_timeout_ms:5000})
11
+ });
12
+ const DEADLINES=Object.freeze({
13
+ normal:Object.freeze({timeout:120000,maxTotalTimeout:180000}),
14
+ autonomous:Object.freeze({timeout:900000,maxTotalTimeout:1200000}),
15
+ desktop_observe:Object.freeze({timeout:30000,maxTotalTimeout:60000}),
16
+ desktop_action:Object.freeze({timeout:30000,maxTotalTimeout:45000})
17
+ });
18
+
19
+ function insist(condition,message){ if(!condition) throw new Error(message); }
20
+ function toolClass(name){
21
+ const value=String(name??'');
22
+ if(value==='autonomous_goal_run') return 'autonomous';
23
+ if(value==='desktop_action') return 'desktop_action';
24
+ if(value.startsWith('desktop_')) return 'desktop_observe';
25
+ return 'normal';
26
+ }
27
+ function estimateBase64Bytes(value){
28
+ if(typeof value!=='string') return 0;
29
+ const clean=value.replace(/\s/g,'');
30
+ if(clean.length===0) return 0;
31
+ const padding=clean.endsWith('==')?2:clean.endsWith('=')?1:0;
32
+ return Math.floor(clean.length*3/4)-padding;
33
+ }
34
+ function scanDesktopPayload(value,{maxPreviewBytes},path='result',seen=new Set()){
35
+ if(value===null||value===undefined) return;
36
+ if(typeof value==='string'||typeof value==='number'||typeof value==='boolean') return;
37
+ if(typeof value!=='object') return;
38
+ if(seen.has(value)) throw new Error('bridge desktop result contains cyclic value');
39
+ seen.add(value);
40
+ if(Array.isArray(value)){
41
+ for(let i=0;i<value.length;i++) scanDesktopPayload(value[i],{maxPreviewBytes},`${path}[${i}]`,seen);
42
+ seen.delete(value); return;
43
+ }
44
+ for(const [key,child] of Object.entries(value)){
45
+ const lower=key.toLowerCase();
46
+ if(DESKTOP_RAW_KEYS.has(lower)) throw new Error(`bridge desktop result contains forbidden raw frame field '${path}.${key}'`);
47
+ if((lower==='preview_png_base64'||lower==='preview_jpeg_base64')&&typeof child==='string'){
48
+ const bytes=estimateBase64Bytes(child);
49
+ if(bytes>maxPreviewBytes) throw new Error(`bridge desktop preview exceeds ${maxPreviewBytes} byte limit`);
50
+ }
51
+ if(lower==='data'&&value.type==='image'&&typeof child==='string'){
52
+ const bytes=estimateBase64Bytes(child);
53
+ if(bytes>maxPreviewBytes) throw new Error(`bridge MCP image content exceeds ${maxPreviewBytes} byte limit`);
54
+ }
55
+ scanDesktopPayload(child,{maxPreviewBytes},`${path}.${key}`,seen);
56
+ }
57
+ seen.delete(value);
58
+ }
59
+
60
+ export function bridgeToolClass(name){ return toolClass(name); }
61
+ export function bridgeDeadlineForTool(name){ return DEADLINES[toolClass(name)]; }
62
+ export function bridgeCatalogSha256(toolNames){
63
+ insist(Array.isArray(toolNames)&&toolNames.every(x=>typeof x==='string'),'bridge catalog names invalid');
64
+ const sorted=[...new Set(toolNames)].sort();
65
+ insist(sorted.length===toolNames.length,'bridge catalog contains duplicate tool name');
66
+ return createHash('sha256').update(JSON.stringify(sorted),'utf8').digest('hex');
67
+ }
68
+ export function verifyCompactCatalogAttestation(actualNames,toolResult){
69
+ insist(Array.isArray(actualNames)&&actualNames.every(x=>typeof x==='string'&&x.length>0),'actual bridge catalog invalid');
70
+ const actual=[...actualNames].sort();
71
+ insist(new Set(actual).size===actual.length,'actual bridge catalog contains duplicate tool name');
72
+ const envelope=toolResult?.structuredContent;
73
+ insist(envelope?.status==='ok'&&envelope?.op==='manifest','capability manifest tool result invalid');
74
+ const manifest=envelope.result;
75
+ insist(manifest?.schema==='deadbyte.capability-manifest.v2'||manifest?.schema==='deadbyte.capability-manifest.v3','capability manifest schema mismatch');
76
+ insist(manifest.profile==='compact','capability manifest profile mismatch');
77
+ insist(typeof manifest.ledger_sha256==='string'&&/^[0-9a-f]{64}$/.test(manifest.ledger_sha256),'capability manifest ledger hash invalid');
78
+ insist(Array.isArray(manifest.tool_catalog)&&manifest.tool_catalog.every(x=>typeof x==='string'&&x.length>0),'capability manifest tool_catalog invalid');
79
+ const declared=[...manifest.tool_catalog];
80
+ insist(declared.length===manifest.tool_count,'capability manifest tool_count mismatch');
81
+ insist(new Set(declared).size===declared.length,'capability manifest catalog contains duplicate tool name');
82
+ insist(JSON.stringify(declared)===JSON.stringify([...declared].sort()),'capability manifest catalog must be sorted');
83
+ const declaredSha=bridgeCatalogSha256(declared);
84
+ insist(declaredSha===manifest.catalog_sha256,'capability manifest catalog hash mismatch');
85
+ insist(JSON.stringify(actual)===JSON.stringify(declared),'bridge listTools/catalog attestation mismatch');
86
+ return Object.freeze({
87
+ ok:true,profile:'compact',tool_count:declared.length,catalog_sha256:declaredSha,ledger_sha256:manifest.ledger_sha256
88
+ });
89
+ }
90
+
91
+ export function enforceDesktopBridgeResult(toolName,result,{maxPreviewBytes=1024*1024}={}){
92
+ if(!String(toolName??'').startsWith('desktop_')) return result;
93
+ insist(Number.isInteger(maxPreviewBytes)&&maxPreviewBytes>=16*1024&&maxPreviewBytes<=4*1024*1024,'maxPreviewBytes invalid');
94
+ scanDesktopPayload(result,{maxPreviewBytes});
95
+ return result;
96
+ }
97
+
98
+ export function createBridgeGovernor({limits=DEFAULT_LIMITS}={}){
99
+ const classes=['normal','autonomous','desktop_observe','desktop_action'];
100
+ for(const name of classes){
101
+ const cfg=limits[name];
102
+ insist(cfg&&Number.isInteger(cfg.max_active)&&cfg.max_active>=1&&cfg.max_active<=64,`bridge limit ${name}.max_active invalid`);
103
+ insist(Number.isInteger(cfg.max_queue)&&cfg.max_queue>=0&&cfg.max_queue<=256,`bridge limit ${name}.max_queue invalid`);
104
+ insist(Number.isInteger(cfg.queue_timeout_ms)&&cfg.queue_timeout_ms>=100&&cfg.queue_timeout_ms<=120000,`bridge limit ${name}.queue_timeout_ms invalid`);
105
+ }
106
+ const state=new Map(classes.map(name=>[name,{active:0,queue:[]}]));
107
+ let sequence=0;
108
+
109
+ function dispatch(name){
110
+ const cfg=limits[name],s=state.get(name);
111
+ while(s.active<cfg.max_active&&s.queue.length){
112
+ const waiter=s.queue.shift();
113
+ if(waiter.done) continue;
114
+ waiter.done=true; clearTimeout(waiter.timer); s.active++;
115
+ waiter.resolve(makeTicket(name,waiter.tool,waiter.id,waiter.queuedAt));
116
+ }
117
+ }
118
+ function makeTicket(name,tool,id,queuedAt){
119
+ let released=false;
120
+ return Object.freeze({
121
+ id,class:name,tool,queued_ms:Math.max(0,Date.now()-queuedAt),
122
+ release(){
123
+ if(released) return false;
124
+ released=true;
125
+ const s=state.get(name);
126
+ s.active=Math.max(0,s.active-1);
127
+ dispatch(name);
128
+ return true;
129
+ }
130
+ });
131
+ }
132
+ async function acquire(tool){
133
+ const name=toolClass(tool),cfg=limits[name],s=state.get(name),id=++sequence,queuedAt=Date.now();
134
+ if(s.active<cfg.max_active){
135
+ s.active++;
136
+ return makeTicket(name,String(tool),id,queuedAt);
137
+ }
138
+ if(s.queue.length>=cfg.max_queue) throw new Error(`bridge backpressure queue full for ${name}`);
139
+ return await new Promise((resolve,reject)=>{
140
+ const waiter={id,tool:String(tool),queuedAt,resolve,reject,done:false,timer:null};
141
+ waiter.timer=setTimeout(()=>{
142
+ if(waiter.done)return;
143
+ waiter.done=true;
144
+ const index=s.queue.indexOf(waiter); if(index>=0)s.queue.splice(index,1);
145
+ reject(new Error(`bridge backpressure queue timeout for ${name}`));
146
+ },cfg.queue_timeout_ms);
147
+ s.queue.push(waiter);
148
+ });
149
+ }
150
+ function snapshot(){
151
+ return Object.freeze(Object.fromEntries(classes.map(name=>{
152
+ const s=state.get(name),cfg=limits[name];
153
+ return [name,Object.freeze({active:s.active,queued:s.queue.filter(x=>!x.done).length,max_active:cfg.max_active,max_queue:cfg.max_queue})];
154
+ })));
155
+ }
156
+ return Object.freeze({acquire,snapshot});
157
+ }
158
+
159
+ export const BRIDGE_R40_DEFAULT_LIMITS=DEFAULT_LIMITS;
160
+
@@ -3,7 +3,8 @@
3
3
  param(
4
4
  [Parameter(Position=0)]
5
5
  [ValidateSet('menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest','armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest','armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest','supervisorstart','supervisorstop','supervisorstatus','supervisorrecover','armdesktop','disarmdesktop','desktopstatus')]
6
- [string]$Command = 'menu'
6
+ [string]$Command = 'menu',
7
+ [switch]$Json
7
8
  )
8
9
 
9
10
  Set-StrictMode -Version 3.0
@@ -16,6 +17,7 @@ $LogDir = Join-Path $RuntimeDir 'logs'
16
17
  $ConfigPath = if ($env:DEADBYTE_CONTROLLER_CONFIG) { $env:DEADBYTE_CONTROLLER_CONFIG } else { Join-Path $Root 'deadbyte-controller.config.psd1' }
17
18
 
18
19
  function Fail([string]$Message) { throw "DEADBYTE controller: $Message" }
20
+ if ($Json -and $Command -ne 'status') { Fail 'JSON observation is available only for status' }
19
21
 
20
22
  function Get-ControllerMutationMutexName {
21
23
  $normalized = ([System.IO.Path]::GetFullPath($RuntimeDir)).TrimEnd('\\').ToLowerInvariant()
@@ -721,12 +723,14 @@ function Test-LocalReadyOwned($Cfg, $Bridge) {
721
723
  function Get-ObservedState($Cfg) {
722
724
  $bridge = Test-OwnedInstance 'Bridge'
723
725
  $cloud = Test-OwnedInstance 'Cloud'
724
- $ready = if ($bridge.Alive) { try { Test-LocalReadyOwned $Cfg $bridge } catch { $false } } else { $false }
726
+ $core = Get-DownstreamCoreObservation $Cfg $bridge
727
+ $ready = if ($bridge.Alive -and $core.alive) { try { Test-LocalReadyOwned $Cfg $bridge } catch { $false } } else { $false }
725
728
  $state = if (-not $bridge.Alive -and -not $cloud.Alive) { 'OFFLINE' }
726
729
  elseif (-not $bridge.Alive -and $cloud.Alive) { 'PARKED' }
727
730
  elseif ($bridge.Alive -and $cloud.Alive -and $ready) { 'ONLINE' }
728
- else { 'DEGRADED' }
729
- [pscustomobject]@{ State=$state; Bridge=$bridge; Cloud=$cloud; LocalReady=$ready }
731
+ elseif ($bridge.Alive -and $core.reason -eq 'startup-zero-child') { 'STARTING' }
732
+ else { 'FAILED' }
733
+ [pscustomobject]@{ State=$state; Bridge=$bridge; Core=$core; Cloud=$cloud; LocalReady=$ready }
730
734
  }
731
735
 
732
736
  function Wait-LocalReady($Cfg) {
@@ -734,7 +738,10 @@ function Wait-LocalReady($Cfg) {
734
738
  do {
735
739
  $bridge = Test-OwnedInstance 'Bridge'
736
740
  if (-not $bridge.Alive) { return $false }
737
- if (Test-LocalReadyOwned $Cfg $bridge) { return $true }
741
+ $core = Get-DownstreamCoreObservation $Cfg $bridge
742
+ if (-not $core.alive -and $core.reason -ne 'startup-zero-child') { return $false }
743
+ if ($core.alive -and (Test-LocalReadyOwned $Cfg $bridge)) { return $true }
744
+ if ([DateTime]::UtcNow -ge $deadline) { return $false }
738
745
  Start-Sleep -Milliseconds 250
739
746
  } while ([DateTime]::UtcNow -lt $deadline)
740
747
  return $false
@@ -836,7 +843,7 @@ function Invoke-CoreGate($Cfg, [string]$ScriptName, [string[]]$ExtraArguments =
836
843
  function Start-Deadbyte($Cfg) {
837
844
  $state = Get-ObservedState $Cfg
838
845
  if ($state.State -eq 'ONLINE') { return $state }
839
- if ($state.State -eq 'DEGRADED') { Fail 'runtime is DEGRADED; use status and stop only if identities remain verified' }
846
+ if ($state.State -in @('FAILED','STARTING')) { Fail "runtime is $($state.State); inspect status and reconcile verified owned components before restart" }
840
847
  $cloudWasAlive = [bool]$state.Cloud.Alive
841
848
  Assert-LocalReadyPortAvailable $Cfg
842
849
  try {
@@ -1265,6 +1272,73 @@ function Recover-AutonomousSupervisor($Cfg) {
1265
1272
  return [pscustomobject]@{ Runtime=$runtime; Supervisor=$supervisor; Process=$process; Coding=$coding; Autonomous=$autonomous; Desktop=$desktop; Host=$hostStatus }
1266
1273
  }
1267
1274
 
1275
+ function Get-BoundedObservationReason($Value) {
1276
+ $reason = [string]$Value
1277
+ if ($reason -cmatch '^[a-z][a-z0-9-]{0,63}$') { return $reason }
1278
+ return 'unverified'
1279
+ }
1280
+
1281
+ function Convert-OwnedObservation($Owned) {
1282
+ $pidValue = $null; $birth = $null
1283
+ if ($Owned.Alive -and $Owned.Ledger) {
1284
+ $pidValue = [int]$Owned.Ledger.pid
1285
+ $birth = [string]$Owned.Ledger.creation_time_utc
1286
+ }
1287
+ [ordered]@{ alive=[bool]$Owned.Alive; reason=(Get-BoundedObservationReason $Owned.Reason); pid=$pidValue; creation_time_utc=$birth }
1288
+ }
1289
+
1290
+ function Convert-AuthorityObservation($Authority) {
1291
+ [ordered]@{ configured=[bool]$Authority.Configured; armed=[bool]$Authority.Armed; reason=(Get-BoundedObservationReason $Authority.Reason) }
1292
+ }
1293
+
1294
+ function Get-DownstreamCoreObservation($Cfg, $Bridge) {
1295
+ $out = [ordered]@{ alive=$false; reason='bridge-unavailable'; pid=$null; parent_pid=$null; creation_time_utc=$null; identity_basis=$null }
1296
+ if (-not $Bridge.Alive) { return $out }
1297
+ $bridgePid = [int]$Bridge.Ledger.pid
1298
+ if (-not [string]::Equals([IO.Path]::GetFullPath([string]$Bridge.Ledger.script_path), [IO.Path]::GetFullPath([string]$Cfg.Bridge.ScriptPath), [StringComparison]::OrdinalIgnoreCase) -or [string]$Bridge.Ledger.script_sha256 -ne [string]$Cfg.Bridge.ScriptSha256) {
1299
+ $out.reason='bridge-config-mismatch'; return $out
1300
+ }
1301
+ try {
1302
+ $children = @(Get-CimInstance Win32_Process -Filter ("ParentProcessId={0} AND Name='node.exe'" -f $bridgePid) -ErrorAction Stop)
1303
+ if ($children.Count -eq 0) { $out.reason='startup-zero-child'; return $out }
1304
+ if ($children.Count -ne 1) { $out.reason='ambiguous-core'; return $out }
1305
+ $child = $children[0]
1306
+ if ([int]$child.ParentProcessId -ne $bridgePid -or [int]$child.ProcessId -lt 1 -or $null -eq $child.CreationDate) { $out.reason='core-identity-incomplete'; return $out }
1307
+ if (-not [string]::IsNullOrWhiteSpace([string]$child.ExecutablePath) -and -not [string]::Equals([string]$child.ExecutablePath,[string]$Cfg.Bridge.FilePath,[StringComparison]::OrdinalIgnoreCase)) { $out.reason='core-image-mismatch'; return $out }
1308
+ $command = [string]$child.CommandLine
1309
+ $needle = (Join-Path ([string]$Cfg.CoreRoot) 'src\mcp-server.mjs').Replace('/','\').ToLowerInvariant()
1310
+ if ([string]::IsNullOrWhiteSpace($command)) { $basis='verified-bridge-single-opaque-node-child' }
1311
+ elseif ($command.Replace('/','\').ToLowerInvariant().Contains($needle)) { $basis='command-line' }
1312
+ else { $out.reason='wrong-core-generation'; return $out }
1313
+ $out.alive=$true; $out.reason='verified'; $out.pid=[int]$child.ProcessId; $out.parent_pid=$bridgePid
1314
+ $out.creation_time_utc=$child.CreationDate.ToUniversalTime().ToString('o'); $out.identity_basis=$basis
1315
+ return $out
1316
+ } catch { $out.reason='core-observation-failed'; return $out }
1317
+ }
1318
+
1319
+ function Get-StructuredObservation($Cfg) {
1320
+ $s = Get-ObservedState $Cfg
1321
+ $supervisor = Get-AutonomousSupervisorStatus $Cfg
1322
+ [ordered]@{
1323
+ schema='deadbyte.controller-observation.v1'
1324
+ observed_at_utc=[DateTime]::UtcNow.ToString('o')
1325
+ state=[string]$s.State
1326
+ core_root=[string]$Cfg.CoreRoot
1327
+ local_ready=[bool]$s.LocalReady
1328
+ bridge=(Convert-OwnedObservation $s.Bridge)
1329
+ core=$s.Core
1330
+ cloud=(Convert-OwnedObservation $s.Cloud)
1331
+ supervisor=[ordered]@{ configured=[bool]$supervisor.Configured; running=[bool]$supervisor.Running; reason=(Get-BoundedObservationReason $supervisor.Reason) }
1332
+ authority=[ordered]@{
1333
+ process=(Convert-AuthorityObservation (Get-ProcessGrantStatus $Cfg))
1334
+ coding=(Convert-AuthorityObservation (Get-CodingLeaseStatus $Cfg))
1335
+ autonomous=(Convert-AuthorityObservation (Get-AutonomousLeaseStatus $Cfg))
1336
+ desktop=(Convert-AuthorityObservation (Get-DesktopGrantStatus $Cfg))
1337
+ host=(Convert-AuthorityObservation (Get-HostArmStatus $Cfg))
1338
+ }
1339
+ }
1340
+ }
1341
+
1268
1342
  function Show-State($Cfg) {
1269
1343
  $s = Get-ObservedState $Cfg
1270
1344
  $bp = if ($s.Bridge.Alive) { $s.Bridge.Ledger.pid } else { '-' }
@@ -1272,6 +1346,7 @@ function Show-State($Cfg) {
1272
1346
  $url = Get-CurrentUrl $Cfg
1273
1347
  Write-Host ("DEADBYTE MCP = {0}" -f $s.State)
1274
1348
  Write-Host ("Bridge PID : {0} [{1}]" -f $bp, $s.Bridge.Reason)
1349
+ Write-Host ("Core PID : {0} [{1}]" -f $(if ($s.Core.alive) { $s.Core.pid } else { '-' }), $s.Core.reason)
1275
1350
  Write-Host ("Cloud PID : {0} [{1}]" -f $cp, $s.Cloud.Reason)
1276
1351
  Write-Host ("Local ready : {0}" -f $s.LocalReady)
1277
1352
  Write-Host ("URL : {0}" -f $(if ($url) { $url } else { '<unknown>' }))
@@ -1370,14 +1445,15 @@ function Clean-Stale {
1370
1445
  function Run-CommandCore([string]$Name) {
1371
1446
  $cfg = Get-Config
1372
1447
  Assert-ControllerRootBound $cfg
1373
- Ensure-Directory $RuntimeDir; Ensure-Directory $LogDir
1448
+ $readOnly = $Name -in @('status','url','hoststatus','processstatus','codingstatus','autonomousstatus','desktopstatus','supervisorstatus')
1449
+ if (-not $readOnly) { Ensure-Directory $RuntimeDir; Ensure-Directory $LogDir }
1374
1450
  switch ($Name) {
1375
1451
  'start' { Start-Deadbyte $cfg | Out-Null; if ([bool]$cfg.AutonomousSupervisorEnabled) { Start-AutonomousSupervisor $cfg | Out-Null }; Show-State $cfg | Out-Null }
1376
1452
  'resume' { Start-Deadbyte $cfg | Out-Null; if ([bool]$cfg.AutonomousSupervisorEnabled) { Start-AutonomousSupervisor $cfg | Out-Null }; Show-State $cfg | Out-Null }
1377
1453
  'park' { Park-Deadbyte $cfg | Out-Null; Show-State $cfg | Out-Null }
1378
1454
  'stop' { if ([bool]$cfg.AutonomousSupervisorEnabled) { Stop-AutonomousSupervisor $cfg | Out-Null }; Stop-Deadbyte $cfg | Out-Null; Show-State $cfg | Out-Null }
1379
1455
  'restart' { if ([bool]$cfg.AutonomousSupervisorEnabled) { Stop-AutonomousSupervisor $cfg | Out-Null }; Stop-Deadbyte $cfg | Out-Null; Start-Deadbyte $cfg | Out-Null; if ([bool]$cfg.AutonomousSupervisorEnabled) { Start-AutonomousSupervisor $cfg | Out-Null }; Show-State $cfg | Out-Null }
1380
- 'status' { Show-State $cfg | Out-Null }
1456
+ 'status' { if ($Json) { Get-StructuredObservation $cfg | ConvertTo-Json -Depth 6 -Compress | Write-Output } else { Show-State $cfg | Out-Null } }
1381
1457
  'url' { $u=Get-CurrentUrl $cfg; if (-not $u) { Fail 'URL unavailable' }; Write-Output $u }
1382
1458
  'test' { Invoke-Smoke $cfg $false }
1383
1459
  'fulltest'{ Invoke-Smoke $cfg $true }
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "schema": "deadbyte.process-policy.v1",
3
3
  "enabled": true,
4
- "grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.33-r56\\controller\\runtime\\process-grant.json",
5
- "state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.33-r56\\controller\\runtime\\process-state",
4
+ "grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.35-r58\\controller\\runtime\\process-grant.json",
5
+ "state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.35-r58\\controller\\runtime\\process-state",
6
6
  "native_host": {
7
- "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.33-r56\\bin\\deadbyte-process-host.exe",
7
+ "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.35-r58\\bin\\deadbyte-process-host.exe",
8
8
  "sha256": "daf9cfb371bee88cafbf5597eaa507fec504dbe0b0ddd40d0c3c2e02817f49e4"
9
9
  },
10
10
  "roots": {
11
11
  "core": {
12
- "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.33-r56",
12
+ "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.35-r58",
13
13
  "deny_paths": [
14
14
  "node_modules",
15
15
  "controller/runtime",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deadbyte-mcp",
3
- "version": "0.15.33",
3
+ "version": "0.15.35",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
@@ -42,7 +42,7 @@
42
42
  "contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
43
43
  "contained:smoke": "node src/contained-smoke.mjs",
44
44
  "mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
45
- "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r56.ps1",
45
+ "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r58.ps1",
46
46
  "authority:smoke": "node src/authority-smoke.mjs",
47
47
  "mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
48
48
  "mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
@@ -78,7 +78,10 @@
78
78
  "r53:focused:test": "node --test --test-concurrency=1 test/r53-release-contract.test.mjs test/stabilization-update-child-root.test.mjs test/stabilization-state-root.test.mjs test/stabilization-guardian.test.mjs test/stabilization-semver.test.mjs test/stabilization-powershell.test.mjs test/release-slot.test.mjs test/runtime-self-update.test.mjs test/r51-runtime-coherence.test.mjs test/remote-session-cli.test.mjs test/r52-offline-predecessor-recovery.test.mjs test/r52-host-revocation.test.mjs",
79
79
  "r54:focused:test": "node --test --test-concurrency=1 test/r54-release-contract.test.mjs test/r54-offline-predecessor-self-exclusion.test.mjs test/r52-offline-predecessor-recovery.test.mjs test/runtime-self-update.test.mjs test/r51-runtime-coherence.test.mjs test/remote-session-cli.test.mjs",
80
80
  "r55:focused:test": "node --test --test-concurrency=1 test/r55-release-contract.test.mjs test/r55-offline-predecessor-guardian-family.test.mjs test/r54-offline-predecessor-self-exclusion.test.mjs test/r52-offline-predecessor-recovery.test.mjs test/runtime-self-update.test.mjs test/r51-runtime-coherence.test.mjs test/remote-session-cli.test.mjs",
81
- "r56:focused:test": "node --test --test-concurrency=1 test/r56-release-contract.test.mjs test/r56-rollback-launcher-restore.test.mjs test/r55-offline-predecessor-guardian-family.test.mjs test/r54-offline-predecessor-self-exclusion.test.mjs test/runtime-self-update.test.mjs test/release-slot.test.mjs test/r51-runtime-coherence.test.mjs"
81
+ "r56:focused:test": "node --test --test-concurrency=1 test/r56-release-contract.test.mjs test/r56-rollback-launcher-restore.test.mjs test/r55-offline-predecessor-guardian-family.test.mjs test/r54-offline-predecessor-self-exclusion.test.mjs test/runtime-self-update.test.mjs test/release-slot.test.mjs test/r51-runtime-coherence.test.mjs",
82
+ "r57:focused:test": "node --test --test-concurrency=1 test/r57-release-contract.test.mjs test/r57-core-startup-race.test.mjs test/r56-rollback-launcher-restore.test.mjs test/r55-offline-predecessor-guardian-family.test.mjs test/r54-offline-predecessor-self-exclusion.test.mjs test/runtime-self-update.test.mjs test/release-slot.test.mjs test/r51-runtime-coherence.test.mjs test/remote-session-cli.test.mjs",
83
+ "r58:focused:test": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/r58-focused.ps1",
84
+ "r58:cross-plane:test": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/r58-cross-plane.ps1"
82
85
  },
83
86
  "bundleDependencies": [
84
87
  "@modelcontextprotocol/server",
@@ -0,0 +1,67 @@
1
+ import {mkdir,readFile,writeFile,rm} from 'node:fs/promises';
2
+ import {spawn} from 'node:child_process';
3
+ import {randomBytes,createHash} from 'node:crypto';
4
+ import {createServer} from 'node:net';
5
+ import {performance} from 'node:perf_hooks';
6
+ import {setTimeout as delay} from 'node:timers/promises';
7
+ import path from 'node:path';
8
+ import {pathToFileURL} from 'node:url';
9
+ import {Client,StreamableHTTPClientTransport} from '@modelcontextprotocol/client';
10
+ import {generateTrustKeypair} from '../src/trust.mjs';
11
+ import {loadCodingPolicy} from '../src/coding-plane.mjs';
12
+
13
+ const run=path.resolve(process.argv[2]||'');const base=path.resolve('D:/Projects/deadbyte-mcp/testing/0.15.35');const rel=path.relative(base,run);
14
+ if(!rel||rel.startsWith('..')||path.isAbsolute(rel))throw new Error('new D: R58 run root required');await mkdir(run);
15
+ const core='C:/Users/DEADBYTE/.deadbyte-mcp/releases/v0.15.34-2199bb59f0e0fc20';
16
+ const targets={baseline:'D:/Projects/deadbyte-chatgpt-bridge-r40-dev',candidate:'D:/Projects/deadbyte-mcp/development/deadbyte-mcp-0.15.35-r58/bridge'};
17
+ const entries=Object.entries(targets);if(process.argv[3]==='candidate-first')entries.reverse();
18
+ const sha=b=>createHash('sha256').update(b).digest('hex');
19
+ if(sha(await readFile(path.join(core,'MANIFEST.SHA256')))!=='2199bb59f0e0fc205d470d11f990d3ce3df444be5eba2a7d8dbc60d5f5b790bb')throw new Error('core baseline drift');
20
+ const summaries={};
21
+ const extended=process.argv.includes('--extended');
22
+ const corpus=[{name:'coding_session_status',arguments:{}},{name:'capability_manifest',arguments:{}}];
23
+ if(extended)corpus.push({name:'coding_file_read',arguments:{root_id:'bench',path:'input.txt'}},{name:'coding_tree',arguments:{root_id:'bench',path:'.',max_depth:2,max_entries:100}});
24
+ for(const [label,target] of entries){
25
+ const root=path.join(run,label);await mkdir(root);const state=path.join(root,'state'),workspace=path.join(root,'workspace'),temp=path.join(root,'temp');
26
+ for(const dir of [state,workspace,temp])await mkdir(dir);
27
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
28
+ const policy=path.join(root,'policy.json');
29
+ await writeFile(policy,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:path.join(state,'grant.json'),evidence_dir:path.join(state,'evidence'),roots:{bench:{path:workspace,read:true,write:false,exec:false,deny_paths:[]}},commands:{},max_read_bytes:65536,max_write_bytes:65536}),{flag:'wx'});
30
+ const fixture='bounded fixture alpha\n'.repeat(100);await writeFile(path.join(workspace,'input.txt'),fixture,{flag:'wx'});
31
+ if(extended){const loaded=await loadCodingPolicy(policy);await writeFile(path.join(state,'grant.json'),JSON.stringify({schema:'deadbyte.coding-grant.v2',policy_sha256:loaded.policy_sha256,instance_nonce:randomBytes(32).toString('hex'),root_ids:['bench']}),{flag:'wx'});}
32
+ const reservation=createServer();await new Promise(resolve=>reservation.listen(0,'127.0.0.1',resolve));const port=reservation.address().port;await new Promise(resolve=>reservation.close(resolve));
33
+ const token=randomBytes(32).toString('hex');const env={...process.env};for(const key of Object.keys(env))if(key.startsWith('DEADBYTE_'))delete env[key];
34
+ Object.assign(env,{TEMP:temp,TMP:temp,npm_config_cache:path.join(root,'npm-cache'),DEADBYTE_CORE_ROOT:core,DEADBYTE_STATE_ROOT:state,DEADBYTE_WORKSPACE_ROOT:workspace,DEADBYTE_BRIDGE_PORT:String(port),DEADBYTE_BRIDGE_PATH_TOKEN:token,DEADBYTE_SIGNING_KEY:keys.privateKeyPath,DEADBYTE_VERIFY_KEY:keys.publicKeyPath,DEADBYTE_PRIVILEGED_POLICY:'',DEADBYTE_CAPABILITY_PROFILE:'compact',DEADBYTE_MACHINE_RUNTIME:'0',DEADBYTE_AGENT_RUNTIME:'0',DEADBYTE_PROCESS_RUNTIME:'0',DEADBYTE_CODING_RUNTIME:'1',DEADBYTE_CODING_POLICY:policy,DEADBYTE_MACHINE_FS_RUNTIME:'0',DEADBYTE_OBSERVATION_RUNTIME:'0',DEADBYTE_DESKTOP_RUNTIME:'0',DEADBYTE_AUTONOMOUS_RUNTIME:'0',DEADBYTE_AUDIT_RUNTIME:'0'});
35
+ const bridgePath=path.join(target,'src/bridge.mjs');const script=`process.on('message',m=>{if(m==='stop')process.emit('SIGTERM')});await import(${JSON.stringify(pathToFileURL(bridgePath).href)});`;
36
+ const start=performance.now();const child=spawn(process.execPath,['--input-type=module','-e',script],{cwd:target,env,windowsHide:true,stdio:['ignore','pipe','pipe','ipc']});
37
+ let stdout='',stderr='';child.stdout.on('data',b=>{stdout+=b;});child.stderr.on('data',b=>{stderr+=b;});const exited=new Promise(resolve=>child.once('exit',code=>resolve(code)));
38
+ const samples=[];let catalog;
39
+ try{
40
+ const deadline=Date.now()+20000;while(!stdout.includes('BRIDGE_READY')&&child.exitCode===null&&Date.now()<deadline)await delay(20);
41
+ if(!stdout.includes('BRIDGE_READY'))throw new Error(`${label} bridge startup failed: ${stderr}`);
42
+ const startup=performance.now()-start;
43
+ for(let batch=0;batch<3;batch++){
44
+ const client=new Client({name:'r58-isolated-bridge-benchmark',version:'1.0.0'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
45
+ try{
46
+ await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${port}/mcp/${token}`)));
47
+ const tools=(await client.listTools()).tools;if(!catalog){catalog=tools;await writeFile(path.join(root,'catalog.json'),JSON.stringify(tools,null,2),{flag:'wx'});}
48
+ for(let iteration=0;iteration<120;iteration++)for(const request of corpus){
49
+ const {name}=request;const t=performance.now();const result=await client.callTool(request);const elapsed=performance.now()-t;
50
+ if(result.isError||!result.structuredContent)throw new Error(`${label} benchmark tool failed: ${name}`);
51
+ if(name==='coding_file_read'&&(result.structuredContent.content!==fixture||result.structuredContent.sha256!==sha(fixture)))throw new Error('read behavior/hash oracle mismatch');
52
+ if(iteration>=20)samples.push({batch,iteration:iteration-20,tool:name,roundtrip_ms:elapsed});
53
+ }
54
+ }finally{await client.close();}
55
+ }
56
+ const quant=values=>{const v=[...values].sort((a,b)=>a-b),q=p=>v[Math.ceil(v.length*p)-1];return{n:v.length,min:v[0],p50:q(.5),p90:q(.9),p95:q(.95),p99:q(.99),max:v.at(-1)}};
57
+ summaries[label]={startup_ms:startup,script_sha256:sha(await readFile(bridgePath)),catalog_count:catalog.length,rows:Object.fromEntries(corpus.map(({name})=>[name,quant(samples.filter(s=>s.tool===name).map(s=>s.roundtrip_ms))])),aggregate:quant(samples.map(s=>s.roundtrip_ms))};
58
+ await writeFile(path.join(root,'raw.json'),JSON.stringify(samples),{flag:'wx'});
59
+ }finally{
60
+ await rm(path.join(state,'grant.json'),{force:true});
61
+ if(child.connected)child.send('stop');
62
+ const code=await Promise.race([exited,delay(5000).then(()=>null)]);if(code===null){child.kill();throw new Error('owned fixture bridge did not close through normal shutdown');}
63
+ await writeFile(path.join(root,'stdout.log'),stdout,{flag:'wx'});await writeFile(path.join(root,'stderr.log'),stderr,{flag:'wx'});
64
+ }
65
+ }
66
+ const result={schema:'deadbyte.r58.isolated-bridge-performance.v1',status:'MEASURED_NOT_FULL_PERFORMANCE_ACCEPTANCE',core,corpus,workload_sha256:sha(JSON.stringify(corpus)),test_read_grant:extended,grant_removed_after_target:true,summaries,p95_reduction_pct:100*(1-summaries.candidate.aggregate.p95/summaries.baseline.aggregate.p95),limitations:['bounded read-only categories only','not production machine ping/public transport','no mutation/build/test/durable workload','sequential target order; no statistical inference','no production activation']};
67
+ await writeFile(path.join(run,'summary.json'),JSON.stringify(result,null,2),{flag:'wx'});console.log(JSON.stringify(result,null,2));
@@ -4,7 +4,7 @@ import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { spawnSync } from 'node:child_process';
6
6
  import { fileURLToPath } from 'node:url';
7
- import { loadPowerShellDataFile, runSlotUpdateCli } from '../src/runtime-update.mjs';
7
+ import { runSlotUpdateCli } from '../src/runtime-update.mjs';
8
8
  import { parseActivePointer } from '../src/release-slot.mjs';
9
9
 
10
10
  const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
@@ -58,8 +58,7 @@ async function waitForActivation({handoffPath,expectedVersion,expectedManifest,t
58
58
 
59
59
  const manifest=await sha(path.join(root,'MANIFEST.SHA256'));
60
60
  const pointer=JSON.parse(await readFile(path.join(state,'active-release.json'),'utf8'));
61
- const cfg=await loadPowerShellDataFile(pointer.config_path);
62
- const bridgeRoot=path.resolve(cfg.Bridge.WorkingDirectory);
61
+ const bridgeRoot=path.join(root,'bridge');
63
62
  const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs');
64
63
  const pkg=JSON.parse(await readFile(path.join(root,'package.json'),'utf8'));
65
64
  const expectedVersion=pkg.version;
@@ -0,0 +1,27 @@
1
+ $ErrorActionPreference = 'Stop'
2
+ Set-StrictMode -Version 3.0
3
+
4
+ function Invoke-GateStep {
5
+ param([Parameter(Mandatory)][string]$Name,[Parameter(Mandatory)][string[]]$NpmArgs)
6
+ Write-Host "==== $Name ===="
7
+ & npm.cmd @NpmArgs
8
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE 0.15.34 / R57 gate failed at $Name with exit code $LASTEXITCODE" }
9
+ }
10
+ function Invoke-NodeTest {
11
+ param([Parameter(Mandatory)][string]$Name,[Parameter(Mandatory)][string[]]$TestFiles)
12
+ Write-Host "==== $Name ===="
13
+ & node.exe --test --test-concurrency=1 @TestFiles
14
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE 0.15.34 / R57 gate failed at $Name with exit code $LASTEXITCODE" }
15
+ }
16
+
17
+ Invoke-NodeTest 'r57-package-boundary' @('test/package-boundary.test.mjs')
18
+ Invoke-GateStep 'r57-focused-contracts' @('run','r57:focused:test')
19
+ Write-Host '==== full-regression-evidence ===='
20
+ $matrix=Get-Content -LiteralPath (Join-Path (Split-Path $PSScriptRoot -Parent) 'TEST-MATRIX.json') -Raw | ConvertFrom-Json
21
+ if($matrix.observed_pre_release_evidence.full_regression.status -ne 'PASS'){ throw 'R57 full regression evidence is not PASS' }
22
+ Invoke-GateStep 'manifest-write' @('run','manifest:write')
23
+ Invoke-GateStep 'manifest-verify' @('run','manifest:verify')
24
+ Invoke-GateStep 'doctor' @('run','doctor')
25
+ & node.exe (Join-Path $PSScriptRoot 'windows-gate-evidence-r57.mjs')
26
+ if ($LASTEXITCODE -ne 0) { throw "R57 evidence writer failed with exit code $LASTEXITCODE" }
27
+ Write-Host '==== DEADBYTE 0.15.34 / R57 WINDOWS GATE: PASS ===='
@@ -0,0 +1,33 @@
1
+ $ErrorActionPreference = 'Stop'
2
+ Set-StrictMode -Version 3.0
3
+
4
+ function Invoke-GateStep {
5
+ param([Parameter(Mandatory)][string]$Name,[Parameter(Mandatory)][string[]]$NpmArgs)
6
+ Write-Host "==== $Name ===="
7
+ & npm.cmd @NpmArgs
8
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE 0.15.35 / R58 gate failed at $Name with exit code $LASTEXITCODE" }
9
+ }
10
+ function Invoke-NodeTest {
11
+ param([Parameter(Mandatory)][string]$Name,[Parameter(Mandatory)][string[]]$TestFiles)
12
+ Write-Host "==== $Name ===="
13
+ & node.exe --test --test-concurrency=1 @TestFiles
14
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE 0.15.35 / R58 gate failed at $Name with exit code $LASTEXITCODE" }
15
+ }
16
+
17
+ Invoke-NodeTest 'r58-package-boundary' @('test/package-boundary.test.mjs','test/r58-bundled-bridge.test.mjs')
18
+ Invoke-NodeTest 'r58-process-policy' @('test/process-policy-refresh.test.mjs','test/process-release-gate.test.mjs')
19
+ Invoke-GateStep 'r58-focused-contracts' @('run','r58:focused:test')
20
+
21
+ Write-Host '==== recorded-prepublish-evidence ===='
22
+ $matrix=Get-Content -LiteralPath (Join-Path (Split-Path $PSScriptRoot -Parent) 'TEST-MATRIX.json') -Raw | ConvertFrom-Json
23
+ if($matrix.observed_pre_release_evidence.performance.status -ne 'PASS_BOUNDED_PREPUBLISH'){ throw 'R58 performance evidence is not PASS_BOUNDED_PREPUBLISH' }
24
+ if($matrix.observed_pre_release_evidence.cross_plane.status -ne 'PASS'){ throw 'R58 cross-plane evidence is not PASS' }
25
+ if($matrix.observed_pre_release_evidence.public_surface.status -ne 'PASS'){ throw 'R58 public surface evidence is not PASS' }
26
+ if($matrix.observed_pre_release_evidence.full_regression.status -ne 'PASS'){ throw 'R58 fresh full regression evidence is not PASS' }
27
+
28
+ Invoke-GateStep 'manifest-write' @('run','manifest:write')
29
+ Invoke-GateStep 'manifest-verify' @('run','manifest:verify')
30
+ Invoke-GateStep 'doctor' @('run','doctor')
31
+ & node.exe (Join-Path $PSScriptRoot 'windows-gate-evidence-r58.mjs')
32
+ if ($LASTEXITCODE -ne 0) { throw "R58 evidence writer failed with exit code $LASTEXITCODE" }
33
+ Write-Host '==== DEADBYTE 0.15.35 / R58 WINDOWS GATE: PASS ===='
@@ -0,0 +1,31 @@
1
+ import {spawn,spawnSync} from 'node:child_process';
2
+ import {writeFile} from 'node:fs/promises';
3
+ import {performance} from 'node:perf_hooks';
4
+ import {createHash} from 'node:crypto';
5
+ import path from 'node:path';
6
+ import {windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
7
+
8
+ // Diagnostic only. Queries only a child created and held by this process.
9
+ // Not an ownership authority, cleanup path, or public PID control tool.
10
+ const out=path.resolve(process.argv[2]||'');
11
+ const base=path.resolve('D:/Projects/deadbyte-mcp/testing/0.15.35');
12
+ const rel=path.relative(base,out);
13
+ if(!rel||rel.startsWith('..')||path.isAbsolute(rel))throw new Error('D: R58 evidence destination required');
14
+ const ps=path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe');
15
+ const child=spawn(process.execPath,['-e','setTimeout(()=>{},30000)'],{stdio:'ignore',windowsHide:true});
16
+ const closed=new Promise(resolve=>child.once('close',resolve));
17
+ const samples=[];
18
+ try{
19
+ if(!Number.isInteger(child.pid)||child.pid<1)throw new Error('diagnostic child failed');
20
+ for(let i=0;i<3;i++){
21
+ const query=`$p=Get-CimInstance Win32_Process -Filter 'ProcessId=${child.pid}'; if ($null -eq $p) {exit 2}; [pscustomobject]@{pid=$p.ProcessId; parent_pid=$p.ParentProcessId; creation_utc=$p.CreationDate.ToUniversalTime().ToString('o'); executable_path=$p.ExecutablePath; command_line=$p.CommandLine} | ConvertTo-Json -Compress`;
22
+ const t=performance.now();const result=spawnSync(ps,['-NoLogo','-NoProfile','-Command',query],{encoding:'utf8',windowsHide:true,env:windowsPowerShellEnvironment(process.env),timeout:15000});
23
+ if(result.error||result.status!==0)throw new Error('narrow process diagnostic failed');
24
+ const info=JSON.parse(result.stdout);
25
+ if(info.pid!==child.pid||info.parent_pid!==process.pid||path.resolve(info.executable_path).toLowerCase()!==path.resolve(process.execPath).toLowerCase())throw new Error('owned diagnostic process identity mismatch');
26
+ samples.push({pid:info.pid,parent_pid:info.parent_pid,creation_utc:info.creation_utc,executable_path:info.executable_path,command_line_sha256:createHash('sha256').update(info.command_line).digest('hex'),query_ms:performance.now()-t});
27
+ }
28
+ if(new Set(samples.map(s=>s.creation_utc)).size!==1)throw new Error('creation identity changed');
29
+ await writeFile(out,JSON.stringify({schema:'deadbyte.r58.owner-probe.v1',observed_at:new Date().toISOString(),status:'DIAGNOSTIC_ONLY',samples,limitations:['not production ownership verification','not PID-reuse recovery acceptance','CIM spawn latency unsuitable for frequent guardian polling without measured redesign']},null,2),{flag:'wx'});
30
+ console.log(JSON.stringify({status:'DIAGNOSTIC_ONLY',samples:samples.length,query_ms:samples.map(s=>s.query_ms)}));
31
+ } finally {if(child.exitCode===null)child.kill();await closed;}